OSDN Git Service

7122422f94c1640e929f641084a9dce8f44de456
[mikumikustudio/MikuMikuStudio.git] / src / com / jme / scene / Line.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
33 package com.jme.scene;
34
35 import java.io.IOException;
36 import java.nio.FloatBuffer;
37 import java.nio.IntBuffer;
38 import java.util.logging.Logger;
39
40 import com.jme.intersection.CollisionResults;
41 import com.jme.math.FastMath;
42 import com.jme.math.Vector2f;
43 import com.jme.math.Vector3f;
44 import com.jme.renderer.ColorRGBA;
45 import com.jme.renderer.Renderer;
46 import com.jme.util.export.InputCapsule;
47 import com.jme.util.export.JMEExporter;
48 import com.jme.util.export.JMEImporter;
49 import com.jme.util.export.OutputCapsule;
50 import com.jme.util.geom.BufferUtils;
51
52 /**
53  * <code>Line</code> subclasses geometry and defines a collection of lines.
54  * For every two points, a line is created. If mode is set to CONNECTED, these
55  * lines as connected as one big line. If it is set to LOOP, it is also rendered
56  * connected but the last point is connected to the first point.
57  * 
58  * @author Mark Powell
59  * @author Joshua Slack
60  * @version $Id: Line.java,v 1.26 2007/08/02 21:54:36 nca Exp $
61  */
62 public class Line extends Geometry {
63     private static final Logger logger = Logger.getLogger(Line.class.getName());
64
65     private static final long serialVersionUID = 1L;
66
67     protected transient IntBuffer indexBuffer;
68
69     private float lineWidth = 1.0f;
70     private Mode mode = Mode.Segments;
71     private short stipplePattern = (short) 0xFFFF;
72     private int stippleFactor = 1;
73     private boolean antialiased = false;
74
75     public enum Mode {
76         /**
77          * Every two vertices referenced by the indexbuffer will be considered a
78          * stand-alone line segment.
79          */
80         Segments,
81         /**
82          * The first two vertices referenced by the indexbuffer create a line,
83          * from there, every additional vertex is paired with the preceding
84          * vertex to make a new, connected line.
85          */
86         Connected,
87         /**
88          * Identical to <i>Connected</i> except the final indexed vertex is
89          * then connected back to the initial vertex to form a loop.
90          */
91         Loop;
92     }
93
94     public Line() {
95
96     }
97
98     /**
99      * Constructs a new line with the given name. By default, the line has no
100      * information.
101      * 
102      * @param name
103      *            The name of the line.
104      */
105     public Line(String name) {
106         super(name);
107     }
108
109     /**
110      * Constructor instantiates a new <code>Line</code> object with a given
111      * set of data. Any data can be null except for the vertex list. If vertices
112      * are null an exception will be thrown.
113      * 
114      * @param name
115      *            the name of the scene element. This is required for
116      *            identification and comparision purposes.
117      * @param vertex
118      *            the vertices that make up the lines.
119      * @param normal
120      *            the normals of the lines.
121      * @param color
122      *            the color of each point of the lines.
123      * @param coords
124      *            the texture coordinates of the lines.
125      */
126     public Line(String name, FloatBuffer vertex, FloatBuffer normal,
127             FloatBuffer color, TexCoords coords) {
128         super(name, vertex, normal, color, coords);
129         generateIndices();
130         logger.info("Line created.");
131     }
132
133     /**
134      * Constructor instantiates a new <code>Line</code> object with a given
135      * set of data. Any data can be null except for the vertex list. If vertices
136      * are null an exception will be thrown.
137      * 
138      * @param name
139      *            the name of the scene element. This is required for
140      *            identification and comparision purposes.
141      * @param vertex
142      *            the vertices that make up the lines.
143      * @param normal
144      *            the normals of the lines.
145      * @param color
146      *            the color of each point of the lines.
147      * @param texture
148      *            the texture coordinates of the lines.
149      */
150     public Line(String name, Vector3f[] vertex, Vector3f[] normal,
151             ColorRGBA[] color, Vector2f[] texture) {
152         super(name, BufferUtils.createFloatBuffer(vertex), BufferUtils
153                 .createFloatBuffer(normal), BufferUtils
154                 .createFloatBuffer(color), TexCoords.makeNew(texture));
155         generateIndices();
156         logger.info("Line created.");
157     }
158
159     @Override
160     public void reconstruct(FloatBuffer vertices, FloatBuffer normals,
161             FloatBuffer colors, TexCoords coords) {
162         super.reconstruct(vertices, normals, colors, coords);
163         generateIndices();
164     }
165
166     public void generateIndices() {
167         if (getIndexBuffer() == null
168                 || getIndexBuffer().limit() != getVertexCount()) {
169             setIndexBuffer(BufferUtils.createIntBuffer(getVertexCount()));
170         } else
171             getIndexBuffer().rewind();
172
173         for (int x = 0; x < getVertexCount(); x++)
174             getIndexBuffer().put(x);
175     }
176
177     /**
178      * <code>getIndexBuffer</code> retrieves the indices array as an
179      * <code>IntBuffer</code>.
180      * 
181      * @return the indices array as an <code>IntBuffer</code>.
182      */
183     public IntBuffer getIndexBuffer() {
184         return indexBuffer;
185     }
186
187     /**
188      * <code>setIndexBuffer</code> sets the index array for this
189      * <code>Line</code>.
190      * 
191      * @param indices
192      *            the index array as an IntBuffer.
193      */
194     public void setIndexBuffer(IntBuffer indices) {
195         indexBuffer = indices;
196     }
197
198     /*
199      * unsupported
200      * 
201      * @see com.jme.scene.Spatial#hasCollision(com.jme.scene.Spatial,
202      *      com.jme.intersection.CollisionResults)
203      */
204     public void findCollisions(Spatial scene, CollisionResults results) {
205         // unsupported
206     }
207
208     /**
209      * Always return false for lines.
210      * 
211      * @return always false for lines
212      */
213     public boolean hasCollision(Spatial scene, boolean checkTriangles) {
214         return false;
215     }
216
217     /**
218      * Puts a circle into vertex and normal buffer at the current buffer
219      * position. The buffers are enlarged and copied if they are too small.
220      * 
221      * @param radius
222      *            radius of the circle
223      * @param x
224      *            x coordinate of circle center
225      * @param y
226      *            y coordinate of circle center
227      * @param segments
228      *            number of line segments the circle is built from
229      * @param insideOut
230      *            false for normal winding (ccw), true for clockwise winding
231      */
232     public void appendCircle(float radius, float x, float y, int segments,
233             boolean insideOut) {
234         int requiredFloats = segments * 2 * 3;
235         FloatBuffer verts = BufferUtils.ensureLargeEnough(getVertexBuffer(),
236                 requiredFloats);
237         setVertexBuffer(verts);
238         FloatBuffer normals = BufferUtils.ensureLargeEnough(getNormalBuffer(),
239                 requiredFloats);
240         setNormalBuffer(normals);
241         float angle = 0;
242         float step = FastMath.PI * 2 / segments;
243         for (int i = 0; i < segments; i++) {
244             float dx = FastMath.cos(insideOut ? -angle : angle) * radius;
245             float dy = FastMath.sin(insideOut ? -angle : angle) * radius;
246             if (i > 0) {
247                 verts.put(dx + x).put(dy + y).put(0);
248                 normals.put(dx).put(dy).put(0);
249             }
250             verts.put(dx + x).put(dy + y).put(0);
251             normals.put(dx).put(dy).put(0);
252             angle += step;
253         }
254         verts.put(radius + x).put(y).put(0);
255         normals.put(radius).put(0).put(0);
256         generateIndices();
257     }
258
259     /**
260      * @return true if points are to be drawn antialiased
261      */
262     public boolean isAntialiased() {
263         return antialiased;
264     }
265
266     /**
267      * Sets whether the point should be antialiased. May decrease performance.
268      * If you want to enabled antialiasing, you should also use an alphastate
269      * with a source of SourceFunction.SourceAlpha and a destination of DB_ONE_MINUS_SRC_ALPHA
270      * or DB_ONE.
271      * 
272      * @param antialiased
273      *            true if the line should be antialiased.
274      */
275     public void setAntialiased(boolean antialiased) {
276         this.antialiased = antialiased;
277     }
278
279     /**
280      * @return either SEGMENTS, CONNECTED or LOOP. See class description.
281      */
282     public Mode getMode() {
283         return mode;
284     }
285
286     /**
287      * @param mode
288      *            either SEGMENTS, CONNECTED or LOOP. See class description.
289      */
290     public void setMode(Mode mode) {
291         this.mode = mode;
292     }
293
294     /**
295      * @return the width of this line.
296      */
297     public float getLineWidth() {
298         return lineWidth;
299     }
300
301     /**
302      * Sets the width of the line when drawn. Non anti-aliased line widths are
303      * rounded to the nearest whole number by opengl.
304      * 
305      * @param lineWidth
306      *            The lineWidth to set.
307      */
308     public void setLineWidth(float lineWidth) {
309         this.lineWidth = lineWidth;
310     }
311
312     /**
313      * @return the set stipplePattern. 0xFFFF means no stipple.
314      */
315     public short getStipplePattern() {
316         return stipplePattern;
317     }
318
319     /**
320      * The stipple or pattern to use when drawing this line. 0xFFFF is a solid
321      * line.
322      * 
323      * @param stipplePattern
324      *            a 16bit short whose bits describe the pattern to use when
325      *            drawing this line
326      */
327     public void setStipplePattern(short stipplePattern) {
328         this.stipplePattern = stipplePattern;
329     }
330
331     /**
332      * @return the set stippleFactor.
333      */
334     public int getStippleFactor() {
335         return stippleFactor;
336     }
337
338     /**
339      * @param stippleFactor
340      *            magnification factor to apply to the stipple pattern.
341      */
342     public void setStippleFactor(int stippleFactor) {
343         this.stippleFactor = stippleFactor;
344     }
345
346     /**
347      * Used with Serialization. Do not call this directly.
348      * 
349      * @param s
350      * @throws IOException
351      * @see java.io.Serializable
352      */
353     private void writeObject(java.io.ObjectOutputStream s) throws IOException {
354         s.defaultWriteObject();
355         if (getIndexBuffer() == null)
356             s.writeInt(0);
357         else {
358             s.writeInt(getIndexBuffer().limit());
359             getIndexBuffer().rewind();
360             for (int x = 0, len = getIndexBuffer().limit(); x < len; x++)
361                 s.writeInt(getIndexBuffer().get());
362         }
363     }
364
365     /**
366      * Used with Serialization. Do not call this directly.
367      * 
368      * @param s
369      * @throws IOException
370      * @throws ClassNotFoundException
371      * @see java.io.Serializable
372      */
373     private void readObject(java.io.ObjectInputStream s) throws IOException,
374             ClassNotFoundException {
375         s.defaultReadObject();
376         int len = s.readInt();
377         if (len == 0) {
378             setIndexBuffer(null);
379         } else {
380             IntBuffer buf = BufferUtils.createIntBuffer(len);
381             for (int x = 0; x < len; x++)
382                 buf.put(s.readInt());
383             setIndexBuffer(buf);
384         }
385     }
386
387     public void write(JMEExporter e) throws IOException {
388         super.write(e);
389         OutputCapsule capsule = e.getCapsule(this);
390         capsule.write(lineWidth, "lineWidth", 1);
391         capsule.write(mode, "mode", Mode.Segments);
392         capsule.write(stipplePattern, "stipplePattern", (short) 0xFFFF);
393         capsule.write(antialiased, "antialiased", false);
394         capsule.write(indexBuffer, "indexBuffer", null);
395     }
396
397     public void read(JMEImporter e) throws IOException {
398         super.read(e);
399         InputCapsule capsule = e.getCapsule(this);
400         lineWidth = capsule.readFloat("lineWidth", 1);
401         mode = (Mode) capsule.readEnum("mode", Mode.class, Mode.Segments);
402         stipplePattern = capsule.readShort("stipplePattern", (short) 0xFFFF);
403         antialiased = capsule.readBoolean("antialiased", false);
404         indexBuffer = capsule.readIntBuffer("indexBuffer", null);
405     }
406
407     public void draw(Renderer r) {
408         if (!r.isProcessingQueue()) {
409             if (r.checkAndAdd(this))
410                 return;
411         }
412
413         r.draw(this);
414     }
415
416 }
417