• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
computeLodEntropy(Mesh terrainBlock, IntBuffer lodIndices)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