Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/bullet/BulletCollision/CollisionShapes/btCompoundShape.cpp @ 2776

Last change on this file since 2776 was 2662, checked in by rgrieder, 16 years ago

Merged presentation branch back to trunk.

  • Property svn:eol-style set to native
File size: 7.6 KB
Line 
1/*
2Bullet Continuous Collision Detection and Physics Library
3Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
4
5This software is provided 'as-is', without any express or implied warranty.
6In no event will the authors be held liable for any damages arising from the use of this software.
7Permission is granted to anyone to use this software for any purpose,
8including commercial applications, and to alter it and redistribute it freely,
9subject to the following restrictions:
10
111. 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.
122. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
133. This notice may not be removed or altered from any source distribution.
14*/
15
16#include "btCompoundShape.h"
17#include "btCollisionShape.h"
18#include "BulletCollision/BroadphaseCollision/btDbvt.h"
19
20btCompoundShape::btCompoundShape(bool enableDynamicAabbTree)
21: m_localAabbMin(btScalar(1e30),btScalar(1e30),btScalar(1e30)),
22m_localAabbMax(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)),
23m_collisionMargin(btScalar(0.)),
24m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)),
25m_dynamicAabbTree(0)
26{
27        m_shapeType = COMPOUND_SHAPE_PROXYTYPE;
28
29        if (enableDynamicAabbTree)
30        {
31                void* mem = btAlignedAlloc(sizeof(btDbvt),16);
32                m_dynamicAabbTree = new(mem) btDbvt();
33                btAssert(mem==m_dynamicAabbTree);
34        }
35}
36
37
38btCompoundShape::~btCompoundShape()
39{
40        if (m_dynamicAabbTree)
41        {
42                m_dynamicAabbTree->~btDbvt();
43                btAlignedFree(m_dynamicAabbTree);
44        }
45}
46
47void    btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape)
48{
49        //m_childTransforms.push_back(localTransform);
50        //m_childShapes.push_back(shape);
51        btCompoundShapeChild child;
52        child.m_transform = localTransform;
53        child.m_childShape = shape;
54        child.m_childShapeType = shape->getShapeType();
55        child.m_childMargin = shape->getMargin();
56
57        m_children.push_back(child);
58
59        //extend the local aabbMin/aabbMax
60        btVector3 localAabbMin,localAabbMax;
61        shape->getAabb(localTransform,localAabbMin,localAabbMax);
62        for (int i=0;i<3;i++)
63        {
64                if (m_localAabbMin[i] > localAabbMin[i])
65                {
66                        m_localAabbMin[i] = localAabbMin[i];
67                }
68                if (m_localAabbMax[i] < localAabbMax[i])
69                {
70                        m_localAabbMax[i] = localAabbMax[i];
71                }
72
73        }
74        if (m_dynamicAabbTree)
75        {
76                const btDbvtVolume      bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
77                int index = m_children.size()-1;
78                child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index);
79        }
80
81}
82
83void    btCompoundShape::updateChildTransform(int childIndex, const btTransform& newChildTransform)
84{
85        m_children[childIndex].m_transform = newChildTransform;
86
87        if (m_dynamicAabbTree)
88        {
89                ///update the dynamic aabb tree
90                btVector3 localAabbMin,localAabbMax;
91                m_children[childIndex].m_childShape->getAabb(newChildTransform,localAabbMin,localAabbMax);
92                ATTRIBUTE_ALIGNED16(btDbvtVolume)       bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
93                int index = m_children.size()-1;
94                m_dynamicAabbTree->update(m_children[childIndex].m_node,bounds);
95        }
96
97        recalculateLocalAabb();
98}
99
100void btCompoundShape::removeChildShapeByIndex(int childShapeIndex)
101{
102        btAssert(childShapeIndex >=0 && childShapeIndex < m_children.size());
103        if (m_dynamicAabbTree)
104        {
105                m_dynamicAabbTree->remove(m_children[childShapeIndex].m_node);
106        }
107        m_children.swap(childShapeIndex,m_children.size()-1);
108        m_children.pop_back();
109
110}
111
112
113
114void btCompoundShape::removeChildShape(btCollisionShape* shape)
115{
116        // Find the children containing the shape specified, and remove those children.
117        //note: there might be multiple children using the same shape!
118        for(int i = m_children.size()-1; i >= 0 ; i--)
119        {
120                if(m_children[i].m_childShape == shape)
121                {
122                        m_children.swap(i,m_children.size()-1);
123                        m_children.pop_back();
124                        //remove it from the m_dynamicAabbTree too
125                        //@todo: this leads to problems due to caching in the btCompoundCollisionAlgorithm
126                        //so effectively, removeChildShape is broken at the moment
127                        //m_dynamicAabbTree->remove(m_aabbProxies[i]);
128                        //m_aabbProxies.swap(i,m_children.size()-1);
129                        //m_aabbProxies.pop_back();
130                }
131        }
132
133
134
135        recalculateLocalAabb();
136}
137
138void btCompoundShape::recalculateLocalAabb()
139{
140        // Recalculate the local aabb
141        // Brute force, it iterates over all the shapes left.
142        m_localAabbMin = btVector3(btScalar(1e30),btScalar(1e30),btScalar(1e30));
143        m_localAabbMax = btVector3(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30));
144
145        //extend the local aabbMin/aabbMax
146        for (int j = 0; j < m_children.size(); j++)
147        {
148                btVector3 localAabbMin,localAabbMax;
149                m_children[j].m_childShape->getAabb(m_children[j].m_transform, localAabbMin, localAabbMax);
150                for (int i=0;i<3;i++)
151                {
152                        if (m_localAabbMin[i] > localAabbMin[i])
153                                m_localAabbMin[i] = localAabbMin[i];
154                        if (m_localAabbMax[i] < localAabbMax[i])
155                                m_localAabbMax[i] = localAabbMax[i];
156                }
157        }
158}
159
160///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
161void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
162{
163        btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin);
164        localHalfExtents += btVector3(getMargin(),getMargin(),getMargin());
165        btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin);
166
167        btMatrix3x3 abs_b = trans.getBasis().absolute(); 
168
169        btVector3 center = trans(localCenter);
170
171        btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents),
172                abs_b[1].dot(localHalfExtents),
173                abs_b[2].dot(localHalfExtents));
174        aabbMin = center-extent;
175        aabbMax = center+extent;
176
177}
178
179void    btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
180{
181        //approximation: take the inertia from the aabb for now
182        btTransform ident;
183        ident.setIdentity();
184        btVector3 aabbMin,aabbMax;
185        getAabb(ident,aabbMin,aabbMax);
186
187        btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
188
189        btScalar lx=btScalar(2.)*(halfExtents.x());
190        btScalar ly=btScalar(2.)*(halfExtents.y());
191        btScalar lz=btScalar(2.)*(halfExtents.z());
192
193        inertia[0] = mass/(btScalar(12.0)) * (ly*ly + lz*lz);
194        inertia[1] = mass/(btScalar(12.0)) * (lx*lx + lz*lz);
195        inertia[2] = mass/(btScalar(12.0)) * (lx*lx + ly*ly);
196
197}
198
199
200
201
202void btCompoundShape::calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const
203{
204        int n = m_children.size();
205
206        btScalar totalMass = 0;
207        btVector3 center(0, 0, 0);
208        int k;
209
210        for (k = 0; k < n; k++)
211        {
212                center += m_children[k].m_transform.getOrigin() * masses[k];
213                totalMass += masses[k];
214        }
215        center /= totalMass;
216        principal.setOrigin(center);
217
218        btMatrix3x3 tensor(0, 0, 0, 0, 0, 0, 0, 0, 0);
219        for ( k = 0; k < n; k++)
220        {
221                btVector3 i;
222                m_children[k].m_childShape->calculateLocalInertia(masses[k], i);
223
224                const btTransform& t = m_children[k].m_transform;
225                btVector3 o = t.getOrigin() - center;
226
227                //compute inertia tensor in coordinate system of compound shape
228                btMatrix3x3 j = t.getBasis().transpose();
229                j[0] *= i[0];
230                j[1] *= i[1];
231                j[2] *= i[2];
232                j = t.getBasis() * j;
233
234                //add inertia tensor
235                tensor[0] += j[0];
236                tensor[1] += j[1];
237                tensor[2] += j[2];
238
239                //compute inertia tensor of pointmass at o
240                btScalar o2 = o.length2();
241                j[0].setValue(o2, 0, 0);
242                j[1].setValue(0, o2, 0);
243                j[2].setValue(0, 0, o2);
244                j[0] += o * -o.x(); 
245                j[1] += o * -o.y(); 
246                j[2] += o * -o.z();
247
248                //add inertia tensor of pointmass
249                tensor[0] += masses[k] * j[0];
250                tensor[1] += masses[k] * j[1];
251                tensor[2] += masses[k] * j[2];
252        }
253
254        tensor.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
255        inertia.setValue(tensor[0][0], tensor[1][1], tensor[2][2]);
256}
257
258
259
Note: See TracBrowser for help on using the repository browser.