bullet: Update to current svn, r2636
[blender.git] / extern / bullet2 / src / BulletCollision / CollisionShapes / btBox2dShape.h
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.
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