Home | History | Annotate | Download | only in shape
      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 
     33 package com.jme3.scene.shape;
     34 
     35 import com.jme3.export.InputCapsule;
     36 import com.jme3.export.JmeExporter;
     37 import com.jme3.export.JmeImporter;
     38 import com.jme3.export.OutputCapsule;
     39 import com.jme3.math.Vector3f;
     40 import com.jme3.scene.Mesh;
     41 import java.io.IOException;
     42 
     43 /**
     44  * An eight sided box.
     45  * <p>
     46  * A {@code Box} is defined by a minimal point and a maximal point. The eight
     47  * vertices that make the box are then computed, they are computed in such
     48  * a way as to generate an axis-aligned box.
     49  * <p>
     50  * This class does not control how the geometry data is generated, see {@link Box}
     51  * for that.
     52  *
     53  * @author <a href="mailto:ianp (at) ianp.org">Ian Phillips</a>
     54  * @version $Revision: 4131 $, $Date: 2009-03-19 16:15:28 -0400 (Thu, 19 Mar 2009) $
     55  */
     56 public abstract class AbstractBox extends Mesh {
     57 
     58     public final Vector3f center = new Vector3f(0f, 0f, 0f);
     59 
     60     public float xExtent, yExtent, zExtent;
     61 
     62     public AbstractBox() {
     63         super();
     64     }
     65 
     66     /**
     67      * Gets the array or vectors representing the 8 vertices of the box.
     68      *
     69      * @return a newly created array of vertex vectors.
     70      */
     71     protected final Vector3f[] computeVertices() {
     72         Vector3f[] axes = {
     73                 Vector3f.UNIT_X.mult(xExtent),
     74                 Vector3f.UNIT_Y.mult(yExtent),
     75                 Vector3f.UNIT_Z.mult(zExtent)
     76         };
     77         return new Vector3f[] {
     78                 center.subtract(axes[0]).subtractLocal(axes[1]).subtractLocal(axes[2]),
     79                 center.add(axes[0]).subtractLocal(axes[1]).subtractLocal(axes[2]),
     80                 center.add(axes[0]).addLocal(axes[1]).subtractLocal(axes[2]),
     81                 center.subtract(axes[0]).addLocal(axes[1]).subtractLocal(axes[2]),
     82                 center.add(axes[0]).subtractLocal(axes[1]).addLocal(axes[2]),
     83                 center.subtract(axes[0]).subtractLocal(axes[1]).addLocal(axes[2]),
     84                 center.add(axes[0]).addLocal(axes[1]).addLocal(axes[2]),
     85                 center.subtract(axes[0]).addLocal(axes[1]).addLocal(axes[2])
     86         };
     87     }
     88 
     89     /**
     90      * Convert the indices into the list of vertices that define the box's geometry.
     91      */
     92     protected abstract void duUpdateGeometryIndices();
     93 
     94     /**
     95      * Update the normals of each of the box's planes.
     96      */
     97     protected abstract void duUpdateGeometryNormals();
     98 
     99     /**
    100      * Update the points that define the texture of the box.
    101      * <p>
    102      * It's a one-to-one ratio, where each plane of the box has it's own copy
    103      * of the texture. That is, the texture is repeated one time for each face.
    104      */
    105     protected abstract void duUpdateGeometryTextures();
    106 
    107     /**
    108      * Update the position of the vertices that define the box.
    109      * <p>
    110      * These eight points are determined from the minimum and maximum point.
    111      */
    112     protected abstract void duUpdateGeometryVertices();
    113 
    114     /**
    115      * Get the center point of this box.
    116      */
    117     public final Vector3f getCenter() {
    118         return center;
    119     }
    120 
    121     /**
    122      * Get the x-axis size (extent) of this box.
    123      */
    124     public final float getXExtent() {
    125         return xExtent;
    126     }
    127 
    128     /**
    129      * Get the y-axis size (extent) of this box.
    130      */
    131     public final float getYExtent() {
    132         return yExtent;
    133     }
    134 
    135     /**
    136      * Get the z-axis size (extent) of this box.
    137      */
    138     public final float getZExtent() {
    139         return zExtent;
    140     }
    141 
    142     /**
    143      * Rebuilds the box after a property has been directly altered.
    144      * <p>
    145      * For example, if you call {@code getXExtent().x = 5.0f} then you will
    146      * need to call this method afterwards in order to update the box.
    147      */
    148     public final void updateGeometry() {
    149         duUpdateGeometryVertices();
    150         duUpdateGeometryNormals();
    151         duUpdateGeometryTextures();
    152         duUpdateGeometryIndices();
    153     }
    154 
    155     /**
    156      * Rebuilds this box based on a new set of parameters.
    157      * <p>
    158      * Note that the actual sides will be twice the given extent values because
    159      * the box extends in both directions from the center for each extent.
    160      *
    161      * @param center the center of the box.
    162      * @param x the x extent of the box, in each directions.
    163      * @param y the y extent of the box, in each directions.
    164      * @param z the z extent of the box, in each directions.
    165      */
    166     public final void updateGeometry(Vector3f center, float x, float y, float z) {
    167         if (center != null) {this.center.set(center); }
    168         this.xExtent = x;
    169         this.yExtent = y;
    170         this.zExtent = z;
    171         updateGeometry();
    172     }
    173 
    174     /**
    175      * Rebuilds this box based on a new set of parameters.
    176      * <p>
    177      * The box is updated so that the two opposite corners are {@code minPoint}
    178      * and {@code maxPoint}, the other corners are created from those two positions.
    179      *
    180      * @param minPoint the new minimum point of the box.
    181      * @param maxPoint the new maximum point of the box.
    182      */
    183     public final void updateGeometry(Vector3f minPoint, Vector3f maxPoint) {
    184         center.set(maxPoint).addLocal(minPoint).multLocal(0.5f);
    185         float x = maxPoint.x - center.x;
    186         float y = maxPoint.y - center.y;
    187         float z = maxPoint.z - center.z;
    188         updateGeometry(center, x, y, z);
    189     }
    190 
    191     @Override
    192     public void read(JmeImporter e) throws IOException {
    193         super.read(e);
    194         InputCapsule capsule = e.getCapsule(this);
    195         xExtent = capsule.readFloat("xExtent", 0);
    196         yExtent = capsule.readFloat("yExtent", 0);
    197         zExtent = capsule.readFloat("zExtent", 0);
    198         center.set((Vector3f) capsule.readSavable("center", Vector3f.ZERO.clone()));
    199     }
    200 
    201     @Override
    202     public void write(JmeExporter e) throws IOException {
    203         super.write(e);
    204         OutputCapsule capsule = e.getCapsule(this);
    205         capsule.write(xExtent, "xExtent", 0);
    206         capsule.write(yExtent, "yExtent", 0);
    207         capsule.write(zExtent, "zExtent", 0);
    208         capsule.write(center, "center", Vector3f.ZERO);
    209     }
    210 
    211 }
    212