123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458 |
- /*
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 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.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- #if defined(_WIN32) || defined(__i386__)
- #define BT_USE_SSE_IN_API
- #endif
- #include "btConvexShape.h"
- #include "btTriangleShape.h"
- #include "btSphereShape.h"
- #include "btCylinderShape.h"
- #include "btConeShape.h"
- #include "btCapsuleShape.h"
- #include "btConvexHullShape.h"
- #include "btConvexPointCloudShape.h"
- ///not supported on IBM SDK, until we fix the alignment of btVector3
- #if defined(__CELLOS_LV2__) && defined(__SPU__)
- #include <spu_intrinsics.h>
- static inline vec_float4 vec_dot3(vec_float4 vec0, vec_float4 vec1)
- {
- vec_float4 result;
- result = spu_mul(vec0, vec1);
- result = spu_madd(spu_rlqwbyte(vec0, 4), spu_rlqwbyte(vec1, 4), result);
- return spu_madd(spu_rlqwbyte(vec0, 8), spu_rlqwbyte(vec1, 8), result);
- }
- #endif //__SPU__
- btConvexShape::btConvexShape()
- {
- }
- btConvexShape::~btConvexShape()
- {
- }
- void btConvexShape::project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max, btVector3& witnesPtMin, btVector3& witnesPtMax) const
- {
- btVector3 localAxis = dir * trans.getBasis();
- btVector3 vtx1 = trans(localGetSupportingVertex(localAxis));
- btVector3 vtx2 = trans(localGetSupportingVertex(-localAxis));
- min = vtx1.dot(dir);
- max = vtx2.dot(dir);
- witnesPtMax = vtx2;
- witnesPtMin = vtx1;
- if (min > max)
- {
- btScalar tmp = min;
- min = max;
- max = tmp;
- witnesPtMax = vtx1;
- witnesPtMin = vtx2;
- }
- }
- static btVector3 convexHullSupport(const btVector3& localDirOrg, const btVector3* points, int numPoints, const btVector3& localScaling)
- {
- btVector3 vec = localDirOrg * localScaling;
- #if defined(__CELLOS_LV2__) && defined(__SPU__)
- btVector3 localDir = vec;
- vec_float4 v_distMax = {-FLT_MAX, 0, 0, 0};
- vec_int4 v_idxMax = {-999, 0, 0, 0};
- int v = 0;
- int numverts = numPoints;
- for (; v < (int)numverts - 4; v += 4)
- {
- vec_float4 p0 = vec_dot3(points[v].get128(), localDir.get128());
- vec_float4 p1 = vec_dot3(points[v + 1].get128(), localDir.get128());
- vec_float4 p2 = vec_dot3(points[v + 2].get128(), localDir.get128());
- vec_float4 p3 = vec_dot3(points[v + 3].get128(), localDir.get128());
- const vec_int4 i0 = {v, 0, 0, 0};
- const vec_int4 i1 = {v + 1, 0, 0, 0};
- const vec_int4 i2 = {v + 2, 0, 0, 0};
- const vec_int4 i3 = {v + 3, 0, 0, 0};
- vec_uint4 retGt01 = spu_cmpgt(p0, p1);
- vec_float4 pmax01 = spu_sel(p1, p0, retGt01);
- vec_int4 imax01 = spu_sel(i1, i0, retGt01);
- vec_uint4 retGt23 = spu_cmpgt(p2, p3);
- vec_float4 pmax23 = spu_sel(p3, p2, retGt23);
- vec_int4 imax23 = spu_sel(i3, i2, retGt23);
- vec_uint4 retGt0123 = spu_cmpgt(pmax01, pmax23);
- vec_float4 pmax0123 = spu_sel(pmax23, pmax01, retGt0123);
- vec_int4 imax0123 = spu_sel(imax23, imax01, retGt0123);
- vec_uint4 retGtMax = spu_cmpgt(v_distMax, pmax0123);
- v_distMax = spu_sel(pmax0123, v_distMax, retGtMax);
- v_idxMax = spu_sel(imax0123, v_idxMax, retGtMax);
- }
- for (; v < (int)numverts; v++)
- {
- vec_float4 p = vec_dot3(points[v].get128(), localDir.get128());
- const vec_int4 i = {v, 0, 0, 0};
- vec_uint4 retGtMax = spu_cmpgt(v_distMax, p);
- v_distMax = spu_sel(p, v_distMax, retGtMax);
- v_idxMax = spu_sel(i, v_idxMax, retGtMax);
- }
- int ptIndex = spu_extract(v_idxMax, 0);
- const btVector3& supVec = points[ptIndex] * localScaling;
- return supVec;
- #else
- btScalar maxDot;
- long ptIndex = vec.maxDot(points, numPoints, maxDot);
- btAssert(ptIndex >= 0);
- if (ptIndex < 0)
- {
- ptIndex = 0;
- }
- btVector3 supVec = points[ptIndex] * localScaling;
- return supVec;
- #endif //__SPU__
- }
- btVector3 btConvexShape::localGetSupportVertexWithoutMarginNonVirtual(const btVector3& localDir) const
- {
- switch (m_shapeType)
- {
- case SPHERE_SHAPE_PROXYTYPE:
- {
- return btVector3(0, 0, 0);
- }
- case BOX_SHAPE_PROXYTYPE:
- {
- btBoxShape* convexShape = (btBoxShape*)this;
- const btVector3& halfExtents = convexShape->getImplicitShapeDimensions();
- #if defined(__APPLE__) && (defined(BT_USE_SSE) || defined(BT_USE_NEON))
- #if defined(BT_USE_SSE)
- return btVector3(_mm_xor_ps(_mm_and_ps(localDir.mVec128, (__m128){-0.0f, -0.0f, -0.0f, -0.0f}), halfExtents.mVec128));
- #elif defined(BT_USE_NEON)
- return btVector3((float32x4_t)(((uint32x4_t)localDir.mVec128 & (uint32x4_t){0x80000000, 0x80000000, 0x80000000, 0x80000000}) ^ (uint32x4_t)halfExtents.mVec128));
- #else
- #error unknown vector arch
- #endif
- #else
- return btVector3(btFsels(localDir.x(), halfExtents.x(), -halfExtents.x()),
- btFsels(localDir.y(), halfExtents.y(), -halfExtents.y()),
- btFsels(localDir.z(), halfExtents.z(), -halfExtents.z()));
- #endif
- }
- case TRIANGLE_SHAPE_PROXYTYPE:
- {
- btTriangleShape* triangleShape = (btTriangleShape*)this;
- btVector3 dir(localDir.getX(), localDir.getY(), localDir.getZ());
- btVector3* vertices = &triangleShape->m_vertices1[0];
- btVector3 dots = dir.dot3(vertices[0], vertices[1], vertices[2]);
- btVector3 sup = vertices[dots.maxAxis()];
- return btVector3(sup.getX(), sup.getY(), sup.getZ());
- }
- case CYLINDER_SHAPE_PROXYTYPE:
- {
- btCylinderShape* cylShape = (btCylinderShape*)this;
- //mapping of halfextents/dimension onto radius/height depends on how cylinder local orientation is (upAxis)
- btVector3 halfExtents = cylShape->getImplicitShapeDimensions();
- btVector3 v(localDir.getX(), localDir.getY(), localDir.getZ());
- int cylinderUpAxis = cylShape->getUpAxis();
- int XX(1), YY(0), ZZ(2);
- switch (cylinderUpAxis)
- {
- case 0:
- {
- XX = 1;
- YY = 0;
- ZZ = 2;
- }
- break;
- case 1:
- {
- XX = 0;
- YY = 1;
- ZZ = 2;
- }
- break;
- case 2:
- {
- XX = 0;
- YY = 2;
- ZZ = 1;
- }
- break;
- default:
- btAssert(0);
- break;
- };
- btScalar radius = halfExtents[XX];
- btScalar halfHeight = halfExtents[cylinderUpAxis];
- btVector3 tmp;
- btScalar d;
- btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
- if (s != btScalar(0.0))
- {
- d = radius / s;
- tmp[XX] = v[XX] * d;
- tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
- tmp[ZZ] = v[ZZ] * d;
- return btVector3(tmp.getX(), tmp.getY(), tmp.getZ());
- }
- else
- {
- tmp[XX] = radius;
- tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
- tmp[ZZ] = btScalar(0.0);
- return btVector3(tmp.getX(), tmp.getY(), tmp.getZ());
- }
- }
- case CAPSULE_SHAPE_PROXYTYPE:
- {
- btVector3 vec0(localDir.getX(), localDir.getY(), localDir.getZ());
- btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
- btScalar halfHeight = capsuleShape->getHalfHeight();
- int capsuleUpAxis = capsuleShape->getUpAxis();
- btVector3 supVec(0, 0, 0);
- btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
- btVector3 vec = vec0;
- btScalar lenSqr = vec.length2();
- if (lenSqr < SIMD_EPSILON * SIMD_EPSILON)
- {
- vec.setValue(1, 0, 0);
- }
- else
- {
- btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
- vec *= rlen;
- }
- btVector3 vtx;
- btScalar newDot;
- {
- btVector3 pos(0, 0, 0);
- pos[capsuleUpAxis] = halfHeight;
- vtx = pos;
- newDot = vec.dot(vtx);
- if (newDot > maxDot)
- {
- maxDot = newDot;
- supVec = vtx;
- }
- }
- {
- btVector3 pos(0, 0, 0);
- pos[capsuleUpAxis] = -halfHeight;
- vtx = pos;
- newDot = vec.dot(vtx);
- if (newDot > maxDot)
- {
- maxDot = newDot;
- supVec = vtx;
- }
- }
- return btVector3(supVec.getX(), supVec.getY(), supVec.getZ());
- }
- case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
- {
- btConvexPointCloudShape* convexPointCloudShape = (btConvexPointCloudShape*)this;
- btVector3* points = convexPointCloudShape->getUnscaledPoints();
- int numPoints = convexPointCloudShape->getNumPoints();
- return convexHullSupport(localDir, points, numPoints, convexPointCloudShape->getLocalScalingNV());
- }
- case CONVEX_HULL_SHAPE_PROXYTYPE:
- {
- btConvexHullShape* convexHullShape = (btConvexHullShape*)this;
- btVector3* points = convexHullShape->getUnscaledPoints();
- int numPoints = convexHullShape->getNumPoints();
- return convexHullSupport(localDir, points, numPoints, convexHullShape->getLocalScalingNV());
- }
- default:
- #ifndef __SPU__
- return this->localGetSupportingVertexWithoutMargin(localDir);
- #else
- btAssert(0);
- #endif
- }
- // should never reach here
- btAssert(0);
- return btVector3(btScalar(0.0f), btScalar(0.0f), btScalar(0.0f));
- }
- btVector3 btConvexShape::localGetSupportVertexNonVirtual(const btVector3& localDir) const
- {
- btVector3 localDirNorm = localDir;
- if (localDirNorm.length2() < (SIMD_EPSILON * SIMD_EPSILON))
- {
- localDirNorm.setValue(btScalar(-1.), btScalar(-1.), btScalar(-1.));
- }
- localDirNorm.normalize();
- return localGetSupportVertexWithoutMarginNonVirtual(localDirNorm) + getMarginNonVirtual() * localDirNorm;
- }
- /* TODO: This should be bumped up to btCollisionShape () */
- btScalar btConvexShape::getMarginNonVirtual() const
- {
- switch (m_shapeType)
- {
- case SPHERE_SHAPE_PROXYTYPE:
- {
- btSphereShape* sphereShape = (btSphereShape*)this;
- return sphereShape->getRadius();
- }
- case BOX_SHAPE_PROXYTYPE:
- {
- btBoxShape* convexShape = (btBoxShape*)this;
- return convexShape->getMarginNV();
- }
- case TRIANGLE_SHAPE_PROXYTYPE:
- {
- btTriangleShape* triangleShape = (btTriangleShape*)this;
- return triangleShape->getMarginNV();
- }
- case CYLINDER_SHAPE_PROXYTYPE:
- {
- btCylinderShape* cylShape = (btCylinderShape*)this;
- return cylShape->getMarginNV();
- }
- case CONE_SHAPE_PROXYTYPE:
- {
- btConeShape* conShape = (btConeShape*)this;
- return conShape->getMarginNV();
- }
- case CAPSULE_SHAPE_PROXYTYPE:
- {
- btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
- return capsuleShape->getMarginNV();
- }
- case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
- /* fall through */
- case CONVEX_HULL_SHAPE_PROXYTYPE:
- {
- btPolyhedralConvexShape* convexHullShape = (btPolyhedralConvexShape*)this;
- return convexHullShape->getMarginNV();
- }
- default:
- #ifndef __SPU__
- return this->getMargin();
- #else
- btAssert(0);
- #endif
- }
- // should never reach here
- btAssert(0);
- return btScalar(0.0f);
- }
- #ifndef __SPU__
- void btConvexShape::getAabbNonVirtual(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
- {
- switch (m_shapeType)
- {
- case SPHERE_SHAPE_PROXYTYPE:
- {
- btSphereShape* sphereShape = (btSphereShape*)this;
- btScalar radius = sphereShape->getImplicitShapeDimensions().getX(); // * convexShape->getLocalScaling().getX();
- btScalar margin = radius + sphereShape->getMarginNonVirtual();
- const btVector3& center = t.getOrigin();
- btVector3 extent(margin, margin, margin);
- aabbMin = center - extent;
- aabbMax = center + extent;
- }
- break;
- case CYLINDER_SHAPE_PROXYTYPE:
- /* fall through */
- case BOX_SHAPE_PROXYTYPE:
- {
- btBoxShape* convexShape = (btBoxShape*)this;
- btScalar margin = convexShape->getMarginNonVirtual();
- btVector3 halfExtents = convexShape->getImplicitShapeDimensions();
- halfExtents += btVector3(margin, margin, margin);
- btMatrix3x3 abs_b = t.getBasis().absolute();
- btVector3 center = t.getOrigin();
- btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
- aabbMin = center - extent;
- aabbMax = center + extent;
- break;
- }
- case TRIANGLE_SHAPE_PROXYTYPE:
- {
- btTriangleShape* triangleShape = (btTriangleShape*)this;
- btScalar margin = triangleShape->getMarginNonVirtual();
- for (int i = 0; i < 3; i++)
- {
- btVector3 vec(btScalar(0.), btScalar(0.), btScalar(0.));
- vec[i] = btScalar(1.);
- btVector3 sv = localGetSupportVertexWithoutMarginNonVirtual(vec * t.getBasis());
- btVector3 tmp = t(sv);
- aabbMax[i] = tmp[i] + margin;
- vec[i] = btScalar(-1.);
- tmp = t(localGetSupportVertexWithoutMarginNonVirtual(vec * t.getBasis()));
- aabbMin[i] = tmp[i] - margin;
- }
- }
- break;
- case CAPSULE_SHAPE_PROXYTYPE:
- {
- btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
- btVector3 halfExtents(capsuleShape->getRadius(), capsuleShape->getRadius(), capsuleShape->getRadius());
- int m_upAxis = capsuleShape->getUpAxis();
- halfExtents[m_upAxis] = capsuleShape->getRadius() + capsuleShape->getHalfHeight();
- btMatrix3x3 abs_b = t.getBasis().absolute();
- btVector3 center = t.getOrigin();
- btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
- aabbMin = center - extent;
- aabbMax = center + extent;
- }
- break;
- case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
- case CONVEX_HULL_SHAPE_PROXYTYPE:
- {
- btPolyhedralConvexAabbCachingShape* convexHullShape = (btPolyhedralConvexAabbCachingShape*)this;
- btScalar margin = convexHullShape->getMarginNonVirtual();
- convexHullShape->getNonvirtualAabb(t, aabbMin, aabbMax, margin);
- }
- break;
- default:
- #ifndef __SPU__
- this->getAabb(t, aabbMin, aabbMax);
- #else
- btAssert(0);
- #endif
- break;
- }
- // should never reach here
- btAssert(0);
- }
- #endif //__SPU__
|