aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/ModifiedBulletX/ModifiedBulletX/Collision/CollisionShapes/HeightfieldTerrainShape.cs
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/ModifiedBulletX/ModifiedBulletX/Collision/CollisionShapes/HeightfieldTerrainShape.cs')
-rw-r--r--libraries/ModifiedBulletX/ModifiedBulletX/Collision/CollisionShapes/HeightfieldTerrainShape.cs360
1 files changed, 360 insertions, 0 deletions
diff --git a/libraries/ModifiedBulletX/ModifiedBulletX/Collision/CollisionShapes/HeightfieldTerrainShape.cs b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/CollisionShapes/HeightfieldTerrainShape.cs
new file mode 100644
index 0000000..0f30f1f
--- /dev/null
+++ b/libraries/ModifiedBulletX/ModifiedBulletX/Collision/CollisionShapes/HeightfieldTerrainShape.cs
@@ -0,0 +1,360 @@
1/*
2 * WARNING!: this class is not in the original BulletX
3 * By the way it's based on the Bullet btHeightfieldTerrainShape:
4 * http://www.continuousphysics.com/Bullet/BulletFull/classbtHeightfieldTerrainShape.html
5 *****************************************************************************************
6 * 3RD PARTY LICENSE. The next it's the original 3rd party lincense of Bullet:
7 * ----------------------------------------------------------------------------
8Bullet Continuous Collision Detection and Physics Library
9Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
10
11This software is provided 'as-is', without any express or implied warranty.
12In no event will the authors be held liable for any damages arising from the use of this software.
13Permission is granted to anyone to use this software for any purpose,
14including commercial applications, and to alter it and redistribute it freely,
15subject to the following restrictions:
16
171. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
182. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
193. This notice may not be removed or altered from any source distribution.
20 * ------------------------------------------------------------------------------
21*/
22using System;
23using System.Collections.Generic;
24using System.Text;
25using MonoXnaCompactMaths;
26
27namespace XnaDevRu.BulletX
28{
29 public class HeightfieldTerrainShape : ConcaveShape
30 {
31 private Vector3 _localAabbMin;
32 private Vector3 _localAabbMax;
33 private Vector3 _localScaling = new Vector3(1f,1f,1f);
34 private int _width;
35 private int _length;
36 private float[] _heightfieldData;
37 private float _maxHeight;
38 private int _upAxis;
39 private bool _useFloatData;
40 private bool _flipQuadEdges;
41 private bool _useDiamondSubdivision = false;
42 private float _defaultCollisionMargin = 0.6f;
43
44 public HeightfieldTerrainShape(int width, int length, float[] heightfieldData, float maxHeight,
45 int upAxis, bool useFloatData, bool flipQuadEdges)
46 {
47 _width = width;
48 _length = length;
49 _heightfieldData = heightfieldData;
50 _maxHeight = maxHeight;
51 _upAxis = upAxis;
52 _useFloatData = useFloatData;
53 _flipQuadEdges = flipQuadEdges;
54 this.Margin = _defaultCollisionMargin;
55
56 float quantizationMargin = 1f;
57
58 //enlarge the AABB to avoid division by zero when initializing the quantization value
59 Vector3 clampValue = new Vector3(quantizationMargin, quantizationMargin, quantizationMargin);
60 Vector3 halfExtents = new Vector3(0, 0, 0);
61
62 switch (_upAxis)
63 {
64 case 0:
65 halfExtents.X = _maxHeight;
66 halfExtents.Y = _width;
67 halfExtents.Z = _length;
68 break;
69 case 1:
70 halfExtents.X = _width;
71 halfExtents.Y = _maxHeight;
72 halfExtents.Z = _length;
73 break;
74 case 2:
75 halfExtents.X = _width;
76 halfExtents.Y = _length;
77 halfExtents.Z = _maxHeight;
78 break;
79 default:
80 //need to get valid _upAxis
81 //btAssert(0);
82 throw new Exception("HeightfieldTerrainShape: need to get valid _upAxis");
83 }
84
85 halfExtents *= 0.5f;
86
87 _localAabbMin = -halfExtents - clampValue;
88 _localAabbMax = halfExtents + clampValue;
89 //Vector3 aabbSize = new Vector3();
90 //aabbSize = m_localAabbMax - m_localAabbMin;
91
92 }
93
94 protected Vector3 LocalAabbMin
95 { get { return _localAabbMin; } set { _localAabbMin = value; } }
96 protected Vector3 LocalAabbMax
97 { get { return _localAabbMax; } set { _localAabbMax = value; } }
98 public override string Name
99 {
100 get
101 {
102 return "HeightfieldTerrain";
103 }
104 }
105 public override Vector3 LocalScaling
106 {
107 get
108 {
109 return _localScaling;
110 }
111 set
112 {
113 _localScaling = value;
114 }
115 }
116 public override float Margin
117 {
118 get
119 {
120 return base.Margin;
121 }
122 set
123 {
124 base.Margin = value;
125 }
126 }
127 public override BroadphaseNativeTypes ShapeType
128 {
129 get { return BroadphaseNativeTypes.Terrain; }
130 }
131 public Vector3 HalfExtents
132 {
133 get
134 {
135 Vector3 halfExtents = new Vector3();
136 switch (_upAxis)
137 {
138 case 0:
139 halfExtents.X = 2f;//_maxHeight;
140 halfExtents.Y = _width;
141 halfExtents.Z = _length;
142 break;
143 case 1:
144 halfExtents.X = _width;
145 halfExtents.Y = 2f;// _maxHeight;
146 halfExtents.Z = _length;
147 break;
148 case 2:
149 halfExtents.X = _width;
150 halfExtents.Y = _length;
151 halfExtents.Z = 2f;// _maxHeight;
152 break;
153 default:
154 //need to get valid m_upAxis
155 //btAssert(0);
156 throw new Exception("HeightfieldTerrainShape: need to get valid _upAxis");
157 //break;
158 }
159 halfExtents *= 0.5f;
160 return halfExtents;
161 }
162 }
163
164 public override void ProcessAllTriangles(ITriangleCallback callback, Vector3 aabbMin, Vector3 aabbMax)
165 {
166 //(void)callback;
167 //(void)aabbMax;
168 //(void)aabbMin;
169
170 //quantize the aabbMin and aabbMax, and adjust the start/end ranges
171
172 int[] quantizedAabbMin = new int[3];
173 int[] quantizedAabbMax = new int[3];
174
175 Vector3 localAabbMin = aabbMin * new Vector3(1f/_localScaling.X,1f/_localScaling.Y,1f/_localScaling.Z );
176 Vector3 localAabbMax = aabbMax * new Vector3(1f/_localScaling.X,1f/_localScaling.Y,1f/_localScaling.Z);
177
178 quantizeWithClamp(ref quantizedAabbMin, localAabbMin);
179 quantizeWithClamp(ref quantizedAabbMax, localAabbMax);
180
181
182
183 int startX=0;
184 int endX=_width-1;
185 int startJ=0;
186 int endJ=_length-1;
187
188 switch(_upAxis)
189 {
190 case 0:
191 quantizedAabbMin[1]+=_width/2-1;
192 quantizedAabbMax[1]+=_width/2+1;
193 quantizedAabbMin[2]+=_length/2-1;
194 quantizedAabbMax[2]+=_length/2+1;
195
196 if (quantizedAabbMin[1]>startX)
197 startX = quantizedAabbMin[1];
198 if (quantizedAabbMax[1]<endX)
199 endX = quantizedAabbMax[1];
200 if (quantizedAabbMin[2]>startJ)
201 startJ = quantizedAabbMin[2];
202 if (quantizedAabbMax[2]<endJ)
203 endJ = quantizedAabbMax[2];
204 break;
205 case 1:
206 quantizedAabbMin[0]+=_width/2-1;
207 quantizedAabbMax[0]+=_width/2+1;
208 quantizedAabbMin[2]+=_length/2-1;
209 quantizedAabbMax[2]+=_length/2+1;
210
211 if (quantizedAabbMin[0]>startX)
212 startX = quantizedAabbMin[0];
213 if (quantizedAabbMax[0]<endX)
214 endX = quantizedAabbMax[0];
215 if (quantizedAabbMin[2]>startJ)
216 startJ = quantizedAabbMin[2];
217 if (quantizedAabbMax[2]<endJ)
218 endJ = quantizedAabbMax[2];
219 break;
220 case 2:
221 quantizedAabbMin[0]+=_width/2-1;
222 quantizedAabbMax[0]+=_width/2+1;
223 quantizedAabbMin[1]+=_length/2-1;
224 quantizedAabbMax[1]+=_length/2+1;
225
226 if (quantizedAabbMin[0]>startX)
227 startX = quantizedAabbMin[0];
228 if (quantizedAabbMax[0]<endX)
229 endX = quantizedAabbMax[0];
230 if (quantizedAabbMin[1]>startJ)
231 startJ = quantizedAabbMin[1];
232 if (quantizedAabbMax[1]<endJ)
233 endJ = quantizedAabbMax[1];
234 break;
235 default:
236 //need to get valid m_upAxis
237 throw new Exception("HeightfieldTerrainShape: need to get valid _upAxis");
238 //break;
239 }
240
241 for(int j=startJ; j<endJ; j++)
242 {
243 for(int x=startX; x<endX; x++)
244 {
245 Vector3[] vertices = new Vector3[3];
246 //if (m_flipQuadEdges || (m_useDiamondSubdivision && ((j + x) & 1)))
247 if (_flipQuadEdges || (_useDiamondSubdivision && (((j + x) & 1) > 0)))
248 {
249 //first triangle
250 getVertex(x,j,ref vertices[0]);
251 getVertex(x+1,j,ref vertices[1]);
252 getVertex(x+1,j+1,ref vertices[2]);
253 //callback->processTriangle(vertices,x,j);
254 callback.ProcessTriangle(vertices,x,j);
255
256 //second triangle
257 getVertex(x,j,ref vertices[0]);
258 getVertex(x+1,j+1,ref vertices[1]);
259 getVertex(x,j+1,ref vertices[2]);
260 //callback->processTriangle(vertices,x,j);
261 callback.ProcessTriangle(vertices, x, j);
262 }
263 else
264 {
265 //first triangle
266 getVertex(x,j,ref vertices[0]);
267 getVertex(x,j+1,ref vertices[1]);
268 getVertex(x+1,j,ref vertices[2]);
269 //callback->processTriangle(vertices,x,j);
270 callback.ProcessTriangle(vertices,x,j);
271
272 //second triangle
273 getVertex(x+1,j,ref vertices[0]);
274 getVertex(x,j+1,ref vertices[1]);
275 getVertex(x+1,j+1,ref vertices[2]);
276 //callback->processTriangle(vertices,x,j);
277 callback.ProcessTriangle(vertices,x,j);
278 }
279 }
280 }
281 }
282 public override void GetAabb(Matrix t, out Vector3 aabbMin, out Vector3 aabbMax)
283 {
284 //aabbMin = new Vector3(-1e30f, -1e30f, -1e30f);
285 //aabbMax = new Vector3(1e30f, 1e30f, 1e30f);
286
287 Vector3 halfExtents = (_localAabbMax - _localAabbMin) * _localScaling * 0.5f;
288
289 Vector3 center = t.Translation;
290 Vector3 extent = new Vector3(Math.Abs(halfExtents.X), Math.Abs(halfExtents.Y), Math.Abs(halfExtents.Z));
291 extent += new Vector3(Margin, Margin, Margin);
292
293 aabbMin = center - extent;
294 aabbMax = center + extent;
295 }
296 public override void CalculateLocalInertia(float mass, out Vector3 inertia)
297 {
298 //moving concave objects not supported
299 inertia = new Vector3();
300 }
301 public float getHeightFieldValue(int x,int y)
302 {
303 float val = 0f;
304 if (_useFloatData)
305 {
306 val = _heightfieldData[(y * _width) + x];
307 }
308 else
309 {
310 //assume unsigned short int
311 int heightFieldValue = (int)_heightfieldData[(y * _width) + x];
312 val = heightFieldValue * _maxHeight/65535f;
313 }
314 return val;
315 }
316 public void getVertex(int x,int y,ref Vector3 vertex)
317 {
318 if (x < 0) x = 0;
319 if (y < 0) y = 0;
320 if (x >= _width) x = _width - 1;
321 if (y >= _length) y = _length - 1;
322 float height = getHeightFieldValue(x,y);
323 switch(_upAxis)
324 {
325 case 0:
326 vertex.X = height;
327 vertex.Y = (- _width/2 ) + x;
328 vertex.Z = (- _length/2 ) + y;
329 break;
330 case 1:
331 vertex.X = (- _width/2 ) + x;
332 vertex.Y = height;
333 vertex.Z = (- _length/2 ) + y;
334 break;
335 case 2:
336 vertex.X = (- _width/2 ) + x;
337 vertex.Y = (- _length/2 ) + y;
338 vertex.Z = height;
339 break;
340 default:
341 //need to get valid m_upAxis
342 throw new Exception("HeightfieldTerrainShape: need to get valid _upAxis");
343 //break;
344 }
345 vertex *= _localScaling;
346 }
347 public void quantizeWithClamp(ref int[] _out,Vector3 point)
348 {
349 Vector3 clampedPoint = point;
350 MathHelper.SetMax(ref clampedPoint,_localAabbMin);
351 MathHelper.SetMin(ref clampedPoint, _localAabbMax);
352 Vector3 v = clampedPoint;
353
354 _out[0] = (int)(v.X);
355 _out[1] = (int)(v.Y);
356 _out[2] = (int)(v.Z);
357 //correct for
358 }
359 }
360}