Blender V2.61 - r43446

btConvexShape.cpp

Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
00004 
00005 This software is provided 'as-is', without any express or implied warranty.
00006 In no event will the authors be held liable for any damages arising from the use of this software.
00007 Permission is granted to anyone to use this software for any purpose, 
00008 including commercial applications, and to alter it and redistribute it freely, 
00009 subject to the following restrictions:
00010 
00011 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.
00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00013 3. This notice may not be removed or altered from any source distribution.
00014 */
00015 
00016 #include "btConvexShape.h"
00017 #include "btTriangleShape.h"
00018 #include "btSphereShape.h"
00019 #include "btCylinderShape.h"
00020 #include "btCapsuleShape.h"
00021 #include "btConvexHullShape.h"
00022 #include "btConvexPointCloudShape.h"
00023 
00025 #if defined (__CELLOS_LV2__) && defined (__SPU__)
00026 #include <spu_intrinsics.h>
00027 static inline vec_float4 vec_dot3( vec_float4 vec0, vec_float4 vec1 )
00028 {
00029     vec_float4 result;
00030     result = spu_mul( vec0, vec1 );
00031     result = spu_madd( spu_rlqwbyte( vec0, 4 ), spu_rlqwbyte( vec1, 4 ), result );
00032     return spu_madd( spu_rlqwbyte( vec0, 8 ), spu_rlqwbyte( vec1, 8 ), result );
00033 }
00034 #endif //__SPU__
00035 
00036 btConvexShape::btConvexShape ()
00037 {
00038 }
00039 
00040 btConvexShape::~btConvexShape()
00041 {
00042 
00043 }
00044 
00045 
00046 
00047 static btVector3 convexHullSupport (const btVector3& localDirOrg, const btVector3* points, int numPoints, const btVector3& localScaling)
00048 {   
00049 
00050     btVector3 vec = localDirOrg * localScaling;
00051 
00052 #if defined (__CELLOS_LV2__) && defined (__SPU__)
00053 
00054     btVector3 localDir = vec;
00055 
00056     vec_float4 v_distMax = {-FLT_MAX,0,0,0};
00057     vec_int4 v_idxMax = {-999,0,0,0};
00058     int v=0;
00059     int numverts = numPoints;
00060 
00061     for(;v<(int)numverts-4;v+=4) {
00062         vec_float4 p0 = vec_dot3(points[v  ].get128(),localDir.get128());
00063         vec_float4 p1 = vec_dot3(points[v+1].get128(),localDir.get128());
00064         vec_float4 p2 = vec_dot3(points[v+2].get128(),localDir.get128());
00065         vec_float4 p3 = vec_dot3(points[v+3].get128(),localDir.get128());
00066         const vec_int4 i0 = {v  ,0,0,0};
00067         const vec_int4 i1 = {v+1,0,0,0};
00068         const vec_int4 i2 = {v+2,0,0,0};
00069         const vec_int4 i3 = {v+3,0,0,0};
00070         vec_uint4  retGt01 = spu_cmpgt(p0,p1);
00071         vec_float4 pmax01 = spu_sel(p1,p0,retGt01);
00072         vec_int4   imax01 = spu_sel(i1,i0,retGt01);
00073         vec_uint4  retGt23 = spu_cmpgt(p2,p3);
00074         vec_float4 pmax23 = spu_sel(p3,p2,retGt23);
00075         vec_int4   imax23 = spu_sel(i3,i2,retGt23);
00076         vec_uint4  retGt0123 = spu_cmpgt(pmax01,pmax23);
00077         vec_float4 pmax0123 = spu_sel(pmax23,pmax01,retGt0123);
00078         vec_int4   imax0123 = spu_sel(imax23,imax01,retGt0123);
00079         vec_uint4  retGtMax = spu_cmpgt(v_distMax,pmax0123);
00080         v_distMax = spu_sel(pmax0123,v_distMax,retGtMax);
00081         v_idxMax = spu_sel(imax0123,v_idxMax,retGtMax);
00082     }
00083     for(;v<(int)numverts;v++) {
00084         vec_float4 p = vec_dot3(points[v].get128(),localDir.get128());
00085         const vec_int4 i = {v,0,0,0};
00086         vec_uint4  retGtMax = spu_cmpgt(v_distMax,p);
00087         v_distMax = spu_sel(p,v_distMax,retGtMax);
00088         v_idxMax = spu_sel(i,v_idxMax,retGtMax);
00089     }
00090     int ptIndex = spu_extract(v_idxMax,0);
00091     const btVector3& supVec= points[ptIndex] * localScaling;
00092     return supVec;
00093 #else
00094 
00095     btScalar newDot,maxDot = btScalar(-BT_LARGE_FLOAT);
00096     int ptIndex = -1;
00097 
00098     for (int i=0;i<numPoints;i++)
00099     {
00100 
00101         newDot = vec.dot(points[i]);
00102         if (newDot > maxDot)
00103         {
00104             maxDot = newDot;
00105             ptIndex = i;
00106         }
00107     }
00108     btAssert(ptIndex >= 0);
00109     btVector3 supVec = points[ptIndex] * localScaling;
00110     return supVec;
00111 #endif //__SPU__
00112 }
00113 
00114 btVector3 btConvexShape::localGetSupportVertexWithoutMarginNonVirtual (const btVector3& localDir) const
00115 {
00116     switch (m_shapeType)
00117     {
00118     case SPHERE_SHAPE_PROXYTYPE:
00119     {
00120         return btVector3(0,0,0);
00121     }
00122     case BOX_SHAPE_PROXYTYPE:
00123     {
00124         btBoxShape* convexShape = (btBoxShape*)this;
00125         const btVector3& halfExtents = convexShape->getImplicitShapeDimensions();
00126 
00127         return btVector3(btFsels(localDir.x(), halfExtents.x(), -halfExtents.x()),
00128             btFsels(localDir.y(), halfExtents.y(), -halfExtents.y()),
00129             btFsels(localDir.z(), halfExtents.z(), -halfExtents.z()));
00130     }
00131     case TRIANGLE_SHAPE_PROXYTYPE:
00132     {
00133         btTriangleShape* triangleShape = (btTriangleShape*)this;
00134         btVector3 dir(localDir.getX(),localDir.getY(),localDir.getZ());
00135         btVector3* vertices = &triangleShape->m_vertices1[0];
00136         btVector3 dots(dir.dot(vertices[0]), dir.dot(vertices[1]), dir.dot(vertices[2]));
00137         btVector3 sup = vertices[dots.maxAxis()];
00138         return btVector3(sup.getX(),sup.getY(),sup.getZ());
00139     }
00140     case CYLINDER_SHAPE_PROXYTYPE:
00141     {
00142         btCylinderShape* cylShape = (btCylinderShape*)this;
00143         //mapping of halfextents/dimension onto radius/height depends on how cylinder local orientation is (upAxis)
00144 
00145         btVector3 halfExtents = cylShape->getImplicitShapeDimensions();
00146         btVector3 v(localDir.getX(),localDir.getY(),localDir.getZ());
00147         int cylinderUpAxis = cylShape->getUpAxis();
00148         int XX(1),YY(0),ZZ(2);
00149 
00150         switch (cylinderUpAxis)
00151         {
00152         case 0:
00153         {
00154             XX = 1;
00155             YY = 0;
00156             ZZ = 2;
00157         }
00158         break;
00159         case 1:
00160         {
00161             XX = 0;
00162             YY = 1;
00163             ZZ = 2; 
00164         }
00165         break;
00166         case 2:
00167         {
00168             XX = 0;
00169             YY = 2;
00170             ZZ = 1;
00171             
00172         }
00173         break;
00174         default:
00175             btAssert(0);
00176         break;
00177         };
00178 
00179         btScalar radius = halfExtents[XX];
00180         btScalar halfHeight = halfExtents[cylinderUpAxis];
00181 
00182         btVector3 tmp;
00183         btScalar d ;
00184 
00185         btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
00186         if (s != btScalar(0.0))
00187         {
00188             d = radius / s;  
00189             tmp[XX] = v[XX] * d;
00190             tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
00191             tmp[ZZ] = v[ZZ] * d;
00192             return btVector3(tmp.getX(),tmp.getY(),tmp.getZ());
00193         } else {
00194             tmp[XX] = radius;
00195             tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
00196             tmp[ZZ] = btScalar(0.0);
00197             return btVector3(tmp.getX(),tmp.getY(),tmp.getZ());
00198         }
00199     }
00200     case CAPSULE_SHAPE_PROXYTYPE:
00201     {
00202         btVector3 vec0(localDir.getX(),localDir.getY(),localDir.getZ());
00203 
00204         btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
00205         btScalar halfHeight = capsuleShape->getHalfHeight();
00206         int capsuleUpAxis = capsuleShape->getUpAxis();
00207 
00208         btScalar radius = capsuleShape->getRadius();
00209         btVector3 supVec(0,0,0);
00210 
00211         btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
00212 
00213         btVector3 vec = vec0;
00214         btScalar lenSqr = vec.length2();
00215         if (lenSqr < btScalar(0.0001))
00216         {
00217             vec.setValue(1,0,0);
00218         } else
00219         {
00220             btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
00221             vec *= rlen;
00222         }
00223         btVector3 vtx;
00224         btScalar newDot;
00225         {
00226             btVector3 pos(0,0,0);
00227             pos[capsuleUpAxis] = halfHeight;
00228 
00229             //vtx = pos +vec*(radius);
00230             vtx = pos +vec*capsuleShape->getLocalScalingNV()*(radius) - vec * capsuleShape->getMarginNV();
00231             newDot = vec.dot(vtx);
00232             
00233 
00234             if (newDot > maxDot)
00235             {
00236                 maxDot = newDot;
00237                 supVec = vtx;
00238             }
00239         }
00240         {
00241             btVector3 pos(0,0,0);
00242             pos[capsuleUpAxis] = -halfHeight;
00243 
00244             //vtx = pos +vec*(radius);
00245             vtx = pos +vec*capsuleShape->getLocalScalingNV()*(radius) - vec * capsuleShape->getMarginNV();
00246             newDot = vec.dot(vtx);
00247             if (newDot > maxDot)
00248             {
00249                 maxDot = newDot;
00250                 supVec = vtx;
00251             }
00252         }
00253         return btVector3(supVec.getX(),supVec.getY(),supVec.getZ());    
00254     }
00255     case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
00256     {
00257         btConvexPointCloudShape* convexPointCloudShape = (btConvexPointCloudShape*)this;
00258         btVector3* points = convexPointCloudShape->getUnscaledPoints ();
00259         int numPoints = convexPointCloudShape->getNumPoints ();
00260         return convexHullSupport (localDir, points, numPoints,convexPointCloudShape->getLocalScalingNV());
00261     }
00262     case CONVEX_HULL_SHAPE_PROXYTYPE:
00263     {
00264         btConvexHullShape* convexHullShape = (btConvexHullShape*)this;
00265         btVector3* points = convexHullShape->getUnscaledPoints();
00266         int numPoints = convexHullShape->getNumPoints ();
00267         return convexHullSupport (localDir, points, numPoints,convexHullShape->getLocalScalingNV());
00268     }
00269     default:
00270 #ifndef __SPU__
00271         return this->localGetSupportingVertexWithoutMargin (localDir);
00272 #else
00273         btAssert (0);
00274 #endif
00275     }
00276 
00277     // should never reach here
00278     btAssert (0);
00279     return btVector3 (btScalar(0.0f), btScalar(0.0f), btScalar(0.0f));
00280 }
00281 
00282 btVector3 btConvexShape::localGetSupportVertexNonVirtual (const btVector3& localDir) const
00283 {
00284     btVector3 localDirNorm = localDir;
00285     if (localDirNorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
00286     {
00287         localDirNorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
00288     }
00289     localDirNorm.normalize ();
00290 
00291     return localGetSupportVertexWithoutMarginNonVirtual(localDirNorm)+ getMarginNonVirtual() * localDirNorm;
00292 }
00293 
00294 /* TODO: This should be bumped up to btCollisionShape () */
00295 btScalar btConvexShape::getMarginNonVirtual () const
00296 {
00297     switch (m_shapeType)
00298     {
00299     case SPHERE_SHAPE_PROXYTYPE:
00300     {
00301         btSphereShape* sphereShape = (btSphereShape*)this;
00302         return sphereShape->getRadius ();
00303     }
00304     case BOX_SHAPE_PROXYTYPE:
00305     {
00306         btBoxShape* convexShape = (btBoxShape*)this;
00307         return convexShape->getMarginNV ();
00308     }
00309     case TRIANGLE_SHAPE_PROXYTYPE:
00310     {
00311         btTriangleShape* triangleShape = (btTriangleShape*)this;
00312         return triangleShape->getMarginNV ();
00313     }
00314     case CYLINDER_SHAPE_PROXYTYPE:
00315     {
00316         btCylinderShape* cylShape = (btCylinderShape*)this;
00317         return cylShape->getMarginNV();
00318     }
00319     case CAPSULE_SHAPE_PROXYTYPE:
00320     {
00321         btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
00322         return capsuleShape->getMarginNV();
00323     }
00324     case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
00325     /* fall through */
00326     case CONVEX_HULL_SHAPE_PROXYTYPE:
00327     {
00328         btPolyhedralConvexShape* convexHullShape = (btPolyhedralConvexShape*)this;
00329         return convexHullShape->getMarginNV();
00330     }
00331     default:
00332 #ifndef __SPU__
00333         return this->getMargin ();
00334 #else
00335         btAssert (0);
00336 #endif
00337     }
00338 
00339     // should never reach here
00340     btAssert (0);
00341     return btScalar(0.0f);
00342 }
00343 #ifndef __SPU__
00344 void btConvexShape::getAabbNonVirtual (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
00345 {
00346     switch (m_shapeType)
00347     {
00348     case SPHERE_SHAPE_PROXYTYPE:
00349     {
00350         btSphereShape* sphereShape = (btSphereShape*)this;
00351         btScalar radius = sphereShape->getImplicitShapeDimensions().getX();// * convexShape->getLocalScaling().getX();
00352         btScalar margin = radius + sphereShape->getMarginNonVirtual();
00353         const btVector3& center = t.getOrigin();
00354         btVector3 extent(margin,margin,margin);
00355         aabbMin = center - extent;
00356         aabbMax = center + extent;
00357     }
00358     break;
00359     case CYLINDER_SHAPE_PROXYTYPE:
00360     /* fall through */
00361     case BOX_SHAPE_PROXYTYPE:
00362     {
00363         btBoxShape* convexShape = (btBoxShape*)this;
00364         btScalar margin=convexShape->getMarginNonVirtual();
00365         btVector3 halfExtents = convexShape->getImplicitShapeDimensions();
00366         halfExtents += btVector3(margin,margin,margin);
00367         btMatrix3x3 abs_b = t.getBasis().absolute();  
00368         btVector3 center = t.getOrigin();
00369         btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents));
00370         
00371         aabbMin = center - extent;
00372         aabbMax = center + extent;
00373         break;
00374     }
00375     case TRIANGLE_SHAPE_PROXYTYPE:
00376     {
00377         btTriangleShape* triangleShape = (btTriangleShape*)this;
00378         btScalar margin = triangleShape->getMarginNonVirtual();
00379         for (int i=0;i<3;i++)
00380         {
00381             btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
00382             vec[i] = btScalar(1.);
00383 
00384             btVector3 sv = localGetSupportVertexWithoutMarginNonVirtual(vec*t.getBasis());
00385 
00386             btVector3 tmp = t(sv);
00387             aabbMax[i] = tmp[i]+margin;
00388             vec[i] = btScalar(-1.);
00389             tmp = t(localGetSupportVertexWithoutMarginNonVirtual(vec*t.getBasis()));
00390             aabbMin[i] = tmp[i]-margin;
00391         }   
00392     }
00393     break;
00394     case CAPSULE_SHAPE_PROXYTYPE:
00395     {
00396         btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
00397         btVector3 halfExtents(capsuleShape->getRadius(),capsuleShape->getRadius(),capsuleShape->getRadius());
00398         int m_upAxis = capsuleShape->getUpAxis();
00399         halfExtents[m_upAxis] = capsuleShape->getRadius() + capsuleShape->getHalfHeight();
00400         halfExtents += btVector3(capsuleShape->getMarginNonVirtual(),capsuleShape->getMarginNonVirtual(),capsuleShape->getMarginNonVirtual());
00401         btMatrix3x3 abs_b = t.getBasis().absolute();  
00402         btVector3 center = t.getOrigin();
00403         btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents));            
00404         aabbMin = center - extent;
00405         aabbMax = center + extent;
00406     }
00407     break;
00408     case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
00409     case CONVEX_HULL_SHAPE_PROXYTYPE:
00410     {
00411         btPolyhedralConvexAabbCachingShape* convexHullShape = (btPolyhedralConvexAabbCachingShape*)this;
00412         btScalar margin = convexHullShape->getMarginNonVirtual();
00413         convexHullShape->getNonvirtualAabb (t, aabbMin, aabbMax, margin);
00414     }
00415     break;
00416     default:
00417 #ifndef __SPU__
00418         this->getAabb (t, aabbMin, aabbMax);
00419 #else
00420         btAssert (0);
00421 #endif
00422     break;
00423     }
00424 
00425     // should never reach here
00426     btAssert (0);
00427 }
00428 
00429 #endif //__SPU__