diff options
Diffstat (limited to 'engine/src/tools/jme3tools/optimize/TriangleCollector.java')
-rw-r--r-- | engine/src/tools/jme3tools/optimize/TriangleCollector.java | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/engine/src/tools/jme3tools/optimize/TriangleCollector.java b/engine/src/tools/jme3tools/optimize/TriangleCollector.java new file mode 100644 index 0000000..9ce4ffa --- /dev/null +++ b/engine/src/tools/jme3tools/optimize/TriangleCollector.java @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2009-2012 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package jme3tools.optimize; + +import com.jme3.light.Light; +import com.jme3.scene.Geometry; +import com.jme3.scene.Mesh; +import com.jme3.scene.VertexBuffer; +import com.jme3.scene.VertexBuffer.Type; +import com.jme3.util.BufferUtils; +import com.jme3.util.IntMap; +import com.jme3.util.IntMap.Entry; +import java.nio.Buffer; +import java.nio.ShortBuffer; +import java.util.*; + +public class TriangleCollector { + + private static final GeomTriComparator comparator = new GeomTriComparator(); + + private static class GeomTriComparator implements Comparator<OCTTriangle> { + public int compare(OCTTriangle a, OCTTriangle b) { + if (a.getGeometryIndex() < b.getGeometryIndex()){ + return -1; + }else if (a.getGeometryIndex() > b.getGeometryIndex()){ + return 1; + }else{ + return 0; + } + } + } + + private static class Range { + + private int start, length; + + public Range(int start, int length) { + this.start = start; + this.length = length; + } + + public int getLength() { + return length; + } + + public void setLength(int length) { + this.length = length; + } + + public int getStart() { + return start; + } + + public void setStart(int start) { + this.start = start; + } + + } + + /** + * Grabs all the triangles specified in <code>tris</code> from the input array + * (using the indices OCTTriangle.getGeometryIndex() & OCTTriangle.getTriangleIndex()) + * then organizes them into output geometry. + * + * @param inGeoms + * @param tris + * @return + */ + public static final List<Geometry> gatherTris(Geometry[] inGeoms, List<OCTTriangle> tris){ + Collections.sort(tris, comparator); + HashMap<Integer, Range> ranges = new HashMap<Integer, Range>(); + + for (int i = 0; i < tris.size(); i++){ + Range r = ranges.get(tris.get(i).getGeometryIndex()); + if (r != null){ + // incremenet length + r.setLength(r.getLength()+1); + }else{ + // set offset, length is 1 + ranges.put(tris.get(i).getGeometryIndex(), new Range(i, 1)); + } + } + + List<Geometry> newGeoms = new ArrayList<Geometry>(); + int[] vertIndicies = new int[3]; + int[] newIndices = new int[3]; + boolean[] vertexCreated = new boolean[3]; + HashMap<Integer, Integer> indexCache = new HashMap<Integer, Integer>(); + for (Map.Entry<Integer, Range> entry : ranges.entrySet()){ + int inGeomIndex = entry.getKey().intValue(); + int outOffset = entry.getValue().start; + int outLength = entry.getValue().length; + + Geometry inGeom = inGeoms[inGeomIndex]; + Mesh in = inGeom.getMesh(); + Mesh out = new Mesh(); + + int outElementCount = outLength * 3; + ShortBuffer ib = BufferUtils.createShortBuffer(outElementCount); + out.setBuffer(Type.Index, 3, ib); + + // generate output buffers based on input buffers + IntMap<VertexBuffer> bufs = in.getBuffers(); + for (Entry<VertexBuffer> ent : bufs){ + VertexBuffer vb = ent.getValue(); + if (vb.getBufferType() == Type.Index) + continue; + + // NOTE: we are not actually sure + // how many elements will be in this buffer. + // It will be compacted later. + Buffer b = VertexBuffer.createBuffer(vb.getFormat(), + vb.getNumComponents(), + outElementCount); + + VertexBuffer outVb = new VertexBuffer(vb.getBufferType()); + outVb.setNormalized(vb.isNormalized()); + outVb.setupData(vb.getUsage(), vb.getNumComponents(), vb.getFormat(), b); + out.setBuffer(outVb); + } + + int currentVertex = 0; + for (int i = outOffset; i < outOffset + outLength; i++){ + OCTTriangle t = tris.get(i); + + // find vertex indices for triangle t + in.getTriangle(t.getTriangleIndex(), vertIndicies); + + // find indices in new buf + Integer i0 = indexCache.get(vertIndicies[0]); + Integer i1 = indexCache.get(vertIndicies[1]); + Integer i2 = indexCache.get(vertIndicies[2]); + + // check which ones were not created + // if not created in new IB, create them + if (i0 == null){ + vertexCreated[0] = true; + newIndices[0] = currentVertex++; + indexCache.put(vertIndicies[0], newIndices[0]); + }else{ + newIndices[0] = i0.intValue(); + vertexCreated[0] = false; + } + if (i1 == null){ + vertexCreated[1] = true; + newIndices[1] = currentVertex++; + indexCache.put(vertIndicies[1], newIndices[1]); + }else{ + newIndices[1] = i1.intValue(); + vertexCreated[1] = false; + } + if (i2 == null){ + vertexCreated[2] = true; + newIndices[2] = currentVertex++; + indexCache.put(vertIndicies[2], newIndices[2]); + }else{ + newIndices[2] = i2.intValue(); + vertexCreated[2] = false; + } + + // if any verticies were created for this triangle + // copy them to the output mesh + IntMap<VertexBuffer> inbufs = in.getBuffers(); + for (Entry<VertexBuffer> ent : inbufs){ + VertexBuffer vb = ent.getValue(); + if (vb.getBufferType() == Type.Index) + continue; + + VertexBuffer outVb = out.getBuffer(vb.getBufferType()); + // copy verticies that were created for this triangle + for (int v = 0; v < 3; v++){ + if (!vertexCreated[v]) + continue; + + // copy triangle's attribute from one + // buffer to another + vb.copyElement(vertIndicies[v], outVb, newIndices[v]); + } + } + + // write the indices onto the output index buffer + ib.put((short)newIndices[0]) + .put((short)newIndices[1]) + .put((short)newIndices[2]); + } + ib.clear(); + indexCache.clear(); + + // since some verticies were cached, it means there's + // extra data in some buffers + IntMap<VertexBuffer> outbufs = out.getBuffers(); + for (Entry<VertexBuffer> ent : outbufs){ + VertexBuffer vb = ent.getValue(); + if (vb.getBufferType() == Type.Index) + continue; + + vb.compact(currentVertex); + } + + out.updateBound(); + out.updateCounts(); + out.setStatic(); + //out.setInterleaved(); + Geometry outGeom = new Geometry("Geom"+entry.getKey(), out); + outGeom.setLocalTransform(inGeom.getWorldTransform()); + outGeom.setMaterial(inGeom.getMaterial()); + for (Light light : inGeom.getWorldLightList()){ + outGeom.addLight(light); + } + + outGeom.updateGeometricState(); + newGeoms.add(outGeom); + } + + return newGeoms; + } + +} |