• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * To change this template, choose Tools | Templates
3  * and open the template in the editor.
4  */
5 
6 package com.jme3.bullet.collision.shapes;
7 
8 import com.bulletphysics.dom.HeightfieldTerrainShape;
9 import com.jme3.bullet.util.Converter;
10 import com.jme3.export.InputCapsule;
11 import com.jme3.export.JmeExporter;
12 import com.jme3.export.JmeImporter;
13 import com.jme3.export.OutputCapsule;
14 import com.jme3.math.FastMath;
15 import com.jme3.math.Vector3f;
16 import com.jme3.scene.Mesh;
17 import java.io.IOException;
18 
19 /**
20  * Uses Bullet Physics Heightfield terrain collision system. This is MUCH faster
21  * than using a regular mesh.
22  * There are a couple tricks though:
23  *	-No rotation or translation is supported.
24  *	-The collision bbox must be centered around 0,0,0 with the height above and below the y-axis being
25  *	equal on either side. If not, the whole collision box is shifted vertically and things don't collide
26  *	as they should.
27  *
28  * @author Brent Owens
29  */
30 public class HeightfieldCollisionShape extends CollisionShape {
31 
32 	//protected HeightfieldTerrainShape heightfieldShape;
33 	protected int heightStickWidth;
34 	protected int heightStickLength;
35 	protected float[] heightfieldData;
36 	protected float heightScale;
37 	protected float minHeight;
38 	protected float maxHeight;
39 	protected int upAxis;
40 	protected boolean flipQuadEdges;
41 
HeightfieldCollisionShape()42 	public HeightfieldCollisionShape() {
43 
44 	}
45 
HeightfieldCollisionShape(float[] heightmap)46 	public HeightfieldCollisionShape(float[] heightmap) {
47 		createCollisionHeightfield(heightmap, Vector3f.UNIT_XYZ);
48 	}
49 
HeightfieldCollisionShape(float[] heightmap, Vector3f scale)50 	public HeightfieldCollisionShape(float[] heightmap, Vector3f scale) {
51 		createCollisionHeightfield(heightmap, scale);
52 	}
53 
createCollisionHeightfield(float[] heightmap, Vector3f worldScale)54 	protected void createCollisionHeightfield(float[] heightmap, Vector3f worldScale) {
55 		this.scale = worldScale;
56 		this.heightScale = 1;//don't change away from 1, we use worldScale instead to scale
57 
58 		this.heightfieldData = heightmap;
59 
60 		float min = heightfieldData[0];
61 		float max = heightfieldData[0];
62 		// calculate min and max height
63 		for (int i=0; i<heightfieldData.length; i++) {
64 			if (heightfieldData[i] < min)
65 				min = heightfieldData[i];
66 			if (heightfieldData[i] > max)
67 				max = heightfieldData[i];
68 		}
69 		// we need to center the terrain collision box at 0,0,0 for BulletPhysics. And to do that we need to set the
70 		// min and max height to be equal on either side of the y axis, otherwise it gets shifted and collision is incorrect.
71 		if (max < 0)
72 			max = -min;
73 		else {
74 			if (Math.abs(max) > Math.abs(min))
75 				min = -max;
76 			else
77 				max = -min;
78 		}
79 		this.minHeight = min;
80 		this.maxHeight = max;
81 
82 		this.upAxis = HeightfieldTerrainShape.YAXIS;
83 		this.flipQuadEdges = false;
84 
85 		heightStickWidth = (int) FastMath.sqrt(heightfieldData.length);
86 		heightStickLength = heightStickWidth;
87 
88 
89 		createShape();
90 	}
91 
createShape()92 	protected void createShape() {
93 
94 		HeightfieldTerrainShape shape = new HeightfieldTerrainShape(heightStickWidth, heightStickLength, heightfieldData, heightScale, minHeight, maxHeight, upAxis, flipQuadEdges);
95 		shape.setLocalScaling(new javax.vecmath.Vector3f(scale.x, scale.y, scale.z));
96 		cShape = shape;
97 		cShape.setLocalScaling(Converter.convert(getScale()));
98                 cShape.setMargin(margin);
99 	}
100 
createJmeMesh()101 	public Mesh createJmeMesh(){
102         //TODO return Converter.convert(bulletMesh);
103 		return null;
104     }
105 
write(JmeExporter ex)106     public void write(JmeExporter ex) throws IOException {
107         super.write(ex);
108         OutputCapsule capsule = ex.getCapsule(this);
109         capsule.write(heightStickWidth, "heightStickWidth", 0);
110         capsule.write(heightStickLength, "heightStickLength", 0);
111         capsule.write(heightScale, "heightScale", 0);
112         capsule.write(minHeight, "minHeight", 0);
113         capsule.write(maxHeight, "maxHeight", 0);
114         capsule.write(upAxis, "upAxis", 1);
115         capsule.write(heightfieldData, "heightfieldData", new float[0]);
116         capsule.write(flipQuadEdges, "flipQuadEdges", false);
117     }
118 
read(JmeImporter im)119     public void read(JmeImporter im) throws IOException {
120         super.read(im);
121         InputCapsule capsule = im.getCapsule(this);
122         heightStickWidth = capsule.readInt("heightStickWidth", 0);
123         heightStickLength = capsule.readInt("heightStickLength", 0);
124         heightScale = capsule.readFloat("heightScale", 0);
125         minHeight = capsule.readFloat("minHeight", 0);
126         maxHeight = capsule.readFloat("maxHeight", 0);
127         upAxis = capsule.readInt("upAxis", 1);
128         heightfieldData = capsule.readFloatArray("heightfieldData", new float[0]);
129         flipQuadEdges = capsule.readBoolean("flipQuadEdges", false);
130         createShape();
131     }
132 
133 }
134