1 /*
2  * Copyright (c) 2009-2010 jMonkeyEngine
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17  *   may be used to endorse or promote products derived from this software
18  *   without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 package com.jme3.math;
33 
34 import com.jme3.export.JmeExporter;
35 import com.jme3.export.JmeImporter;
36 import com.jme3.export.Savable;
37 import java.io.IOException;
38 
39 /**
40  * <code>Triangle</code> defines an object for containing triangle information.
41  * The triangle is defined by a collection of three {@link Vector3f}
42  * objects.
43  *
44  * @author Mark Powell
45  * @author Joshua Slack
46  */
47 public class Triangle extends AbstractTriangle implements Savable, java.io.Serializable {
48 
49     static final long serialVersionUID = 1;
50 
51     private Vector3f pointa = new Vector3f();
52     private Vector3f pointb = new Vector3f();
53     private Vector3f pointc = new Vector3f();
54     private transient Vector3f center;
55     private transient Vector3f normal;
56     private float projection;
57     private int index;
58 
Triangle()59     public Triangle() {
60     }
61 
62     /**
63      * Constructor instantiates a new <Code>Triangle</code> object with the
64      * supplied vectors as the points. It is recommended that the vertices
65      * be supplied in a counter clockwise winding to support normals for a
66      * right handed coordinate system.
67      * @param p1 the first point of the triangle.
68      * @param p2 the second point of the triangle.
69      * @param p3 the third point of the triangle.
70      */
Triangle(Vector3f p1, Vector3f p2, Vector3f p3)71     public Triangle(Vector3f p1, Vector3f p2, Vector3f p3) {
72         pointa.set(p1);
73         pointb.set(p2);
74         pointc.set(p3);
75     }
76 
77     /**
78      *
79      * <code>get</code> retrieves a point on the triangle denoted by the index
80      * supplied.
81      * @param i the index of the point.
82      * @return the point.
83      */
get(int i)84     public Vector3f get(int i) {
85         switch (i) {
86             case 0:
87                 return pointa;
88             case 1:
89                 return pointb;
90             case 2:
91                 return pointc;
92             default:
93                 return null;
94         }
95     }
96 
get1()97     public Vector3f get1() {
98         return pointa;
99     }
100 
get2()101     public Vector3f get2() {
102         return pointb;
103     }
104 
get3()105     public Vector3f get3() {
106         return pointc;
107     }
108 
109     /**
110      *
111      * <code>set</code> sets one of the triangle's points to that specified as
112      * a parameter.
113      * @param i the index to place the point.
114      * @param point the point to set.
115      */
set(int i, Vector3f point)116     public void set(int i, Vector3f point) {
117         switch (i) {
118             case 0:
119                 pointa.set(point);
120                 break;
121             case 1:
122                 pointb.set(point);
123                 break;
124             case 2:
125                 pointc.set(point);
126                 break;
127         }
128     }
129 
130     /**
131      *
132      * <code>set</code> sets one of the triangle's points to that specified as
133      * a parameter.
134      * @param i the index to place the point.
135      */
set(int i, float x, float y, float z)136     public void set(int i, float x, float y, float z) {
137         switch (i) {
138             case 0:
139                 pointa.set(x, y, z);
140                 break;
141             case 1:
142                 pointb.set(x, y, z);
143                 break;
144             case 2:
145                 pointc.set(x, y, z);
146                 break;
147         }
148     }
149 
set1(Vector3f v)150     public void set1(Vector3f v) {
151         pointa.set(v);
152     }
153 
set2(Vector3f v)154     public void set2(Vector3f v) {
155         pointb.set(v);
156     }
157 
set3(Vector3f v)158     public void set3(Vector3f v) {
159         pointc.set(v);
160     }
161 
set(Vector3f v1, Vector3f v2, Vector3f v3)162     public void set(Vector3f v1, Vector3f v2, Vector3f v3) {
163         pointa.set(v1);
164         pointb.set(v2);
165         pointc.set(v3);
166     }
167 
168     /**
169      * calculateCenter finds the average point of the triangle.
170      *
171      */
calculateCenter()172     public void calculateCenter() {
173         if (center == null) {
174             center = new Vector3f(pointa);
175         } else {
176             center.set(pointa);
177         }
178         center.addLocal(pointb).addLocal(pointc).multLocal(FastMath.ONE_THIRD);
179     }
180 
181     /**
182      * calculateNormal generates the normal for this triangle
183      *
184      */
calculateNormal()185     public void calculateNormal() {
186         if (normal == null) {
187             normal = new Vector3f(pointb);
188         } else {
189             normal.set(pointb);
190         }
191         normal.subtractLocal(pointa).crossLocal(pointc.x - pointa.x, pointc.y - pointa.y, pointc.z - pointa.z);
192         normal.normalizeLocal();
193     }
194 
195     /**
196      * obtains the center point of this triangle (average of the three triangles)
197      * @return the center point.
198      */
getCenter()199     public Vector3f getCenter() {
200         if (center == null) {
201             calculateCenter();
202         }
203         return center;
204     }
205 
206     /**
207      * sets the center point of this triangle (average of the three triangles)
208      * @param center the center point.
209      */
setCenter(Vector3f center)210     public void setCenter(Vector3f center) {
211         this.center = center;
212     }
213 
214     /**
215      * obtains the unit length normal vector of this triangle, if set or
216      * calculated
217      *
218      * @return the normal vector
219      */
getNormal()220     public Vector3f getNormal() {
221         if (normal == null) {
222             calculateNormal();
223         }
224         return normal;
225     }
226 
227     /**
228      * sets the normal vector of this triangle (to conform, must be unit length)
229      * @param normal the normal vector.
230      */
setNormal(Vector3f normal)231     public void setNormal(Vector3f normal) {
232         this.normal = normal;
233     }
234 
235     /**
236      * obtains the projection of the vertices relative to the line origin.
237      * @return the projection of the triangle.
238      */
getProjection()239     public float getProjection() {
240         return this.projection;
241     }
242 
243     /**
244      * sets the projection of the vertices relative to the line origin.
245      * @param projection the projection of the triangle.
246      */
setProjection(float projection)247     public void setProjection(float projection) {
248         this.projection = projection;
249     }
250 
251     /**
252      * obtains an index that this triangle represents if it is contained in a OBBTree.
253      * @return the index in an OBBtree
254      */
getIndex()255     public int getIndex() {
256         return index;
257     }
258 
259     /**
260      * sets an index that this triangle represents if it is contained in a OBBTree.
261      * @param index the index in an OBBtree
262      */
setIndex(int index)263     public void setIndex(int index) {
264         this.index = index;
265     }
266 
computeTriangleNormal(Vector3f v1, Vector3f v2, Vector3f v3, Vector3f store)267     public static Vector3f computeTriangleNormal(Vector3f v1, Vector3f v2, Vector3f v3, Vector3f store) {
268         if (store == null) {
269             store = new Vector3f(v2);
270         } else {
271             store.set(v2);
272         }
273 
274         store.subtractLocal(v1).crossLocal(v3.x - v1.x, v3.y - v1.y, v3.z - v1.z);
275         return store.normalizeLocal();
276     }
277 
write(JmeExporter e)278     public void write(JmeExporter e) throws IOException {
279         e.getCapsule(this).write(pointa, "pointa", Vector3f.ZERO);
280         e.getCapsule(this).write(pointb, "pointb", Vector3f.ZERO);
281         e.getCapsule(this).write(pointc, "pointc", Vector3f.ZERO);
282     }
283 
read(JmeImporter e)284     public void read(JmeImporter e) throws IOException {
285         pointa = (Vector3f) e.getCapsule(this).readSavable("pointa", Vector3f.ZERO.clone());
286         pointb = (Vector3f) e.getCapsule(this).readSavable("pointb", Vector3f.ZERO.clone());
287         pointc = (Vector3f) e.getCapsule(this).readSavable("pointc", Vector3f.ZERO.clone());
288     }
289 
290     @Override
clone()291     public Triangle clone() {
292         try {
293             Triangle t = (Triangle) super.clone();
294             t.pointa = pointa.clone();
295             t.pointb = pointb.clone();
296             t.pointc = pointc.clone();
297             return t;
298         } catch (CloneNotSupportedException e) {
299             throw new AssertionError();
300         }
301     }
302 }
303