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; } }
@Override public void updateGeometricState() { if ((refreshFlags & RF_LIGHTLIST) != 0) { updateWorldLightList(); } if ((refreshFlags & RF_TRANSFORM) != 0) { // combine with parent transforms- same for all spatial // subclasses. updateWorldTransforms(); } if (!children.isEmpty()) { // the important part- make sure child geometric state is refreshed // first before updating own world bound. This saves // a round-trip later on. // NOTE 9/19/09 // Although it does save a round trip, for (Spatial child : children.getArray()) { child.updateGeometricState(); } for (Batch batch : batches.getArray()) { if (batch.needMeshUpdate) { batch.geometry.updateModelBound(); batch.geometry.updateWorldBound(); batch.needMeshUpdate = false; } } } if ((refreshFlags & RF_BOUND) != 0) { updateWorldBound(); } assert refreshFlags == 0; }
protected void doBatch() { Map<Material, List<Geometry>> matMap = new HashMap<Material, List<Geometry>>(); int nbGeoms = 0; gatherGeomerties(matMap, this, needsFullRebatch); if (needsFullRebatch) { for (Batch batch : batches.getArray()) { batch.geometry.removeFromParent(); } batches.clear(); batchesByGeom.clear(); } // only reset maxVertCount if there is something new to batch if (matMap.size() > 0) { maxVertCount = 0; } for (Map.Entry<Material, List<Geometry>> entry : matMap.entrySet()) { Mesh m = new Mesh(); Material material = entry.getKey(); List<Geometry> list = entry.getValue(); nbGeoms += list.size(); String batchName = name + "-batch" + batches.size(); Batch batch; if (!needsFullRebatch) { batch = findBatchByMaterial(material); if (batch != null) { list.add(0, batch.geometry); batchName = batch.geometry.getName(); batch.geometry.removeFromParent(); } else { batch = new Batch(); } } else { batch = new Batch(); } mergeGeometries(m, list); m.setDynamic(); batch.updateGeomList(list); batch.geometry = new Geometry(batchName); batch.geometry.setMaterial(material); this.attachChild(batch.geometry); batch.geometry.setMesh(m); batch.geometry.getMesh().updateCounts(); batch.geometry.getMesh().updateBound(); batches.add(batch); } if (batches.size() > 0) { needsFullRebatch = false; } logger.log( Level.FINE, "Batched {0} geometries in {1} batches.", new Object[] {nbGeoms, batches.size()}); // init the temp arrays if something has been batched only. if (matMap.size() > 0) { // TODO these arrays should be allocated by chunk instead to avoid recreating them each time // the batch is changed. // init temp float arrays tmpFloat = new float[maxVertCount * 3]; tmpFloatN = new float[maxVertCount * 3]; if (useTangents) { tmpFloatT = new float[maxVertCount * 4]; } } }