# HG changeset patch # User postspectacular # Date 1327488702 0 # Node ID 599d2a58cdf6a343c6cb54a6206ac25db9b24956 # Parent 032471906b662e0b1708c69035470dd51d8b66ca issue #30 fixed: removing circular build dependency in build_core.xml and moving new mesh classes from toxi.geom.mesh package into new source folder src.newmesh and (temporary) package toxi.newmesh, updating .classpath diff -r 032471906b662e0b1708c69035470dd51d8b66ca -r 599d2a58cdf6a343c6cb54a6206ac25db9b24956 .classpath --- a/.classpath Wed Jan 25 10:47:45 2012 +0000 +++ b/.classpath Wed Jan 25 10:51:42 2012 +0000 @@ -12,6 +12,7 @@ + diff -r 032471906b662e0b1708c69035470dd51d8b66ca -r 599d2a58cdf6a343c6cb54a6206ac25db9b24956 ant/build_core.xml --- a/ant/build_core.xml Wed Jan 25 10:47:45 2012 +0000 +++ b/ant/build_core.xml Wed Jan 25 10:51:42 2012 +0000 @@ -46,11 +46,9 @@ - - diff -r 032471906b662e0b1708c69035470dd51d8b66ca -r 599d2a58cdf6a343c6cb54a6206ac25db9b24956 src.core/toxi/geom/mesh/AttributedEdge.java --- a/src.core/toxi/geom/mesh/AttributedEdge.java Wed Jan 25 10:47:45 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -package toxi.geom.mesh; - -import java.util.ArrayList; -import java.util.List; - -public class AttributedEdge { - - public final int a, b; - public List faces; - - public AttributedEdge(int a, int b) { - this.a = a; - this.b = b; - } - - public void addFace(AttributedFace f) { - if (faces == null) { - faces = new ArrayList(2); - } - faces.add(f); - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - AttributedEdge other = (AttributedEdge) obj; - if (a != other.a) { - return false; - } - if (b != other.b) { - return false; - } - return true; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - final int prime = 31; - int result = prime + a; - result = prime * result + b; - return result; - } - - public String toString() { - return String.format("a=%d, b=%d", a, b); - } -} diff -r 032471906b662e0b1708c69035470dd51d8b66ca -r 599d2a58cdf6a343c6cb54a6206ac25db9b24956 src.core/toxi/geom/mesh/AttributedFace.java --- a/src.core/toxi/geom/mesh/AttributedFace.java Wed Jan 25 10:47:45 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -package toxi.geom.mesh; - -import java.util.HashMap; - -public class AttributedFace { - - public int a, b, c; - public int normal = -1; - public HashMap attribs; - - public AttributedFace(int a, int b, int c, HashMap attribs) { - this.a = a; - this.b = b; - this.c = c; - this.attribs = attribs; - } - - public String toString() { - return String.format("a=%d,b=%d,c=%d,n=%d", a, b, c, normal); - } -} diff -r 032471906b662e0b1708c69035470dd51d8b66ca -r 599d2a58cdf6a343c6cb54a6206ac25db9b24956 src.core/toxi/geom/mesh/IndexedTriangleMesh.java --- a/src.core/toxi/geom/mesh/IndexedTriangleMesh.java Wed Jan 25 10:47:45 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,565 +0,0 @@ -package toxi.geom.mesh; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; - -import toxi.geom.AABB; -import toxi.geom.IsectData3D; -import toxi.geom.Ray3D; -import toxi.geom.ReadonlyVec3D; -import toxi.geom.Sphere; -import toxi.geom.Triangle3D; -import toxi.geom.TriangleIntersector; -import toxi.geom.Vec2D; -import toxi.geom.Vec3D; -import toxi.geom.mesh.subdiv.NewSubdivStrategy; -import toxi.util.datatypes.ItemIndex; -import toxi.util.datatypes.UniqueItemIndex; - -public class IndexedTriangleMesh { - - public static final String ATTR_EDGES = "edges"; - public static final String ATTR_FNORMALS = "fnormals"; - public static final String ATTR_UVCOORDS = "uv"; - public static final String ATTR_VCOLORS = "col"; - public static final String ATTR_VERTICES = "vertices"; - public static final String ATTR_VNORMALS = "vnormals"; - - public SpatialIndex vertices = new SpatialIndex(0.001f); - - public ItemIndex fnormals = new UniqueItemIndex(); - - public final ArrayList faces = new ArrayList(); - - public final HashMap> attributes = new HashMap>(); - - public IndexedTriangleMesh() { - } - - public IndexedTriangleMesh addFace(Vec3D a, Vec3D b, Vec3D c, - HashMap attribs) { - int idA = vertices.index(a); - int idB = vertices.index(b); - int idC = vertices.index(c); - if (idA != idB && idA != idC && idB != idC) { - AttributedFace f = new AttributedFace(idA, idB, idC, - addFaceAttributes(null, attribs)); - faces.add(f); - } - return this; - } - - public IndexedTriangleMesh addFace(Vec3D a, Vec3D b, Vec3D c, Vec2D uva, - Vec2D uvb, Vec2D uvc) { - HashMap attribs = null; - if (uva != null && uvb != null && uvc != null) { - attribs = new HashMap(); - attribs.put(ATTR_UVCOORDS, new Object[] { - uva, uvb, uvc - }); - } - return addFace(a, b, c, attribs); - } - - public HashMap addFaceAttribute(AttributedFace f, - String attrib, Object attA, Object attB, Object attC) { - if (f != null && attrib != null && attA != null && attB != null - && attC != null) { - ItemIndex idx = getAttributeIndex(attrib); - f.attribs.put(attrib, new int[] { - idx.index(attA), idx.index(attB), idx.index(attC) - }); - return f.attribs; - } - return null; - } - - public HashMap addFaceAttributes(AttributedFace f, - HashMap attribs) { - HashMap fattribs = null; - if (attribs != null) { - fattribs = (f != null) ? f.attribs : new HashMap( - attribs.size(), 1); - for (String attID : attribs.keySet()) { - Object[] items = attribs.get(attID); - if (items.length >= 3) { - ItemIndex idx = getAttributeIndex(attID); - int[] ids = new int[] { - idx.index(items[0]), idx.index(items[1]), - idx.index(items[2]) - }; - fattribs.put(attID, ids); - } - } - } - return fattribs; - } - - public IndexedTriangleMesh addMesh(IndexedTriangleMesh mesh) { - Vec3D[] v = null; - for (AttributedFace f : mesh.faces) { - v = mesh.getFaceVertices(f, v); - addFace(v[0], v[1], v[2], null); - } - return this; - } - - public IndexedTriangleMesh addMeshWithAttribs(IndexedTriangleMesh mesh) { - HashMap attribs = new HashMap(); - Vec3D[] v = null; - for (AttributedFace f : mesh.faces) { - attribs.clear(); - for (String a : f.attribs.keySet()) { - attribs.put(a, mesh.getFaceAttribValues(f, a)); - } - v = mesh.getFaceVertices(f, v); - addFace(v[0], v[1], v[2], attribs); - } - return this; - } - - public IndexedTriangleMesh clear() { - vertices.clear(); - fnormals.clear(); - attributes.clear(); - faces.clear(); - return this; - } - - public HashMap compile() { - HashSet attribs = new HashSet(); - attribs.add(ATTR_VERTICES); - attribs.add(ATTR_FNORMALS); - return compile(attribs, null); - } - - public HashMap compile(HashSet attribs, - HashMap compilers) { - HashMap mergedComps = new HashMap( - getDefaultCompilers()); - if (compilers != null) { - mergedComps.putAll(compilers); - } - HashMap buffers = new HashMap(); - int numF = faces.size(); - for (String attrib : attribs) { - MeshAttributeCompiler comp = mergedComps.get(attrib); - if (comp != null) { - comp.setMesh(this); - ItemIndex index = comp.getIndex(); - int faceStride = 3 * comp.getStride(); - float[] buf = new float[numF * faceStride]; - int offset = 0; - for (AttributedFace f : faces) { - comp.compileFace(f, index, buf, offset); - offset += faceStride; - } - buffers.put(attrib, buf); - } - } - return buffers; - } - - public List computeEdges() { - ItemIndex edges = getAttributeIndex(ATTR_EDGES); - edges.clear(); - for (AttributedFace f : faces) { - if (f.attribs == null) { - f.attribs = new HashMap(); - } - f.attribs.put(ATTR_EDGES, new int[] { - indexFaceEdge(f, f.a, f.b), indexFaceEdge(f, f.b, f.c), - indexFaceEdge(f, f.c, f.a) - }); - } - return edges.getItems(); - } - - public List computeFaceNormals() { - fnormals.clear(); - Vec3D[] v = null; - for (AttributedFace f : faces) { - v = getFaceVertices(f, v); - f.normal = fnormals.index(v[0].sub(v[1]).crossSelf(v[0].sub(v[2])) - .normalize()); - } - return fnormals.getItems(); - } - - public List computeVertexNormals() { - Vec3D[] vnorms = new Vec3D[vertices.size()]; - for (int i = 0; i < vnorms.length; i++) { - vnorms[i] = new Vec3D(); - } - for (AttributedFace f : faces) { - final Vec3D n = fnormals.forID(f.normal); - vnorms[f.a].addSelf(n); - vnorms[f.b].addSelf(n); - vnorms[f.c].addSelf(n); - } - for (int i = 0; i < vnorms.length; i++) { - vnorms[i].normalize(); - } - ItemIndex idx = getAttributeIndex(ATTR_VNORMALS); - idx.clear(); - for (AttributedFace f : faces) { - if (f.attribs == null) { - f.attribs = new HashMap(); - } - f.attribs.put( - ATTR_VNORMALS, - new int[] { - idx.index(vnorms[f.a]), idx.index(vnorms[f.b]), - idx.index(vnorms[f.c]) - }); - } - return idx.getItems(); - } - - public IndexedTriangleMesh extrudeFace(AttributedFace f, Vec3D offset, - float scale) { - Vec3D[] v = getFaceVertices(f, null); - Vec3D[] v2 = new Vec3D[3]; - Vec3D c = v[0].add(v[1]).addSelf(v[2]).scaleSelf(1 / 3f); - Vec3D n = c.add(offset); - v2[0] = v[0].sub(c).scaleSelf(scale).addSelf(n); - v2[1] = v[1].sub(c).scaleSelf(scale).addSelf(n); - v2[2] = v[2].sub(c).scaleSelf(scale).addSelf(n); - removeFace(f); - // extruded copy - addFace(v2[0], v2[1], v2[2], null); - // sides - addFace(v[0], v[1], v2[0], null); - addFace(v[1], v2[1], v2[0], null); - addFace(v[1], v[2], v2[1], null); - addFace(v[2], v2[2], v2[1], null); - addFace(v[2], v[0], v2[2], null); - addFace(v[0], v2[0], v2[2], null); - return this; - } - - /** - * Flips the current order of all face vertices and attributes. If face or - * vertex normals are present their direction will be inverted as well. - * - * @return itself - */ - public IndexedTriangleMesh flipVertexOrder() { - for (AttributedFace f : faces) { - int t = f.b; - f.b = f.c; - f.c = t; - if (f.attribs != null) { - for (int[] att : f.attribs.values()) { - t = att[1]; - att[1] = att[2]; - att[2] = t; - } - } - } - for (Vec3D n : fnormals.getItems()) { - fnormals.reindex(n, n.getInverted()); - } - ItemIndex vnormals = attributes.get(ATTR_VNORMALS); - if (vnormals != null) { - for (Object n : vnormals.getItems()) { - vnormals.reindex(n, ((Vec3D) n).getInverted()); - } - } - return this; - } - - public ItemIndex getAttributeIndex(String attID) { - UniqueItemIndex idx = attributes.get(attID); - if (idx == null) { - idx = new UniqueItemIndex(); - attributes.put(attID, idx); - } - return idx; - } - - public Sphere getBoundingSphere() { - return getBounds().getBoundingSphere(); - } - - public AABB getBounds() { - return AABB.getBoundingBox(vertices.getItems()); - } - - public Vec3D getCentroid() { - return new Vec3D(getBounds()); - } - - public Vec3D getClosestVertexToPoint(ReadonlyVec3D p) { - Vec3D closest = null; - float minDist = Float.MAX_VALUE; - for (Vec3D v : vertices.getItems()) { - float d = v.distanceToSquared(p); - if (d < minDist) { - closest = v; - minDist = d; - } - } - return closest; - } - - public HashMap getDefaultCompilers() { - HashMap compilers = new HashMap(); - compilers.put(ATTR_VERTICES, new MeshVertexCompiler()); - compilers.put(ATTR_FNORMALS, new MeshFaceNormalCompiler()); - compilers.put(ATTR_VNORMALS, new MeshVertexNormalCompiler()); - compilers.put(ATTR_UVCOORDS, new MeshUVCompiler()); - compilers.put(ATTR_VCOLORS, new MeshVertexColorCompiler()); - return compilers; - } - - /** - * @return the edges - */ - public List getEdges() { - return getAttributeIndex(ATTR_EDGES).getItems(); - } - - public List getEdgesForVertex(Vec3D v) { - List vedges = null; - int id = vertices.getID(v); - if (id != -1) { - vedges = getEdgesForVertexID(id); - } - return vedges; - } - - public List getEdgesForVertexID(int id) { - List vedges = new ArrayList(2); - for (Object o : getEdges()) { - AttributedEdge e = (AttributedEdge) o; - if (e.a == id || e.b == id) { - vedges.add(e); - } - } - return vedges; - } - - public Triangle3D getFaceAsTriangle(AttributedFace f) { - Vec3D[] verts = getFaceVertices(f, null); - return new Triangle3D(verts[0], verts[1], verts[2]); - } - - public HashMap getFaceAttribValues(AttributedFace f, - String... attribs) { - HashMap values = new HashMap( - attribs.length, 1); - for (String a : attribs) { - values.put(a, getFaceAttribValues(f, a)); - } - return values; - } - - public Object[] getFaceAttribValues(AttributedFace f, String att) { - ItemIndex idx = attributes.get(att); - int[] fattribs = f.attribs.get(att); - if (idx == null || fattribs == null) { - return null; - } - return new Object[] { - idx.forID(fattribs[0]), idx.forID(fattribs[1]), - idx.forID(fattribs[2]) - }; - } - - /** - * @return the fnormals - */ - public List getFaceNormals() { - return fnormals.getItems(); - } - - /** - * @return the faces - */ - public List getFaces() { - return faces; - } - - public List getFacesForVertex(Vec3D v) { - List vfaces = null; - int id = vertices.getID(v); - if (id != -1) { - vfaces = new ArrayList(2); - for (AttributedFace f : faces) { - if (f.a == id || f.b == id || f.c == id) { - vfaces.add(f); - } - } - } - return vfaces; - } - - public final Vec3D[] getFaceVertices(AttributedFace f, Vec3D[] verts) { - if (verts != null) { - verts[0] = vertices.forID(f.a); - verts[1] = vertices.forID(f.b); - verts[2] = vertices.forID(f.c); - return verts; - } else { - return new Vec3D[] { - vertices.forID(f.a), vertices.forID(f.b), - vertices.forID(f.c) - }; - } - } - - public List getNeighborsForVertexID(int id, List neighbors) { - List vedges = getEdgesForVertexID(id); - if (vedges.size() > 0) { - if (neighbors == null) { - neighbors = new ArrayList(); - } else { - neighbors.clear(); - } - for (AttributedEdge e : vedges) { - neighbors.add(vertices.forID((e.a == id) ? e.b : e.a)); - } - } else if (neighbors != null) { - neighbors.clear(); - } - return neighbors; - } - - public final int getNumFaces() { - return faces.size(); - } - - public final int getNumVertices() { - return vertices.size(); - } - - public float getVertexDelta() { - return vertices.getDelta(); - } - - /** - * @return the vertices - */ - public List getVertices() { - return vertices.getItems(); - } - - public List getVerticesForIDs(List verts, int... ids) { - if (verts == null) { - verts = new ArrayList(ids.length); - } - for (int id : ids) { - verts.add(vertices.forID(id)); - } - return verts; - } - - protected final int indexFaceEdge(AttributedFace f, int a, int b) { - final AttributedEdge e1 = new AttributedEdge(a, b); - final AttributedEdge e2 = new AttributedEdge(b, a); - ItemIndex edges = getAttributeIndex(ATTR_EDGES); - final int id1 = edges.getID(e1); - final int id2 = edges.getID(e2); - if (id1 != -1) { - ((AttributedEdge) edges.forID(id1)).addFace(f); - return id1; - } else if (id2 != -1) { - ((AttributedEdge) edges.forID(id2)).addFace(f); - return id2; - } else { - e1.addFace(f); - return edges.index(e1); - } - } - - public IsectData3D intersectsRay(Ray3D ray) { - TriangleIntersector intersector = new TriangleIntersector(); - Triangle3D tri = intersector.getTriangle(); - Vec3D[] v = null; - for (AttributedFace f : faces) { - v = getFaceVertices(f, v); - tri.set(v[0], v[1], v[2]); - if (intersector.intersectsRay(ray)) { - return intersector.getIntersectionData(); - } - } - return null; - } - - public void rebuildVertexIndex() { - SpatialIndex newVerts = new SpatialIndex(vertices.getDelta()); - Vec3D[] v = null; - for (AttributedFace f : faces) { - v = getFaceVertices(f, v); - f.a = newVerts.index(v[0]); - f.b = newVerts.index(v[1]); - f.c = newVerts.index(v[2]); - } - vertices = newVerts; - } - - public IndexedTriangleMesh removeFace(AttributedFace f) { - faces.remove(f); - return this; - } - - public IndexedTriangleMesh setVertexDelta(float delta) { - vertices.setDelta(delta); - return this; - } - - public IndexedTriangleMesh smooth() { - HashMap lapIndex = new HashMap(); - List neighbors = null; - for (int i = 0, numV = getNumVertices(); i < numV; i++) { - neighbors = getNeighborsForVertexID(i, neighbors); - if (neighbors != null && neighbors.size() > 0) { - Vec3D l = new Vec3D(); - for (Vec3D n : neighbors) { - l.addSelf(n); - } - l.scaleSelf(1f / neighbors.size()); - lapIndex.put(i, l); - } - } - SpatialIndex newVerts = new SpatialIndex(vertices.getDelta()); - for (Iterator i = faces.iterator(); i.hasNext();) { - AttributedFace f = i.next(); - f.a = newVerts.index(lapIndex.get(f.a)); - f.b = newVerts.index(lapIndex.get(f.b)); - f.c = newVerts.index(lapIndex.get(f.c)); - if (f.a == f.b || f.a == f.c || f.b == f.c) { - i.remove(); - } - } - vertices = newVerts; - computeEdges(); - return this; - } - - public IndexedTriangleMesh subdivide(NewSubdivStrategy strategy) { - Vec3D[] v = null; - List splitFaces = new ArrayList(); - for (AttributedFace f : new ArrayList(faces)) { - removeFace(f); - v = getFaceVertices(f, v); - for (Vec3D[] fverts : strategy.subdivideTriangle(v[0], v[1], v[2], - splitFaces)) { - addFace(fverts[0], fverts[1], fverts[2], null); - } - splitFaces.clear(); - } - rebuildVertexIndex(); - return this; - } - - @Override - public String toString() { - return String.format("vertices: %d, faces: %d", getNumVertices(), - getNumFaces()); - } -} diff -r 032471906b662e0b1708c69035470dd51d8b66ca -r 599d2a58cdf6a343c6cb54a6206ac25db9b24956 src.core/toxi/geom/mesh/MeshAttributeCompiler.java --- a/src.core/toxi/geom/mesh/MeshAttributeCompiler.java Wed Jan 25 10:47:45 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -package toxi.geom.mesh; - -import toxi.util.datatypes.ItemIndex; - -public abstract class MeshAttributeCompiler { - - protected IndexedTriangleMesh mesh; - - public abstract void compileFace(AttributedFace f, ItemIndex index, - float[] buf, int offset); - - public abstract ItemIndex getIndex(); - - public abstract int getStride(); - - public void setMesh(IndexedTriangleMesh mesh) { - this.mesh = mesh; - } -} diff -r 032471906b662e0b1708c69035470dd51d8b66ca -r 599d2a58cdf6a343c6cb54a6206ac25db9b24956 src.core/toxi/geom/mesh/MeshFaceNormalCompiler.java --- a/src.core/toxi/geom/mesh/MeshFaceNormalCompiler.java Wed Jan 25 10:47:45 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -package toxi.geom.mesh; - -import toxi.geom.Vec3D; -import toxi.util.datatypes.ItemIndex; - -public class MeshFaceNormalCompiler extends MeshAttributeCompiler { - - @Override - public void compileFace(AttributedFace f, ItemIndex index, float[] buf, - int offset) { - Vec3D v = (Vec3D) index.forID(f.normal); - buf[offset++] = v.x; - buf[offset++] = v.y; - buf[offset++] = v.z; - buf[offset++] = v.x; - buf[offset++] = v.y; - buf[offset++] = v.z; - buf[offset++] = v.x; - buf[offset++] = v.y; - buf[offset++] = v.z; - } - - @Override - public ItemIndex getIndex() { - return mesh.fnormals; - } - - @Override - public int getStride() { - return 3; - } - -} diff -r 032471906b662e0b1708c69035470dd51d8b66ca -r 599d2a58cdf6a343c6cb54a6206ac25db9b24956 src.core/toxi/geom/mesh/MeshUVCompiler.java --- a/src.core/toxi/geom/mesh/MeshUVCompiler.java Wed Jan 25 10:47:45 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -package toxi.geom.mesh; - -import toxi.geom.Vec2D; -import toxi.util.datatypes.ItemIndex; - -public class MeshUVCompiler extends MeshAttributeCompiler { - - @Override - public void compileFace(AttributedFace f, ItemIndex index, float[] buf, - int offset) { - int[] vn = f.attribs.get(IndexedTriangleMesh.ATTR_UVCOORDS); - Vec2D v = (Vec2D) index.forID(vn[0]); - buf[offset++] = v.x; - buf[offset++] = v.y; - v = (Vec2D) index.forID(vn[1]); - buf[offset++] = v.x; - buf[offset++] = v.y; - v = (Vec2D) index.forID(vn[2]); - buf[offset++] = v.x; - buf[offset++] = v.y; - } - - @Override - public ItemIndex getIndex() { - return mesh.attributes.get(IndexedTriangleMesh.ATTR_UVCOORDS); - } - - @Override - public int getStride() { - return 2; - } - -} diff -r 032471906b662e0b1708c69035470dd51d8b66ca -r 599d2a58cdf6a343c6cb54a6206ac25db9b24956 src.core/toxi/geom/mesh/MeshVertexColorCompiler.java --- a/src.core/toxi/geom/mesh/MeshVertexColorCompiler.java Wed Jan 25 10:47:45 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -package toxi.geom.mesh; - -import toxi.color.ReadonlyTColor; -import toxi.util.datatypes.ItemIndex; - -public class MeshVertexColorCompiler extends MeshAttributeCompiler { - - @Override - public void compileFace(AttributedFace f, ItemIndex index, float[] buf, - int offset) { - int[] vn = f.attribs.get(IndexedTriangleMesh.ATTR_VCOLORS); - ReadonlyTColor c = (ReadonlyTColor) index.forID(vn[0]); - c.toRGBAArray(buf, offset); - c = (ReadonlyTColor) index.forID(vn[1]); - c.toRGBAArray(buf, offset + 4); - c = (ReadonlyTColor) index.forID(vn[2]); - c.toRGBAArray(buf, offset + 8); - } - - @Override - public ItemIndex getIndex() { - return mesh.attributes.get(IndexedTriangleMesh.ATTR_VCOLORS); - } - - @Override - public int getStride() { - return 4; - } - -} diff -r 032471906b662e0b1708c69035470dd51d8b66ca -r 599d2a58cdf6a343c6cb54a6206ac25db9b24956 src.core/toxi/geom/mesh/MeshVertexCompiler.java --- a/src.core/toxi/geom/mesh/MeshVertexCompiler.java Wed Jan 25 10:47:45 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -package toxi.geom.mesh; - -import toxi.geom.Vec3D; -import toxi.util.datatypes.ItemIndex; - -public class MeshVertexCompiler extends MeshAttributeCompiler { - - @Override - public void compileFace(AttributedFace f, ItemIndex index, float[] buf, - int offset) { - Vec3D v = (Vec3D) index.forID(f.a); - buf[offset++] = v.x; - buf[offset++] = v.y; - buf[offset++] = v.z; - v = (Vec3D) index.forID(f.b); - buf[offset++] = v.x; - buf[offset++] = v.y; - buf[offset++] = v.z; - v = (Vec3D) index.forID(f.c); - buf[offset++] = v.x; - buf[offset++] = v.y; - buf[offset++] = v.z; - } - - @Override - public ItemIndex getIndex() { - return mesh.vertices; - } - - @Override - public int getStride() { - return 3; - } - -} diff -r 032471906b662e0b1708c69035470dd51d8b66ca -r 599d2a58cdf6a343c6cb54a6206ac25db9b24956 src.core/toxi/geom/mesh/MeshVertexNormalCompiler.java --- a/src.core/toxi/geom/mesh/MeshVertexNormalCompiler.java Wed Jan 25 10:47:45 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -package toxi.geom.mesh; - -import toxi.geom.Vec3D; -import toxi.util.datatypes.ItemIndex; - -public class MeshVertexNormalCompiler extends MeshAttributeCompiler { - - @Override - public void compileFace(AttributedFace f, ItemIndex index, float[] buf, - int offset) { - int[] vn = f.attribs.get(IndexedTriangleMesh.ATTR_VNORMALS); - Vec3D v = (Vec3D) index.forID(vn[0]); - buf[offset++] = v.x; - buf[offset++] = v.y; - buf[offset++] = v.z; - v = (Vec3D) index.forID(vn[1]); - buf[offset++] = v.x; - buf[offset++] = v.y; - buf[offset++] = v.z; - v = (Vec3D) index.forID(vn[2]); - buf[offset++] = v.x; - buf[offset++] = v.y; - buf[offset++] = v.z; - } - - @Override - public ItemIndex getIndex() { - return mesh.attributes.get(IndexedTriangleMesh.ATTR_VNORMALS); - } - - @Override - public int getStride() { - return 3; - } - -} diff -r 032471906b662e0b1708c69035470dd51d8b66ca -r 599d2a58cdf6a343c6cb54a6206ac25db9b24956 src.core/toxi/geom/mesh/SpatialIndex.java --- a/src.core/toxi/geom/mesh/SpatialIndex.java Wed Jan 25 10:47:45 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -package toxi.geom.mesh; - -import toxi.geom.Vec3D; -import toxi.util.datatypes.UniqueItemIndex; - -public class SpatialIndex extends UniqueItemIndex { - - public float delta, deltaSq; - - public SpatialIndex(float delta) { - setDelta(delta); - } - - private int getClosestIndexed(Vec3D item) { - int c = -1; - float minD = deltaSq; - for (int i = 0, num = index.size(); i < num; i++) { - float d = index.get(i).distanceToSquared(item); - if (d < minD) { - minD = d; - c = i; - } - } - return c; - } - - public float getDelta() { - return delta; - } - - @Override - public int index(Vec3D item) { - int id = getID(item); - if (id == -1) { - id = getClosestIndexed(item); - } - if (id != -1) { - return id; - } else { - return super.index(item); - } - } - - public void setDelta(float delta) { - this.delta = delta; - this.deltaSq = delta * delta; - } -} diff -r 032471906b662e0b1708c69035470dd51d8b66ca -r 599d2a58cdf6a343c6cb54a6206ac25db9b24956 src.newmesh/toxi/newmesh/AttributedEdge.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src.newmesh/toxi/newmesh/AttributedEdge.java Wed Jan 25 10:51:42 2012 +0000 @@ -0,0 +1,65 @@ +package toxi.newmesh; + +import java.util.ArrayList; +import java.util.List; + +public class AttributedEdge { + + public final int a, b; + public List faces; + + public AttributedEdge(int a, int b) { + this.a = a; + this.b = b; + } + + public void addFace(AttributedFace f) { + if (faces == null) { + faces = new ArrayList(2); + } + faces.add(f); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + AttributedEdge other = (AttributedEdge) obj; + if (a != other.a) { + return false; + } + if (b != other.b) { + return false; + } + return true; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = prime + a; + result = prime * result + b; + return result; + } + + public String toString() { + return String.format("a=%d, b=%d", a, b); + } +} diff -r 032471906b662e0b1708c69035470dd51d8b66ca -r 599d2a58cdf6a343c6cb54a6206ac25db9b24956 src.newmesh/toxi/newmesh/AttributedFace.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src.newmesh/toxi/newmesh/AttributedFace.java Wed Jan 25 10:51:42 2012 +0000 @@ -0,0 +1,21 @@ +package toxi.newmesh; + +import java.util.HashMap; + +public class AttributedFace { + + public int a, b, c; + public int normal = -1; + public HashMap attribs; + + public AttributedFace(int a, int b, int c, HashMap attribs) { + this.a = a; + this.b = b; + this.c = c; + this.attribs = attribs; + } + + public String toString() { + return String.format("a=%d,b=%d,c=%d,n=%d", a, b, c, normal); + } +} diff -r 032471906b662e0b1708c69035470dd51d8b66ca -r 599d2a58cdf6a343c6cb54a6206ac25db9b24956 src.newmesh/toxi/newmesh/IndexedTriangleMesh.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src.newmesh/toxi/newmesh/IndexedTriangleMesh.java Wed Jan 25 10:51:42 2012 +0000 @@ -0,0 +1,565 @@ +package toxi.newmesh; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; + +import toxi.geom.AABB; +import toxi.geom.IsectData3D; +import toxi.geom.Ray3D; +import toxi.geom.ReadonlyVec3D; +import toxi.geom.Sphere; +import toxi.geom.Triangle3D; +import toxi.geom.TriangleIntersector; +import toxi.geom.Vec2D; +import toxi.geom.Vec3D; +import toxi.geom.mesh.subdiv.NewSubdivStrategy; +import toxi.util.datatypes.ItemIndex; +import toxi.util.datatypes.UniqueItemIndex; + +public class IndexedTriangleMesh { + + public static final String ATTR_EDGES = "edges"; + public static final String ATTR_FNORMALS = "fnormals"; + public static final String ATTR_UVCOORDS = "uv"; + public static final String ATTR_VCOLORS = "col"; + public static final String ATTR_VERTICES = "vertices"; + public static final String ATTR_VNORMALS = "vnormals"; + + public SpatialIndex vertices = new SpatialIndex(0.001f); + + public ItemIndex fnormals = new UniqueItemIndex(); + + public final ArrayList faces = new ArrayList(); + + public final HashMap> attributes = new HashMap>(); + + public IndexedTriangleMesh() { + } + + public IndexedTriangleMesh addFace(Vec3D a, Vec3D b, Vec3D c, + HashMap attribs) { + int idA = vertices.index(a); + int idB = vertices.index(b); + int idC = vertices.index(c); + if (idA != idB && idA != idC && idB != idC) { + AttributedFace f = new AttributedFace(idA, idB, idC, + addFaceAttributes(null, attribs)); + faces.add(f); + } + return this; + } + + public IndexedTriangleMesh addFace(Vec3D a, Vec3D b, Vec3D c, Vec2D uva, + Vec2D uvb, Vec2D uvc) { + HashMap attribs = null; + if (uva != null && uvb != null && uvc != null) { + attribs = new HashMap(); + attribs.put(ATTR_UVCOORDS, new Object[] { + uva, uvb, uvc + }); + } + return addFace(a, b, c, attribs); + } + + public HashMap addFaceAttribute(AttributedFace f, + String attrib, Object attA, Object attB, Object attC) { + if (f != null && attrib != null && attA != null && attB != null + && attC != null) { + ItemIndex idx = getAttributeIndex(attrib); + f.attribs.put(attrib, new int[] { + idx.index(attA), idx.index(attB), idx.index(attC) + }); + return f.attribs; + } + return null; + } + + public HashMap addFaceAttributes(AttributedFace f, + HashMap attribs) { + HashMap fattribs = null; + if (attribs != null) { + fattribs = (f != null) ? f.attribs : new HashMap( + attribs.size(), 1); + for (String attID : attribs.keySet()) { + Object[] items = attribs.get(attID); + if (items.length >= 3) { + ItemIndex idx = getAttributeIndex(attID); + int[] ids = new int[] { + idx.index(items[0]), idx.index(items[1]), + idx.index(items[2]) + }; + fattribs.put(attID, ids); + } + } + } + return fattribs; + } + + public IndexedTriangleMesh addMesh(IndexedTriangleMesh mesh) { + Vec3D[] v = null; + for (AttributedFace f : mesh.faces) { + v = mesh.getFaceVertices(f, v); + addFace(v[0], v[1], v[2], null); + } + return this; + } + + public IndexedTriangleMesh addMeshWithAttribs(IndexedTriangleMesh mesh) { + HashMap attribs = new HashMap(); + Vec3D[] v = null; + for (AttributedFace f : mesh.faces) { + attribs.clear(); + for (String a : f.attribs.keySet()) { + attribs.put(a, mesh.getFaceAttribValues(f, a)); + } + v = mesh.getFaceVertices(f, v); + addFace(v[0], v[1], v[2], attribs); + } + return this; + } + + public IndexedTriangleMesh clear() { + vertices.clear(); + fnormals.clear(); + attributes.clear(); + faces.clear(); + return this; + } + + public HashMap compile() { + HashSet attribs = new HashSet(); + attribs.add(ATTR_VERTICES); + attribs.add(ATTR_FNORMALS); + return compile(attribs, null); + } + + public HashMap compile(HashSet attribs, + HashMap compilers) { + HashMap mergedComps = new HashMap( + getDefaultCompilers()); + if (compilers != null) { + mergedComps.putAll(compilers); + } + HashMap buffers = new HashMap(); + int numF = faces.size(); + for (String attrib : attribs) { + MeshAttributeCompiler comp = mergedComps.get(attrib); + if (comp != null) { + comp.setMesh(this); + ItemIndex index = comp.getIndex(); + int faceStride = 3 * comp.getStride(); + float[] buf = new float[numF * faceStride]; + int offset = 0; + for (AttributedFace f : faces) { + comp.compileFace(f, index, buf, offset); + offset += faceStride; + } + buffers.put(attrib, buf); + } + } + return buffers; + } + + public List computeEdges() { + ItemIndex edges = getAttributeIndex(ATTR_EDGES); + edges.clear(); + for (AttributedFace f : faces) { + if (f.attribs == null) { + f.attribs = new HashMap(); + } + f.attribs.put(ATTR_EDGES, new int[] { + indexFaceEdge(f, f.a, f.b), indexFaceEdge(f, f.b, f.c), + indexFaceEdge(f, f.c, f.a) + }); + } + return edges.getItems(); + } + + public List computeFaceNormals() { + fnormals.clear(); + Vec3D[] v = null; + for (AttributedFace f : faces) { + v = getFaceVertices(f, v); + f.normal = fnormals.index(v[0].sub(v[1]).crossSelf(v[0].sub(v[2])) + .normalize()); + } + return fnormals.getItems(); + } + + public List computeVertexNormals() { + Vec3D[] vnorms = new Vec3D[vertices.size()]; + for (int i = 0; i < vnorms.length; i++) { + vnorms[i] = new Vec3D(); + } + for (AttributedFace f : faces) { + final Vec3D n = fnormals.forID(f.normal); + vnorms[f.a].addSelf(n); + vnorms[f.b].addSelf(n); + vnorms[f.c].addSelf(n); + } + for (int i = 0; i < vnorms.length; i++) { + vnorms[i].normalize(); + } + ItemIndex idx = getAttributeIndex(ATTR_VNORMALS); + idx.clear(); + for (AttributedFace f : faces) { + if (f.attribs == null) { + f.attribs = new HashMap(); + } + f.attribs.put( + ATTR_VNORMALS, + new int[] { + idx.index(vnorms[f.a]), idx.index(vnorms[f.b]), + idx.index(vnorms[f.c]) + }); + } + return idx.getItems(); + } + + public IndexedTriangleMesh extrudeFace(AttributedFace f, Vec3D offset, + float scale) { + Vec3D[] v = getFaceVertices(f, null); + Vec3D[] v2 = new Vec3D[3]; + Vec3D c = v[0].add(v[1]).addSelf(v[2]).scaleSelf(1 / 3f); + Vec3D n = c.add(offset); + v2[0] = v[0].sub(c).scaleSelf(scale).addSelf(n); + v2[1] = v[1].sub(c).scaleSelf(scale).addSelf(n); + v2[2] = v[2].sub(c).scaleSelf(scale).addSelf(n); + removeFace(f); + // extruded copy + addFace(v2[0], v2[1], v2[2], null); + // sides + addFace(v[0], v[1], v2[0], null); + addFace(v[1], v2[1], v2[0], null); + addFace(v[1], v[2], v2[1], null); + addFace(v[2], v2[2], v2[1], null); + addFace(v[2], v[0], v2[2], null); + addFace(v[0], v2[0], v2[2], null); + return this; + } + + /** + * Flips the current order of all face vertices and attributes. If face or + * vertex normals are present their direction will be inverted as well. + * + * @return itself + */ + public IndexedTriangleMesh flipVertexOrder() { + for (AttributedFace f : faces) { + int t = f.b; + f.b = f.c; + f.c = t; + if (f.attribs != null) { + for (int[] att : f.attribs.values()) { + t = att[1]; + att[1] = att[2]; + att[2] = t; + } + } + } + for (Vec3D n : fnormals.getItems()) { + fnormals.reindex(n, n.getInverted()); + } + ItemIndex vnormals = attributes.get(ATTR_VNORMALS); + if (vnormals != null) { + for (Object n : vnormals.getItems()) { + vnormals.reindex(n, ((Vec3D) n).getInverted()); + } + } + return this; + } + + public ItemIndex getAttributeIndex(String attID) { + UniqueItemIndex idx = attributes.get(attID); + if (idx == null) { + idx = new UniqueItemIndex(); + attributes.put(attID, idx); + } + return idx; + } + + public Sphere getBoundingSphere() { + return getBounds().getBoundingSphere(); + } + + public AABB getBounds() { + return AABB.getBoundingBox(vertices.getItems()); + } + + public Vec3D getCentroid() { + return new Vec3D(getBounds()); + } + + public Vec3D getClosestVertexToPoint(ReadonlyVec3D p) { + Vec3D closest = null; + float minDist = Float.MAX_VALUE; + for (Vec3D v : vertices.getItems()) { + float d = v.distanceToSquared(p); + if (d < minDist) { + closest = v; + minDist = d; + } + } + return closest; + } + + public HashMap getDefaultCompilers() { + HashMap compilers = new HashMap(); + compilers.put(ATTR_VERTICES, new MeshVertexCompiler()); + compilers.put(ATTR_FNORMALS, new MeshFaceNormalCompiler()); + compilers.put(ATTR_VNORMALS, new MeshVertexNormalCompiler()); + compilers.put(ATTR_UVCOORDS, new MeshUVCompiler()); + compilers.put(ATTR_VCOLORS, new MeshVertexColorCompiler()); + return compilers; + } + + /** + * @return the edges + */ + public List getEdges() { + return getAttributeIndex(ATTR_EDGES).getItems(); + } + + public List getEdgesForVertex(Vec3D v) { + List vedges = null; + int id = vertices.getID(v); + if (id != -1) { + vedges = getEdgesForVertexID(id); + } + return vedges; + } + + public List getEdgesForVertexID(int id) { + List vedges = new ArrayList(2); + for (Object o : getEdges()) { + AttributedEdge e = (AttributedEdge) o; + if (e.a == id || e.b == id) { + vedges.add(e); + } + } + return vedges; + } + + public Triangle3D getFaceAsTriangle(AttributedFace f) { + Vec3D[] verts = getFaceVertices(f, null); + return new Triangle3D(verts[0], verts[1], verts[2]); + } + + public HashMap getFaceAttribValues(AttributedFace f, + String... attribs) { + HashMap values = new HashMap( + attribs.length, 1); + for (String a : attribs) { + values.put(a, getFaceAttribValues(f, a)); + } + return values; + } + + public Object[] getFaceAttribValues(AttributedFace f, String att) { + ItemIndex idx = attributes.get(att); + int[] fattribs = f.attribs.get(att); + if (idx == null || fattribs == null) { + return null; + } + return new Object[] { + idx.forID(fattribs[0]), idx.forID(fattribs[1]), + idx.forID(fattribs[2]) + }; + } + + /** + * @return the fnormals + */ + public List getFaceNormals() { + return fnormals.getItems(); + } + + /** + * @return the faces + */ + public List getFaces() { + return faces; + } + + public List getFacesForVertex(Vec3D v) { + List vfaces = null; + int id = vertices.getID(v); + if (id != -1) { + vfaces = new ArrayList(2); + for (AttributedFace f : faces) { + if (f.a == id || f.b == id || f.c == id) { + vfaces.add(f); + } + } + } + return vfaces; + } + + public final Vec3D[] getFaceVertices(AttributedFace f, Vec3D[] verts) { + if (verts != null) { + verts[0] = vertices.forID(f.a); + verts[1] = vertices.forID(f.b); + verts[2] = vertices.forID(f.c); + return verts; + } else { + return new Vec3D[] { + vertices.forID(f.a), vertices.forID(f.b), + vertices.forID(f.c) + }; + } + } + + public List getNeighborsForVertexID(int id, List neighbors) { + List vedges = getEdgesForVertexID(id); + if (vedges.size() > 0) { + if (neighbors == null) { + neighbors = new ArrayList(); + } else { + neighbors.clear(); + } + for (AttributedEdge e : vedges) { + neighbors.add(vertices.forID((e.a == id) ? e.b : e.a)); + } + } else if (neighbors != null) { + neighbors.clear(); + } + return neighbors; + } + + public final int getNumFaces() { + return faces.size(); + } + + public final int getNumVertices() { + return vertices.size(); + } + + public float getVertexDelta() { + return vertices.getDelta(); + } + + /** + * @return the vertices + */ + public List getVertices() { + return vertices.getItems(); + } + + public List getVerticesForIDs(List verts, int... ids) { + if (verts == null) { + verts = new ArrayList(ids.length); + } + for (int id : ids) { + verts.add(vertices.forID(id)); + } + return verts; + } + + protected final int indexFaceEdge(AttributedFace f, int a, int b) { + final AttributedEdge e1 = new AttributedEdge(a, b); + final AttributedEdge e2 = new AttributedEdge(b, a); + ItemIndex edges = getAttributeIndex(ATTR_EDGES); + final int id1 = edges.getID(e1); + final int id2 = edges.getID(e2); + if (id1 != -1) { + ((AttributedEdge) edges.forID(id1)).addFace(f); + return id1; + } else if (id2 != -1) { + ((AttributedEdge) edges.forID(id2)).addFace(f); + return id2; + } else { + e1.addFace(f); + return edges.index(e1); + } + } + + public IsectData3D intersectsRay(Ray3D ray) { + TriangleIntersector intersector = new TriangleIntersector(); + Triangle3D tri = intersector.getTriangle(); + Vec3D[] v = null; + for (AttributedFace f : faces) { + v = getFaceVertices(f, v); + tri.set(v[0], v[1], v[2]); + if (intersector.intersectsRay(ray)) { + return intersector.getIntersectionData(); + } + } + return null; + } + + public void rebuildVertexIndex() { + SpatialIndex newVerts = new SpatialIndex(vertices.getDelta()); + Vec3D[] v = null; + for (AttributedFace f : faces) { + v = getFaceVertices(f, v); + f.a = newVerts.index(v[0]); + f.b = newVerts.index(v[1]); + f.c = newVerts.index(v[2]); + } + vertices = newVerts; + } + + public IndexedTriangleMesh removeFace(AttributedFace f) { + faces.remove(f); + return this; + } + + public IndexedTriangleMesh setVertexDelta(float delta) { + vertices.setDelta(delta); + return this; + } + + public IndexedTriangleMesh smooth() { + HashMap lapIndex = new HashMap(); + List neighbors = null; + for (int i = 0, numV = getNumVertices(); i < numV; i++) { + neighbors = getNeighborsForVertexID(i, neighbors); + if (neighbors != null && neighbors.size() > 0) { + Vec3D l = new Vec3D(); + for (Vec3D n : neighbors) { + l.addSelf(n); + } + l.scaleSelf(1f / neighbors.size()); + lapIndex.put(i, l); + } + } + SpatialIndex newVerts = new SpatialIndex(vertices.getDelta()); + for (Iterator i = faces.iterator(); i.hasNext();) { + AttributedFace f = i.next(); + f.a = newVerts.index(lapIndex.get(f.a)); + f.b = newVerts.index(lapIndex.get(f.b)); + f.c = newVerts.index(lapIndex.get(f.c)); + if (f.a == f.b || f.a == f.c || f.b == f.c) { + i.remove(); + } + } + vertices = newVerts; + computeEdges(); + return this; + } + + public IndexedTriangleMesh subdivide(NewSubdivStrategy strategy) { + Vec3D[] v = null; + List splitFaces = new ArrayList(); + for (AttributedFace f : new ArrayList(faces)) { + removeFace(f); + v = getFaceVertices(f, v); + for (Vec3D[] fverts : strategy.subdivideTriangle(v[0], v[1], v[2], + splitFaces)) { + addFace(fverts[0], fverts[1], fverts[2], null); + } + splitFaces.clear(); + } + rebuildVertexIndex(); + return this; + } + + @Override + public String toString() { + return String.format("vertices: %d, faces: %d", getNumVertices(), + getNumFaces()); + } +} diff -r 032471906b662e0b1708c69035470dd51d8b66ca -r 599d2a58cdf6a343c6cb54a6206ac25db9b24956 src.newmesh/toxi/newmesh/MeshAttributeCompiler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src.newmesh/toxi/newmesh/MeshAttributeCompiler.java Wed Jan 25 10:51:42 2012 +0000 @@ -0,0 +1,19 @@ +package toxi.newmesh; + +import toxi.util.datatypes.ItemIndex; + +public abstract class MeshAttributeCompiler { + + protected IndexedTriangleMesh mesh; + + public abstract void compileFace(AttributedFace f, ItemIndex index, + float[] buf, int offset); + + public abstract ItemIndex getIndex(); + + public abstract int getStride(); + + public void setMesh(IndexedTriangleMesh mesh) { + this.mesh = mesh; + } +} diff -r 032471906b662e0b1708c69035470dd51d8b66ca -r 599d2a58cdf6a343c6cb54a6206ac25db9b24956 src.newmesh/toxi/newmesh/MeshFaceNormalCompiler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src.newmesh/toxi/newmesh/MeshFaceNormalCompiler.java Wed Jan 25 10:51:42 2012 +0000 @@ -0,0 +1,33 @@ +package toxi.newmesh; + +import toxi.geom.Vec3D; +import toxi.util.datatypes.ItemIndex; + +public class MeshFaceNormalCompiler extends MeshAttributeCompiler { + + @Override + public void compileFace(AttributedFace f, ItemIndex index, float[] buf, + int offset) { + Vec3D v = (Vec3D) index.forID(f.normal); + buf[offset++] = v.x; + buf[offset++] = v.y; + buf[offset++] = v.z; + buf[offset++] = v.x; + buf[offset++] = v.y; + buf[offset++] = v.z; + buf[offset++] = v.x; + buf[offset++] = v.y; + buf[offset++] = v.z; + } + + @Override + public ItemIndex getIndex() { + return mesh.fnormals; + } + + @Override + public int getStride() { + return 3; + } + +} diff -r 032471906b662e0b1708c69035470dd51d8b66ca -r 599d2a58cdf6a343c6cb54a6206ac25db9b24956 src.newmesh/toxi/newmesh/MeshUVCompiler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src.newmesh/toxi/newmesh/MeshUVCompiler.java Wed Jan 25 10:51:42 2012 +0000 @@ -0,0 +1,33 @@ +package toxi.newmesh; + +import toxi.geom.Vec2D; +import toxi.util.datatypes.ItemIndex; + +public class MeshUVCompiler extends MeshAttributeCompiler { + + @Override + public void compileFace(AttributedFace f, ItemIndex index, float[] buf, + int offset) { + int[] vn = f.attribs.get(IndexedTriangleMesh.ATTR_UVCOORDS); + Vec2D v = (Vec2D) index.forID(vn[0]); + buf[offset++] = v.x; + buf[offset++] = v.y; + v = (Vec2D) index.forID(vn[1]); + buf[offset++] = v.x; + buf[offset++] = v.y; + v = (Vec2D) index.forID(vn[2]); + buf[offset++] = v.x; + buf[offset++] = v.y; + } + + @Override + public ItemIndex getIndex() { + return mesh.attributes.get(IndexedTriangleMesh.ATTR_UVCOORDS); + } + + @Override + public int getStride() { + return 2; + } + +} diff -r 032471906b662e0b1708c69035470dd51d8b66ca -r 599d2a58cdf6a343c6cb54a6206ac25db9b24956 src.newmesh/toxi/newmesh/MeshVertexColorCompiler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src.newmesh/toxi/newmesh/MeshVertexColorCompiler.java Wed Jan 25 10:51:42 2012 +0000 @@ -0,0 +1,30 @@ +package toxi.newmesh; + +import toxi.color.ReadonlyTColor; +import toxi.util.datatypes.ItemIndex; + +public class MeshVertexColorCompiler extends MeshAttributeCompiler { + + @Override + public void compileFace(AttributedFace f, ItemIndex index, float[] buf, + int offset) { + int[] vn = f.attribs.get(IndexedTriangleMesh.ATTR_VCOLORS); + ReadonlyTColor c = (ReadonlyTColor) index.forID(vn[0]); + c.toRGBAArray(buf, offset); + c = (ReadonlyTColor) index.forID(vn[1]); + c.toRGBAArray(buf, offset + 4); + c = (ReadonlyTColor) index.forID(vn[2]); + c.toRGBAArray(buf, offset + 8); + } + + @Override + public ItemIndex getIndex() { + return mesh.attributes.get(IndexedTriangleMesh.ATTR_VCOLORS); + } + + @Override + public int getStride() { + return 4; + } + +} diff -r 032471906b662e0b1708c69035470dd51d8b66ca -r 599d2a58cdf6a343c6cb54a6206ac25db9b24956 src.newmesh/toxi/newmesh/MeshVertexCompiler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src.newmesh/toxi/newmesh/MeshVertexCompiler.java Wed Jan 25 10:51:42 2012 +0000 @@ -0,0 +1,35 @@ +package toxi.newmesh; + +import toxi.geom.Vec3D; +import toxi.util.datatypes.ItemIndex; + +public class MeshVertexCompiler extends MeshAttributeCompiler { + + @Override + public void compileFace(AttributedFace f, ItemIndex index, float[] buf, + int offset) { + Vec3D v = (Vec3D) index.forID(f.a); + buf[offset++] = v.x; + buf[offset++] = v.y; + buf[offset++] = v.z; + v = (Vec3D) index.forID(f.b); + buf[offset++] = v.x; + buf[offset++] = v.y; + buf[offset++] = v.z; + v = (Vec3D) index.forID(f.c); + buf[offset++] = v.x; + buf[offset++] = v.y; + buf[offset++] = v.z; + } + + @Override + public ItemIndex getIndex() { + return mesh.vertices; + } + + @Override + public int getStride() { + return 3; + } + +} diff -r 032471906b662e0b1708c69035470dd51d8b66ca -r 599d2a58cdf6a343c6cb54a6206ac25db9b24956 src.newmesh/toxi/newmesh/MeshVertexNormalCompiler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src.newmesh/toxi/newmesh/MeshVertexNormalCompiler.java Wed Jan 25 10:51:42 2012 +0000 @@ -0,0 +1,36 @@ +package toxi.newmesh; + +import toxi.geom.Vec3D; +import toxi.util.datatypes.ItemIndex; + +public class MeshVertexNormalCompiler extends MeshAttributeCompiler { + + @Override + public void compileFace(AttributedFace f, ItemIndex index, float[] buf, + int offset) { + int[] vn = f.attribs.get(IndexedTriangleMesh.ATTR_VNORMALS); + Vec3D v = (Vec3D) index.forID(vn[0]); + buf[offset++] = v.x; + buf[offset++] = v.y; + buf[offset++] = v.z; + v = (Vec3D) index.forID(vn[1]); + buf[offset++] = v.x; + buf[offset++] = v.y; + buf[offset++] = v.z; + v = (Vec3D) index.forID(vn[2]); + buf[offset++] = v.x; + buf[offset++] = v.y; + buf[offset++] = v.z; + } + + @Override + public ItemIndex getIndex() { + return mesh.attributes.get(IndexedTriangleMesh.ATTR_VNORMALS); + } + + @Override + public int getStride() { + return 3; + } + +} diff -r 032471906b662e0b1708c69035470dd51d8b66ca -r 599d2a58cdf6a343c6cb54a6206ac25db9b24956 src.newmesh/toxi/newmesh/SpatialIndex.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src.newmesh/toxi/newmesh/SpatialIndex.java Wed Jan 25 10:51:42 2012 +0000 @@ -0,0 +1,48 @@ +package toxi.newmesh; + +import toxi.geom.Vec3D; +import toxi.util.datatypes.UniqueItemIndex; + +public class SpatialIndex extends UniqueItemIndex { + + public float delta, deltaSq; + + public SpatialIndex(float delta) { + setDelta(delta); + } + + private int getClosestIndexed(Vec3D item) { + int c = -1; + float minD = deltaSq; + for (int i = 0, num = index.size(); i < num; i++) { + float d = index.get(i).distanceToSquared(item); + if (d < minD) { + minD = d; + c = i; + } + } + return c; + } + + public float getDelta() { + return delta; + } + + @Override + public int index(Vec3D item) { + int id = getID(item); + if (id == -1) { + id = getClosestIndexed(item); + } + if (id != -1) { + return id; + } else { + return super.index(item); + } + } + + public void setDelta(float delta) { + this.delta = delta; + this.deltaSq = delta * delta; + } +}