Commits

Michael Ludwig  committed 6b21287

Complete (sort of tested) triangle depth sorting for rendered objects

  • Participants
  • Parent commits 7f05a8f

Comments (0)

Files changed (4)

File ferox-demos/src/main/java/com/ferox/scene/controller/ffp/TransparentDemo.java

 import com.ferox.renderer.Renderer.DrawStyle;
 import com.ferox.renderer.impl.lwjgl.LwjglFramework;
 import com.ferox.scene.AmbientLight;
+import com.ferox.scene.BlinnPhongMaterial;
 import com.ferox.scene.Camera;
 import com.ferox.scene.DiffuseColor;
 import com.ferox.scene.PointLight;
 import com.ferox.scene.controller.light.ComputeLightGroupTask;
 import com.ferox.scene.controller.light.ComputeShadowFrustumTask;
 import com.ferox.util.ApplicationStub;
-import com.ferox.util.geom.Box;
 import com.ferox.util.geom.Geometry;
+import com.ferox.util.geom.Teapot;
 import com.ferox.util.profile.Profiler;
 import com.lhkbob.entreri.Entity;
 import com.lhkbob.entreri.EntitySystem;
 public class TransparentDemo extends ApplicationStub {
     protected static final int BOUNDS = 50;
     protected static final double BOX_SIZE = 1.5;
-    protected static final int NUM_X = 5;
-    protected static final int NUM_Y = 5;
-    protected static final int NUM_Z = 5;
-    protected static final double GAP_X = 1;
-    protected static final double GAP_Y = 1;
-    protected static final double GAP_Z = 1;
+    protected static final int NUM_X = 1;
+    protected static final int NUM_Y = 1;
+    protected static final int NUM_Z = 1;
+    protected static final double GAP_X = 0;
+    protected static final double GAP_Y = 0;
+    protected static final double GAP_Z = 0;
 
     protected static final AxisAlignedBox worldBounds = new AxisAlignedBox(new Vector3(-2 * BOUNDS - 1,
                                                                                        -2 * BOUNDS - 1,
         updateCameraOrientation();
 
         // boxes
-        Geometry boxGeom = Box.create(BOX_SIZE);
+        Geometry boxGeom = Teapot.create(BOX_SIZE); //Box.create(BOX_SIZE);
         for (int x = 0; x < NUM_X; x++) {
             for (int y = 0; y < NUM_Y; y++) {
                 for (int z = 0; z < NUM_Z; z++) {
                     box.add(Renderable.class)
                        .getData()
                        .setVertices(boxGeom.getVertices())
-                       .setDrawStyle(DrawStyle.SOLID, DrawStyle.NONE)
+                       .setDrawStyle(DrawStyle.SOLID, DrawStyle.SOLID)
                        .setIndices(boxGeom.getPolygonType(), boxGeom.getIndices(),
                                    boxGeom.getIndexOffset(), boxGeom.getIndexCount())
                        .setLocalBounds(boxGeom.getBounds());
-                    //                    box.add(BlinnPhongMaterial.class).getData()
-                    //                       .setNormals(boxGeom.getNormals());
-                    box.add(DiffuseColor.class)
-                       .getData()
-                       .setColor(new ColorRGB(x / (double) NUM_X,
-                                              y / (double) NUM_Y,
-                                              z / (double) NUM_Z));
+                    box.add(BlinnPhongMaterial.class).getData()
+                       .setNormals(boxGeom.getNormals());
+                    box.add(DiffuseColor.class).getData()
+                    //                       .setColor(new ColorRGB(x / (double) NUM_X,
+                    //                                              y / (double) NUM_Y,
+                    //                                              z / (double) NUM_Z));
+                       .setColor(new ColorRGB(.5, .5, .5));
                     double rand = Math.random();
-                    if (rand < .3) {
-                        box.add(Transparent.class).getData().setOpacity(.5)
-                           .setAdditive(true);
-                    } else if (rand < .6) {
-                        box.add(Transparent.class).getData().setOpacity(.5)
-                           .setAdditive(false);
-                    }
+                    //                    if (rand < .3) {
+                    //                        box.add(Transparent.class).getData().setOpacity(.5)
+                    //                           .setAdditive(true);
+                    //                    } else if (rand < .6) {
+                    box.add(Transparent.class).getData().setOpacity(.5)
+                       .setAdditive(false);
+                    //                    }
 
                     box.get(Transform.class).getData()
                        .setMatrix(new Matrix4().setIdentity().setCol(3, pos));

File ferox-renderer/ferox-renderer-api/src/main/java/com/ferox/util/geom/TopologyUtil.java

 package com.ferox.util.geom;
 
-import com.ferox.resource.VertexBufferObject;
+import com.ferox.renderer.Renderer.PolygonType;
+import com.ferox.resource.BufferData;
+import com.ferox.resource.UnsignedDataView;
 
 public final class TopologyUtil {
     private TopologyUtil() {}
 
-    public static void inflateTriangleStrip(VertexBufferObject strips, int stripOffset,
-                                            int stripCount,
-                                            VertexBufferObject targetTris, int triOffset) {
+    public static int inflateTriangleStrip(BufferData strips, int stripOffset,
+                                           int stripCount, BufferData targetTris,
+                                           int triOffset) {
+        int triangleCount = PolygonType.TRIANGLE_STRIP.getPolygonCount(stripCount);
+        if (targetTris.getLength() - triOffset < triangleCount * 3) {
+            throw new IndexOutOfBoundsException("Target triangle index buffer is not large enough");
+        }
+        if (stripOffset + stripCount > strips.getLength()) {
+            throw new IndexOutOfBoundsException("Offset and count access invalid indices in source buffer");
+        }
+        if (stripOffset < 0 || stripCount < 0 || triOffset < 0) {
+            throw new IllegalArgumentException("Offsets and count must be positive");
+        }
 
+        UnsignedDataView source = strips.getUnsignedView();
+        UnsignedDataView target = targetTris.getUnsignedView();
+
+        // if we actually have triangles, fill the buffer
+        if (triangleCount >= 1) {
+            // first three vertices form a triangle
+            target.set(triOffset, source.get(stripOffset)); // set a = 0, writeA = false
+            target.set(triOffset + 1, source.get(stripOffset + 1)); // set b = 1, writeA = true
+            target.set(triOffset + 2, source.get(stripOffset + 2)); // set a = 2, writeA = false
+
+            // according to the OpenGL spec, triangle strips form triangles with
+            // the A vertex, B vertex, and the current vertex. The current vertex
+            // is then assigned to A or B alternating between the two to maintain
+            // proper winding.
+            // - in this loop we remove the storage for A or B and alternate
+            //   which index is inserted first (i - 1) or (i - 2)
+            boolean aFirst = false;
+
+            int ti = triOffset + 3;
+            for (int i = stripOffset + 3; i < stripOffset + stripCount; i++) {
+                if (aFirst) {
+                    target.set(ti++, source.get(i - 2));
+                    target.set(ti++, source.get(i - 1));
+                } else {
+                    target.set(ti++, source.get(i - 1));
+                    target.set(ti++, source.get(i - 2));
+                }
+                target.set(ti++, source.get(i));
+                aFirst = !aFirst;
+            }
+        }
+
+        return triangleCount * 3;
     }
 
-    public static void inflateQuadStrip(VertexBufferObject strips, int stripOffset,
-                                        int stripCount, VertexBufferObject targetQuads,
-                                        int quadOffset) {
+    public static int inflateTriangleStripArray(int stripOffset, int stripCount,
+                                                BufferData targetTris, int triOffset) {
+        int triangleCount = PolygonType.TRIANGLE_STRIP.getPolygonCount(stripCount);
+        if (targetTris.getLength() - triOffset < triangleCount * 3) {
+            throw new IndexOutOfBoundsException("Target triangle index buffer is not large enough");
+        }
+        if (stripOffset < 0 || stripCount < 0 || triOffset < 0) {
+            throw new IllegalArgumentException("Offsets and count must be positive");
+        }
 
-    }
+        UnsignedDataView target = targetTris.getUnsignedView();
 
-    public static void inflateTriangleStripArray(int stripOffset, int stripCount,
-                                                 VertexBufferObject targetTris,
-                                                 int triOffset) {
+        // if we actually have triangles, fill the buffer
+        if (triangleCount >= 1) {
+            // first three vertices form a triangle
+            target.set(triOffset, stripOffset);
+            target.set(triOffset + 1, stripOffset + 1);
+            target.set(triOffset + 2, stripOffset + 2);
 
-    }
+            // according to the OpenGL spec, triangle strips form triangles with
+            // the A vertex, B vertex, and the current vertex. The current vertex
+            // is then assigned to A or B alternating between the two to maintain
+            // proper winding.
+            // - in this loop we remove the storage for A or B and alternate
+            //   which index is inserted first (i - 1) or (i - 2)
+            boolean aFirst = false;
 
-    public static void inflateQuadStripArray(int stripOffset, int stripCount,
-                                             VertexBufferObject targetQuads,
-                                             int quadOffset) {
+            int ti = triOffset + 3;
+            for (int i = stripOffset + 3; i < stripOffset + stripCount; i++) {
+                if (aFirst) {
+                    target.set(ti++, i - 2);
+                    target.set(ti++, i - 1);
+                } else {
+                    target.set(ti++, i - 1);
+                    target.set(ti++, i - 2);
+                }
+                target.set(ti++, i);
+                aFirst = !aFirst;
+            }
+        }
 
+        return triangleCount * 3;
     }
 
     public static void inflateSimpleArray(int stripOffset, int stripCount,
-                                          VertexBufferObject target, int targetOffset) {
+                                          BufferData target, int targetOffset) {
+        if (targetOffset + stripCount > target.getLength()) {
+            throw new IndexOutOfBoundsException("Target triangle index buffer is not large enough");
+        }
 
+        UnsignedDataView out = target.getUnsignedView();
+        int ti = targetOffset;
+        for (int i = stripOffset; i < stripOffset + stripCount; i++) {
+            out.set(ti++, i);
+        }
     }
 }

File ferox-scene/src/main/java/com/ferox/scene/controller/ffp/IndexBufferState.java

                                             .getFixedFunctionRenderer();
 
             int inflatedIndexCount = polyType.getPolygonCount(indexCount) * polyType.getPolygonSize();
-            if (sortedIndicesShared.getData().getLength() < inflatedIndexCount) {
-                sortedIndicesShared.setData(new BufferData(new int[inflatedIndexCount]));
-            }
+            synchronized (sortedIndicesShared) {
+                if (sortedIndicesShared.getData().getLength() < inflatedIndexCount) {
+                    sortedIndicesShared.setData(new BufferData(new int[inflatedIndexCount]));
+                }
+                BufferData sharedData = sortedIndicesShared.getData();
 
-            if (indices == null) {
-                switch (polyType) {
-                case TRIANGLE_STRIP:
-                    TopologyUtil.inflateTriangleStripArray(indexOffset, indexCount,
-                                                           sortedIndicesShared, 0);
-                    break;
-                default:
-                    TopologyUtil.inflateSimpleArray(indexOffset, indexCount,
-                                                    sortedIndicesShared, 0);
-                    break;
-                }
-            } else {
-                switch (polyType) {
-                case TRIANGLE_STRIP:
-                    TopologyUtil.inflateTriangleStrip(indices, indexOffset, indexCount,
-                                                      sortedIndicesShared, 0);
-                    break;
-                default:
-                    System.arraycopy(indices.getData().getArray(), indexOffset,
-                                     sortedIndicesShared.getData().getArray(), 0,
-                                     indexCount);
-                    break;
+                if (indices == null) {
+                    switch (polyType) {
+                    case TRIANGLE_STRIP:
+                        TopologyUtil.inflateTriangleStripArray(indexOffset, indexCount,
+                                                               sharedData, 0);
+                        break;
+                    default:
+                        TopologyUtil.inflateSimpleArray(indexOffset, indexCount,
+                                                        sharedData, 0);
+                        break;
+                    }
+                } else {
+                    switch (polyType) {
+                    case TRIANGLE_STRIP:
+                        TopologyUtil.inflateTriangleStrip(indices.getData(), indexOffset,
+                                                          indexCount, sharedData, 0);
+                        break;
+                    default:
+                        UnsignedDataView source = indices.getData().getUnsignedView();
+                        UnsignedDataView target = sharedData.getUnsignedView();
+
+                        for (int i = 0; i < indexCount; i++) {
+                            target.set(i, source.get(i + indexOffset));
+                        }
+                        break;
+                    }
                 }
             }
 
                 r.setModelViewMatrix(modelMatrix);
 
                 // sort indices within sortedIndicesShared
-                QuickSort.sort(view);
-                sortedIndicesShared.markDirty(0, inflatedIndexCount);
+                synchronized (sortedIndicesShared) {
+                    QuickSort.sort(view);
+                    sortedIndicesShared.markDirty(0, inflatedIndexCount);
+                }
 
                 // clear, update and rebind sorted indices
                 r.setIndices(null);

File ferox-scene/src/main/java/com/ferox/scene/controller/ffp/TransparentState.java

         AppliedEffects newEffects = effects.applyBlending(src, dst);
 
         newEffects.pushBlending(access.getCurrentContext().getFixedFunctionRenderer());
+        access.getCurrentContext().getFixedFunctionRenderer()
+              .setTwoSidedLightingEnabled(newEffects.isBlendingEnabled());
         currentNode.visitChildren(newEffects, access);
     }
 }