1 /*
2 This source file is part of GIMPACT Library.
3 
4 For the latest info, see http://gimpact.sourceforge.net/
5 
6 Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
7 email: projectileman@yahoo.com
8 
9 
10 This software is provided 'as-is', without any express or implied warranty.
11 In no event will the authors be held liable for any damages arising from the use of this software.
12 Permission is granted to anyone to use this software for any purpose,
13 including commercial applications, and to alter it and redistribute it freely,
14 subject to the following restrictions:
15 
16 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.
17 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
19 */
20 
21 #include "btGImpactShape.h"
22 #include "btGImpactMassUtil.h"
23 
btGImpactMeshShapePart(btStridingMeshInterface * meshInterface,int part)24 btGImpactMeshShapePart::btGImpactMeshShapePart(btStridingMeshInterface* meshInterface, int part)
25 {
26 	// moved from .h to .cpp because of conditional compilation
27 	// (The setting of BT_THREADSAFE may differ between various cpp files, so it is best to
28 	// avoid using it in h files)
29 	m_primitive_manager.m_meshInterface = meshInterface;
30 	m_primitive_manager.m_part = part;
31 	m_box_set.setPrimitiveManager(&m_primitive_manager);
32 #if BT_THREADSAFE
33 	// If threadsafe is requested, this object uses a different lock/unlock
34 	//  model with the btStridingMeshInterface -- lock once when the object is constructed
35 	//  and unlock once in the destructor.
36 	// The other way of locking and unlocking for each collision check in the narrowphase
37 	// is not threadsafe.  Note these are not thread-locks, they are calls to the meshInterface's
38 	// getLockedReadOnlyVertexIndexBase virtual function, which by default just returns a couple of
39 	// pointers.  In theory a client could override the lock function to do all sorts of
40 	// things like reading data from GPU memory, or decompressing data on the fly, but such things
41 	// do not seem all that likely or useful, given the performance cost.
42 	m_primitive_manager.lock();
43 #endif
44 }
45 
~btGImpactMeshShapePart()46 btGImpactMeshShapePart::~btGImpactMeshShapePart()
47 {
48 	// moved from .h to .cpp because of conditional compilation
49 #if BT_THREADSAFE
50 	m_primitive_manager.unlock();
51 #endif
52 }
53 
lockChildShapes() const54 void btGImpactMeshShapePart::lockChildShapes() const
55 {
56 	// moved from .h to .cpp because of conditional compilation
57 #if !BT_THREADSAFE
58 	// called in the narrowphase -- not threadsafe!
59 	void* dummy = (void*)(m_box_set.getPrimitiveManager());
60 	TrimeshPrimitiveManager* dummymanager = static_cast<TrimeshPrimitiveManager*>(dummy);
61 	dummymanager->lock();
62 #endif
63 }
64 
unlockChildShapes() const65 void btGImpactMeshShapePart::unlockChildShapes() const
66 {
67 	// moved from .h to .cpp because of conditional compilation
68 #if !BT_THREADSAFE
69 	// called in the narrowphase -- not threadsafe!
70 	void* dummy = (void*)(m_box_set.getPrimitiveManager());
71 	TrimeshPrimitiveManager* dummymanager = static_cast<TrimeshPrimitiveManager*>(dummy);
72 	dummymanager->unlock();
73 #endif
74 }
75 
76 #define CALC_EXACT_INERTIA 1
77 
calculateLocalInertia(btScalar mass,btVector3 & inertia) const78 void btGImpactCompoundShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
79 {
80 	lockChildShapes();
81 #ifdef CALC_EXACT_INERTIA
82 	inertia.setValue(0.f, 0.f, 0.f);
83 
84 	int i = this->getNumChildShapes();
85 	btScalar shapemass = mass / btScalar(i);
86 
87 	while (i--)
88 	{
89 		btVector3 temp_inertia;
90 		m_childShapes[i]->calculateLocalInertia(shapemass, temp_inertia);
91 		if (childrenHasTransform())
92 		{
93 			inertia = gim_inertia_add_transformed(inertia, temp_inertia, m_childTransforms[i]);
94 		}
95 		else
96 		{
97 			inertia = gim_inertia_add_transformed(inertia, temp_inertia, btTransform::getIdentity());
98 		}
99 	}
100 
101 #else
102 
103 	// Calc box inertia
104 
105 	btScalar lx = m_localAABB.m_max[0] - m_localAABB.m_min[0];
106 	btScalar ly = m_localAABB.m_max[1] - m_localAABB.m_min[1];
107 	btScalar lz = m_localAABB.m_max[2] - m_localAABB.m_min[2];
108 	const btScalar x2 = lx * lx;
109 	const btScalar y2 = ly * ly;
110 	const btScalar z2 = lz * lz;
111 	const btScalar scaledmass = mass * btScalar(0.08333333);
112 
113 	inertia = scaledmass * (btVector3(y2 + z2, x2 + z2, x2 + y2));
114 
115 #endif
116 	unlockChildShapes();
117 }
118 
calculateLocalInertia(btScalar mass,btVector3 & inertia) const119 void btGImpactMeshShapePart::calculateLocalInertia(btScalar mass, btVector3& inertia) const
120 {
121 	lockChildShapes();
122 
123 #ifdef CALC_EXACT_INERTIA
124 	inertia.setValue(0.f, 0.f, 0.f);
125 
126 	int i = this->getVertexCount();
127 	btScalar pointmass = mass / btScalar(i);
128 
129 	while (i--)
130 	{
131 		btVector3 pointintertia;
132 		this->getVertex(i, pointintertia);
133 		pointintertia = gim_get_point_inertia(pointintertia, pointmass);
134 		inertia += pointintertia;
135 	}
136 
137 #else
138 
139 	// Calc box inertia
140 
141 	btScalar lx = m_localAABB.m_max[0] - m_localAABB.m_min[0];
142 	btScalar ly = m_localAABB.m_max[1] - m_localAABB.m_min[1];
143 	btScalar lz = m_localAABB.m_max[2] - m_localAABB.m_min[2];
144 	const btScalar x2 = lx * lx;
145 	const btScalar y2 = ly * ly;
146 	const btScalar z2 = lz * lz;
147 	const btScalar scaledmass = mass * btScalar(0.08333333);
148 
149 	inertia = scaledmass * (btVector3(y2 + z2, x2 + z2, x2 + y2));
150 
151 #endif
152 
153 	unlockChildShapes();
154 }
155 
calculateLocalInertia(btScalar mass,btVector3 & inertia) const156 void btGImpactMeshShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
157 {
158 #ifdef CALC_EXACT_INERTIA
159 	inertia.setValue(0.f, 0.f, 0.f);
160 
161 	int i = this->getMeshPartCount();
162 	btScalar partmass = mass / btScalar(i);
163 
164 	while (i--)
165 	{
166 		btVector3 partinertia;
167 		getMeshPart(i)->calculateLocalInertia(partmass, partinertia);
168 		inertia += partinertia;
169 	}
170 
171 #else
172 
173 	// Calc box inertia
174 
175 	btScalar lx = m_localAABB.m_max[0] - m_localAABB.m_min[0];
176 	btScalar ly = m_localAABB.m_max[1] - m_localAABB.m_min[1];
177 	btScalar lz = m_localAABB.m_max[2] - m_localAABB.m_min[2];
178 	const btScalar x2 = lx * lx;
179 	const btScalar y2 = ly * ly;
180 	const btScalar z2 = lz * lz;
181 	const btScalar scaledmass = mass * btScalar(0.08333333);
182 
183 	inertia = scaledmass * (btVector3(y2 + z2, x2 + z2, x2 + y2));
184 
185 #endif
186 }
187 
rayTest(const btVector3 & rayFrom,const btVector3 & rayTo,btCollisionWorld::RayResultCallback & resultCallback) const188 void btGImpactMeshShape::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const
189 {
190 }
191 
processAllTrianglesRay(btTriangleCallback * callback,const btVector3 & rayFrom,const btVector3 & rayTo) const192 void btGImpactMeshShapePart::processAllTrianglesRay(btTriangleCallback* callback, const btVector3& rayFrom, const btVector3& rayTo) const
193 {
194 	lockChildShapes();
195 
196 	btAlignedObjectArray<int> collided;
197 	btVector3 rayDir(rayTo - rayFrom);
198 	rayDir.normalize();
199 	m_box_set.rayQuery(rayDir, rayFrom, collided);
200 
201 	if (collided.size() == 0)
202 	{
203 		unlockChildShapes();
204 		return;
205 	}
206 
207 	int part = (int)getPart();
208 	btPrimitiveTriangle triangle;
209 	int i = collided.size();
210 	while (i--)
211 	{
212 		getPrimitiveTriangle(collided[i], triangle);
213 		callback->processTriangle(triangle.m_vertices, part, collided[i]);
214 	}
215 	unlockChildShapes();
216 }
217 
processAllTriangles(btTriangleCallback * callback,const btVector3 & aabbMin,const btVector3 & aabbMax) const218 void btGImpactMeshShapePart::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
219 {
220 	lockChildShapes();
221 	btAABB box;
222 	box.m_min = aabbMin;
223 	box.m_max = aabbMax;
224 
225 	btAlignedObjectArray<int> collided;
226 	m_box_set.boxQuery(box, collided);
227 
228 	if (collided.size() == 0)
229 	{
230 		unlockChildShapes();
231 		return;
232 	}
233 
234 	int part = (int)getPart();
235 	btPrimitiveTriangle triangle;
236 	int i = collided.size();
237 	while (i--)
238 	{
239 		this->getPrimitiveTriangle(collided[i], triangle);
240 		callback->processTriangle(triangle.m_vertices, part, collided[i]);
241 	}
242 	unlockChildShapes();
243 }
244 
processAllTriangles(btTriangleCallback * callback,const btVector3 & aabbMin,const btVector3 & aabbMax) const245 void btGImpactMeshShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
246 {
247 	int i = m_mesh_parts.size();
248 	while (i--)
249 	{
250 		m_mesh_parts[i]->processAllTriangles(callback, aabbMin, aabbMax);
251 	}
252 }
253 
processAllTrianglesRay(btTriangleCallback * callback,const btVector3 & rayFrom,const btVector3 & rayTo) const254 void btGImpactMeshShape::processAllTrianglesRay(btTriangleCallback* callback, const btVector3& rayFrom, const btVector3& rayTo) const
255 {
256 	int i = m_mesh_parts.size();
257 	while (i--)
258 	{
259 		m_mesh_parts[i]->processAllTrianglesRay(callback, rayFrom, rayTo);
260 	}
261 }
262 
263 ///fills the dataBuffer and returns the struct name (and 0 on failure)
serialize(void * dataBuffer,btSerializer * serializer) const264 const char* btGImpactMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
265 {
266 	btGImpactMeshShapeData* trimeshData = (btGImpactMeshShapeData*)dataBuffer;
267 
268 	btCollisionShape::serialize(&trimeshData->m_collisionShapeData, serializer);
269 
270 	m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer);
271 
272 	trimeshData->m_collisionMargin = float(m_collisionMargin);
273 
274 	localScaling.serializeFloat(trimeshData->m_localScaling);
275 
276 	trimeshData->m_gimpactSubType = int(getGImpactShapeType());
277 
278 	return "btGImpactMeshShapeData";
279 }
280