protected void updateSubBatch(Geometry bg) { Batch batch = batchesByGeom.get(bg); if (batch != null) { Mesh mesh = batch.geometry.getMesh(); Mesh origMesh = bg.getMesh(); VertexBuffer pvb = mesh.getBuffer(VertexBuffer.Type.Position); FloatBuffer posBuf = (FloatBuffer) pvb.getData(); VertexBuffer nvb = mesh.getBuffer(VertexBuffer.Type.Normal); FloatBuffer normBuf = (FloatBuffer) nvb.getData(); VertexBuffer opvb = origMesh.getBuffer(VertexBuffer.Type.Position); FloatBuffer oposBuf = (FloatBuffer) opvb.getData(); VertexBuffer onvb = origMesh.getBuffer(VertexBuffer.Type.Normal); FloatBuffer onormBuf = (FloatBuffer) onvb.getData(); Matrix4f transformMat = getTransformMatrix(bg); if (mesh.getBuffer(VertexBuffer.Type.Tangent) != null) { VertexBuffer tvb = mesh.getBuffer(VertexBuffer.Type.Tangent); FloatBuffer tanBuf = (FloatBuffer) tvb.getData(); VertexBuffer otvb = origMesh.getBuffer(VertexBuffer.Type.Tangent); FloatBuffer otanBuf = (FloatBuffer) otvb.getData(); doTransformsTangents( oposBuf, onormBuf, otanBuf, posBuf, normBuf, tanBuf, bg.startIndex, bg.startIndex + bg.getVertexCount(), transformMat); tvb.updateData(tanBuf); } else { doTransforms( oposBuf, onormBuf, posBuf, normBuf, bg.startIndex, bg.startIndex + bg.getVertexCount(), transformMat); } pvb.updateData(posBuf); nvb.updateData(normBuf); batch.needMeshUpdate = true; } }
private Mesh[] findTargets(Node node) { Mesh sharedMesh = null; ArrayList<Mesh> animatedMeshes = new ArrayList<Mesh>(); for (Spatial child : node.getChildren()) { if (!(child instanceof Geometry)) { continue; // could be an attachment node, ignore. } Geometry geom = (Geometry) child; // is this geometry using a shared mesh? Mesh childSharedMesh = geom.getUserData(UserData.JME_SHAREDMESH); if (childSharedMesh != null) { // Don't bother with non-animated shared meshes if (isMeshAnimated(childSharedMesh)) { // child is using shared mesh, // so animate the shared mesh but ignore child if (sharedMesh == null) { sharedMesh = childSharedMesh; } else if (sharedMesh != childSharedMesh) { throw new IllegalStateException("Two conflicting shared meshes for " + node); } } } else { Mesh mesh = geom.getMesh(); if (isMeshAnimated(mesh)) { animatedMeshes.add(mesh); } } } if (sharedMesh != null) { animatedMeshes.add(sharedMesh); } return animatedMeshes.toArray(new Mesh[animatedMeshes.size()]); }
/** * Merges all geometries in the collection into the output mesh. Does not take into account * materials. * * @param geometries * @param outMesh */ private void mergeGeometries(Mesh outMesh, List<Geometry> geometries) { int[] compsForBuf = new int[VertexBuffer.Type.values().length]; VertexBuffer.Format[] formatForBuf = new VertexBuffer.Format[compsForBuf.length]; int totalVerts = 0; int totalTris = 0; int totalLodLevels = 0; int maxWeights = -1; Mesh.Mode mode = null; for (Geometry geom : geometries) { totalVerts += geom.getVertexCount(); totalTris += geom.getTriangleCount(); totalLodLevels = Math.min(totalLodLevels, geom.getMesh().getNumLodLevels()); if (maxVertCount < geom.getVertexCount()) { maxVertCount = geom.getVertexCount(); } Mesh.Mode listMode; int components; switch (geom.getMesh().getMode()) { case Points: listMode = Mesh.Mode.Points; components = 1; break; case LineLoop: case LineStrip: case Lines: listMode = Mesh.Mode.Lines; components = 2; break; case TriangleFan: case TriangleStrip: case Triangles: listMode = Mesh.Mode.Triangles; components = 3; break; default: throw new UnsupportedOperationException(); } for (VertexBuffer vb : geom.getMesh().getBufferList().getArray()) { compsForBuf[vb.getBufferType().ordinal()] = vb.getNumComponents(); formatForBuf[vb.getBufferType().ordinal()] = vb.getFormat(); } maxWeights = Math.max(maxWeights, geom.getMesh().getMaxNumWeights()); if (mode != null && mode != listMode) { throw new UnsupportedOperationException( "Cannot combine different" + " primitive types: " + mode + " != " + listMode); } mode = listMode; compsForBuf[VertexBuffer.Type.Index.ordinal()] = components; } outMesh.setMaxNumWeights(maxWeights); outMesh.setMode(mode); if (totalVerts >= 65536) { // make sure we create an UnsignedInt buffer so // we can fit all of the meshes formatForBuf[VertexBuffer.Type.Index.ordinal()] = VertexBuffer.Format.UnsignedInt; } else { formatForBuf[VertexBuffer.Type.Index.ordinal()] = VertexBuffer.Format.UnsignedShort; } // generate output buffers based on retrieved info for (int i = 0; i < compsForBuf.length; i++) { if (compsForBuf[i] == 0) { continue; } Buffer data; if (i == VertexBuffer.Type.Index.ordinal()) { data = VertexBuffer.createBuffer(formatForBuf[i], compsForBuf[i], totalTris); } else { data = VertexBuffer.createBuffer(formatForBuf[i], compsForBuf[i], totalVerts); } VertexBuffer vb = new VertexBuffer(VertexBuffer.Type.values()[i]); vb.setupData(VertexBuffer.Usage.Dynamic, compsForBuf[i], formatForBuf[i], data); outMesh.setBuffer(vb); } int globalVertIndex = 0; int globalTriIndex = 0; for (Geometry geom : geometries) { Mesh inMesh = geom.getMesh(); if (!isBatch(geom)) { geom.batch(this, globalVertIndex); } int geomVertCount = inMesh.getVertexCount(); int geomTriCount = inMesh.getTriangleCount(); for (int bufType = 0; bufType < compsForBuf.length; bufType++) { VertexBuffer inBuf = inMesh.getBuffer(VertexBuffer.Type.values()[bufType]); VertexBuffer outBuf = outMesh.getBuffer(VertexBuffer.Type.values()[bufType]); if (outBuf == null) { continue; } if (VertexBuffer.Type.Index.ordinal() == bufType) { int components = compsForBuf[bufType]; IndexBuffer inIdx = inMesh.getIndicesAsList(); IndexBuffer outIdx = outMesh.getIndexBuffer(); for (int tri = 0; tri < geomTriCount; tri++) { for (int comp = 0; comp < components; comp++) { int idx = inIdx.get(tri * components + comp) + globalVertIndex; outIdx.put((globalTriIndex + tri) * components + comp, idx); } } } else if (VertexBuffer.Type.Position.ordinal() == bufType) { FloatBuffer inPos = (FloatBuffer) inBuf.getData(); FloatBuffer outPos = (FloatBuffer) outBuf.getData(); doCopyBuffer(inPos, globalVertIndex, outPos, 3); } else if (VertexBuffer.Type.Normal.ordinal() == bufType || VertexBuffer.Type.Tangent.ordinal() == bufType) { FloatBuffer inPos = (FloatBuffer) inBuf.getData(); FloatBuffer outPos = (FloatBuffer) outBuf.getData(); doCopyBuffer(inPos, globalVertIndex, outPos, compsForBuf[bufType]); if (VertexBuffer.Type.Tangent.ordinal() == bufType) { useTangents = true; } } else { inBuf.copyElements(0, outBuf, globalVertIndex, geomVertCount); // for (int vert = 0; vert < geomVertCount; vert++) { // int curGlobalVertIndex = globalVertIndex + vert; // inBuf.copyElement(vert, outBuf, curGlobalVertIndex); // } } } globalVertIndex += geomVertCount; globalTriIndex += geomTriCount; } }