Home | History | Annotate | Download | only in math
      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 
     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      */
     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      */
     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 
     97     public Vector3f get1() {
     98         return pointa;
     99     }
    100 
    101     public Vector3f get2() {
    102         return pointb;
    103     }
    104 
    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      */
    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      */
    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 
    150     public void set1(Vector3f v) {
    151         pointa.set(v);
    152     }
    153 
    154     public void set2(Vector3f v) {
    155         pointb.set(v);
    156     }
    157 
    158     public void set3(Vector3f v) {
    159         pointc.set(v);
    160     }
    161 
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    263     public void setIndex(int index) {
    264         this.index = index;
    265     }
    266 
    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 
    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 
    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
    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