1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
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_MINKOWSKI_H
17 #define BT_OBB_BOX_MINKOWSKI_H
18 
19 #include "btPolyhedralConvexShape.h"
20 #include "btCollisionMargin.h"
21 #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
22 #include "LinearMath/btVector3.h"
23 #include "LinearMath/btMinMax.h"
24 
25 ///The btBoxShape 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)
27 btBoxShape : public btPolyhedralConvexShape
28 {
29 	//btVector3	m_boxHalfExtents1; //use m_implicitShapeDimensions instead
30 
31 public:
32 	BT_DECLARE_ALIGNED_ALLOCATOR();
33 
34 	btVector3 getHalfExtentsWithMargin() const
35 	{
36 		btVector3 halfExtents = getHalfExtentsWithoutMargin();
37 		btVector3 margin(getMargin(), getMargin(), getMargin());
38 		halfExtents += margin;
39 		return halfExtents;
40 	}
41 
42 	const btVector3& getHalfExtentsWithoutMargin() const
43 	{
44 		return m_implicitShapeDimensions;  //scaling is included, margin is not
45 	}
46 
47 	virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
48 	{
49 		btVector3 halfExtents = getHalfExtentsWithoutMargin();
50 		btVector3 margin(getMargin(), getMargin(), getMargin());
51 		halfExtents += margin;
52 
53 		return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
54 						 btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
55 						 btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
56 	}
57 
58 	SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const
59 	{
60 		const btVector3& halfExtents = getHalfExtentsWithoutMargin();
61 
62 		return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
63 						 btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
64 						 btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
65 	}
66 
67 	virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
68 	{
69 		const btVector3& halfExtents = getHalfExtentsWithoutMargin();
70 
71 		for (int i = 0; i < numVectors; i++)
72 		{
73 			const btVector3& vec = vectors[i];
74 			supportVerticesOut[i].setValue(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
75 										   btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
76 										   btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
77 		}
78 	}
79 
80 	btBoxShape(const btVector3& boxHalfExtents);
81 
82 	virtual void setMargin(btScalar collisionMargin)
83 	{
84 		//correct the m_implicitShapeDimensions for the margin
85 		btVector3 oldMargin(getMargin(), getMargin(), getMargin());
86 		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions + oldMargin;
87 
88 		btConvexInternalShape::setMargin(collisionMargin);
89 		btVector3 newMargin(getMargin(), getMargin(), getMargin());
90 		m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
91 	}
92 	virtual void setLocalScaling(const btVector3& scaling)
93 	{
94 		btVector3 oldMargin(getMargin(), getMargin(), getMargin());
95 		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions + oldMargin;
96 		btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
97 
98 		btConvexInternalShape::setLocalScaling(scaling);
99 
100 		m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
101 	}
102 
103 	virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
104 
105 	virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
106 
107 	virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const
108 	{
109 		//this plane might not be aligned...
110 		btVector4 plane;
111 		getPlaneEquation(plane, i);
112 		planeNormal = btVector3(plane.getX(), plane.getY(), plane.getZ());
113 		planeSupport = localGetSupportingVertex(-planeNormal);
114 	}
115 
116 	virtual int getNumPlanes() const
117 	{
118 		return 6;
119 	}
120 
121 	virtual int getNumVertices() const
122 	{
123 		return 8;
124 	}
125 
126 	virtual int getNumEdges() const
127 	{
128 		return 12;
129 	}
130 
131 	virtual void getVertex(int i, btVector3& vtx) const
132 	{
133 		btVector3 halfExtents = getHalfExtentsWithMargin();
134 
135 		vtx = btVector3(
136 			halfExtents.x() * (1 - (i & 1)) - halfExtents.x() * (i & 1),
137 			halfExtents.y() * (1 - ((i & 2) >> 1)) - halfExtents.y() * ((i & 2) >> 1),
138 			halfExtents.z() * (1 - ((i & 4) >> 2)) - halfExtents.z() * ((i & 4) >> 2));
139 	}
140 
141 	virtual void getPlaneEquation(btVector4 & plane, int i) const
142 	{
143 		btVector3 halfExtents = getHalfExtentsWithoutMargin();
144 
145 		switch (i)
146 		{
147 			case 0:
148 				plane.setValue(btScalar(1.), btScalar(0.), btScalar(0.), -halfExtents.x());
149 				break;
150 			case 1:
151 				plane.setValue(btScalar(-1.), btScalar(0.), btScalar(0.), -halfExtents.x());
152 				break;
153 			case 2:
154 				plane.setValue(btScalar(0.), btScalar(1.), btScalar(0.), -halfExtents.y());
155 				break;
156 			case 3:
157 				plane.setValue(btScalar(0.), btScalar(-1.), btScalar(0.), -halfExtents.y());
158 				break;
159 			case 4:
160 				plane.setValue(btScalar(0.), btScalar(0.), btScalar(1.), -halfExtents.z());
161 				break;
162 			case 5:
163 				plane.setValue(btScalar(0.), btScalar(0.), btScalar(-1.), -halfExtents.z());
164 				break;
165 			default:
166 				btAssert(0);
167 		}
168 	}
169 
170 	virtual void getEdge(int i, btVector3& pa, btVector3& pb) const
171 	//virtual void getEdge(int i,Edge& edge) const
172 	{
173 		int edgeVert0 = 0;
174 		int edgeVert1 = 0;
175 
176 		switch (i)
177 		{
178 			case 0:
179 				edgeVert0 = 0;
180 				edgeVert1 = 1;
181 				break;
182 			case 1:
183 				edgeVert0 = 0;
184 				edgeVert1 = 2;
185 				break;
186 			case 2:
187 				edgeVert0 = 1;
188 				edgeVert1 = 3;
189 
190 				break;
191 			case 3:
192 				edgeVert0 = 2;
193 				edgeVert1 = 3;
194 				break;
195 			case 4:
196 				edgeVert0 = 0;
197 				edgeVert1 = 4;
198 				break;
199 			case 5:
200 				edgeVert0 = 1;
201 				edgeVert1 = 5;
202 
203 				break;
204 			case 6:
205 				edgeVert0 = 2;
206 				edgeVert1 = 6;
207 				break;
208 			case 7:
209 				edgeVert0 = 3;
210 				edgeVert1 = 7;
211 				break;
212 			case 8:
213 				edgeVert0 = 4;
214 				edgeVert1 = 5;
215 				break;
216 			case 9:
217 				edgeVert0 = 4;
218 				edgeVert1 = 6;
219 				break;
220 			case 10:
221 				edgeVert0 = 5;
222 				edgeVert1 = 7;
223 				break;
224 			case 11:
225 				edgeVert0 = 6;
226 				edgeVert1 = 7;
227 				break;
228 			default:
229 				btAssert(0);
230 		}
231 
232 		getVertex(edgeVert0, pa);
233 		getVertex(edgeVert1, pb);
234 	}
235 
236 	virtual bool isInside(const btVector3& pt, btScalar tolerance) const
237 	{
238 		btVector3 halfExtents = getHalfExtentsWithoutMargin();
239 
240 		//btScalar minDist = 2*tolerance;
241 
242 		bool result = (pt.x() <= (halfExtents.x() + tolerance)) &&
243 					  (pt.x() >= (-halfExtents.x() - tolerance)) &&
244 					  (pt.y() <= (halfExtents.y() + tolerance)) &&
245 					  (pt.y() >= (-halfExtents.y() - tolerance)) &&
246 					  (pt.z() <= (halfExtents.z() + tolerance)) &&
247 					  (pt.z() >= (-halfExtents.z() - tolerance));
248 
249 		return result;
250 	}
251 
252 	//debugging
253 	virtual const char* getName() const
254 	{
255 		return "Box";
256 	}
257 
258 	virtual int getNumPreferredPenetrationDirections() const
259 	{
260 		return 6;
261 	}
262 
263 	virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
264 	{
265 		switch (index)
266 		{
267 			case 0:
268 				penetrationVector.setValue(btScalar(1.), btScalar(0.), btScalar(0.));
269 				break;
270 			case 1:
271 				penetrationVector.setValue(btScalar(-1.), btScalar(0.), btScalar(0.));
272 				break;
273 			case 2:
274 				penetrationVector.setValue(btScalar(0.), btScalar(1.), btScalar(0.));
275 				break;
276 			case 3:
277 				penetrationVector.setValue(btScalar(0.), btScalar(-1.), btScalar(0.));
278 				break;
279 			case 4:
280 				penetrationVector.setValue(btScalar(0.), btScalar(0.), btScalar(1.));
281 				break;
282 			case 5:
283 				penetrationVector.setValue(btScalar(0.), btScalar(0.), btScalar(-1.));
284 				break;
285 			default:
286 				btAssert(0);
287 		}
288 	}
289 };
290 
291 #endif  //BT_OBB_BOX_MINKOWSKI_H
292