1 package com.jme3.terrain.geomipmap.lodcalc.util; 2 3 import com.jme3.bounding.BoundingBox; 4 import com.jme3.collision.CollisionResults; 5 import com.jme3.math.Matrix4f; 6 import com.jme3.math.Ray; 7 import com.jme3.math.Vector3f; 8 import com.jme3.scene.Mesh; 9 import com.jme3.scene.VertexBuffer; 10 import com.jme3.scene.VertexBuffer.Type; 11 import com.jme3.util.BufferUtils; 12 import java.nio.FloatBuffer; 13 import java.nio.IntBuffer; 14 15 /** 16 * Computes the entropy value (delta) for a given terrain block and 17 * LOD level. 18 * See the geomipmapping paper section 19 * "2.3.1 Choosing the appropriate GeoMipMap level" 20 * 21 * @author Kirill Vainer 22 */ 23 public class EntropyComputeUtil { 24 25 public static float computeLodEntropy(Mesh terrainBlock, IntBuffer lodIndices){ 26 // Bounding box for the terrain block 27 BoundingBox bbox = (BoundingBox) terrainBlock.getBound(); 28 29 // Vertex positions for the block 30 FloatBuffer positions = terrainBlock.getFloatBuffer(Type.Position); 31 32 // Prepare to cast rays 33 Vector3f pos = new Vector3f(); 34 Vector3f dir = new Vector3f(0, -1, 0); 35 Ray ray = new Ray(pos, dir); 36 37 // Prepare collision results 38 CollisionResults results = new CollisionResults(); 39 40 // Set the LOD indices on the block 41 VertexBuffer originalIndices = terrainBlock.getBuffer(Type.Index); 42 43 terrainBlock.clearBuffer(Type.Index); 44 terrainBlock.setBuffer(Type.Index, 3, lodIndices); 45 46 // Recalculate collision mesh 47 terrainBlock.createCollisionData(); 48 49 float entropy = 0; 50 for (int i = 0; i < positions.capacity() / 3; i++){ 51 BufferUtils.populateFromBuffer(pos, positions, i); 52 53 float realHeight = pos.y; 54 55 pos.addLocal(0, bbox.getYExtent(), 0); 56 ray.setOrigin(pos); 57 58 results.clear(); 59 terrainBlock.collideWith(ray, Matrix4f.IDENTITY, bbox, results); 60 61 if (results.size() > 0){ 62 Vector3f contactPoint = results.getClosestCollision().getContactPoint(); 63 float delta = Math.abs(realHeight - contactPoint.y); 64 entropy = Math.max(delta, entropy); 65 } 66 } 67 68 // Restore original indices 69 terrainBlock.clearBuffer(Type.Index); 70 terrainBlock.setBuffer(originalIndices); 71 72 return entropy; 73 } 74 75 } 76