1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
4
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10
11 1. 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.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15
16 #ifndef BT_OBB_BOX_2D_SHAPE_H
17 #define BT_OBB_BOX_2D_SHAPE_H
18
19 #include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
20 #include "BulletCollision/CollisionShapes/btCollisionMargin.h"
21 #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
22 #include "LinearMath/btVector3.h"
23 #include "LinearMath/btMinMax.h"
24
25 ///The btBox2dShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space.
ATTRIBUTE_ALIGNED16(class)26 ATTRIBUTE_ALIGNED16(class) btBox2dShape: public btPolyhedralConvexShape
27 {
28
29 //btVector3 m_boxHalfExtents1; //use m_implicitShapeDimensions instead
30
31 btVector3 m_centroid;
32 btVector3 m_vertices[4];
33 btVector3 m_normals[4];
34
35 public:
36
37 BT_DECLARE_ALIGNED_ALLOCATOR();
38
39 btVector3 getHalfExtentsWithMargin() const
40 {
41 btVector3 halfExtents = getHalfExtentsWithoutMargin();
42 btVector3 margin(getMargin(),getMargin(),getMargin());
43 halfExtents += margin;
44 return halfExtents;
45 }
46
47 const btVector3& getHalfExtentsWithoutMargin() const
48 {
49 return m_implicitShapeDimensions;//changed in Bullet 2.63: assume the scaling and margin are included
50 }
51
52
53 virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
54 {
55 btVector3 halfExtents = getHalfExtentsWithoutMargin();
56 btVector3 margin(getMargin(),getMargin(),getMargin());
57 halfExtents += margin;
58
59 return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
60 btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
61 btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
62 }
63
64 SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const
65 {
66 const btVector3& halfExtents = getHalfExtentsWithoutMargin();
67
68 return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
69 btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
70 btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
71 }
72
73 virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
74 {
75 const btVector3& halfExtents = getHalfExtentsWithoutMargin();
76
77 for (int i=0;i<numVectors;i++)
78 {
79 const btVector3& vec = vectors[i];
80 supportVerticesOut[i].setValue(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
81 btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
82 btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
83 }
84
85 }
86
87
88 ///a btBox2dShape is a flat 2D box in the X-Y plane (Z extents are zero)
89 btBox2dShape( const btVector3& boxHalfExtents)
90 : btPolyhedralConvexShape(),
91 m_centroid(0,0,0)
92 {
93 m_vertices[0].setValue(-boxHalfExtents.getX(),-boxHalfExtents.getY(),0);
94 m_vertices[1].setValue(boxHalfExtents.getX(),-boxHalfExtents.getY(),0);
95 m_vertices[2].setValue(boxHalfExtents.getX(),boxHalfExtents.getY(),0);
96 m_vertices[3].setValue(-boxHalfExtents.getX(),boxHalfExtents.getY(),0);
97
98 m_normals[0].setValue(0,-1,0);
99 m_normals[1].setValue(1,0,0);
100 m_normals[2].setValue(0,1,0);
101 m_normals[3].setValue(-1,0,0);
102
103 btScalar minDimension = boxHalfExtents.getX();
104 if (minDimension>boxHalfExtents.getY())
105 minDimension = boxHalfExtents.getY();
106 setSafeMargin(minDimension);
107
108 m_shapeType = BOX_2D_SHAPE_PROXYTYPE;
109 btVector3 margin(getMargin(),getMargin(),getMargin());
110 m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
111 };
112
113 virtual void setMargin(btScalar collisionMargin)
114 {
115 //correct the m_implicitShapeDimensions for the margin
116 btVector3 oldMargin(getMargin(),getMargin(),getMargin());
117 btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
118
119 btConvexInternalShape::setMargin(collisionMargin);
120 btVector3 newMargin(getMargin(),getMargin(),getMargin());
121 m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
122
123 }
124 virtual void setLocalScaling(const btVector3& scaling)
125 {
126 btVector3 oldMargin(getMargin(),getMargin(),getMargin());
127 btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
128 btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
129
130 btConvexInternalShape::setLocalScaling(scaling);
131
132 m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
133
134 }
135
136 virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
137
138
139
140 virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
141
142
143
144
145
146 int getVertexCount() const
147 {
148 return 4;
149 }
150
151 virtual int getNumVertices()const
152 {
153 return 4;
154 }
155
156 const btVector3* getVertices() const
157 {
158 return &m_vertices[0];
159 }
160
161 const btVector3* getNormals() const
162 {
163 return &m_normals[0];
164 }
165
166
167
168
169
170
171
172 virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const
173 {
174 //this plane might not be aligned...
175 btVector4 plane ;
176 getPlaneEquation(plane,i);
177 planeNormal = btVector3(plane.getX(),plane.getY(),plane.getZ());
178 planeSupport = localGetSupportingVertex(-planeNormal);
179 }
180
181
182 const btVector3& getCentroid() const
183 {
184 return m_centroid;
185 }
186
187 virtual int getNumPlanes() const
188 {
189 return 6;
190 }
191
192
193
194 virtual int getNumEdges() const
195 {
196 return 12;
197 }
198
199
200 virtual void getVertex(int i,btVector3& vtx) const
201 {
202 btVector3 halfExtents = getHalfExtentsWithoutMargin();
203
204 vtx = btVector3(
205 halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1),
206 halfExtents.y() * (1-((i&2)>>1)) - halfExtents.y() * ((i&2)>>1),
207 halfExtents.z() * (1-((i&4)>>2)) - halfExtents.z() * ((i&4)>>2));
208 }
209
210
211 virtual void getPlaneEquation(btVector4& plane,int i) const
212 {
213 btVector3 halfExtents = getHalfExtentsWithoutMargin();
214
215 switch (i)
216 {
217 case 0:
218 plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.),-halfExtents.x());
219 break;
220 case 1:
221 plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.),-halfExtents.x());
222 break;
223 case 2:
224 plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.),-halfExtents.y());
225 break;
226 case 3:
227 plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.),-halfExtents.y());
228 break;
229 case 4:
230 plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.),-halfExtents.z());
231 break;
232 case 5:
233 plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.),-halfExtents.z());
234 break;
235 default:
236 btAssert(0);
237 }
238 }
239
240
241 virtual void getEdge(int i,btVector3& pa,btVector3& pb) const
242 //virtual void getEdge(int i,Edge& edge) const
243 {
244 int edgeVert0 = 0;
245 int edgeVert1 = 0;
246
247 switch (i)
248 {
249 case 0:
250 edgeVert0 = 0;
251 edgeVert1 = 1;
252 break;
253 case 1:
254 edgeVert0 = 0;
255 edgeVert1 = 2;
256 break;
257 case 2:
258 edgeVert0 = 1;
259 edgeVert1 = 3;
260
261 break;
262 case 3:
263 edgeVert0 = 2;
264 edgeVert1 = 3;
265 break;
266 case 4:
267 edgeVert0 = 0;
268 edgeVert1 = 4;
269 break;
270 case 5:
271 edgeVert0 = 1;
272 edgeVert1 = 5;
273
274 break;
275 case 6:
276 edgeVert0 = 2;
277 edgeVert1 = 6;
278 break;
279 case 7:
280 edgeVert0 = 3;
281 edgeVert1 = 7;
282 break;
283 case 8:
284 edgeVert0 = 4;
285 edgeVert1 = 5;
286 break;
287 case 9:
288 edgeVert0 = 4;
289 edgeVert1 = 6;
290 break;
291 case 10:
292 edgeVert0 = 5;
293 edgeVert1 = 7;
294 break;
295 case 11:
296 edgeVert0 = 6;
297 edgeVert1 = 7;
298 break;
299 default:
300 btAssert(0);
301
302 }
303
304 getVertex(edgeVert0,pa );
305 getVertex(edgeVert1,pb );
306 }
307
308
309
310
311
312 virtual bool isInside(const btVector3& pt,btScalar tolerance) const
313 {
314 btVector3 halfExtents = getHalfExtentsWithoutMargin();
315
316 //btScalar minDist = 2*tolerance;
317
318 bool result = (pt.x() <= (halfExtents.x()+tolerance)) &&
319 (pt.x() >= (-halfExtents.x()-tolerance)) &&
320 (pt.y() <= (halfExtents.y()+tolerance)) &&
321 (pt.y() >= (-halfExtents.y()-tolerance)) &&
322 (pt.z() <= (halfExtents.z()+tolerance)) &&
323 (pt.z() >= (-halfExtents.z()-tolerance));
324
325 return result;
326 }
327
328
329 //debugging
330 virtual const char* getName()const
331 {
332 return "Box2d";
333 }
334
335 virtual int getNumPreferredPenetrationDirections() const
336 {
337 return 6;
338 }
339
340 virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
341 {
342 switch (index)
343 {
344 case 0:
345 penetrationVector.setValue(btScalar(1.),btScalar(0.),btScalar(0.));
346 break;
347 case 1:
348 penetrationVector.setValue(btScalar(-1.),btScalar(0.),btScalar(0.));
349 break;
350 case 2:
351 penetrationVector.setValue(btScalar(0.),btScalar(1.),btScalar(0.));
352 break;
353 case 3:
354 penetrationVector.setValue(btScalar(0.),btScalar(-1.),btScalar(0.));
355 break;
356 case 4:
357 penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(1.));
358 break;
359 case 5:
360 penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(-1.));
361 break;
362 default:
363 btAssert(0);
364 }
365 }
366
367 };
368
369 #endif //BT_OBB_BOX_2D_SHAPE_H
370
371
372