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__

Generated on Mon Feb 15 22:17:03 2010 for Bullet Collision Detection & Physics Library by  doxygen 1.6.1