diff options
Diffstat (limited to 'src/ru/olamedia/geom')
-rw-r--r-- | src/ru/olamedia/geom/ChunkMesh.java | 83 | ||||
-rw-r--r-- | src/ru/olamedia/geom/ChunkMeshNode.java | 97 | ||||
-rw-r--r-- | src/ru/olamedia/geom/ChunkMeshOctree.java | 95 | ||||
-rw-r--r-- | src/ru/olamedia/geom/DisplayList.java | 1 | ||||
-rw-r--r-- | src/ru/olamedia/geom/Frustum.java | 34 | ||||
-rw-r--r-- | src/ru/olamedia/geom/Frustum2.java | 282 | ||||
-rw-r--r-- | src/ru/olamedia/geom/ImmModeMesh.java | 465 | ||||
-rw-r--r-- | src/ru/olamedia/geom/IndexedMeshBulder.java | 207 | ||||
-rw-r--r-- | src/ru/olamedia/geom/Mesh.java | 76 | ||||
-rw-r--r-- | src/ru/olamedia/geom/MultiMesh.java | 34 | ||||
-rw-r--r-- | src/ru/olamedia/geom/SimpleQuadMesh.java | 145 | ||||
-rw-r--r-- | src/ru/olamedia/geom/VoxelRaypicker.java | 37 |
12 files changed, 1502 insertions, 54 deletions
diff --git a/src/ru/olamedia/geom/ChunkMesh.java b/src/ru/olamedia/geom/ChunkMesh.java new file mode 100644 index 0000000..3ff36df --- /dev/null +++ b/src/ru/olamedia/geom/ChunkMesh.java @@ -0,0 +1,83 @@ +package ru.olamedia.geom; + +import ru.olamedia.olacraft.render.jogl.ChunkRangeRenderer; + +public class ChunkMesh { + private ImmModeMesh opaqueMesh; + private ImmModeMesh mesh; + private boolean isCompiled = false; + private boolean isValid = false; + private int vertexCount = 0; + + private void updateVertexCount() { + vertexCount = 0; + if (null != mesh) { + vertexCount += mesh.getVertexCount(); + } + if (null != opaqueMesh) { + vertexCount += opaqueMesh.getVertexCount(); + } + } + + public int getVertexCount() { + return vertexCount; + } + + public void setMesh(ImmModeMesh m) { + mesh = m; + updateVertexCount(); + } + + public void setOpaqueMesh(ImmModeMesh m) { + opaqueMesh = m; + updateVertexCount(); + } + + public void render(int pass) { + if (pass == ChunkRangeRenderer.OPAQUE_PASS) { + if (null != opaqueMesh) { + opaqueMesh.draw(); + } + } else { + if (null != mesh) { + mesh.draw(); + } + } + } + + public boolean isCompiled() { + return isCompiled; + } + + public void setCompiled(boolean isCompiled) { + this.isCompiled = isCompiled; + } + + public boolean isValid() { + return isValid; + } + + public void setValid(boolean isValid) { + this.isValid = isValid; + } + + public boolean isEmpty() { + return isValid() && (null == mesh) && (null == opaqueMesh); + } + + public ImmModeMesh getTransparentMesh() { + return mesh; + } + + public ImmModeMesh getOpaqueMesh() { + return opaqueMesh; + } + + public int getOpaqueVertexCount() { + return null == opaqueMesh ? 0 : opaqueMesh.getVertexCount(); + } + + public int getTransparentVertexCount() { + return null == mesh ? 0 : mesh.getVertexCount(); + } +} diff --git a/src/ru/olamedia/geom/ChunkMeshNode.java b/src/ru/olamedia/geom/ChunkMeshNode.java new file mode 100644 index 0000000..f0593f3 --- /dev/null +++ b/src/ru/olamedia/geom/ChunkMeshNode.java @@ -0,0 +1,97 @@ +package ru.olamedia.geom; + +public class ChunkMeshNode { + private ChunkMesh mesh = new ChunkMesh(); + private ChunkMesh[] leafs = new ChunkMesh[8]; + private int vertexCount = 0; + private int opaqueVertexCount = 0; + private int transparentVertexCount = 0; + private int level = 1; + private int axisChunks = 2; + private int axisShift = 1; + private int volumeChunks = 8; + + public ChunkMeshNode(int level) { + this.level = level; + this.axisChunks = (int) Math.pow(2, level); + this.axisShift = level; + this.volumeChunks = (int) Math.pow(8, level); + } + + public void putChunkMesh(int chunkX, int chunkY, int chunkZ, ChunkMesh mesh) { + // id = 0..7 + // final int id = (chunkX & )*4 + ()*2+(chunkZ & ); + } + + private void updateVertexCount() { + if (!mesh.isValid()) { + vertexCount = 0; + opaqueVertexCount = 0; + transparentVertexCount = 0; + for (ChunkMesh m : leafs) { + if (null != m) { + vertexCount += m.getVertexCount(); + opaqueVertexCount += m.getOpaqueVertexCount(); + transparentVertexCount += m.getTransparentVertexCount(); + } + } + } + } + + public int getVertexCount() { + return vertexCount; + } + + public void render(int pass) { + if (mesh.isValid()) { + mesh.render(pass); + } else { + for (ChunkMesh m : leafs) { + if (null != m) { + m.render(pass); + } + } + } + } + + public void combine() { + updateVertexCount(); + if (!mesh.isValid()) { + if (transparentVertexCount > 0) { + final ImmModeMesh tMesh = ImmModeMesh.allocate(transparentVertexCount); + tMesh.setGLSL(true); + tMesh.enableColor4(); + tMesh.enableTexCoord2(); + tMesh.enableVertex3(); + tMesh.beginQuads(); + for (ChunkMesh m : leafs) { + if (null != m) { + tMesh.put(m.getTransparentMesh()); + } + } + tMesh.end(); + mesh.setMesh(tMesh); + } else { + mesh.setMesh(null); + } + if (opaqueVertexCount > 0) { + final ImmModeMesh oMesh = ImmModeMesh.allocate(opaqueVertexCount); + oMesh.setGLSL(true); + oMesh.enableColor4(); + oMesh.enableTexCoord2(); + oMesh.enableVertex3(); + oMesh.beginQuads(); + for (ChunkMesh m : leafs) { + if (null != m) { + oMesh.put(m.getOpaqueMesh()); + } + } + oMesh.end(); + mesh.setOpaqueMesh(oMesh); + } else { + mesh.setOpaqueMesh(null); + } + mesh.setValid(true); + } + } +} diff --git a/src/ru/olamedia/geom/ChunkMeshOctree.java b/src/ru/olamedia/geom/ChunkMeshOctree.java new file mode 100644 index 0000000..1c5202c --- /dev/null +++ b/src/ru/olamedia/geom/ChunkMeshOctree.java @@ -0,0 +1,95 @@ +package ru.olamedia.geom; + +import java.util.HashMap; + +import ru.olamedia.olacraft.game.Game; + +public class ChunkMeshOctree { + private HashMap<Integer, HashMap<Integer, HashMap<Integer, ChunkMeshNode>>> nodes = new HashMap<Integer, HashMap<Integer, HashMap<Integer, ChunkMeshNode>>>(); + private static int level = 2; + private static int nodeAxisChunks = 4; + private static int nodeChunks = 64; + private static int levelp = 4; + + private int getRenderDistance() { + return Game.instance.player.settings.renderDistance; + } + + private int getCameraX() { + return (int) Game.instance.player.camera.getCameraX(); + } + + private int getCameraY() { + return (int) Game.instance.player.camera.getCameraY(); + } + + private int getCameraZ() { + return (int) Game.instance.player.camera.getCameraZ(); + } + + public void render(int pass) { + final int startX = getCameraX() - getRenderDistance() / 2; + final int startY = getCameraY() - getRenderDistance() / 2; + final int startZ = getCameraZ() - getRenderDistance() / 2; + final int deltaChunks = getRenderDistance() / 16; + // renderDistance = 256, deltaChunks = 16 + // renderDistance = 128, deltaChunks = 8 + // renderDistance = 64, deltaChunks = 4 + // renderDistance = 32, deltaChunks = 2 + // level = 1: 1 parent quadtree node (32x32x32), each root node = 8 + // chunks + // level = 2: 2 parent quadtree nodes (64x64x64), each root node = 64 + // chunks + final int chunkStartX = (startX / 16) / nodeAxisChunks; + final int chunkStartY = (startY / 16) / nodeAxisChunks; + final int chunkStartZ = (startZ / 16) / nodeAxisChunks; + for (int ix = chunkStartX; ix < nodeAxisChunks; ix++) { + for (int iy = chunkStartY; iy < nodeAxisChunks; iy++) { + for (int iz = chunkStartZ; iz < nodeAxisChunks; iz++) { + renderNode(ix, iy, iz, pass); + } + } + } + } + + private void renderNode(int ix, int iy, int iz, int pass) { + if (!nodes.containsKey(ix)) { + return; + } + if (!nodes.get(ix).containsKey(iy)) { + return; + } + if (!nodes.get(ix).get(iy).containsKey(iz)) { + return; + } + nodes.get(ix).get(iy).get(iz).render(pass); + } + + public void render(int x, int y, int z, int pass) { + final int ix = x >> 2; + final int iy = y >> 2; + final int iz = z >> 2; + if (!nodes.containsKey(ix)) { + nodes.put(ix, new HashMap<Integer, HashMap<Integer, ChunkMeshNode>>()); + nodes.get(ix).put(iy, new HashMap<Integer, ChunkMeshNode>()); + // nodes.get(ix).get(iy).put(iz, new ChunkMeshNode()); + } + } + + public void put(int chunkX, int chunkY, int chunkZ, ChunkMesh mesh) { + final int ix = chunkX / nodeAxisChunks; + final int iy = chunkY / nodeAxisChunks; + final int iz = chunkZ / nodeAxisChunks; + final int id = (chunkX & 64) * +(chunkY & 64) * +(chunkZ & 64); + if (!nodes.containsKey(ix)) { + nodes.put(ix, new HashMap<Integer, HashMap<Integer, ChunkMeshNode>>()); + } + if (!nodes.get(ix).containsKey(iy)) { + nodes.get(ix).put(iy, new HashMap<Integer, ChunkMeshNode>()); + } + if (!nodes.get(ix).get(iy).containsKey(iz)) { + nodes.get(ix).get(iy).put(iz, new ChunkMeshNode(level)); + } + nodes.get(ix).get(iy).get(iz).combine(); + } +} diff --git a/src/ru/olamedia/geom/DisplayList.java b/src/ru/olamedia/geom/DisplayList.java index aeaffc7..eb6cf04 100644 --- a/src/ru/olamedia/geom/DisplayList.java +++ b/src/ru/olamedia/geom/DisplayList.java @@ -2,7 +2,6 @@ package ru.olamedia.geom; import javax.media.opengl.GL; import javax.media.opengl.GL2; -import javax.media.opengl.GLAutoDrawable; public class DisplayList { private GL2 gl; diff --git a/src/ru/olamedia/geom/Frustum.java b/src/ru/olamedia/geom/Frustum.java index 2065157..1a9d58d 100644 --- a/src/ru/olamedia/geom/Frustum.java +++ b/src/ru/olamedia/geom/Frustum.java @@ -1,9 +1,43 @@ package ru.olamedia.geom; +import java.nio.FloatBuffer; + +import org.openmali.vecmath2.Matrix4f; + +import com.jogamp.opengl.util.PMVMatrix; + //import org.openmali.spatial.bodies.Frustum; public class Frustum extends org.openmali.spatial.bodies.Frustum { + protected PMVMatrix pmvMatrix; + protected int mvOffset; + public Frustum() { super(); } + + public Frustum(PMVMatrix matrix) { + super(); + this.pmvMatrix = matrix; + } + + public float[] getMatrixFloat(FloatBuffer b) { + if (pmvMatrix.usesBackingArray()) { + return b.array(); + } else { + int p = b.position(); + float[] pm = new float[16]; + b.get(pm, p, 16); + b.position(p); + return pm; + } + } + + public void compute() { + Matrix4f proj = new Matrix4f(getMatrixFloat(pmvMatrix.glGetPMatrixf())); + // proj.transpose(); + Matrix4f modl = new Matrix4f(getMatrixFloat(pmvMatrix.glGetMviMatrixf())); + // modl.transpose(); + compute(proj, modl); + } } diff --git a/src/ru/olamedia/geom/Frustum2.java b/src/ru/olamedia/geom/Frustum2.java new file mode 100644 index 0000000..9c382b0 --- /dev/null +++ b/src/ru/olamedia/geom/Frustum2.java @@ -0,0 +1,282 @@ +package ru.olamedia.geom; + +import java.nio.FloatBuffer; + +import org.ode4j.ode.internal.gimpact.GimGeometry.aabb3f; +import org.openmali.spatial.bodies.Box; +import org.openmali.spatial.bodies.Classifier; +import org.openmali.vecmath2.Matrix4f; + +import com.jogamp.opengl.math.FloatUtil; +import com.jogamp.opengl.math.geom.AABBox; +import com.jogamp.opengl.util.PMVMatrix; + +public class Frustum2 { + protected Plane[] planes = new Plane[6]; + protected PMVMatrix pmvMatrix; + protected FloatBuffer pmv = FloatBuffer.allocate(16); + protected float[] mvp = new float[16]; + protected int pmvOffset; + + public Frustum2() { + for (int i = 0; i < 6; ++i) { + planes[i] = new Plane(); + } + } + + public Frustum2(PMVMatrix matrix) { + setMatrix(matrix); + for (int i = 0; i < 6; ++i) { + planes[i] = new Plane(); + } + } + + public void setMatrix(PMVMatrix matrix) { + this.pmvMatrix = matrix; + // pmv = pmvMatrix.glGetPMvMatrixf(); + // pmvOffset = pmv.position(); + makePmvMatrix(); + } + + protected Matrix4f proj; + protected Matrix4f modl; + + private static FloatBuffer b; + private static int bOffset; + + private static float f(int offset) { + return b.get(bOffset + offset); + } + + public static Matrix4f getMatrix4f(FloatBuffer buf) { + b = buf; + bOffset = b.position(); + return new Matrix4f(f(0), f(1), f(2), f(3), f(4), f(5), f(6)/* 12 */, f(7), f(8), f(9), f(10), f(11), f(12), + f(13), f(14), f(15)); + } + + public void makePmvMatrix() { + FloatUtil.multMatrixf(pmvMatrix.glGetPMatrixf(), pmvMatrix.glGetMvMatrixf(), mvp, 0); + getMatrix4f(pmvMatrix.glGetPMatrixf()).mul(getMatrix4f(pmvMatrix.glGetMvMatrixf())).writeToBuffer(pmv, true, + false); + } + + protected class Vector3f { + public float x; + public float y; + public float z; + + @Override + public String toString() { + return "{" + x + "," + y + "," + z + "}"; + } + } + + protected class Plane { + public Vector3f n = new Vector3f(); + public float d; + + public final float distanceTo(float x, float y, float z) { + return (n.x * x) + (n.y * y) + (n.z * z) + d; + } + + @Override + public String toString() { + return "Plane[" + n + ", " + d + "]"; + } + } + + protected float[] getMatrixFloat(FloatBuffer b) { + if (pmvMatrix.usesBackingArray()) { + return b.array(); + } else { + int p = b.position(); + float[] pm = new float[16]; + b.get(pm, p, 16); + b.position(p); + return pm; + } + } + + protected float m(int a) { + return mvp[a]; + // return pmv.get(a); + } + + private static final boolean isInside(Plane p, AABBox box) { + final float[] low = box.getLow(); + final float[] high = box.getHigh(); + if (p.distanceTo(low[0], low[1], low[2]) > 0.0f) + return (true); + if (p.distanceTo(high[0], low[1], low[2]) > 0.0f) + return (true); + if (p.distanceTo(low[0], high[1], low[2]) > 0.0f) + return (true); + if (p.distanceTo(high[0], high[1], low[2]) > 0.0f) + return (true); + if (p.distanceTo(low[0], low[1], high[2]) > 0.0f) + return (true); + if (p.distanceTo(high[0], low[1], high[2]) > 0.0f) + return (true); + if (p.distanceTo(low[0], high[1], high[2]) > 0.0f) + return (true); + if (p.distanceTo(high[0], high[1], high[2]) > 0.0f) + return (true); + + return (false); + } + + /** + * Quick check to see if an orthogonal bounding box is inside the frustum + */ + public final boolean isOutside(AABBox box) { + + // if all points are behind 1 specific plane, we are out + // if we are in with all points, then we are fully in + for (int p = 0; p < 6; ++p) { + if (!isInside(planes[p], box)) { + return true; + } + } + + // so if iTotalIn is 6, then all are inside the view + // if(iTotalIn == 6) + // return(IN); + + // we must be partly in then otherwise + return false; + // for (int i = 0; i < 3; ++i) { + // if (!quickClassify(planes[i], box)) + // return true; + // } + // + // // We make no attempt to determine whether it's fully inside or not. + // return false; + } + + protected float[] mat = new float[16]; + + public void extractFrustumPlanes(boolean normalize) { + // Left: [30+00, 31+01, 32+02, 33+03] + // comboMatrix.m[12] + comboMatrix.m[0]; + + planes[0].n.x = m(12) + m(0); + planes[0].n.y = m(13) + m(1); + planes[0].n.z = m(14) + m(2); + planes[0].d = m(15) + m(3); + + // Right: [30-00, 31-01, 32-02, 33-03] + + planes[1].n.x = m(12) - m(0); + planes[1].n.y = m(13) - m(1); + planes[1].n.z = m(14) - m(2); + planes[1].d = m(15) - m(3); + + // Bottom: [30+10, 31+11, 32+12, 33+13] + + planes[2].n.x = m(12) + m(4); + planes[2].n.y = m(13) + m(5); + planes[2].n.z = m(14) + m(6); + planes[2].d = m(15) + m(7); + + // Top: [30-10, 31-11, 32-12, 33-13] + + planes[3].n.x = m(12) - m(4); + planes[3].n.y = m(13) - m(5); + planes[3].n.z = m(14) - m(6); + planes[3].d = m(15) - m(7); + + // Far: [30-20, 31-21, 32-22, 33-23] + + planes[5].n.x = m(12) - m(8); + planes[5].n.y = m(13) - m(9); + planes[5].n.z = m(14) - m(10); + planes[5].d = m(15) - m(11); + + // Near: [30+20, 31+21, 32+22, 33+23] + + planes[4].n.x = m(12) + m(8); + planes[4].n.y = m(13) + m(9); + planes[4].n.z = m(14) + m(10); + planes[4].d = m(15) + m(11); + + // Normalize + if (normalize) { + for (int i = 0; i < 6; ++i) { + double mag = Math.sqrt(planes[i].n.x * planes[i].n.x + planes[i].n.y * planes[i].n.y + planes[i].n.z + * planes[i].n.z); + + planes[i].n.x /= mag; + planes[i].n.y /= mag; + planes[i].n.z /= mag; + planes[i].d /= mag; + } + } + } + + public void extractFrustumPlanes2(boolean normalize) { + // Left: [30+00, 31+01, 32+02, 33+03] + // comboMatrix.m[12] + comboMatrix.m[0]; + + planes[0].n.x = m(3) + m(0); + planes[0].n.y = m(7) + m(4); + planes[0].n.z = m(11) + m(8); + planes[0].d = m(15) + m(12); + + // Right: [30-00, 31-01, 32-02, 33-03] + + planes[1].n.x = m(3) - m(0); + planes[1].n.y = m(7) - m(4); + planes[1].n.z = m(11) - m(8); + planes[1].d = m(15) - m(12); + + // Bottom: [30+10, 31+11, 32+12, 33+13] + + planes[2].n.x = m(3) + m(1); + planes[2].n.y = m(7) + m(5); + planes[2].n.z = m(11) + m(9); + planes[2].d = m(15) + m(13); + + // Top: [30-10, 31-11, 32-12, 33-13] + + planes[3].n.x = m(3) - m(1); + planes[3].n.y = m(7) - m(5); + planes[3].n.z = m(11) - m(9); + planes[3].d = m(15) - m(13); + + // Far: [30-20, 31-21, 32-22, 33-23] + + planes[5].n.x = m(3) - m(2); + planes[5].n.y = m(7) - m(6); + planes[5].n.z = m(11) - m(10); + planes[5].d = m(15) - m(14); + + // Near: [30+20, 31+21, 32+22, 33+23] + + planes[4].n.x = m(3) + m(2); + planes[4].n.y = m(7) + m(6); + planes[4].n.z = m(11) + m(10); + planes[4].d = m(15) + m(14); + + // Normalize + if (normalize) { + for (int i = 0; i < 6; ++i) { + double mag = Math.sqrt(planes[i].n.x * planes[i].n.x + planes[i].n.y * planes[i].n.y + planes[i].n.z + * planes[i].n.z); + + planes[i].n.x /= mag; + planes[i].n.y /= mag; + planes[i].n.z /= mag; + planes[i].d /= mag; + } + } + } + + @Override + public String toString() { + return "f2\n" + m(0) + " " + m(1) + " " + m(2) + " " + m(3) + "\n" + m(4) + " " + m(5) + " " + m(6) + " " + + m(7) + "\n" + m(8) + " " + m(9) + " " + m(10) + " " + m(11) + "\n" + m(12) + " " + m(13) + " " + + m(14) + " " + m(15) + " " + "Frustum2[" + planes[0] + ", " + planes[1] + ", " + planes[2] + ", " + + planes[3] + ", " + planes[4] + ", " + planes[5] + "]"; + } +} diff --git a/src/ru/olamedia/geom/ImmModeMesh.java b/src/ru/olamedia/geom/ImmModeMesh.java new file mode 100644 index 0000000..4ce419b --- /dev/null +++ b/src/ru/olamedia/geom/ImmModeMesh.java @@ -0,0 +1,465 @@ +package ru.olamedia.geom; + +import java.nio.Buffer; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLContext; +import javax.media.opengl.fixedfunc.GLPointerFunc; + +import com.jogamp.common.nio.Buffers; +import com.jogamp.opengl.util.GLArrayDataServer; + +public class ImmModeMesh { + private IndexedMeshBulder indexed = IndexedMeshBulder.instance; + private boolean useIndexed = false; + protected GLArrayDataServer interleaved; + protected FloatBuffer buf; + private int vertexCount = 0; + protected int mode = GL2.GL_QUADS; + protected boolean isGLSL = false; + protected byte vertexComponent = 0; + protected byte normalComponent = 0; + protected byte colorComponent = 0; + protected byte texCoordComponent = 0; + protected float red = 1; + protected float green = 1; + protected float blue = 1; + protected float alpha = 1; + protected float offsetX = 0; + protected float offsetY = 0; + protected float offsetZ = 0; + protected float x = 0; + protected float y = 0; + protected float z = 0; + protected float nx = 0; + protected float ny = 0; + protected float nz = 0; + protected float u = 0; + protected float v = 0; + protected boolean isFinished = false; + protected boolean isServer = false; + + public void setGLSL(boolean glsl) { + this.isGLSL = glsl; + } + + public void makeServer() { + if (null == interleaved) { + if (isGLSL) { + allocateGLSLBuffer(); + } else { + allocateFixedBuffer(); + } + if (null != buf) { + buf.flip(); + interleaved.put(buf); + buf.clear(); + buf = null; + } + interleaved.seal(true); + isServer = true; + } + } + + public Buffer getBuffer() { + if (!isServer) { + return buf; + } + return interleaved.getBuffer(); + } + + public void put(ImmModeMesh mesh) { + if (isServer) { + final FloatBuffer b = (FloatBuffer) mesh.getBuffer(); + b.rewind(); + interleaved.put(b); + } else { + final FloatBuffer b = (FloatBuffer) mesh.getBuffer(); + b.rewind(); + if (null == buf) { + allocateBuffer(); + } + growBufferIfNecessary(b.remaining()); + buf.put(b); + } + vertexCount += mesh.getVertexCount(); + } + + public void destroy() { + if (isServer) { + interleaved.destroy(GLContext.getCurrentGL().getGL2ES2()); + interleaved = null; + } else { + if (null != buf) { + buf.clear(); + buf = null; + } + } + } + + public int getComponents() { + return vertexComponent + normalComponent + colorComponent + texCoordComponent; + } + + protected void allocateBuffer() { + if (!isServer) { + buf = Buffers.newDirectFloatBuffer(getComponents() * getVertexCount()); + } else { + if (isGLSL) { + allocateGLSLBuffer(); + } else { + allocateFixedBuffer(); + } + } + } + + protected final void growBuffer(int additionalElements) { + final int osize = (buf != null) ? buf.capacity() : 0; + final int nsize = osize + (additionalElements * getComponents()); + FloatBuffer newFBuffer = Buffers.newDirectFloatBuffer(nsize); + if (buf != null) { + buf.flip(); + newFBuffer.put((FloatBuffer) buf); + } + buf = newFBuffer; + } + + protected void allocateFixedBuffer() { + final GLArrayDataServer buf = GLArrayDataServer.createFixedInterleaved(getComponents(), GL.GL_FLOAT, false, + getVertexCount(), GL.GL_STATIC_DRAW); + if (vertexComponent != 0) { + buf.addFixedSubArray(GLPointerFunc.GL_VERTEX_ARRAY, vertexComponent, GL.GL_ARRAY_BUFFER); + } + if (colorComponent != 0) { + buf.addFixedSubArray(GLPointerFunc.GL_COLOR_ARRAY, colorComponent, GL.GL_ARRAY_BUFFER); + } + if (normalComponent != 0) { + buf.addFixedSubArray(GLPointerFunc.GL_NORMAL_ARRAY, normalComponent, GL.GL_ARRAY_BUFFER); + } + if (texCoordComponent != 0) { + buf.addFixedSubArray(GLPointerFunc.GL_TEXTURE_COORD_ARRAY, texCoordComponent, GL.GL_ARRAY_BUFFER); + } + interleaved = buf; + } + + protected void allocateGLSLBuffer() { + final GLArrayDataServer buf = GLArrayDataServer.createGLSLInterleaved(getComponents(), GL.GL_FLOAT, false, + getVertexCount(), GL.GL_STATIC_DRAW); + if (vertexComponent != 0) { + buf.addGLSLSubArray("mesh_vertices", vertexComponent, GL.GL_ARRAY_BUFFER); + } + if (colorComponent != 0) { + buf.addGLSLSubArray("mesh_colors", colorComponent, GL.GL_ARRAY_BUFFER); + } + if (normalComponent != 0) { + buf.addGLSLSubArray("mesh_normal", normalComponent, GL.GL_ARRAY_BUFFER); + } + if (texCoordComponent != 0) { + buf.addGLSLSubArray("mesh_texCoord", texCoordComponent, GL.GL_ARRAY_BUFFER); + } + buf.rewind(); + interleaved = buf; + } + + protected final boolean growBufferIfNecessary(int spare) { + if (buf == null || buf.remaining() < spare) { + growBuffer(spare); + return true; + } + return false; + } + + private void putf(float f) { + if (isServer) { + if (null == interleaved) { + allocateBuffer(); + } + interleaved.putf(f); + } else { + // buf.put(f); + growBufferIfNecessary(256); + Buffers.putf(buf, f); + } + } + + protected void putVertex() { + if (vertexComponent > 0) { + putf(x); + putf(y); + if (vertexComponent > 2) { + putf(z); + } + } + if (colorComponent > 0) { + putf(red); + putf(green); + putf(blue); + if (colorComponent > 3) { + putf(alpha); + } + } + if (normalComponent != 0) { + putf(nx); + putf(ny); + if (normalComponent > 2) { + putf(nz); + } + } + if (texCoordComponent > 0) { + putf(u); + putf(v); + } + } + + public void getIndexed() { + + } + + public void enableColor3() { + colorComponent = 3; + if (useIndexed) { + indexed.setColorComponent(colorComponent); + } + } + + public void enableColor4() { + colorComponent = 4; + if (useIndexed) { + indexed.setColorComponent(colorComponent); + } + } + + public void enableVertex2() { + vertexComponent = 2; + if (useIndexed) { + indexed.setVertexComponent(vertexComponent); + } + } + + public void enableVertex3() { + vertexComponent = 3; + if (useIndexed) { + indexed.setVertexComponent(vertexComponent); + } + } + + public void enableNormal3() { + normalComponent = 3; + if (useIndexed) { + indexed.setNormalComponent(normalComponent); + } + } + + public void enableTexCoord2() { + texCoordComponent = 2; + if (useIndexed) { + indexed.setUVComponent(texCoordComponent); + } + } + + public void enableTexCoord4() { + texCoordComponent = 4; + if (useIndexed) { + indexed.setUVComponent(texCoordComponent); + } + } + + public void glBegin(int mode) { + this.mode = mode; + allocateBuffer(); + if (useIndexed) { + indexed.reset(); + } + } + + public void beginQuads() { + glBegin(GL2.GL_QUADS); + } + + public void beginTriangles() { + glBegin(GL2.GL_TRIANGLES); + } + + public void glEnd() { + if (useIndexed) { + indexed.end(); + final IntBuffer ind = indexed.getIndices(); + System.out.println("glEnd: " + vertexCount + " / " + ind.limit()); + } + if (isServer) { + if (null == interleaved) { + allocateBuffer(); + } + interleaved.seal(true); + } + isFinished = true; + } + + public void end() { + glEnd(); + } + + public void setServer(boolean isServer) { + this.isServer = isServer; + } + + public int getVBOName() { + return interleaved.getVBOName(); + } + + public int getMode() { + return mode; + } + + public boolean draw() { + if (!isFinished) { + return false; + } + makeServer(); + final GL2ES2 gl = GLContext.getCurrentGL().getGL2ES2(); + interleaved.enableBuffer(gl, true); + // Вывод геометрии VBO выполняется такими же функциями, как и при + // использовании буфера в оперативной памяти. + gl.glDrawArrays(mode, 0, interleaved.getElementCount()); + interleaved.enableBuffer(gl, false); + //gl.glFlush(); + return true; + } + + public void setColor(float red, float green, float blue) { + this.red = red; + this.green = green; + this.blue = blue; + if (useIndexed) { + indexed.glColor3f(red, green, blue); + } + } + + public void setColor(float red, float green, float blue, float alpha) { + this.red = red; + this.green = green; + this.blue = blue; + this.alpha = alpha; + if (useIndexed) { + indexed.glColor4f(red, green, blue, alpha); + } + } + + public void glColor3f(float red, float green, float blue) { + this.red = red; + this.green = green; + this.blue = blue; + if (useIndexed) { + indexed.glColor3f(red, green, blue); + } + } + + public void glColor4f(float red, float green, float blue, float alpha) { + this.red = red; + this.green = green; + this.blue = blue; + this.alpha = alpha; + if (useIndexed) { + indexed.glColor4f(red, green, blue, alpha); + } + } + + public void glVertex3f(float x, float y, float z) { + this.x = offsetX + x; + this.y = offsetY + y; + this.z = offsetZ + z; + putVertex(); + if (useIndexed) { + indexed.glVertex3f(x, y, z); + } + } + + public void glVertex2f(float x, float y) { + this.x = offsetX + x; + this.y = offsetY + y; + putVertex(); + if (useIndexed) { + indexed.glVertex2f(x, y); + } + } + + public void setUV(float u, float v) { + this.u = u; + this.v = v; + if (useIndexed) { + indexed.setUV(u, v); + } + } + + public void glTexCoord2f(float u, float v) { + this.u = u; + this.v = v; + if (useIndexed) { + indexed.setUV(u, v); + } + } + + public void glRectf(float x1, float y1, float x2, float y2) { + glVertex2f(x1, y1); + glVertex2f(x1, y2); + glVertex2f(x2, y2); + glVertex2f(x2, y1); + } + + protected ImmModeMesh(int vertexCount) { + this.setVertexCount(vertexCount); + } + + public static ImmModeMesh allocate(int elementCount) { + return new ImmModeMesh(elementCount); + } + + public int getVertexCount() { + return vertexCount; + } + + public void setVertexCount(int vertexCount) { + this.vertexCount = vertexCount; + } + + public void glTranslate(float x, float y, float z) { + offsetX = x; + offsetY = y; + offsetZ = z; + if (useIndexed) { + indexed.glTranslate(x, y, z); + } + } + + public void dispose() { + if (null != interleaved) { + interleaved.destroy(GLContext.getCurrentGL().getGL2ES2()); + } + if (null != buf) { + buf.clear(); + buf = null; + } + } + + public void compact() { + if (null != interleaved) { + if (null != interleaved.getBuffer()) { + interleaved.getBuffer().flip(); + ((FloatBuffer) interleaved.getBuffer()).compact(); + } + } + } + + public void glNormal3f(float nx, float ny, float nz) { + this.nx = nx; + this.ny = ny; + this.nz = nz; + if (useIndexed) { + indexed.glNormal3f(nx, ny, nz); + } + } +} diff --git a/src/ru/olamedia/geom/IndexedMeshBulder.java b/src/ru/olamedia/geom/IndexedMeshBulder.java new file mode 100644 index 0000000..ec66305 --- /dev/null +++ b/src/ru/olamedia/geom/IndexedMeshBulder.java @@ -0,0 +1,207 @@ +package ru.olamedia.geom; + +import java.nio.FloatBuffer; +import java.nio.IntBuffer; + +public class IndexedMeshBulder { + protected static IndexedMeshBulder instance = new IndexedMeshBulder(); + protected IntBuffer indices = IntBuffer.allocate(4096); + protected FloatBuffer vertex = FloatBuffer.allocate(4096 * 3); + protected FloatBuffer color = FloatBuffer.allocate(4096 * 4); + protected FloatBuffer normal = FloatBuffer.allocate(4096 * 3); + protected FloatBuffer uv = FloatBuffer.allocate(4096 * 2); + protected int indexCount = 0; + protected int vertexCount = 0; + protected int colorCount = 0; + protected int normalCount = 0; + protected int uvCount = 0; + + protected byte vertexComponent = 0; + protected byte normalComponent = 0; + protected byte colorComponent = 0; + protected byte uvComponent = 0; + + protected float red = 1; + protected float green = 1; + protected float blue = 1; + protected float alpha = 1; + protected float offsetX = 0; + protected float offsetY = 0; + protected float offsetZ = 0; + protected float x = 0; + protected float y = 0; + protected float z = 0; + protected float nx = 0; + protected float ny = 0; + protected float nz = 0; + protected float u = 0; + protected float v = 0; + + public void reset() { + vertex.clear(); + color.clear(); + normal.clear(); + uv.clear(); + indices.clear(); + vertexCount = indexCount = vertexComponent = colorComponent = normalComponent = uvComponent = 0; + } + + public void end(){ + indices.flip(); + vertex.flip(); + color.flip(); + normal.flip(); + uv.flip(); + } + + public IntBuffer getIndices() { + IntBuffer ind = IntBuffer.allocate(indices.limit()); + ind.put(indices); + return ind; + } + + private boolean _sameVertex(int i) { + if (vertexComponent != 0) { + if (vertex.get(i * vertexComponent) == z) { + if (vertex.get(i * vertexComponent + 1) == y) { + if ((vertexComponent == 2) || (vertex.get(i * vertexComponent) == z)) { + return true; + } + } + } + } + return false; + } + + private boolean _sameColor(int i) { + if (colorComponent != 0) { + if (color.get(i * colorComponent) == red) { + if (color.get(i * colorComponent + 1) == green) { + if (color.get(i * colorComponent + 2) == blue) { + if ((colorComponent == 2) || (color.get(i * colorComponent) == alpha)) { + return true; + } + } + } + } + } + return false; + } + + private boolean _sameUV(int i) { + if (uvComponent != 0) { + if (uv.get(i * uvComponent) == u) { + if (uv.get(i * uvComponent + 1) == v) { + return true; + } + } + } + return false; + } + + private void _addVertex() { + if (vertexComponent != 0) { + vertex.put(x); + vertex.put(y); + if (vertexComponent > 2) { + vertex.put(z); + } + } + if (colorComponent != 0) { + color.put(red); + color.put(green); + color.put(blue); + if (colorComponent > 3) { + color.put(alpha); + } + } + if (normalComponent != 0) { + normal.put(nx); + normal.put(ny); + if (normalComponent > 2) { + normal.put(nz); + } + } + if (uvComponent != 0) { + uv.put(u); + uv.put(v); + } + indices.put(indexCount); + indexCount++; + } + + private void putVertex() { + vertexCount++; + for (int i = 0; i < vertexCount; i++) { + if (_sameVertex(i) && _sameColor(i) && _sameUV(i)) { + indices.put(i); + return; + } + } + _addVertex(); + } + + public void setVertexComponent(byte vertexComponent) { + this.vertexComponent = vertexComponent; + } + + public void setNormalComponent(byte normalComponent) { + this.normalComponent = normalComponent; + } + + public void setColorComponent(byte colorComponent) { + this.colorComponent = colorComponent; + } + + public void setUVComponent(byte uvComponent) { + this.uvComponent = uvComponent; + } + + private int comps() { + return vertexComponent + normalComponent + colorComponent + uvComponent; + } + + public void glTranslate(float x, float y, float z) { + offsetX = x; + offsetY = y; + offsetZ = z; + } + + public void glColor3f(float red, float green, float blue) { + this.red = red; + this.green = green; + this.blue = blue; + } + + public void glColor4f(float red, float green, float blue, float alpha) { + this.red = red; + this.green = green; + this.blue = blue; + this.alpha = alpha; + } + + public void glVertex3f(float x, float y, float z) { + this.x = offsetX + x; + this.y = offsetY + y; + this.z = offsetZ + z; + putVertex(); + } + + public void glVertex2f(float x, float y) { + this.x = offsetX + x; + this.y = offsetY + y; + putVertex(); + } + + public void glNormal3f(float nx, float ny, float nz) { + this.nx = nx; + this.ny = ny; + this.nz = nz; + } + + public void setUV(float u, float v) { + this.u = u; + this.v = v; + } + +} diff --git a/src/ru/olamedia/geom/Mesh.java b/src/ru/olamedia/geom/Mesh.java index bda53b9..7e25666 100644 --- a/src/ru/olamedia/geom/Mesh.java +++ b/src/ru/olamedia/geom/Mesh.java @@ -10,12 +10,52 @@ import javax.media.opengl.GL2; import javax.media.opengl.GL2ES2; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLContext; -import javax.media.opengl.fixedfunc.GLPointerFunc; +import javax.media.opengl.GLException; +import javax.media.opengl.GLUniformData; +import javax.vecmath.Point3f; + +import ru.olamedia.asset.Shader; +import ru.olamedia.olacraft.game.Game; import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderState; import com.jogamp.opengl.util.texture.Texture; public class Mesh { + private static Shader shader = null; + private static GLUniformData pmvMatrixUniform; + private static GLUniformData sunColor; + + private static Shader getShader() { + if (null == shader) { + shader = new Shader(); + shader.compile(); + GL2ES2 gl = GLContext.getCurrentGL().getGL2ES2(); + ShaderState state = shader.getState(); + PMVMatrix pmvMatrix = Game.client.getScene().getPmvMatrix(); + state.attachObject("pmvMatrix", pmvMatrix); + pmvMatrixUniform = new GLUniformData("pmvMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + state.ownUniform(pmvMatrixUniform); + state.uniform(gl, pmvMatrixUniform); + + state.attachObject("sunColor", sunColor); + sunColor = new GLUniformData("sunColor", 4, Game.client.getScene().dayTime.sunColor); + state.ownUniform(sunColor); + state.uniform(gl, sunColor); + + // if (!state.uniform(gl, new GLUniformData("sunColor", 4, + // Game.client.getScene().time.sunColor))) { + // throw new GLException("Error setting sunColor in shader: " + + // state); + // } + if (!state.uniform(gl, new GLUniformData("mesh_ActiveTexture", 0))) { + throw new GLException("Error setting mesh_ActiveTexture in shader: " + state); + } + } + return shader; + } + public void invalidate() { buffer = null; data = null; @@ -103,11 +143,11 @@ public class Mesh { } for (Integer m : materials.keySet()) { int matVertCount = materials.get(m); - final GLArrayDataServer interleaved = GLArrayDataServer.createFixedInterleaved(9, GL2.GL_FLOAT, false, + final GLArrayDataServer interleaved = GLArrayDataServer.createGLSLInterleaved(9, GL2.GL_FLOAT, false, matVertCount, GL.GL_STATIC_DRAW); - interleaved.addFixedSubArray(GLPointerFunc.GL_VERTEX_ARRAY, 3, GL.GL_ARRAY_BUFFER); - interleaved.addFixedSubArray(GLPointerFunc.GL_COLOR_ARRAY, 4, GL.GL_ARRAY_BUFFER); - interleaved.addFixedSubArray(GLPointerFunc.GL_TEXTURE_COORD_ARRAY, 2, GL.GL_ARRAY_BUFFER); + interleaved.addGLSLSubArray("mesh_vertices", 3, GL.GL_ARRAY_BUFFER); + interleaved.addGLSLSubArray("mesh_colors", 4, GL.GL_ARRAY_BUFFER); + interleaved.addGLSLSubArray("mesh_texCoord", 2, GL.GL_ARRAY_BUFFER); arrays.put(m, interleaved); } for (int n = 0; n < vertexCount; n++) { @@ -143,6 +183,10 @@ public class Mesh { zOffset = z; } + public void setPoint3f(Point3f point) { + setPoint3f(point.x, point.y, point.z); + } + public void setPoint3f(float x, float y, float z) { ptr = vertexPtr * vertexSize; data[ptr + 0] = x + xOffset; @@ -225,19 +269,24 @@ public class Mesh { return; } GL glx = GLContext.getCurrentGL(); - if (true){ - GL2 gl = glx.getGL2(); - gl.glShadeModel(GL2.GL_FLAT); - } if (useVbo) { GL2ES2 gl = glx.getGL2ES2(); // GL2 gl = glx.getGL2(); + getShader().enable(); + Game.client.getScene().dayTime.getClearColor(); + getShader().getState().uniform(gl, pmvMatrixUniform); + getShader().getState().uniform(gl, sunColor); for (Integer m : materials.keySet()) { - - gl.glEnable(GL.GL_TEXTURE_2D); + gl.glActiveTexture(GL.GL_TEXTURE0); gl.glBindTexture(GL.GL_TEXTURE_2D, (int) m); - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST_MIPMAP_NEAREST); + // gl.glTexParameteri(GL.GL_TEXTURE_2D, + // GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); + // gl.glTexParameteri(GL.GL_TEXTURE_2D, + // GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST_MIPMAP_NEAREST); + // gl.glTexParameteri(GL.GL_TEXTURE_2D, + // GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); + // gl.glTexParameteri(GL.GL_TEXTURE_2D, + // GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_LINEAR); arrays.get(m).enableBuffer(gl, true); gl.glEnable(GL.GL_CULL_FACE); gl.glEnable(GL.GL_DEPTH_TEST); @@ -246,6 +295,7 @@ public class Mesh { arrays.get(m).enableBuffer(gl, false); // System.exit(0); } + getShader().disable(); } else { GL2 gl = glx.getGL2(); if (useDisplayList) { diff --git a/src/ru/olamedia/geom/MultiMesh.java b/src/ru/olamedia/geom/MultiMesh.java new file mode 100644 index 0000000..98becd1 --- /dev/null +++ b/src/ru/olamedia/geom/MultiMesh.java @@ -0,0 +1,34 @@ +package ru.olamedia.geom; + +import java.nio.IntBuffer; + +import javax.media.opengl.GL2; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GL3; +import javax.media.opengl.GLContext; + +public class MultiMesh { + private IntBuffer vboIndices; + private IntBuffer counts; + private int mode = GL2.GL_TRIANGLES; + + public void clear() { + vboIndices.clear(); + } + + public void add(ImmModeMesh mesh) { + vboIndices.put(mesh.getVBOName()); + } + + public void draw() { + final GL3 gl = GLContext.getCurrentGL().getGL3(); + } + + public MultiMesh(int meshCount) { + vboIndices = IntBuffer.allocate(meshCount); + } + + public static MultiMesh allocate(int meshCount) { + return new MultiMesh(meshCount); + } +} diff --git a/src/ru/olamedia/geom/SimpleQuadMesh.java b/src/ru/olamedia/geom/SimpleQuadMesh.java index ad3c27c..c28c799 100644 --- a/src/ru/olamedia/geom/SimpleQuadMesh.java +++ b/src/ru/olamedia/geom/SimpleQuadMesh.java @@ -1,9 +1,28 @@ package ru.olamedia.geom; +import javax.vecmath.Point3f; + +import ru.olamedia.asset.SpriteRectangle; + public class SimpleQuadMesh extends Mesh { public boolean restart = true; + public Point3f bottomLeftBack = new Point3f(); + public Point3f bottomLeftFront = new Point3f(); + public Point3f bottomRightBack = new Point3f(); + public Point3f bottomRightFront = new Point3f(); + + public Point3f topLeftBack = new Point3f(); + public Point3f topLeftFront = new Point3f(); + public Point3f topRightBack = new Point3f(); + public Point3f topRightFront = new Point3f(); + + public float textureTop = 1; + public float textureBottom = 0; + public float textureLeft = 0; + public float textureRight = 1; + public void restart() { restart = true; } @@ -16,108 +35,154 @@ public class SimpleQuadMesh extends Mesh { super(size * 4); } - private void addBottomLeftBackVertex() { - setPoint3f(-0.5f, -0.5f, -0.5f); + public void addBottomLeftBackVertex() { + setPoint3f(bottomLeftBack); } - private void addBottomLeftFrontVertex() { - setPoint3f(-0.5f, -0.5f, 0.5f); + public void addBottomLeftFrontVertex() { + setPoint3f(bottomLeftFront); } - private void addBottomRightBackVertex() { - setPoint3f(0.5f, -0.5f, -0.5f); + public void addBottomRightBackVertex() { + setPoint3f(bottomRightBack); } - private void addBottomRightFrontVertex() { - setPoint3f(0.5f, -0.5f, 0.5f); + public void addBottomRightFrontVertex() { + setPoint3f(bottomRightFront); } - private void addTopLeftBackVertex() { - setPoint3f(-0.5f, 0.5f, -0.5f); + public void addTopLeftBackVertex() { + setPoint3f(topLeftBack); } - private void addTopLeftFrontVertex() { - setPoint3f(-0.5f, 0.5f, 0.5f); + public void addTopLeftFrontVertex() { + setPoint3f(topLeftFront); } - private void addTopRightBackVertex() { - setPoint3f(0.5f, 0.5f, -0.5f); + public void addTopRightBackVertex() { + setPoint3f(topRightBack); } - private void addTopRightFrontVertex() { - setPoint3f(0.5f, 0.5f, 0.5f); + public void addTopRightFrontVertex() { + setPoint3f(topRightFront); } public void addFrontQuad() { // triangle strip: И - setUV(0, 1); + setUV(textureLeft, textureTop); addTopLeftFrontVertex(); // top left - setUV(0, 0); + setUV(textureLeft, textureBottom); addBottomLeftFrontVertex(); // bottom left - setUV(1, 0); + setUV(textureRight, textureBottom); addBottomRightFrontVertex(); // bottom right - setUV(1, 1); + setUV(textureRight, textureTop); addTopRightFrontVertex(); // top right } public void addBackQuad() { // triangle strip: И - setUV(0, 1); + setUV(textureLeft, textureTop); addTopRightBackVertex(); - setUV(0, 0); + setUV(textureLeft, textureBottom); addBottomRightBackVertex(); - setUV(1, 0); + setUV(textureRight, textureBottom); addBottomLeftBackVertex(); - setUV(1, 1); + setUV(textureRight, textureTop); addTopLeftBackVertex(); } public void addLeftQuad() { // triangle strip: И - setUV(0, 1); + setUV(textureLeft, textureTop); addTopLeftBackVertex(); - setUV(0, 0); + setUV(textureLeft, textureBottom); addBottomLeftBackVertex(); - setUV(1, 0); + setUV(textureRight, textureBottom); addBottomLeftFrontVertex(); - setUV(1, 1); + setUV(textureRight, textureTop); addTopLeftFrontVertex(); } public void addRightQuad() { // triangle strip: И - setUV(0, 1); + setUV(textureLeft, textureTop); addTopRightFrontVertex(); - setUV(0, 0); + setUV(textureLeft, textureBottom); addBottomRightFrontVertex(); - setUV(1, 0); + setUV(textureRight, textureBottom); addBottomRightBackVertex(); - setUV(1, 1); + setUV(textureRight, textureTop); addTopRightBackVertex(); } public void addTopQuad() { // triangle strip: И - setUV(0, 0); + setUV(textureLeft, textureBottom); addTopLeftBackVertex(); - setUV(0, 1); + setUV(textureLeft, textureTop); addTopLeftFrontVertex(); - setUV(1, 1); + setUV(textureRight, textureTop); addTopRightFrontVertex(); - setUV(1, 0); + setUV(textureRight, textureBottom); addTopRightBackVertex(); } public void addBottomQuad() { // triangle strip: И - setUV(0, 0); + setUV(textureLeft, textureBottom); addBottomLeftFrontVertex(); - setUV(0, 1); + setUV(textureLeft, textureTop); addBottomLeftBackVertex(); - setUV(1, 1); + setUV(textureRight, textureTop); addBottomRightBackVertex(); - setUV(1, 0); + setUV(textureRight, textureBottom); addBottomRightFrontVertex(); } + public void setPointOffset(float offset) { + bottomLeftBack.x = -offset; + bottomLeftBack.y = -offset; + bottomLeftBack.z = -offset; + // + bottomLeftFront.x = -offset; + bottomLeftFront.y = -offset; + bottomLeftFront.z = offset; + // + bottomRightBack.x = offset; + bottomRightBack.y = -offset; + bottomRightBack.z = -offset; + // + bottomRightFront.x = offset; + bottomRightFront.y = -offset; + bottomRightFront.z = offset; + // + topLeftBack.x = -offset; + topLeftBack.y = offset; + topLeftBack.z = -offset; + // + topLeftFront.x = -offset; + topLeftFront.y = offset; + topLeftFront.z = offset; + // + topRightBack.x = offset; + topRightBack.y = offset; + topRightBack.z = -offset; + // + topRightFront.x = offset; + topRightFront.y = offset; + topRightFront.z = offset; + + } + + public void setTextureOffset(SpriteRectangle offset) { + if (null != offset) { + // System.out.print("Offset " + "[" + offset.topLeft.x + "," + + // offset.topLeft.y + "]"); + textureTop = offset.topLeft.y; + textureLeft = offset.topLeft.x; + textureRight = offset.bottomRight.x; + textureBottom = offset.bottomRight.y; + } + } + } diff --git a/src/ru/olamedia/geom/VoxelRaypicker.java b/src/ru/olamedia/geom/VoxelRaypicker.java new file mode 100644 index 0000000..9e8c533 --- /dev/null +++ b/src/ru/olamedia/geom/VoxelRaypicker.java @@ -0,0 +1,37 @@ +package ru.olamedia.geom; + +public class VoxelRaypicker { + public float[] center = new float[3]; + public float[] dir = new float[3]; + public float radius; + public float[] picker = new float[3]; + public float[] minDelta = new float[3]; + public float[] delta = new float[3]; + public float[] absDelta = new float[3]; + + private void calcDelta(byte i) { + if (dir[i] > 0) { + delta[i] = ((float) ((int) (center[i] + 1)) - center[i]) / dir[i]; + absDelta[i] = delta[i]; + } else if (dir[0] < 0) { + delta[i] = -((float) ((int) (center[i] - 1)) - center[i]) / dir[i]; + absDelta[i] = delta[i]; + } else { + delta[i] = 0; + absDelta[i] = 0; + } + minDelta[i] = delta[i]; + } + + public void reset() { + picker[0] = center[0]; + picker[1] = center[1]; + picker[2] = center[2]; + calcDelta((byte) 0); + calcDelta((byte) 1); + calcDelta((byte) 2); + } + + public void next() { + } +} |