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 // $Id: Torus.java 4131 2009-03-19 20:15:28Z blaine.dev $
     34 package com.jme3.scene.shape;
     35 
     36 import com.jme3.export.InputCapsule;
     37 import com.jme3.export.JmeExporter;
     38 import com.jme3.export.JmeImporter;
     39 import com.jme3.export.OutputCapsule;
     40 import com.jme3.math.FastMath;
     41 import com.jme3.math.Vector3f;
     42 import com.jme3.scene.Mesh;
     43 import com.jme3.scene.VertexBuffer.Type;
     44 import com.jme3.util.BufferUtils;
     45 import java.io.IOException;
     46 import java.nio.FloatBuffer;
     47 import java.nio.ShortBuffer;
     48 
     49 /**
     50  * An ordinary (single holed) torus.
     51  * <p>
     52  * The center is by default the origin.
     53  *
     54  * @author Mark Powell
     55  * @version $Revision: 4131 $, $Date: 2009-03-19 16:15:28 -0400 (Thu, 19 Mar 2009) $
     56  */
     57 public class Torus extends Mesh {
     58 
     59     private int circleSamples;
     60 
     61     private int radialSamples;
     62 
     63     private float innerRadius;
     64 
     65     private float outerRadius;
     66 
     67     public Torus() {
     68     }
     69 
     70     /**
     71      * Constructs a new Torus. Center is the origin, but the Torus may be
     72      * transformed.
     73      *
     74      * @param circleSamples
     75      *            The number of samples along the circles.
     76      * @param radialSamples
     77      *            The number of samples along the radial.
     78      * @param innerRadius
     79      *            The radius of the inner begining of the Torus.
     80      * @param outerRadius
     81      *            The radius of the outter end of the Torus.
     82      */
     83     public Torus(int circleSamples, int radialSamples,
     84             float innerRadius, float outerRadius) {
     85         super();
     86         updateGeometry(circleSamples, radialSamples, innerRadius, outerRadius);
     87     }
     88 
     89     public int getCircleSamples() {
     90         return circleSamples;
     91     }
     92 
     93     public float getInnerRadius() {
     94         return innerRadius;
     95     }
     96 
     97     public float getOuterRadius() {
     98         return outerRadius;
     99     }
    100 
    101     public int getRadialSamples() {
    102         return radialSamples;
    103     }
    104 
    105     @Override
    106     public void read(JmeImporter e) throws IOException {
    107         super.read(e);
    108         InputCapsule capsule = e.getCapsule(this);
    109         circleSamples = capsule.readInt("circleSamples", 0);
    110         radialSamples = capsule.readInt("radialSamples", 0);
    111         innerRadius = capsule.readFloat("innerRadius", 0);
    112         outerRadius = capsule.readFloat("outerRaidus", 0);
    113     }
    114 
    115     private void setGeometryData() {
    116         // allocate vertices
    117         int vertCount = (circleSamples + 1) * (radialSamples + 1);
    118         FloatBuffer fpb = BufferUtils.createVector3Buffer(vertCount);
    119         setBuffer(Type.Position, 3, fpb);
    120 
    121         // allocate normals if requested
    122         FloatBuffer fnb = BufferUtils.createVector3Buffer(vertCount);
    123         setBuffer(Type.Normal, 3, fnb);
    124 
    125         // allocate texture coordinates
    126         FloatBuffer ftb = BufferUtils.createVector2Buffer(vertCount);
    127         setBuffer(Type.TexCoord, 2, ftb);
    128 
    129         // generate geometry
    130         float inverseCircleSamples = 1.0f / circleSamples;
    131         float inverseRadialSamples = 1.0f / radialSamples;
    132         int i = 0;
    133         // generate the cylinder itself
    134         Vector3f radialAxis = new Vector3f(), torusMiddle = new Vector3f(), tempNormal = new Vector3f();
    135         for (int circleCount = 0; circleCount < circleSamples; circleCount++) {
    136             // compute center point on torus circle at specified angle
    137             float circleFraction = circleCount * inverseCircleSamples;
    138             float theta = FastMath.TWO_PI * circleFraction;
    139             float cosTheta = FastMath.cos(theta);
    140             float sinTheta = FastMath.sin(theta);
    141             radialAxis.set(cosTheta, sinTheta, 0);
    142             radialAxis.mult(outerRadius, torusMiddle);
    143 
    144             // compute slice vertices with duplication at end point
    145             int iSave = i;
    146             for (int radialCount = 0; radialCount < radialSamples; radialCount++) {
    147                 float radialFraction = radialCount * inverseRadialSamples;
    148                 // in [0,1)
    149                 float phi = FastMath.TWO_PI * radialFraction;
    150                 float cosPhi = FastMath.cos(phi);
    151                 float sinPhi = FastMath.sin(phi);
    152                 tempNormal.set(radialAxis).multLocal(cosPhi);
    153                 tempNormal.z += sinPhi;
    154                 fnb.put(tempNormal.x).put(tempNormal.y).put(
    155                         tempNormal.z);
    156 
    157                 tempNormal.multLocal(innerRadius).addLocal(torusMiddle);
    158                 fpb.put(tempNormal.x).put(tempNormal.y).put(
    159                         tempNormal.z);
    160 
    161                 ftb.put(radialFraction).put(circleFraction);
    162                 i++;
    163             }
    164 
    165             BufferUtils.copyInternalVector3(fpb, iSave, i);
    166             BufferUtils.copyInternalVector3(fnb, iSave, i);
    167 
    168             ftb.put(1.0f).put(circleFraction);
    169 
    170             i++;
    171         }
    172 
    173         // duplicate the cylinder ends to form a torus
    174         for (int iR = 0; iR <= radialSamples; iR++, i++) {
    175             BufferUtils.copyInternalVector3(fpb, iR, i);
    176             BufferUtils.copyInternalVector3(fnb, iR, i);
    177             BufferUtils.copyInternalVector2(ftb, iR, i);
    178             ftb.put(i * 2 + 1, 1.0f);
    179         }
    180     }
    181 
    182     private void setIndexData() {
    183         // allocate connectivity
    184         int triCount = 2 * circleSamples * radialSamples;
    185 
    186         ShortBuffer sib = BufferUtils.createShortBuffer(3 * triCount);
    187         setBuffer(Type.Index, 3, sib);
    188 
    189         int i;
    190         // generate connectivity
    191         int connectionStart = 0;
    192         int index = 0;
    193         for (int circleCount = 0; circleCount < circleSamples; circleCount++) {
    194             int i0 = connectionStart;
    195             int i1 = i0 + 1;
    196             connectionStart += radialSamples + 1;
    197             int i2 = connectionStart;
    198             int i3 = i2 + 1;
    199             for (i = 0; i < radialSamples; i++, index += 6) {
    200 //                if (true) {
    201                     sib.put((short)i0++);
    202                     sib.put((short)i2);
    203                     sib.put((short)i1);
    204                     sib.put((short)i1++);
    205                     sib.put((short)i2++);
    206                     sib.put((short)i3++);
    207 
    208 //                    getIndexBuffer().put(i0++);
    209 //                    getIndexBuffer().put(i2);
    210 //                    getIndexBuffer().put(i1);
    211 //                    getIndexBuffer().put(i1++);
    212 //                    getIndexBuffer().put(i2++);
    213 //                    getIndexBuffer().put(i3++);
    214 //                } else {
    215 //                    getIndexBuffer().put(i0++);
    216 //                    getIndexBuffer().put(i1);
    217 //                    getIndexBuffer().put(i2);
    218 //                    getIndexBuffer().put(i1++);
    219 //                    getIndexBuffer().put(i3++);
    220 //                    getIndexBuffer().put(i2++);
    221 //                }
    222             }
    223         }
    224     }
    225 
    226     /**
    227      * Rebuilds this torus based on a new set of parameters.
    228      *
    229      * @param circleSamples the number of samples along the circles.
    230      * @param radialSamples the number of samples along the radial.
    231      * @param innerRadius the radius of the inner begining of the Torus.
    232      * @param outerRadius the radius of the outter end of the Torus.
    233      */
    234     public void updateGeometry(int circleSamples, int radialSamples, float innerRadius, float outerRadius) {
    235         this.circleSamples = circleSamples;
    236         this.radialSamples = radialSamples;
    237         this.innerRadius = innerRadius;
    238         this.outerRadius = outerRadius;
    239         setGeometryData();
    240         setIndexData();
    241         updateBound();
    242         updateCounts();
    243     }
    244 
    245     @Override
    246     public void write(JmeExporter e) throws IOException {
    247         super.write(e);
    248         OutputCapsule capsule = e.getCapsule(this);
    249         capsule.write(circleSamples, "circleSamples", 0);
    250         capsule.write(radialSamples, "radialSamples", 0);
    251         capsule.write(innerRadius, "innerRadius", 0);
    252         capsule.write(outerRadius, "outerRadius", 0);
    253     }
    254 
    255 }