2 * Copyright (c) 2003-2009 jMonkeyEngine
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
33 package com.jme.scene;
35 import java.io.IOException;
36 import java.nio.FloatBuffer;
37 import java.nio.IntBuffer;
38 import java.util.logging.Logger;
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;
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.
59 * @author Joshua Slack
60 * @version $Id: Line.java,v 1.26 2007/08/02 21:54:36 nca Exp $
62 public class Line extends Geometry {
63 private static final Logger logger = Logger.getLogger(Line.class.getName());
65 private static final long serialVersionUID = 1L;
67 protected transient IntBuffer indexBuffer;
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;
77 * Every two vertices referenced by the indexbuffer will be considered a
78 * stand-alone line segment.
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.
88 * Identical to <i>Connected</i> except the final indexed vertex is
89 * then connected back to the initial vertex to form a loop.
99 * Constructs a new line with the given name. By default, the line has no
103 * The name of the line.
105 public Line(String name) {
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.
115 * the name of the scene element. This is required for
116 * identification and comparision purposes.
118 * the vertices that make up the lines.
120 * the normals of the lines.
122 * the color of each point of the lines.
124 * the texture coordinates of the lines.
126 public Line(String name, FloatBuffer vertex, FloatBuffer normal,
127 FloatBuffer color, TexCoords coords) {
128 super(name, vertex, normal, color, coords);
130 logger.info("Line created.");
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.
139 * the name of the scene element. This is required for
140 * identification and comparision purposes.
142 * the vertices that make up the lines.
144 * the normals of the lines.
146 * the color of each point of the lines.
148 * the texture coordinates of the lines.
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));
156 logger.info("Line created.");
160 public void reconstruct(FloatBuffer vertices, FloatBuffer normals,
161 FloatBuffer colors, TexCoords coords) {
162 super.reconstruct(vertices, normals, colors, coords);
166 public void generateIndices() {
167 if (getIndexBuffer() == null
168 || getIndexBuffer().limit() != getVertexCount()) {
169 setIndexBuffer(BufferUtils.createIntBuffer(getVertexCount()));
171 getIndexBuffer().rewind();
173 for (int x = 0; x < getVertexCount(); x++)
174 getIndexBuffer().put(x);
178 * <code>getIndexBuffer</code> retrieves the indices array as an
179 * <code>IntBuffer</code>.
181 * @return the indices array as an <code>IntBuffer</code>.
183 public IntBuffer getIndexBuffer() {
188 * <code>setIndexBuffer</code> sets the index array for this
192 * the index array as an IntBuffer.
194 public void setIndexBuffer(IntBuffer indices) {
195 indexBuffer = indices;
201 * @see com.jme.scene.Spatial#hasCollision(com.jme.scene.Spatial,
202 * com.jme.intersection.CollisionResults)
204 public void findCollisions(Spatial scene, CollisionResults results) {
209 * Always return false for lines.
211 * @return always false for lines
213 public boolean hasCollision(Spatial scene, boolean checkTriangles) {
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.
222 * radius of the circle
224 * x coordinate of circle center
226 * y coordinate of circle center
228 * number of line segments the circle is built from
230 * false for normal winding (ccw), true for clockwise winding
232 public void appendCircle(float radius, float x, float y, int segments,
234 int requiredFloats = segments * 2 * 3;
235 FloatBuffer verts = BufferUtils.ensureLargeEnough(getVertexBuffer(),
237 setVertexBuffer(verts);
238 FloatBuffer normals = BufferUtils.ensureLargeEnough(getNormalBuffer(),
240 setNormalBuffer(normals);
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;
247 verts.put(dx + x).put(dy + y).put(0);
248 normals.put(dx).put(dy).put(0);
250 verts.put(dx + x).put(dy + y).put(0);
251 normals.put(dx).put(dy).put(0);
254 verts.put(radius + x).put(y).put(0);
255 normals.put(radius).put(0).put(0);
260 * @return true if points are to be drawn antialiased
262 public boolean isAntialiased() {
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
273 * true if the line should be antialiased.
275 public void setAntialiased(boolean antialiased) {
276 this.antialiased = antialiased;
280 * @return either SEGMENTS, CONNECTED or LOOP. See class description.
282 public Mode getMode() {
288 * either SEGMENTS, CONNECTED or LOOP. See class description.
290 public void setMode(Mode mode) {
295 * @return the width of this line.
297 public float getLineWidth() {
302 * Sets the width of the line when drawn. Non anti-aliased line widths are
303 * rounded to the nearest whole number by opengl.
306 * The lineWidth to set.
308 public void setLineWidth(float lineWidth) {
309 this.lineWidth = lineWidth;
313 * @return the set stipplePattern. 0xFFFF means no stipple.
315 public short getStipplePattern() {
316 return stipplePattern;
320 * The stipple or pattern to use when drawing this line. 0xFFFF is a solid
323 * @param stipplePattern
324 * a 16bit short whose bits describe the pattern to use when
327 public void setStipplePattern(short stipplePattern) {
328 this.stipplePattern = stipplePattern;
332 * @return the set stippleFactor.
334 public int getStippleFactor() {
335 return stippleFactor;
339 * @param stippleFactor
340 * magnification factor to apply to the stipple pattern.
342 public void setStippleFactor(int stippleFactor) {
343 this.stippleFactor = stippleFactor;
347 * Used with Serialization. Do not call this directly.
350 * @throws IOException
351 * @see java.io.Serializable
353 private void writeObject(java.io.ObjectOutputStream s) throws IOException {
354 s.defaultWriteObject();
355 if (getIndexBuffer() == null)
358 s.writeInt(getIndexBuffer().limit());
359 getIndexBuffer().rewind();
360 for (int x = 0, len = getIndexBuffer().limit(); x < len; x++)
361 s.writeInt(getIndexBuffer().get());
366 * Used with Serialization. Do not call this directly.
369 * @throws IOException
370 * @throws ClassNotFoundException
371 * @see java.io.Serializable
373 private void readObject(java.io.ObjectInputStream s) throws IOException,
374 ClassNotFoundException {
375 s.defaultReadObject();
376 int len = s.readInt();
378 setIndexBuffer(null);
380 IntBuffer buf = BufferUtils.createIntBuffer(len);
381 for (int x = 0; x < len; x++)
382 buf.put(s.readInt());
387 public void write(JMEExporter e) throws IOException {
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);
397 public void read(JMEImporter e) throws IOException {
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);
407 public void draw(Renderer r) {
408 if (!r.isProcessingQueue()) {
409 if (r.checkAndAdd(this))