[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-physics / third-party / bullet3 / src / BulletCollision / Gimpact / btGImpactShape.cpp
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
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
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
54 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
65 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
78 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
119 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
156 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
188 void btGImpactMeshShape::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const
189 {
190 }
191
192 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
218 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
245 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
254 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)
264 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 }