OSDN Git Service

06b97efe4b6d7f2f7693f154bba94be746a716e8
[mikumikustudio/MikuMikuStudio.git] / src / com / jme / scene / shape / Dome.java
1 /*
2  * Copyright (c) 2003-2009 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 // $Id$
33 package com.jme.scene.shape;
34
35 import static com.jme.util.geom.BufferUtils.*;
36
37 import java.io.IOException;
38
39 import com.jme.math.FastMath;
40 import com.jme.math.Vector3f;
41 import com.jme.scene.TexCoords;
42 import com.jme.scene.TriMesh;
43 import com.jme.util.export.InputCapsule;
44 import com.jme.util.export.JMEExporter;
45 import com.jme.util.export.JMEImporter;
46 import com.jme.util.export.OutputCapsule;
47 import com.jme.util.geom.BufferUtils;
48
49 /**
50  * A hemisphere.
51  * 
52  * @author Peter Andersson
53  * @author Joshua Slack (Original sphere code that was adapted)
54  * @version $Revision$, $Date$
55  */
56 public class Dome extends TriMesh {
57
58     private static final long serialVersionUID = 1L;
59
60     private int planes;
61
62     private int radialSamples;
63
64     /** The radius of the dome */
65     private float radius;
66
67     /** The center of the dome */
68     private Vector3f center;
69     
70     private boolean outsideView = true;
71
72     private static Vector3f tempVa = new Vector3f();
73
74     private static Vector3f tempVb = new Vector3f();
75
76     private static Vector3f tempVc = new Vector3f();
77
78     /** <strong>NOT API:</strong> for internal use, do not call from user code. */
79     public Dome() {}
80
81     /**
82      * Constructs a dome. By default the dome has not geometry data or center.
83      * 
84      * @param name
85      *            The name of the dome.
86      */
87     public Dome(String name) {
88         super(name);
89     }
90
91     /**
92      * Constructs a dome with center at the origin. For details, see the other
93      * constructor.
94      * 
95      * @param name
96      *            Name of dome.
97      * @param planes
98      *            The number of planes along the Z-axis.
99      * @param radialSamples
100      *            The samples along the radial.
101      * @param radius
102      *            Radius of the dome.
103      * @see #Dome(java.lang.String, com.jme.math.Vector3f, int, int, float)
104      */
105     public Dome(String name, int planes, int radialSamples, float radius) {
106         this(name, new Vector3f(0, 0, 0), planes, radialSamples, radius);
107     }
108
109     /**
110      * Constructs a dome. All geometry data buffers are updated automatically.
111      * Both planes and radialSamples increase the quality of the generated dome.
112      * 
113      * @param name
114      *            Name of the dome.
115      * @param center
116      *            Center of the dome.
117      * @param planes
118      *            The number of planes along the Z-axis.
119      * @param radialSamples
120      *            The number of samples along the radial.
121      * @param radius
122      *            The radius of the dome.
123      */
124     public Dome(String name, Vector3f center, int planes, int radialSamples,
125             float radius) {
126         super(name);
127         updateGeometry(center, planes, radialSamples, radius, true);
128     }
129
130     /**
131      * Constructs a dome. All geometry data buffers are updated automatically.
132      * Both planes and radialSamples increase the quality of the generated dome.
133      * 
134      * @param name
135      *            Name of the dome.
136      * @param center
137      *            Center of the dome.
138      * @param planes
139      *            The number of planes along the Z-axis.
140      * @param radialSamples
141      *            The number of samples along the radial.
142      * @param radius
143      *            The radius of the dome.
144      * @param outsideView
145      *            If true, the triangles will be connected for a view outside of
146      *            the dome.
147      */
148     public Dome(String name, Vector3f center, int planes, int radialSamples,
149             float radius, boolean outsideView) {
150         super(name);
151         updateGeometry(center, planes, radialSamples, radius, outsideView);
152     }
153
154     public Vector3f getCenter() {
155         return center;
156     }
157
158     /** Get the number of planar segments along the z-axis of the dome. */
159     public int getPlanes() {
160         return planes;
161     }
162
163     /** Get the number of samples radially around the main axis of the dome. */
164     public int getRadialSamples() {
165         return radialSamples;
166     }
167
168     /** Get the radius of the dome. */
169     public float getRadius() {
170         return radius;
171     }
172
173     /**
174      * Are the triangles connected in such a way as to present aview out from the dome or not.
175      * 
176      * @return
177      */
178     public boolean isOutsideView() {
179         return outsideView;
180     }
181
182     public void read(JMEImporter e) throws IOException {
183         super.read(e);
184         InputCapsule capsule = e.getCapsule(this);
185         planes = capsule.readInt("planes", 0);
186         radialSamples = capsule.readInt("radialSamples", 0);
187         radius = capsule.readFloat("radius", 0);
188         center = (Vector3f) capsule.readSavable("center", Vector3f.ZERO.clone());
189     }
190
191     /**
192      * @deprecated use {@link #updateGeometry(Vector3f, int, int, float, boolean)}.
193      */
194     public void setData(Vector3f center, int planes, int radialSamples,
195             float radius, boolean updateBuffers, boolean outsideView) {
196         updateGeometry(center, planes, radialSamples, radius, outsideView);
197     }
198
199     /**
200      * Rebuilds the dome with a new set of parameters.
201      * 
202      * @param center the new center of the dome.
203      * @param planes the number of planes along the Z-axis.
204      * @param radialSamples the new number of radial samples of the dome.
205      * @param radius the new radius of the dome.
206      * @param outsideView should the dome be set up to be viewed from the inside looking out.
207      */
208     public void updateGeometry(Vector3f center, int planes,
209             int radialSamples, float radius, boolean outsideView) {
210         this.outsideView = outsideView;
211         this.center = center != null ? center : new Vector3f(0, 0, 0);
212         this.planes = planes;
213         this.radialSamples = radialSamples;
214         this.radius = radius;
215
216         // Allocate vertices, allocating one extra in each radial to get the
217         // correct texture coordinates
218         setVertexCount(((planes - 1) * (radialSamples + 1)) + 1);
219         setVertexBuffer(createVector3Buffer(getVertexCount()));
220
221         // allocate normals
222         setNormalBuffer(createVector3Buffer(getVertexCount()));
223
224         // allocate texture coordinates
225         getTextureCoords().set(0, new TexCoords(createVector2Buffer(getVertexCount())));
226
227         // generate geometry
228         float fInvRS = 1.0f / radialSamples;
229         float fYFactor = 1.0f / (planes - 1);
230
231         // Generate points on the unit circle to be used in computing the mesh
232         // points on a dome slice.
233         float[] afSin = new float[(radialSamples)];
234         float[] afCos = new float[(radialSamples)];
235         for (int iR = 0; iR < radialSamples; iR++) {
236             float fAngle = FastMath.TWO_PI * fInvRS * iR;
237             afCos[iR] = FastMath.cos(fAngle);
238             afSin[iR] = FastMath.sin(fAngle);
239         }
240
241         // generate the dome itself
242         int i = 0;
243         for (int iY = 0; iY < (planes - 1); iY++, i++) {
244             float fYFraction = fYFactor * iY; // in (0,1)
245             float fY = radius * fYFraction;
246             // compute center of slice
247             Vector3f kSliceCenter = tempVb.set(center);
248             kSliceCenter.y += fY;
249
250             // compute radius of slice
251             float fSliceRadius = FastMath.sqrt(FastMath.abs(radius * radius - fY * fY));
252
253             // compute slice vertices
254             Vector3f kNormal;
255             int iSave = i;
256             for (int iR = 0; iR < radialSamples; iR++, i++) {
257                 float fRadialFraction = iR * fInvRS; // in [0,1)
258                 Vector3f kRadial = tempVc.set(afCos[iR], 0, afSin[iR]);
259                 kRadial.mult(fSliceRadius, tempVa);
260                 getVertexBuffer().put(kSliceCenter.x + tempVa.x).put(
261                         kSliceCenter.y + tempVa.y).put(
262                         kSliceCenter.z + tempVa.z);
263
264                 populateFromBuffer(tempVa, getVertexBuffer(), i);
265                 kNormal = tempVa.subtractLocal(center);
266                 kNormal.normalizeLocal();
267                 if (outsideView)
268                     getNormalBuffer().put(kNormal.x).put(kNormal.y).put(kNormal.z);
269                 else
270                     getNormalBuffer().put(-kNormal.x).put(-kNormal.y).put(-kNormal.z);
271
272                 getTextureCoords().get(0).coords.put(fRadialFraction).put(fYFraction);
273             }
274             BufferUtils.copyInternalVector3(getVertexBuffer(), iSave, i);
275             BufferUtils.copyInternalVector3(getNormalBuffer(), iSave, i);
276             getTextureCoords().get(0).coords.put(1.0f).put(fYFraction);
277         }
278
279         // pole
280         getVertexBuffer().put(center.x).put(center.y + radius).put(center.z);
281         getNormalBuffer().put(0).put(outsideView ? 1 : -1).put(0);
282         getTextureCoords().get(0).coords.put(0.5f).put(1.0f);
283
284         // allocate connectivity
285         setTriangleQuantity((planes - 2) * radialSamples * 2 + radialSamples);
286         setIndexBuffer(BufferUtils.createIntBuffer(3 * getTriangleCount()));
287
288         // generate connectivity
289         int index = 0;
290         // Generate only for middle planes
291         for (int plane = 1; plane < (planes - 1); plane++) {
292             int bottomPlaneStart = (plane - 1) * (radialSamples + 1);
293             int topPlaneStart = plane * (radialSamples + 1);
294             for (int sample = 0; sample < radialSamples; sample++, index += 6) {
295                 getIndexBuffer().put(bottomPlaneStart + sample);
296                 getIndexBuffer().put(topPlaneStart + sample);
297                 getIndexBuffer().put(bottomPlaneStart + sample + 1);
298                 getIndexBuffer().put(bottomPlaneStart + sample + 1);
299                 getIndexBuffer().put(topPlaneStart + sample);
300                 getIndexBuffer().put(topPlaneStart + sample + 1);
301             }
302         }
303
304         // pole triangles
305         int bottomPlaneStart = (planes - 2) * (radialSamples + 1);
306         for (int samples = 0; samples < radialSamples; samples++, index += 3) {
307             getIndexBuffer().put(bottomPlaneStart + samples);
308             getIndexBuffer().put(getVertexCount() - 1);
309             getIndexBuffer().put(bottomPlaneStart + samples + 1);
310         }
311     }
312
313     /**
314      * Generates the connections
315      */
316     public void write(JMEExporter e) throws IOException {
317         super.write(e);
318         OutputCapsule capsule = e.getCapsule(this);
319         capsule.write(planes, "planes", 0);
320         capsule.write(radialSamples, "radialSamples", 0);
321         capsule.write(radius, "radius", 0);
322         capsule.write(center, "center", Vector3f.ZERO);
323     }
324
325 }