Home | History | Annotate | Download | only in util
      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