159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.terrain.geomipmap.lodcalc.util; 259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bounding.BoundingBox; 459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.collision.CollisionResults; 559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Matrix4f; 659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Ray; 759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Vector3f; 859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Mesh; 959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.VertexBuffer; 1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.VertexBuffer.Type; 1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.BufferUtils; 1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.nio.FloatBuffer; 1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.nio.IntBuffer; 1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/** 1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Computes the entropy value δ (delta) for a given terrain block and 1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * LOD level. 1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * See the geomipmapping paper section 1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * "2.3.1 Choosing the appropriate GeoMipMap level" 2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Kirill Vainer 2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class EntropyComputeUtil { 2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public static float computeLodEntropy(Mesh terrainBlock, IntBuffer lodIndices){ 2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Bounding box for the terrain block 2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta BoundingBox bbox = (BoundingBox) terrainBlock.getBound(); 2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Vertex positions for the block 3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta FloatBuffer positions = terrainBlock.getFloatBuffer(Type.Position); 3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Prepare to cast rays 3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f pos = new Vector3f(); 3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f dir = new Vector3f(0, -1, 0); 3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Ray ray = new Ray(pos, dir); 3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Prepare collision results 3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta CollisionResults results = new CollisionResults(); 3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Set the LOD indices on the block 4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta VertexBuffer originalIndices = terrainBlock.getBuffer(Type.Index); 4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta terrainBlock.clearBuffer(Type.Index); 4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta terrainBlock.setBuffer(Type.Index, 3, lodIndices); 4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Recalculate collision mesh 4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta terrainBlock.createCollisionData(); 4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float entropy = 0; 5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < positions.capacity() / 3; i++){ 5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta BufferUtils.populateFromBuffer(pos, positions, i); 5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float realHeight = pos.y; 5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta pos.addLocal(0, bbox.getYExtent(), 0); 5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ray.setOrigin(pos); 5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta results.clear(); 5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta terrainBlock.collideWith(ray, Matrix4f.IDENTITY, bbox, results); 6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (results.size() > 0){ 6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f contactPoint = results.getClosestCollision().getContactPoint(); 6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float delta = Math.abs(realHeight - contactPoint.y); 6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta entropy = Math.max(delta, entropy); 6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Restore original indices 6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta terrainBlock.clearBuffer(Type.Index); 7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta terrainBlock.setBuffer(originalIndices); 7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return entropy; 7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 76