package jo.util.jgl.obj.tri; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.ShortBuffer; import java.util.Collection; import java.util.Iterator; import jo.sm.logic.utils.FloatUtils; import jo.sm.logic.utils.IntegerUtils; import jo.sm.logic.utils.ShortUtils; import jo.util.jgl.obj.JGLNode; import jo.vecmath.Color3f; import jo.vecmath.Color4f; import jo.vecmath.Matrix4f; import jo.vecmath.Point2f; import jo.vecmath.Point3f; import jo.vecmath.Tuple3f; import jo.vecmath.Tuple4f; import jo.vecmath.logic.MathUtils; import jo.vecmath.logic.Matrix4fLogic; /* * Triangle Based Mesh object */ public class JGLObj extends JGLNode { public static final int TRIANGLES = 0; public static final int QUADS = 1; protected FloatBuffer mVertexBuffer; protected FloatBuffer mNormalBuffer; protected FloatBuffer mTexturesBuffer; protected FloatBuffer mColorBuffer; protected ShortBuffer mIndexShortBuffer; protected IntBuffer mIndexIntBuffer; protected int mTextureID; protected int mMode; // TRIANGLES, QUADS, ... private Color4f mTextureColor; protected boolean mWireframe; protected Color3f mWireColor; private boolean mAnyAlpha; protected int mVertices; protected int mIndices; protected int mColors; public JGLObj() { setInitialized(false); mAnyAlpha = false; } @Override public void recycle() { synchronized (this) { if (mVertexBuffer != null) { mVertexBuffer.clear(); } if (mNormalBuffer != null) { mNormalBuffer.clear(); } if (mTexturesBuffer != null) { mTexturesBuffer.clear(); } if (mColorBuffer != null) { mColorBuffer.clear(); } if (mIndexShortBuffer != null) { mIndexShortBuffer.clear(); } if (mIndexIntBuffer != null) { mIndexIntBuffer.clear(); } } } public boolean isTextured() { return ((mTextureID != 0) && (mTexturesBuffer != null)); } // Buffers to be passed to gl*Pointer() functions // must be direct, i.e., they must be placed on the // native heap where the garbage collector cannot // move them. // // Buffers with multi-byte datatypes (e.g., short, int, float) // must have their byte order set to native order public void setVertices(float[] vertices) { synchronized (this) { ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4); vbb.order(ByteOrder.nativeOrder()); mVertexBuffer = vbb.asFloatBuffer(); mVertexBuffer.put(vertices); mVertexBuffer.position(0); mLowBounds = new Point3f(vertices[0], vertices[1], vertices[2]); mHighBounds = new Point3f(mLowBounds); for (int i = 3; i < vertices.length; i += 3) { mLowBounds.x = Math.min(mLowBounds.x, vertices[i + 0]); mLowBounds.y = Math.min(mLowBounds.y, vertices[i + 1]); mLowBounds.z = Math.min(mLowBounds.z, vertices[i + 2]); mHighBounds.x = Math.max(mHighBounds.x, vertices[i + 0]); mHighBounds.y = Math.max(mHighBounds.y, vertices[i + 1]); mHighBounds.z = Math.max(mHighBounds.z, vertices[i + 2]); } mVertices = vertices.length / 3; } } public void setVertices(Collection<?> vertices) { Object first = vertices.iterator().next(); if (first instanceof Point3f) { float[] cs = new float[vertices.size() * 3]; int idx = 0; for (Iterator<?> i = vertices.iterator(); i.hasNext();) { Point3f p = (Point3f) i.next(); cs[idx++] = (float) p.x; cs[idx++] = (float) p.y; cs[idx++] = (float) p.z; } setVertices(cs); } else { setVertices(FloatUtils.toFloatArray(vertices.toArray())); } } public void setNormals(float[] normals) { synchronized (this) { ByteBuffer nbb = ByteBuffer.allocateDirect(normals.length * 4); nbb.order(ByteOrder.nativeOrder()); mNormalBuffer = nbb.asFloatBuffer(); mNormalBuffer.put(normals); mNormalBuffer.position(0); } } public void setNormals(Collection<?> normals) { Object first = normals.iterator().next(); if (first instanceof Point3f) { float[] cs = new float[normals.size() * 3]; int idx = 0; for (Iterator<?> i = normals.iterator(); i.hasNext();) { Point3f p = (Point3f) i.next(); cs[idx++] = (float) p.x; cs[idx++] = (float) p.y; cs[idx++] = (float) p.z; } setNormals(cs); } else { setNormals(FloatUtils.toFloatArray(normals.toArray())); } } public void setTextures(float[] textures) { synchronized (this) { ByteBuffer nbb = ByteBuffer.allocateDirect(textures.length * 4); nbb.order(ByteOrder.nativeOrder()); mTexturesBuffer = nbb.asFloatBuffer(); mTexturesBuffer.put(textures); mTexturesBuffer.position(0); } } public void setTextures(Collection<?> textures) { Object first = textures.iterator().next(); if (first instanceof Point2f) { float[] cs = new float[textures.size() * 2]; int idx = 0; for (Iterator<?> i = textures.iterator(); i.hasNext();) { Point2f p = (Point2f) i.next(); cs[idx++] = (float) p.x; cs[idx++] = (float) p.y; } setTextures(cs); } else { setTextures(FloatUtils.toFloatArray(textures.toArray())); } } public void setColors(float[] colors) { synchronized (this) { ByteBuffer c2bb = ByteBuffer.allocateDirect(colors.length * 4); c2bb.order(ByteOrder.nativeOrder()); mColorBuffer = c2bb.asFloatBuffer(); mColorBuffer.put(colors); mColorBuffer.position(0); mColors = colors.length / 4; for (int i = 0; i < colors.length; i += 4) { if (!MathUtils.epsilonEquals(colors[i + 3], 1)) { mAnyAlpha = true; break; } } } } public void setColors(Collection<?> colors) { Object first = colors.iterator().next(); if (first instanceof Tuple4f) { float[] cs = new float[colors.size() * 4]; int idx = 0; for (Iterator<?> i = colors.iterator(); i.hasNext();) { Tuple4f p = (Tuple4f) i.next(); cs[idx++] = (float) p.x; cs[idx++] = (float) p.y; cs[idx++] = (float) p.z; cs[idx++] = (float) p.w; } setColors(cs); } else if (first instanceof Tuple3f) { float[] cs = new float[colors.size() * 4]; int idx = 0; for (Iterator<?> i = colors.iterator(); i.hasNext();) { Tuple3f p = (Tuple3f) i.next(); cs[idx++] = (float) p.x; cs[idx++] = (float) p.y; cs[idx++] = (float) p.z; cs[idx++] = 1; } setColors(cs); } else { setColors(FloatUtils.toFloatArray(colors.toArray())); } } public void setIndices(short[] indices) { synchronized (this) { ByteBuffer i2bb = ByteBuffer.allocateDirect(indices.length * 4); i2bb.order(ByteOrder.nativeOrder()); mIndexShortBuffer = i2bb.asShortBuffer(); for (int i = 0; i < indices.length; i++) { mIndexShortBuffer.put(indices[i]); } mIndexShortBuffer.position(0); if (mMode == TRIANGLES) { mIndices = indices.length / 3; } else { mIndices = indices.length / 4; } } } public void setIndices(int[] indices) { synchronized (this) { ByteBuffer i2bb = ByteBuffer.allocateDirect(indices.length * 4); i2bb.order(ByteOrder.nativeOrder()); mIndexIntBuffer = i2bb.asIntBuffer(); for (int i = 0; i < indices.length; i++) { mIndexIntBuffer.put(indices[i]); } mIndexIntBuffer.position(0); if (mMode == TRIANGLES) { mIndices = indices.length / 3; } else { mIndices = indices.length / 4; } } } public void setIndices(Collection<?> normals) { Object[] arr = normals.toArray(); if (arr[0] instanceof Short) { setIndices(ShortUtils.toShortArray(arr)); } else if (arr[0] instanceof Integer) { setIndices(IntegerUtils.toArray(arr)); } } public void setSolidColor(Point3f c) { setSolidColor((float) c.x, (float) c.y, (float) c.z, 1); } public void setSolidColor(Color4f c) { setSolidColor((float) c.x, (float) c.y, (float) c.z, (float) c.w); } public void setSolidColor(float r, float g, float b) { setSolidColor(r, g, b, 1); } public void setSolidColor(float r, float g, float b, float a) { float colors[] = new float[mVertices * 4]; for (int i = 0; i < colors.length; i += 4) { colors[i + 0] = r; colors[i + 1] = g; colors[i + 2] = b; colors[i + 3] = a; } setColors(colors); } public void setFadeColor(Color4f c1, Color4f c2) { setFadeColor((float) c1.x, (float) c1.y, (float) c1.z, (float) c1.w, (float) c2.x, (float) c2.y, (float) c2.z, (float) c2.w); } public void setFadeColor(Point3f c1, Point3f c2) { setFadeColor((float) c1.x, (float) c1.y, (float) c1.z, 1, (float) c2.x, (float) c2.y, (float) c2.z, 1); } public void setFadeColor(float r1, float g1, float b1, float r2, float g2, float b2) { setFadeColor(r1, g1, b1, 1, r2, g2, b2, 1); } // assumes all -x indicies are first and all +x indicies are second public void setFadeColor(float r1, float g1, float b1, float a1, float r2, float g2, float b2, float a2) { float colors1[] = { r1, g1, b1, a1,}; float colors2[] = { r2, g2, b2, a2,}; mColorBuffer.position(0); for (int i = 0; i < mColors / 2; i++) { mColorBuffer.put(colors1); } for (int i = 0; i < mColors / 2; i++) { mColorBuffer.put(colors2); } mColorBuffer.position(0); } // assumes object's central axis goes from -.5z to +.5z public void connect(Point3f top, Point3f bottom, float diameter) { Point3f at = new Point3f(top); at.add(bottom); at.scale(.5f); Matrix4f lookAt = new Matrix4f(); Matrix4fLogic.lookAt(lookAt, at, top); Matrix4f scale = Matrix4fLogic.makeScaleMatrix(diameter, diameter, top.distance(bottom)); getTransform().set(lookAt); getTransform().mul(scale); } public FloatBuffer getVertexBuffer() { return mVertexBuffer; } public void setVertexBuffer(FloatBuffer vertexBuffer) { mVertexBuffer = vertexBuffer; mVertices = mVertexBuffer.limit() / 3; } public FloatBuffer getNormalBuffer() { return mNormalBuffer; } public void setNormalBuffer(FloatBuffer normalBuffer) { mNormalBuffer = normalBuffer; } public FloatBuffer getTexturesBuffer() { return mTexturesBuffer; } public void setTexturesBuffer(FloatBuffer texturesBuffer) { mTexturesBuffer = texturesBuffer; } public FloatBuffer getColorBuffer() { return mColorBuffer; } public void setColorBuffer(FloatBuffer colorBuffer) { mColorBuffer = colorBuffer; mColors = mColorBuffer.limit() / 4; } public ShortBuffer getIndexShortBuffer() { return mIndexShortBuffer; } public void setIndexShortBuffer(ShortBuffer indexBuffer) { mIndexShortBuffer = indexBuffer; if (mMode == TRIANGLES) { mIndices = mIndexShortBuffer.limit() / 3; } else { mIndices = mIndexShortBuffer.limit() / 4; } } public IntBuffer getIndexIntBuffer() { return mIndexIntBuffer; } public void setIndexIntBuffer(IntBuffer indexBuffer) { mIndexIntBuffer = indexBuffer; if (mMode == TRIANGLES) { mIndices = mIndexIntBuffer.limit() / 3; } else { mIndices = mIndexIntBuffer.limit() / 4; } } public int getIndices() { return mIndices; } public void setIndices(int indices) { mIndices = indices; } public int getColors() { return mColors; } public void setColors(int colors) { mColors = colors; } public int getVertices() { return mVertices; } public void setVertices(int vertices) { mVertices = vertices; } public int getTextureID() { return mTextureID; } public void setTextureID(int textureID) { mTextureID = textureID; } public boolean isWireframe() { return mWireframe; } public void setWireframe(boolean wireframe) { mWireframe = wireframe; } public Color3f getWireColor() { return mWireColor; } public void setWireColor(Color3f wireColor) { mWireColor = wireColor; } public boolean isAnyAlpha() { return mAnyAlpha; } public void setAnyAlpha(boolean anyAlpha) { mAnyAlpha = anyAlpha; } public int getMode() { return mMode; } public void setMode(int mode) { mMode = mode; } public Color4f getTextureColor() { return mTextureColor; } public void setTextureColor(Color4f textureColor) { mTextureColor = textureColor; } }