• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Torus()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      */
Torus(int circleSamples, int radialSamples, float innerRadius, float outerRadius)83     public Torus(int circleSamples, int radialSamples,
84             float innerRadius, float outerRadius) {
85         super();
86         updateGeometry(circleSamples, radialSamples, innerRadius, outerRadius);
87     }
88 
getCircleSamples()89     public int getCircleSamples() {
90         return circleSamples;
91     }
92 
getInnerRadius()93     public float getInnerRadius() {
94         return innerRadius;
95     }
96 
getOuterRadius()97     public float getOuterRadius() {
98         return outerRadius;
99     }
100 
getRadialSamples()101     public int getRadialSamples() {
102         return radialSamples;
103     }
104 
105     @Override
read(JmeImporter e)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 
setGeometryData()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 
setIndexData()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      */
updateGeometry(int circleSamples, int radialSamples, float innerRadius, float outerRadius)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
write(JmeExporter e)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 }