Code-style consistency improvement:
Apply clang-format-all.sh using the _clang-format file through all the cpp/.h files. make sure not to apply it to certain serialization structures, since some parser expects the * as part of the name, instead of type. This commit contains no other changes aside from adding and applying clang-format-all.sh
This commit is contained in:
@@ -5,14 +5,13 @@
|
||||
|
||||
struct b3BvhInfo
|
||||
{
|
||||
b3Vector3 m_aabbMin;
|
||||
b3Vector3 m_aabbMax;
|
||||
b3Vector3 m_quantization;
|
||||
int m_numNodes;
|
||||
int m_numSubTrees;
|
||||
int m_nodeOffset;
|
||||
int m_subTreeOffset;
|
||||
|
||||
b3Vector3 m_aabbMin;
|
||||
b3Vector3 m_aabbMax;
|
||||
b3Vector3 m_quantization;
|
||||
int m_numNodes;
|
||||
int m_numSubTrees;
|
||||
int m_nodeOffset;
|
||||
int m_subTreeOffset;
|
||||
};
|
||||
|
||||
#endif //B3_BVH_INFO_H
|
||||
#endif //B3_BVH_INFO_H
|
||||
@@ -15,7 +15,6 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "b3ContactCache.h"
|
||||
#include "Bullet3Common/b3Transform.h"
|
||||
|
||||
@@ -69,7 +68,7 @@ int b3ContactCache::sortCachedPoints(const b3Vector3& pt)
|
||||
maxPenetration = m_pointCache[i].getDistance();
|
||||
}
|
||||
}
|
||||
#endif //KEEP_DEEPEST_POINT
|
||||
#endif //KEEP_DEEPEST_POINT
|
||||
|
||||
b3Scalar res0(b3Scalar(0.)),res1(b3Scalar(0.)),res2(b3Scalar(0.)),res3(b3Scalar(0.));
|
||||
|
||||
@@ -251,8 +250,4 @@ void b3ContactCache::refreshContactPoints(const b3Transform& trA,const b3Transfo
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -17,17 +17,13 @@ subject to the following restrictions:
|
||||
#ifndef B3_CONTACT_CACHE_H
|
||||
#define B3_CONTACT_CACHE_H
|
||||
|
||||
|
||||
#include "Bullet3Common/b3Vector3.h"
|
||||
#include "Bullet3Common/b3Transform.h"
|
||||
#include "Bullet3Common/b3AlignedAllocator.h"
|
||||
|
||||
|
||||
///maximum contact breaking and merging threshold
|
||||
extern b3Scalar gContactBreakingThreshold;
|
||||
|
||||
|
||||
|
||||
#define MANIFOLD_CACHE_SIZE 4
|
||||
|
||||
///b3ContactCache is a contact point cache, it stays persistent as long as objects are overlapping in the broadphase.
|
||||
@@ -37,24 +33,16 @@ extern b3Scalar gContactBreakingThreshold;
|
||||
///reduces the cache to 4 points, when more then 4 points are added, using following rules:
|
||||
///the contact point with deepest penetration is always kept, and it tries to maximuze the area covered by the points
|
||||
///note that some pairs of objects might have more then one contact manifold.
|
||||
B3_ATTRIBUTE_ALIGNED16( class) b3ContactCache
|
||||
B3_ATTRIBUTE_ALIGNED16(class)
|
||||
b3ContactCache
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
/// sort cached points so most isolated points come first
|
||||
int sortCachedPoints(const b3Vector3& pt);
|
||||
|
||||
|
||||
int sortCachedPoints(const b3Vector3& pt);
|
||||
|
||||
public:
|
||||
|
||||
B3_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
|
||||
|
||||
int addManifoldPoint( const b3Vector3& newPoint);
|
||||
int addManifoldPoint(const b3Vector3& newPoint);
|
||||
|
||||
/*void replaceContactPoint(const b3Vector3& newPoint,int insertIndex)
|
||||
{
|
||||
@@ -63,18 +51,12 @@ public:
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
static bool validContactDistance(const b3Vector3& pt);
|
||||
|
||||
|
||||
/// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin
|
||||
static void refreshContactPoints( const b3Transform& trA,const b3Transform& trB, struct b3Contact4Data& newContactCache);
|
||||
|
||||
static void removeContactPoint(struct b3Contact4Data& newContactCache,int i);
|
||||
|
||||
static void refreshContactPoints(const b3Transform& trA, const b3Transform& trB, struct b3Contact4Data& newContactCache);
|
||||
|
||||
static void removeContactPoint(struct b3Contact4Data & newContactCache, int i);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //B3_CONTACT_CACHE_H
|
||||
#endif //B3_CONTACT_CACHE_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,102 +17,90 @@
|
||||
|
||||
//#include "../../dynamics/basic_demo/Stubs/ChNarrowPhase.h"
|
||||
|
||||
|
||||
|
||||
|
||||
struct GpuSatCollision
|
||||
{
|
||||
cl_context m_context;
|
||||
cl_device_id m_device;
|
||||
cl_command_queue m_queue;
|
||||
cl_kernel m_findSeparatingAxisKernel;
|
||||
cl_kernel m_mprPenetrationKernel;
|
||||
cl_kernel m_findSeparatingAxisUnitSphereKernel;
|
||||
|
||||
cl_context m_context;
|
||||
cl_device_id m_device;
|
||||
cl_command_queue m_queue;
|
||||
cl_kernel m_findSeparatingAxisKernel;
|
||||
cl_kernel m_mprPenetrationKernel;
|
||||
cl_kernel m_findSeparatingAxisUnitSphereKernel;
|
||||
|
||||
cl_kernel m_findSeparatingAxisVertexFaceKernel;
|
||||
cl_kernel m_findSeparatingAxisEdgeEdgeKernel;
|
||||
|
||||
cl_kernel m_findConcaveSeparatingAxisKernel;
|
||||
cl_kernel m_findConcaveSeparatingAxisVertexFaceKernel;
|
||||
cl_kernel m_findConcaveSeparatingAxisEdgeEdgeKernel;
|
||||
|
||||
|
||||
|
||||
|
||||
cl_kernel m_findCompoundPairsKernel;
|
||||
cl_kernel m_processCompoundPairsKernel;
|
||||
|
||||
cl_kernel m_clipHullHullKernel;
|
||||
cl_kernel m_clipCompoundsHullHullKernel;
|
||||
|
||||
cl_kernel m_clipFacesAndFindContacts;
|
||||
cl_kernel m_findClippingFacesKernel;
|
||||
|
||||
cl_kernel m_clipHullHullConcaveConvexKernel;
|
||||
// cl_kernel m_extractManifoldAndAddContactKernel;
|
||||
cl_kernel m_newContactReductionKernel;
|
||||
cl_kernel m_findConcaveSeparatingAxisKernel;
|
||||
cl_kernel m_findConcaveSeparatingAxisVertexFaceKernel;
|
||||
cl_kernel m_findConcaveSeparatingAxisEdgeEdgeKernel;
|
||||
|
||||
cl_kernel m_bvhTraversalKernel;
|
||||
cl_kernel m_primitiveContactsKernel;
|
||||
cl_kernel m_findConcaveSphereContactsKernel;
|
||||
cl_kernel m_findCompoundPairsKernel;
|
||||
cl_kernel m_processCompoundPairsKernel;
|
||||
|
||||
cl_kernel m_clipHullHullKernel;
|
||||
cl_kernel m_clipCompoundsHullHullKernel;
|
||||
|
||||
cl_kernel m_clipFacesAndFindContacts;
|
||||
cl_kernel m_findClippingFacesKernel;
|
||||
|
||||
cl_kernel m_clipHullHullConcaveConvexKernel;
|
||||
// cl_kernel m_extractManifoldAndAddContactKernel;
|
||||
cl_kernel m_newContactReductionKernel;
|
||||
|
||||
cl_kernel m_bvhTraversalKernel;
|
||||
cl_kernel m_primitiveContactsKernel;
|
||||
cl_kernel m_findConcaveSphereContactsKernel;
|
||||
|
||||
cl_kernel m_processCompoundPairsPrimitivesKernel;
|
||||
|
||||
cl_kernel m_processCompoundPairsPrimitivesKernel;
|
||||
|
||||
b3OpenCLArray<b3Vector3> m_unitSphereDirections;
|
||||
|
||||
b3OpenCLArray<int> m_totalContactsOut;
|
||||
b3OpenCLArray<int> m_totalContactsOut;
|
||||
|
||||
b3OpenCLArray<b3Vector3> m_sepNormals;
|
||||
b3OpenCLArray<float> m_dmins;
|
||||
|
||||
b3OpenCLArray<int> m_hasSeparatingNormals;
|
||||
b3OpenCLArray<int> m_hasSeparatingNormals;
|
||||
b3OpenCLArray<b3Vector3> m_concaveSepNormals;
|
||||
b3OpenCLArray<int> m_concaveHasSeparatingNormals;
|
||||
b3OpenCLArray<int> m_numConcavePairsOut;
|
||||
b3OpenCLArray<int> m_concaveHasSeparatingNormals;
|
||||
b3OpenCLArray<int> m_numConcavePairsOut;
|
||||
b3OpenCLArray<b3CompoundOverlappingPair> m_gpuCompoundPairs;
|
||||
b3OpenCLArray<b3Vector3> m_gpuCompoundSepNormals;
|
||||
b3OpenCLArray<int> m_gpuHasCompoundSepNormals;
|
||||
b3OpenCLArray<int> m_numCompoundPairsOut;
|
||||
|
||||
b3OpenCLArray<int> m_gpuHasCompoundSepNormals;
|
||||
b3OpenCLArray<int> m_numCompoundPairsOut;
|
||||
|
||||
GpuSatCollision(cl_context ctx,cl_device_id device, cl_command_queue q );
|
||||
GpuSatCollision(cl_context ctx, cl_device_id device, cl_command_queue q);
|
||||
virtual ~GpuSatCollision();
|
||||
|
||||
|
||||
void computeConvexConvexContactsGPUSAT( b3OpenCLArray<b3Int4>* pairs, int nPairs,
|
||||
const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
|
||||
b3OpenCLArray<b3Contact4>* contactOut, int& nContacts,
|
||||
const b3OpenCLArray<b3Contact4>* oldContacts,
|
||||
int maxContactCapacity,
|
||||
int compoundPairCapacity,
|
||||
const b3OpenCLArray<b3ConvexPolyhedronData>& hostConvexData,
|
||||
const b3OpenCLArray<b3Vector3>& vertices,
|
||||
const b3OpenCLArray<b3Vector3>& uniqueEdges,
|
||||
const b3OpenCLArray<b3GpuFace>& faces,
|
||||
const b3OpenCLArray<int>& indices,
|
||||
const b3OpenCLArray<b3Collidable>& gpuCollidables,
|
||||
const b3OpenCLArray<b3GpuChildShape>& gpuChildShapes,
|
||||
|
||||
const b3OpenCLArray<b3Aabb>& clAabbsWorldSpace,
|
||||
const b3OpenCLArray<b3Aabb>& clAabbsLocalSpace,
|
||||
|
||||
b3OpenCLArray<b3Vector3>& worldVertsB1GPU,
|
||||
b3OpenCLArray<b3Int4>& clippingFacesOutGPU,
|
||||
b3OpenCLArray<b3Vector3>& worldNormalsAGPU,
|
||||
b3OpenCLArray<b3Vector3>& worldVertsA1GPU,
|
||||
b3OpenCLArray<b3Vector3>& worldVertsB2GPU,
|
||||
b3AlignedObjectArray<class b3OptimizedBvh*>& bvhData,
|
||||
b3OpenCLArray<b3QuantizedBvhNode>* treeNodesGPU,
|
||||
b3OpenCLArray<b3BvhSubtreeInfo>* subTreesGPU,
|
||||
b3OpenCLArray<b3BvhInfo>* bvhInfo,
|
||||
int numObjects,
|
||||
int maxTriConvexPairCapacity,
|
||||
b3OpenCLArray<b3Int4>& triangleConvexPairs,
|
||||
int& numTriConvexPairsOut
|
||||
);
|
||||
void computeConvexConvexContactsGPUSAT(b3OpenCLArray<b3Int4>* pairs, int nPairs,
|
||||
const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
|
||||
b3OpenCLArray<b3Contact4>* contactOut, int& nContacts,
|
||||
const b3OpenCLArray<b3Contact4>* oldContacts,
|
||||
int maxContactCapacity,
|
||||
int compoundPairCapacity,
|
||||
const b3OpenCLArray<b3ConvexPolyhedronData>& hostConvexData,
|
||||
const b3OpenCLArray<b3Vector3>& vertices,
|
||||
const b3OpenCLArray<b3Vector3>& uniqueEdges,
|
||||
const b3OpenCLArray<b3GpuFace>& faces,
|
||||
const b3OpenCLArray<int>& indices,
|
||||
const b3OpenCLArray<b3Collidable>& gpuCollidables,
|
||||
const b3OpenCLArray<b3GpuChildShape>& gpuChildShapes,
|
||||
|
||||
const b3OpenCLArray<b3Aabb>& clAabbsWorldSpace,
|
||||
const b3OpenCLArray<b3Aabb>& clAabbsLocalSpace,
|
||||
|
||||
b3OpenCLArray<b3Vector3>& worldVertsB1GPU,
|
||||
b3OpenCLArray<b3Int4>& clippingFacesOutGPU,
|
||||
b3OpenCLArray<b3Vector3>& worldNormalsAGPU,
|
||||
b3OpenCLArray<b3Vector3>& worldVertsA1GPU,
|
||||
b3OpenCLArray<b3Vector3>& worldVertsB2GPU,
|
||||
b3AlignedObjectArray<class b3OptimizedBvh*>& bvhData,
|
||||
b3OpenCLArray<b3QuantizedBvhNode>* treeNodesGPU,
|
||||
b3OpenCLArray<b3BvhSubtreeInfo>* subTreesGPU,
|
||||
b3OpenCLArray<b3BvhInfo>* bvhInfo,
|
||||
int numObjects,
|
||||
int maxTriConvexPairCapacity,
|
||||
b3OpenCLArray<b3Int4>& triangleConvexPairs,
|
||||
int& numTriConvexPairsOut);
|
||||
};
|
||||
|
||||
#endif //_CONVEX_HULL_CONTACT_H
|
||||
#endif //_CONVEX_HULL_CONTACT_H
|
||||
|
||||
@@ -4,6 +4,4 @@
|
||||
#include "Bullet3Common/b3Transform.h"
|
||||
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
|
||||
|
||||
|
||||
|
||||
#endif //CONVEX_POLYHEDRON_CL
|
||||
#endif //CONVEX_POLYHEDRON_CL
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,40 +29,39 @@ GJK-EPA collision solver by Nathanael Presson, 2008
|
||||
#include "Bullet3Common/b3Transform.h"
|
||||
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
|
||||
|
||||
|
||||
///btGjkEpaSolver contributed under zlib by Nathanael Presson
|
||||
struct b3GjkEpaSolver2
|
||||
struct b3GjkEpaSolver2
|
||||
{
|
||||
struct sResults
|
||||
struct sResults
|
||||
{
|
||||
enum eStatus
|
||||
enum eStatus
|
||||
{
|
||||
Separated, /* Shapes doesnt penetrate */
|
||||
Penetrating, /* Shapes are penetrating */
|
||||
GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */
|
||||
EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */
|
||||
} status;
|
||||
b3Vector3 witnesses[2];
|
||||
b3Vector3 normal;
|
||||
b3Scalar distance;
|
||||
Separated, /* Shapes doesnt penetrate */
|
||||
Penetrating, /* Shapes are penetrating */
|
||||
GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */
|
||||
EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */
|
||||
} status;
|
||||
b3Vector3 witnesses[2];
|
||||
b3Vector3 normal;
|
||||
b3Scalar distance;
|
||||
};
|
||||
|
||||
static int StackSizeRequirement();
|
||||
static int StackSizeRequirement();
|
||||
|
||||
static bool Distance( const b3Transform& transA, const b3Transform& transB,
|
||||
const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
|
||||
const b3AlignedObjectArray<b3Vector3>& verticesA,
|
||||
const b3AlignedObjectArray<b3Vector3>& verticesB,
|
||||
const b3Vector3& guess,
|
||||
sResults& results);
|
||||
static bool Distance(const b3Transform& transA, const b3Transform& transB,
|
||||
const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
|
||||
const b3AlignedObjectArray<b3Vector3>& verticesA,
|
||||
const b3AlignedObjectArray<b3Vector3>& verticesB,
|
||||
const b3Vector3& guess,
|
||||
sResults& results);
|
||||
|
||||
static bool Penetration( const b3Transform& transA, const b3Transform& transB,
|
||||
const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
|
||||
static bool Penetration(const b3Transform& transA, const b3Transform& transB,
|
||||
const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
|
||||
const b3AlignedObjectArray<b3Vector3>& verticesA,
|
||||
const b3AlignedObjectArray<b3Vector3>& verticesB,
|
||||
const b3Vector3& guess,
|
||||
sResults& results,
|
||||
bool usemargins=true);
|
||||
bool usemargins = true);
|
||||
#if 0
|
||||
static b3Scalar SignedDistance( const b3Vector3& position,
|
||||
b3Scalar margin,
|
||||
@@ -74,9 +73,7 @@ static bool SignedDistance( const btConvexShape* shape0,const btTransform& wtrs
|
||||
const btConvexShape* shape1,const btTransform& wtrs1,
|
||||
const b3Vector3& guess,
|
||||
sResults& results);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif //B3_GJK_EPA2_H
|
||||
|
||||
#endif //B3_GJK_EPA2_H
|
||||
|
||||
@@ -13,50 +13,45 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "b3OptimizedBvh.h"
|
||||
#include "b3StridingMeshInterface.h"
|
||||
#include "Bullet3Geometry/b3AabbUtil.h"
|
||||
|
||||
|
||||
b3OptimizedBvh::b3OptimizedBvh()
|
||||
{
|
||||
{
|
||||
}
|
||||
|
||||
b3OptimizedBvh::~b3OptimizedBvh()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void b3OptimizedBvh::build(b3StridingMeshInterface* triangles, bool useQuantizedAabbCompression, const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax)
|
||||
{
|
||||
m_useQuantization = useQuantizedAabbCompression;
|
||||
|
||||
|
||||
// NodeArray triangleNodes;
|
||||
|
||||
struct NodeTriangleCallback : public b3InternalTriangleIndexCallback
|
||||
struct NodeTriangleCallback : public b3InternalTriangleIndexCallback
|
||||
{
|
||||
|
||||
NodeArray& m_triangleNodes;
|
||||
NodeArray& m_triangleNodes;
|
||||
|
||||
NodeTriangleCallback& operator=(NodeTriangleCallback& other)
|
||||
{
|
||||
m_triangleNodes.copyFromArray(other.m_triangleNodes);
|
||||
return *this;
|
||||
}
|
||||
|
||||
NodeTriangleCallback(NodeArray& triangleNodes)
|
||||
:m_triangleNodes(triangleNodes)
|
||||
|
||||
NodeTriangleCallback(NodeArray& triangleNodes)
|
||||
: m_triangleNodes(triangleNodes)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void internalProcessTriangleIndex(b3Vector3* triangle,int partId,int triangleIndex)
|
||||
virtual void internalProcessTriangleIndex(b3Vector3* triangle, int partId, int triangleIndex)
|
||||
{
|
||||
b3OptimizedBvhNode node;
|
||||
b3Vector3 aabbMin,aabbMax;
|
||||
aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT));
|
||||
aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT));
|
||||
b3Vector3 aabbMin, aabbMax;
|
||||
aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
|
||||
aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
|
||||
aabbMin.setMin(triangle[0]);
|
||||
aabbMax.setMax(triangle[0]);
|
||||
aabbMin.setMin(triangle[1]);
|
||||
@@ -69,17 +64,17 @@ void b3OptimizedBvh::build(b3StridingMeshInterface* triangles, bool useQuantized
|
||||
node.m_aabbMaxOrg = aabbMax;
|
||||
|
||||
node.m_escapeIndex = -1;
|
||||
|
||||
|
||||
//for child nodes
|
||||
node.m_subPart = partId;
|
||||
node.m_triangleIndex = triangleIndex;
|
||||
m_triangleNodes.push_back(node);
|
||||
}
|
||||
};
|
||||
struct QuantizedNodeTriangleCallback : public b3InternalTriangleIndexCallback
|
||||
struct QuantizedNodeTriangleCallback : public b3InternalTriangleIndexCallback
|
||||
{
|
||||
QuantizedNodeArray& m_triangleNodes;
|
||||
const b3QuantizedBvh* m_optimizedTree; // for quantization
|
||||
QuantizedNodeArray& m_triangleNodes;
|
||||
const b3QuantizedBvh* m_optimizedTree; // for quantization
|
||||
|
||||
QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other)
|
||||
{
|
||||
@@ -88,23 +83,23 @@ void b3OptimizedBvh::build(b3StridingMeshInterface* triangles, bool useQuantized
|
||||
return *this;
|
||||
}
|
||||
|
||||
QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes,const b3QuantizedBvh* tree)
|
||||
:m_triangleNodes(triangleNodes),m_optimizedTree(tree)
|
||||
QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes, const b3QuantizedBvh* tree)
|
||||
: m_triangleNodes(triangleNodes), m_optimizedTree(tree)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void internalProcessTriangleIndex(b3Vector3* triangle,int partId,int triangleIndex)
|
||||
virtual void internalProcessTriangleIndex(b3Vector3* triangle, int partId, int triangleIndex)
|
||||
{
|
||||
// The partId and triangle index must fit in the same (positive) integer
|
||||
b3Assert(partId < (1<<MAX_NUM_PARTS_IN_BITS));
|
||||
b3Assert(triangleIndex < (1<<(31-MAX_NUM_PARTS_IN_BITS)));
|
||||
b3Assert(partId < (1 << MAX_NUM_PARTS_IN_BITS));
|
||||
b3Assert(triangleIndex < (1 << (31 - MAX_NUM_PARTS_IN_BITS)));
|
||||
//negative indices are reserved for escapeIndex
|
||||
b3Assert(triangleIndex>=0);
|
||||
b3Assert(triangleIndex >= 0);
|
||||
|
||||
b3QuantizedBvhNode node;
|
||||
b3Vector3 aabbMin,aabbMax;
|
||||
aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT));
|
||||
aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT));
|
||||
b3Vector3 aabbMin, aabbMax;
|
||||
aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
|
||||
aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
|
||||
aabbMin.setMin(triangle[0]);
|
||||
aabbMax.setMax(triangle[0]);
|
||||
aabbMin.setMin(triangle[1]);
|
||||
@@ -131,59 +126,52 @@ void b3OptimizedBvh::build(b3StridingMeshInterface* triangles, bool useQuantized
|
||||
aabbMin.setZ(aabbMin.getZ() - MIN_AABB_HALF_DIMENSION);
|
||||
}
|
||||
|
||||
m_optimizedTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
|
||||
m_optimizedTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
|
||||
m_optimizedTree->quantize(&node.m_quantizedAabbMin[0], aabbMin, 0);
|
||||
m_optimizedTree->quantize(&node.m_quantizedAabbMax[0], aabbMax, 1);
|
||||
|
||||
node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
|
||||
node.m_escapeIndexOrTriangleIndex = (partId << (31 - MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
|
||||
|
||||
m_triangleNodes.push_back(node);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
int numLeafNodes = 0;
|
||||
|
||||
|
||||
if (m_useQuantization)
|
||||
{
|
||||
|
||||
//initialize quantization values
|
||||
setQuantizationValues(bvhAabbMin,bvhAabbMax);
|
||||
setQuantizationValues(bvhAabbMin, bvhAabbMax);
|
||||
|
||||
QuantizedNodeTriangleCallback callback(m_quantizedLeafNodes,this);
|
||||
QuantizedNodeTriangleCallback callback(m_quantizedLeafNodes, this);
|
||||
|
||||
|
||||
triangles->InternalProcessAllTriangles(&callback,m_bvhAabbMin,m_bvhAabbMax);
|
||||
triangles->InternalProcessAllTriangles(&callback, m_bvhAabbMin, m_bvhAabbMax);
|
||||
|
||||
//now we have an array of leafnodes in m_leafNodes
|
||||
numLeafNodes = m_quantizedLeafNodes.size();
|
||||
|
||||
|
||||
m_quantizedContiguousNodes.resize(2*numLeafNodes);
|
||||
|
||||
|
||||
} else
|
||||
m_quantizedContiguousNodes.resize(2 * numLeafNodes);
|
||||
}
|
||||
else
|
||||
{
|
||||
NodeTriangleCallback callback(m_leafNodes);
|
||||
NodeTriangleCallback callback(m_leafNodes);
|
||||
|
||||
b3Vector3 aabbMin=b3MakeVector3(b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT));
|
||||
b3Vector3 aabbMax=b3MakeVector3(b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT));
|
||||
b3Vector3 aabbMin = b3MakeVector3(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
|
||||
b3Vector3 aabbMax = b3MakeVector3(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
|
||||
|
||||
triangles->InternalProcessAllTriangles(&callback,aabbMin,aabbMax);
|
||||
triangles->InternalProcessAllTriangles(&callback, aabbMin, aabbMax);
|
||||
|
||||
//now we have an array of leafnodes in m_leafNodes
|
||||
numLeafNodes = m_leafNodes.size();
|
||||
|
||||
m_contiguousNodes.resize(2*numLeafNodes);
|
||||
m_contiguousNodes.resize(2 * numLeafNodes);
|
||||
}
|
||||
|
||||
m_curNodeIndex = 0;
|
||||
|
||||
buildTree(0,numLeafNodes);
|
||||
buildTree(0, numLeafNodes);
|
||||
|
||||
///if the entire tree is small then subtree size, we need to create a header info for the tree
|
||||
if(m_useQuantization && !m_SubtreeHeaders.size())
|
||||
if (m_useQuantization && !m_SubtreeHeaders.size())
|
||||
{
|
||||
b3BvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
|
||||
subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
|
||||
@@ -199,37 +187,29 @@ void b3OptimizedBvh::build(b3StridingMeshInterface* triangles, bool useQuantized
|
||||
m_leafNodes.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void b3OptimizedBvh::refit(b3StridingMeshInterface* meshInterface,const b3Vector3& aabbMin,const b3Vector3& aabbMax)
|
||||
void b3OptimizedBvh::refit(b3StridingMeshInterface* meshInterface, const b3Vector3& aabbMin, const b3Vector3& aabbMax)
|
||||
{
|
||||
if (m_useQuantization)
|
||||
{
|
||||
setQuantizationValues(aabbMin, aabbMax);
|
||||
|
||||
setQuantizationValues(aabbMin,aabbMax);
|
||||
|
||||
updateBvhNodes(meshInterface,0,m_curNodeIndex,0);
|
||||
updateBvhNodes(meshInterface, 0, m_curNodeIndex, 0);
|
||||
|
||||
///now update all subtree headers
|
||||
|
||||
int i;
|
||||
for (i=0;i<m_SubtreeHeaders.size();i++)
|
||||
for (i = 0; i < m_SubtreeHeaders.size(); i++)
|
||||
{
|
||||
b3BvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
|
||||
subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
|
||||
}
|
||||
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void b3OptimizedBvh::refitPartial(b3StridingMeshInterface* meshInterface,const b3Vector3& aabbMin,const b3Vector3& aabbMax)
|
||||
void b3OptimizedBvh::refitPartial(b3StridingMeshInterface* meshInterface, const b3Vector3& aabbMin, const b3Vector3& aabbMax)
|
||||
{
|
||||
//incrementally initialize quantization values
|
||||
b3Assert(m_useQuantization);
|
||||
@@ -244,147 +224,135 @@ void b3OptimizedBvh::refitPartial(b3StridingMeshInterface* meshInterface,const b
|
||||
|
||||
///we should update all quantization values, using updateBvhNodes(meshInterface);
|
||||
///but we only update chunks that overlap the given aabb
|
||||
|
||||
unsigned short quantizedQueryAabbMin[3];
|
||||
unsigned short quantizedQueryAabbMax[3];
|
||||
|
||||
quantize(&quantizedQueryAabbMin[0],aabbMin,0);
|
||||
quantize(&quantizedQueryAabbMax[0],aabbMax,1);
|
||||
unsigned short quantizedQueryAabbMin[3];
|
||||
unsigned short quantizedQueryAabbMax[3];
|
||||
|
||||
quantize(&quantizedQueryAabbMin[0], aabbMin, 0);
|
||||
quantize(&quantizedQueryAabbMax[0], aabbMax, 1);
|
||||
|
||||
int i;
|
||||
for (i=0;i<this->m_SubtreeHeaders.size();i++)
|
||||
for (i = 0; i < this->m_SubtreeHeaders.size(); i++)
|
||||
{
|
||||
b3BvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
|
||||
|
||||
//PCK: unsigned instead of bool
|
||||
unsigned overlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
|
||||
unsigned overlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, subtree.m_quantizedAabbMin, subtree.m_quantizedAabbMax);
|
||||
if (overlap != 0)
|
||||
{
|
||||
updateBvhNodes(meshInterface,subtree.m_rootNodeIndex,subtree.m_rootNodeIndex+subtree.m_subtreeSize,i);
|
||||
updateBvhNodes(meshInterface, subtree.m_rootNodeIndex, subtree.m_rootNodeIndex + subtree.m_subtreeSize, i);
|
||||
|
||||
subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void b3OptimizedBvh::updateBvhNodes(b3StridingMeshInterface* meshInterface,int firstNode,int endNode,int index)
|
||||
void b3OptimizedBvh::updateBvhNodes(b3StridingMeshInterface* meshInterface, int firstNode, int endNode, int index)
|
||||
{
|
||||
(void)index;
|
||||
|
||||
b3Assert(m_useQuantization);
|
||||
|
||||
int curNodeSubPart=-1;
|
||||
int curNodeSubPart = -1;
|
||||
|
||||
//get access info to trianglemesh data
|
||||
const unsigned char *vertexbase = 0;
|
||||
int numverts = 0;
|
||||
PHY_ScalarType type = PHY_INTEGER;
|
||||
int stride = 0;
|
||||
const unsigned char *indexbase = 0;
|
||||
int indexstride = 0;
|
||||
int numfaces = 0;
|
||||
PHY_ScalarType indicestype = PHY_INTEGER;
|
||||
const unsigned char* vertexbase = 0;
|
||||
int numverts = 0;
|
||||
PHY_ScalarType type = PHY_INTEGER;
|
||||
int stride = 0;
|
||||
const unsigned char* indexbase = 0;
|
||||
int indexstride = 0;
|
||||
int numfaces = 0;
|
||||
PHY_ScalarType indicestype = PHY_INTEGER;
|
||||
|
||||
b3Vector3 triangleVerts[3];
|
||||
b3Vector3 aabbMin,aabbMax;
|
||||
const b3Vector3& meshScaling = meshInterface->getScaling();
|
||||
|
||||
int i;
|
||||
for (i=endNode-1;i>=firstNode;i--)
|
||||
b3Vector3 triangleVerts[3];
|
||||
b3Vector3 aabbMin, aabbMax;
|
||||
const b3Vector3& meshScaling = meshInterface->getScaling();
|
||||
|
||||
int i;
|
||||
for (i = endNode - 1; i >= firstNode; i--)
|
||||
{
|
||||
b3QuantizedBvhNode& curNode = m_quantizedContiguousNodes[i];
|
||||
if (curNode.isLeafNode())
|
||||
{
|
||||
|
||||
|
||||
b3QuantizedBvhNode& curNode = m_quantizedContiguousNodes[i];
|
||||
if (curNode.isLeafNode())
|
||||
//recalc aabb from triangle data
|
||||
int nodeSubPart = curNode.getPartId();
|
||||
int nodeTriangleIndex = curNode.getTriangleIndex();
|
||||
if (nodeSubPart != curNodeSubPart)
|
||||
{
|
||||
//recalc aabb from triangle data
|
||||
int nodeSubPart = curNode.getPartId();
|
||||
int nodeTriangleIndex = curNode.getTriangleIndex();
|
||||
if (nodeSubPart != curNodeSubPart)
|
||||
{
|
||||
if (curNodeSubPart >= 0)
|
||||
meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
|
||||
meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart);
|
||||
if (curNodeSubPart >= 0)
|
||||
meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
|
||||
meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numfaces, indicestype, nodeSubPart);
|
||||
|
||||
curNodeSubPart = nodeSubPart;
|
||||
b3Assert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
|
||||
}
|
||||
//triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts,
|
||||
curNodeSubPart = nodeSubPart;
|
||||
b3Assert(indicestype == PHY_INTEGER || indicestype == PHY_SHORT);
|
||||
}
|
||||
//triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts,
|
||||
|
||||
unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
|
||||
|
||||
|
||||
for (int j=2;j>=0;j--)
|
||||
{
|
||||
|
||||
int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
|
||||
if (type == PHY_FLOAT)
|
||||
{
|
||||
float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
|
||||
triangleVerts[j] = b3MakeVector3(
|
||||
graphicsbase[0]*meshScaling.getX(),
|
||||
graphicsbase[1]*meshScaling.getY(),
|
||||
graphicsbase[2]*meshScaling.getZ());
|
||||
}
|
||||
else
|
||||
{
|
||||
double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
|
||||
triangleVerts[j] = b3MakeVector3( b3Scalar(graphicsbase[0]*meshScaling.getX()), b3Scalar(graphicsbase[1]*meshScaling.getY()), b3Scalar(graphicsbase[2]*meshScaling.getZ()));
|
||||
}
|
||||
}
|
||||
unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
|
||||
|
||||
|
||||
|
||||
aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT));
|
||||
aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT));
|
||||
aabbMin.setMin(triangleVerts[0]);
|
||||
aabbMax.setMax(triangleVerts[0]);
|
||||
aabbMin.setMin(triangleVerts[1]);
|
||||
aabbMax.setMax(triangleVerts[1]);
|
||||
aabbMin.setMin(triangleVerts[2]);
|
||||
aabbMax.setMax(triangleVerts[2]);
|
||||
|
||||
quantize(&curNode.m_quantizedAabbMin[0],aabbMin,0);
|
||||
quantize(&curNode.m_quantizedAabbMax[0],aabbMax,1);
|
||||
|
||||
} else
|
||||
for (int j = 2; j >= 0; j--)
|
||||
{
|
||||
//combine aabb from both children
|
||||
|
||||
b3QuantizedBvhNode* leftChildNode = &m_quantizedContiguousNodes[i+1];
|
||||
|
||||
b3QuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? &m_quantizedContiguousNodes[i+2] :
|
||||
&m_quantizedContiguousNodes[i+1+leftChildNode->getEscapeIndex()];
|
||||
|
||||
|
||||
int graphicsindex = indicestype == PHY_SHORT ? ((unsigned short*)gfxbase)[j] : gfxbase[j];
|
||||
if (type == PHY_FLOAT)
|
||||
{
|
||||
for (int i=0;i<3;i++)
|
||||
{
|
||||
curNode.m_quantizedAabbMin[i] = leftChildNode->m_quantizedAabbMin[i];
|
||||
if (curNode.m_quantizedAabbMin[i]>rightChildNode->m_quantizedAabbMin[i])
|
||||
curNode.m_quantizedAabbMin[i]=rightChildNode->m_quantizedAabbMin[i];
|
||||
|
||||
curNode.m_quantizedAabbMax[i] = leftChildNode->m_quantizedAabbMax[i];
|
||||
if (curNode.m_quantizedAabbMax[i] < rightChildNode->m_quantizedAabbMax[i])
|
||||
curNode.m_quantizedAabbMax[i] = rightChildNode->m_quantizedAabbMax[i];
|
||||
}
|
||||
float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
|
||||
triangleVerts[j] = b3MakeVector3(
|
||||
graphicsbase[0] * meshScaling.getX(),
|
||||
graphicsbase[1] * meshScaling.getY(),
|
||||
graphicsbase[2] * meshScaling.getZ());
|
||||
}
|
||||
else
|
||||
{
|
||||
double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
|
||||
triangleVerts[j] = b3MakeVector3(b3Scalar(graphicsbase[0] * meshScaling.getX()), b3Scalar(graphicsbase[1] * meshScaling.getY()), b3Scalar(graphicsbase[2] * meshScaling.getZ()));
|
||||
}
|
||||
}
|
||||
|
||||
aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
|
||||
aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
|
||||
aabbMin.setMin(triangleVerts[0]);
|
||||
aabbMax.setMax(triangleVerts[0]);
|
||||
aabbMin.setMin(triangleVerts[1]);
|
||||
aabbMax.setMax(triangleVerts[1]);
|
||||
aabbMin.setMin(triangleVerts[2]);
|
||||
aabbMax.setMax(triangleVerts[2]);
|
||||
|
||||
quantize(&curNode.m_quantizedAabbMin[0], aabbMin, 0);
|
||||
quantize(&curNode.m_quantizedAabbMax[0], aabbMax, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
//combine aabb from both children
|
||||
|
||||
if (curNodeSubPart >= 0)
|
||||
meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
|
||||
b3QuantizedBvhNode* leftChildNode = &m_quantizedContiguousNodes[i + 1];
|
||||
|
||||
|
||||
b3QuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? &m_quantizedContiguousNodes[i + 2] : &m_quantizedContiguousNodes[i + 1 + leftChildNode->getEscapeIndex()];
|
||||
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
curNode.m_quantizedAabbMin[i] = leftChildNode->m_quantizedAabbMin[i];
|
||||
if (curNode.m_quantizedAabbMin[i] > rightChildNode->m_quantizedAabbMin[i])
|
||||
curNode.m_quantizedAabbMin[i] = rightChildNode->m_quantizedAabbMin[i];
|
||||
|
||||
curNode.m_quantizedAabbMax[i] = leftChildNode->m_quantizedAabbMax[i];
|
||||
if (curNode.m_quantizedAabbMax[i] < rightChildNode->m_quantizedAabbMax[i])
|
||||
curNode.m_quantizedAabbMax[i] = rightChildNode->m_quantizedAabbMax[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (curNodeSubPart >= 0)
|
||||
meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
|
||||
}
|
||||
|
||||
///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
|
||||
b3OptimizedBvh* b3OptimizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
|
||||
b3OptimizedBvh* b3OptimizedBvh::deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
|
||||
{
|
||||
b3QuantizedBvh* bvh = b3QuantizedBvh::deSerializeInPlace(i_alignedDataBuffer,i_dataBufferSize,i_swapEndian);
|
||||
|
||||
b3QuantizedBvh* bvh = b3QuantizedBvh::deSerializeInPlace(i_alignedDataBuffer, i_dataBufferSize, i_swapEndian);
|
||||
|
||||
//we don't add additional data so just do a static upcast
|
||||
return static_cast<b3OptimizedBvh*>(bvh);
|
||||
}
|
||||
|
||||
@@ -22,44 +22,35 @@ subject to the following restrictions:
|
||||
|
||||
class b3StridingMeshInterface;
|
||||
|
||||
|
||||
///The b3OptimizedBvh extends the b3QuantizedBvh to create AABB tree for triangle meshes, through the b3StridingMeshInterface.
|
||||
B3_ATTRIBUTE_ALIGNED16(class) b3OptimizedBvh : public b3QuantizedBvh
|
||||
B3_ATTRIBUTE_ALIGNED16(class)
|
||||
b3OptimizedBvh : public b3QuantizedBvh
|
||||
{
|
||||
|
||||
public:
|
||||
B3_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
protected:
|
||||
|
||||
public:
|
||||
|
||||
b3OptimizedBvh();
|
||||
|
||||
virtual ~b3OptimizedBvh();
|
||||
|
||||
void build(b3StridingMeshInterface* triangles,bool useQuantizedAabbCompression, const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax);
|
||||
void build(b3StridingMeshInterface * triangles, bool useQuantizedAabbCompression, const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax);
|
||||
|
||||
void refit(b3StridingMeshInterface* triangles,const b3Vector3& aabbMin,const b3Vector3& aabbMax);
|
||||
void refit(b3StridingMeshInterface * triangles, const b3Vector3& aabbMin, const b3Vector3& aabbMax);
|
||||
|
||||
void refitPartial(b3StridingMeshInterface* triangles,const b3Vector3& aabbMin, const b3Vector3& aabbMax);
|
||||
void refitPartial(b3StridingMeshInterface * triangles, const b3Vector3& aabbMin, const b3Vector3& aabbMax);
|
||||
|
||||
void updateBvhNodes(b3StridingMeshInterface* meshInterface,int firstNode,int endNode,int index);
|
||||
void updateBvhNodes(b3StridingMeshInterface * meshInterface, int firstNode, int endNode, int index);
|
||||
|
||||
/// Data buffer MUST be 16 byte aligned
|
||||
virtual bool serializeInPlace(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const
|
||||
virtual bool serializeInPlace(void* o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const
|
||||
{
|
||||
return b3QuantizedBvh::serialize(o_alignedDataBuffer,i_dataBufferSize,i_swapEndian);
|
||||
|
||||
return b3QuantizedBvh::serialize(o_alignedDataBuffer, i_dataBufferSize, i_swapEndian);
|
||||
}
|
||||
|
||||
///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
|
||||
static b3OptimizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
|
||||
|
||||
|
||||
static b3OptimizedBvh* deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
|
||||
};
|
||||
|
||||
|
||||
#endif //B3_OPTIMIZED_BVH_H
|
||||
|
||||
|
||||
#endif //B3_OPTIMIZED_BVH_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -22,11 +22,11 @@ class b3Serializer;
|
||||
#ifdef DEBUG_CHECK_DEQUANTIZATION
|
||||
#ifdef __SPU__
|
||||
#define printf spu_printf
|
||||
#endif //__SPU__
|
||||
#endif //__SPU__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#endif //DEBUG_CHECK_DEQUANTIZATION
|
||||
#endif //DEBUG_CHECK_DEQUANTIZATION
|
||||
|
||||
#include "Bullet3Common/b3Vector3.h"
|
||||
#include "Bullet3Common/b3AlignedAllocator.h"
|
||||
@@ -44,13 +44,10 @@ class b3Serializer;
|
||||
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h"
|
||||
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h"
|
||||
|
||||
|
||||
|
||||
//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp
|
||||
|
||||
|
||||
//Note: currently we have 16 bytes per quantized node
|
||||
#define MAX_SUBTREE_SIZE_IN_BYTES 2048
|
||||
#define MAX_SUBTREE_SIZE_IN_BYTES 2048
|
||||
|
||||
// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one
|
||||
// actually) triangles each (since the sign bit is reserved
|
||||
@@ -58,7 +55,8 @@ class b3Serializer;
|
||||
|
||||
///b3QuantizedBvhNode is a compressed aabb node, 16 bytes.
|
||||
///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
|
||||
B3_ATTRIBUTE_ALIGNED16 (struct) b3QuantizedBvhNode : public b3QuantizedBvhNodeData
|
||||
B3_ATTRIBUTE_ALIGNED16(struct)
|
||||
b3QuantizedBvhNode : public b3QuantizedBvhNodeData
|
||||
{
|
||||
B3_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
@@ -72,48 +70,48 @@ B3_ATTRIBUTE_ALIGNED16 (struct) b3QuantizedBvhNode : public b3QuantizedBvhNodeDa
|
||||
b3Assert(!isLeafNode());
|
||||
return -m_escapeIndexOrTriangleIndex;
|
||||
}
|
||||
int getTriangleIndex() const
|
||||
int getTriangleIndex() const
|
||||
{
|
||||
b3Assert(isLeafNode());
|
||||
unsigned int x=0;
|
||||
unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
|
||||
unsigned int x = 0;
|
||||
unsigned int y = (~(x & 0)) << (31 - MAX_NUM_PARTS_IN_BITS);
|
||||
// Get only the lower bits where the triangle index is stored
|
||||
return (m_escapeIndexOrTriangleIndex&~(y));
|
||||
return (m_escapeIndexOrTriangleIndex & ~(y));
|
||||
}
|
||||
int getPartId() const
|
||||
int getPartId() const
|
||||
{
|
||||
b3Assert(isLeafNode());
|
||||
// Get only the highest bits where the part index is stored
|
||||
return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS));
|
||||
return (m_escapeIndexOrTriangleIndex >> (31 - MAX_NUM_PARTS_IN_BITS));
|
||||
}
|
||||
}
|
||||
;
|
||||
};
|
||||
|
||||
/// b3OptimizedBvhNode contains both internal and leaf node information.
|
||||
/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes.
|
||||
B3_ATTRIBUTE_ALIGNED16 (struct) b3OptimizedBvhNode
|
||||
B3_ATTRIBUTE_ALIGNED16(struct)
|
||||
b3OptimizedBvhNode
|
||||
{
|
||||
B3_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
//32 bytes
|
||||
b3Vector3 m_aabbMinOrg;
|
||||
b3Vector3 m_aabbMaxOrg;
|
||||
b3Vector3 m_aabbMinOrg;
|
||||
b3Vector3 m_aabbMaxOrg;
|
||||
|
||||
//4
|
||||
int m_escapeIndex;
|
||||
int m_escapeIndex;
|
||||
|
||||
//8
|
||||
//for child nodes
|
||||
int m_subPart;
|
||||
int m_triangleIndex;
|
||||
int m_subPart;
|
||||
int m_triangleIndex;
|
||||
|
||||
//pad the size to 64 bytes
|
||||
char m_padding[20];
|
||||
//pad the size to 64 bytes
|
||||
char m_padding[20];
|
||||
};
|
||||
|
||||
|
||||
///b3BvhSubtreeInfo provides info to gather a subtree of limited size
|
||||
B3_ATTRIBUTE_ALIGNED16(class) b3BvhSubtreeInfo : public b3BvhSubtreeInfoData
|
||||
B3_ATTRIBUTE_ALIGNED16(class)
|
||||
b3BvhSubtreeInfo : public b3BvhSubtreeInfoData
|
||||
{
|
||||
public:
|
||||
B3_DECLARE_ALIGNED_ALLOCATOR();
|
||||
@@ -123,8 +121,7 @@ public:
|
||||
//memset(&m_padding[0], 0, sizeof(m_padding));
|
||||
}
|
||||
|
||||
|
||||
void setAabbFromQuantizeNode(const b3QuantizedBvhNode& quantizedNode)
|
||||
void setAabbFromQuantizeNode(const b3QuantizedBvhNode& quantizedNode)
|
||||
{
|
||||
m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0];
|
||||
m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1];
|
||||
@@ -133,14 +130,12 @@ public:
|
||||
m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1];
|
||||
m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2];
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
};
|
||||
|
||||
class b3NodeOverlapCallback
|
||||
{
|
||||
public:
|
||||
virtual ~b3NodeOverlapCallback() {};
|
||||
virtual ~b3NodeOverlapCallback(){};
|
||||
|
||||
virtual void processNode(int subPart, int triangleIndex) = 0;
|
||||
};
|
||||
@@ -148,18 +143,16 @@ public:
|
||||
#include "Bullet3Common/b3AlignedAllocator.h"
|
||||
#include "Bullet3Common/b3AlignedObjectArray.h"
|
||||
|
||||
|
||||
|
||||
///for code readability:
|
||||
typedef b3AlignedObjectArray<b3OptimizedBvhNode> NodeArray;
|
||||
typedef b3AlignedObjectArray<b3QuantizedBvhNode> QuantizedNodeArray;
|
||||
typedef b3AlignedObjectArray<b3BvhSubtreeInfo> BvhSubtreeInfoArray;
|
||||
|
||||
typedef b3AlignedObjectArray<b3OptimizedBvhNode> NodeArray;
|
||||
typedef b3AlignedObjectArray<b3QuantizedBvhNode> QuantizedNodeArray;
|
||||
typedef b3AlignedObjectArray<b3BvhSubtreeInfo> BvhSubtreeInfoArray;
|
||||
|
||||
///The b3QuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU.
|
||||
///It is used by the b3BvhTriangleMeshShape as midphase
|
||||
///It is recommended to use quantization for better performance and lower memory requirements.
|
||||
B3_ATTRIBUTE_ALIGNED16(class) b3QuantizedBvh
|
||||
B3_ATTRIBUTE_ALIGNED16(class)
|
||||
b3QuantizedBvh
|
||||
{
|
||||
public:
|
||||
enum b3TraversalMode
|
||||
@@ -169,56 +162,48 @@ public:
|
||||
TRAVERSAL_RECURSIVE
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
b3Vector3 m_bvhAabbMin;
|
||||
b3Vector3 m_bvhAabbMax;
|
||||
b3Vector3 m_bvhQuantization;
|
||||
b3Vector3 m_bvhAabbMin;
|
||||
b3Vector3 m_bvhAabbMax;
|
||||
b3Vector3 m_bvhQuantization;
|
||||
|
||||
protected:
|
||||
int m_bulletVersion; //for serialization versioning. It could also be used to detect endianess.
|
||||
int m_bulletVersion; //for serialization versioning. It could also be used to detect endianess.
|
||||
|
||||
int m_curNodeIndex;
|
||||
int m_curNodeIndex;
|
||||
//quantization data
|
||||
bool m_useQuantization;
|
||||
bool m_useQuantization;
|
||||
|
||||
NodeArray m_leafNodes;
|
||||
NodeArray m_contiguousNodes;
|
||||
QuantizedNodeArray m_quantizedLeafNodes;
|
||||
QuantizedNodeArray m_quantizedContiguousNodes;
|
||||
|
||||
|
||||
NodeArray m_leafNodes;
|
||||
NodeArray m_contiguousNodes;
|
||||
QuantizedNodeArray m_quantizedLeafNodes;
|
||||
QuantizedNodeArray m_quantizedContiguousNodes;
|
||||
|
||||
b3TraversalMode m_traversalMode;
|
||||
BvhSubtreeInfoArray m_SubtreeHeaders;
|
||||
b3TraversalMode m_traversalMode;
|
||||
BvhSubtreeInfoArray m_SubtreeHeaders;
|
||||
|
||||
//This is only used for serialization so we don't have to add serialization directly to b3AlignedObjectArray
|
||||
mutable int m_subtreeHeaderCount;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!)
|
||||
///this might be refactored into a virtual, it is usually not calculated at run-time
|
||||
void setInternalNodeAabbMin(int nodeIndex, const b3Vector3& aabbMin)
|
||||
void setInternalNodeAabbMin(int nodeIndex, const b3Vector3& aabbMin)
|
||||
{
|
||||
if (m_useQuantization)
|
||||
{
|
||||
quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0);
|
||||
} else
|
||||
quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0], aabbMin, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin;
|
||||
|
||||
}
|
||||
}
|
||||
void setInternalNodeAabbMax(int nodeIndex,const b3Vector3& aabbMax)
|
||||
void setInternalNodeAabbMax(int nodeIndex, const b3Vector3& aabbMax)
|
||||
{
|
||||
if (m_useQuantization)
|
||||
{
|
||||
quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1);
|
||||
} else
|
||||
quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0], aabbMax, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax;
|
||||
}
|
||||
@@ -232,115 +217,102 @@ protected:
|
||||
}
|
||||
//non-quantized
|
||||
return m_leafNodes[nodeIndex].m_aabbMinOrg;
|
||||
|
||||
}
|
||||
b3Vector3 getAabbMax(int nodeIndex) const
|
||||
{
|
||||
if (m_useQuantization)
|
||||
{
|
||||
return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]);
|
||||
}
|
||||
}
|
||||
//non-quantized
|
||||
return m_leafNodes[nodeIndex].m_aabbMaxOrg;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
|
||||
void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
|
||||
{
|
||||
if (m_useQuantization)
|
||||
{
|
||||
m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void mergeInternalNodeAabb(int nodeIndex,const b3Vector3& newAabbMin,const b3Vector3& newAabbMax)
|
||||
void mergeInternalNodeAabb(int nodeIndex, const b3Vector3& newAabbMin, const b3Vector3& newAabbMax)
|
||||
{
|
||||
if (m_useQuantization)
|
||||
{
|
||||
unsigned short int quantizedAabbMin[3];
|
||||
unsigned short int quantizedAabbMax[3];
|
||||
quantize(quantizedAabbMin,newAabbMin,0);
|
||||
quantize(quantizedAabbMax,newAabbMax,1);
|
||||
for (int i=0;i<3;i++)
|
||||
quantize(quantizedAabbMin, newAabbMin, 0);
|
||||
quantize(quantizedAabbMax, newAabbMax, 1);
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i])
|
||||
m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i];
|
||||
|
||||
if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i])
|
||||
m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i];
|
||||
|
||||
}
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
//non-quantized
|
||||
m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin);
|
||||
m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);
|
||||
m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);
|
||||
}
|
||||
}
|
||||
|
||||
void swapLeafNodes(int firstIndex,int secondIndex);
|
||||
void swapLeafNodes(int firstIndex, int secondIndex);
|
||||
|
||||
void assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex);
|
||||
void assignInternalNodeFromLeafNode(int internalNode, int leafNodeIndex);
|
||||
|
||||
protected:
|
||||
void buildTree(int startIndex, int endIndex);
|
||||
|
||||
|
||||
int calcSplittingAxis(int startIndex, int endIndex);
|
||||
|
||||
void buildTree (int startIndex,int endIndex);
|
||||
int sortAndCalcSplittingIndex(int startIndex, int endIndex, int splitAxis);
|
||||
|
||||
int calcSplittingAxis(int startIndex,int endIndex);
|
||||
void walkStacklessTree(b3NodeOverlapCallback * nodeCallback, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const;
|
||||
|
||||
int sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis);
|
||||
|
||||
void walkStacklessTree(b3NodeOverlapCallback* nodeCallback,const b3Vector3& aabbMin,const b3Vector3& aabbMax) const;
|
||||
|
||||
void walkStacklessQuantizedTreeAgainstRay(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
|
||||
void walkStacklessQuantizedTree(b3NodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const;
|
||||
void walkStacklessTreeAgainstRay(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
|
||||
void walkStacklessQuantizedTreeAgainstRay(b3NodeOverlapCallback * nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex, int endNodeIndex) const;
|
||||
void walkStacklessQuantizedTree(b3NodeOverlapCallback * nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax, int startNodeIndex, int endNodeIndex) const;
|
||||
void walkStacklessTreeAgainstRay(b3NodeOverlapCallback * nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex, int endNodeIndex) const;
|
||||
|
||||
///tree traversal designed for small-memory processors like PS3 SPU
|
||||
void walkStacklessQuantizedTreeCacheFriendly(b3NodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
|
||||
void walkStacklessQuantizedTreeCacheFriendly(b3NodeOverlapCallback * nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const;
|
||||
|
||||
///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
|
||||
void walkRecursiveQuantizedTreeAgainstQueryAabb(const b3QuantizedBvhNode* currentNode,b3NodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
|
||||
void walkRecursiveQuantizedTreeAgainstQueryAabb(const b3QuantizedBvhNode* currentNode, b3NodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const;
|
||||
|
||||
///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
|
||||
void walkRecursiveQuantizedTreeAgainstQuantizedTree(const b3QuantizedBvhNode* treeNodeA,const b3QuantizedBvhNode* treeNodeB,b3NodeOverlapCallback* nodeCallback) const;
|
||||
|
||||
void walkRecursiveQuantizedTreeAgainstQuantizedTree(const b3QuantizedBvhNode* treeNodeA, const b3QuantizedBvhNode* treeNodeB, b3NodeOverlapCallback* nodeCallback) const;
|
||||
|
||||
|
||||
|
||||
void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex);
|
||||
void updateSubtreeHeaders(int leftChildNodexIndex, int rightChildNodexIndex);
|
||||
|
||||
public:
|
||||
|
||||
B3_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
b3QuantizedBvh();
|
||||
|
||||
virtual ~b3QuantizedBvh();
|
||||
|
||||
|
||||
///***************************************** expert/internal use only *************************
|
||||
void setQuantizationValues(const b3Vector3& bvhAabbMin,const b3Vector3& bvhAabbMax,b3Scalar quantizationMargin=b3Scalar(1.0));
|
||||
QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
|
||||
void setQuantizationValues(const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax, b3Scalar quantizationMargin = b3Scalar(1.0));
|
||||
QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
|
||||
///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized
|
||||
void buildInternal();
|
||||
void buildInternal();
|
||||
///***************************************** expert/internal use only *************************
|
||||
|
||||
void reportAabbOverlappingNodex(b3NodeOverlapCallback* nodeCallback,const b3Vector3& aabbMin,const b3Vector3& aabbMax) const;
|
||||
void reportRayOverlappingNodex (b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget) const;
|
||||
void reportBoxCastOverlappingNodex(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin,const b3Vector3& aabbMax) const;
|
||||
void reportAabbOverlappingNodex(b3NodeOverlapCallback * nodeCallback, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const;
|
||||
void reportRayOverlappingNodex(b3NodeOverlapCallback * nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget) const;
|
||||
void reportBoxCastOverlappingNodex(b3NodeOverlapCallback * nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const;
|
||||
|
||||
B3_FORCE_INLINE void quantize(unsigned short* out, const b3Vector3& point,int isMax) const
|
||||
B3_FORCE_INLINE void quantize(unsigned short* out, const b3Vector3& point, int isMax) const
|
||||
{
|
||||
|
||||
b3Assert(m_useQuantization);
|
||||
|
||||
b3Assert(point.getX() <= m_bvhAabbMax.getX());
|
||||
@@ -357,16 +329,16 @@ public:
|
||||
///@todo: double-check this
|
||||
if (isMax)
|
||||
{
|
||||
out[0] = (unsigned short) (((unsigned short)(v.getX()+b3Scalar(1.)) | 1));
|
||||
out[1] = (unsigned short) (((unsigned short)(v.getY()+b3Scalar(1.)) | 1));
|
||||
out[2] = (unsigned short) (((unsigned short)(v.getZ()+b3Scalar(1.)) | 1));
|
||||
} else
|
||||
{
|
||||
out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe));
|
||||
out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe));
|
||||
out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe));
|
||||
out[0] = (unsigned short)(((unsigned short)(v.getX() + b3Scalar(1.)) | 1));
|
||||
out[1] = (unsigned short)(((unsigned short)(v.getY() + b3Scalar(1.)) | 1));
|
||||
out[2] = (unsigned short)(((unsigned short)(v.getZ() + b3Scalar(1.)) | 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
out[0] = (unsigned short)(((unsigned short)(v.getX()) & 0xfffe));
|
||||
out[1] = (unsigned short)(((unsigned short)(v.getY()) & 0xfffe));
|
||||
out[2] = (unsigned short)(((unsigned short)(v.getZ()) & 0xfffe));
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_CHECK_DEQUANTIZATION
|
||||
b3Vector3 newPoint = unQuantize(out);
|
||||
@@ -374,105 +346,97 @@ public:
|
||||
{
|
||||
if (newPoint.getX() < point.getX())
|
||||
{
|
||||
printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
|
||||
printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n", newPoint.getX() - point.getX(), newPoint.getX(), point.getX());
|
||||
}
|
||||
if (newPoint.getY() < point.getY())
|
||||
{
|
||||
printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
|
||||
printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n", newPoint.getY() - point.getY(), newPoint.getY(), point.getY());
|
||||
}
|
||||
if (newPoint.getZ() < point.getZ())
|
||||
{
|
||||
|
||||
printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
|
||||
printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n", newPoint.getZ() - point.getZ(), newPoint.getZ(), point.getZ());
|
||||
}
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
if (newPoint.getX() > point.getX())
|
||||
{
|
||||
printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
|
||||
printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n", newPoint.getX() - point.getX(), newPoint.getX(), point.getX());
|
||||
}
|
||||
if (newPoint.getY() > point.getY())
|
||||
{
|
||||
printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
|
||||
printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n", newPoint.getY() - point.getY(), newPoint.getY(), point.getY());
|
||||
}
|
||||
if (newPoint.getZ() > point.getZ())
|
||||
{
|
||||
printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
|
||||
printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n", newPoint.getZ() - point.getZ(), newPoint.getZ(), point.getZ());
|
||||
}
|
||||
}
|
||||
#endif //DEBUG_CHECK_DEQUANTIZATION
|
||||
|
||||
#endif //DEBUG_CHECK_DEQUANTIZATION
|
||||
}
|
||||
|
||||
|
||||
B3_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const b3Vector3& point2,int isMax) const
|
||||
B3_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const b3Vector3& point2, int isMax) const
|
||||
{
|
||||
|
||||
b3Assert(m_useQuantization);
|
||||
|
||||
b3Vector3 clampedPoint(point2);
|
||||
clampedPoint.setMax(m_bvhAabbMin);
|
||||
clampedPoint.setMin(m_bvhAabbMax);
|
||||
|
||||
quantize(out,clampedPoint,isMax);
|
||||
|
||||
quantize(out, clampedPoint, isMax);
|
||||
}
|
||||
|
||||
B3_FORCE_INLINE b3Vector3 unQuantize(const unsigned short* vecIn) const
|
||||
|
||||
B3_FORCE_INLINE b3Vector3 unQuantize(const unsigned short* vecIn) const
|
||||
{
|
||||
b3Vector3 vecOut;
|
||||
vecOut.setValue(
|
||||
b3Vector3 vecOut;
|
||||
vecOut.setValue(
|
||||
(b3Scalar)(vecIn[0]) / (m_bvhQuantization.getX()),
|
||||
(b3Scalar)(vecIn[1]) / (m_bvhQuantization.getY()),
|
||||
(b3Scalar)(vecIn[2]) / (m_bvhQuantization.getZ()));
|
||||
vecOut += m_bvhAabbMin;
|
||||
return vecOut;
|
||||
vecOut += m_bvhAabbMin;
|
||||
return vecOut;
|
||||
}
|
||||
|
||||
///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees.
|
||||
void setTraversalMode(b3TraversalMode traversalMode)
|
||||
void setTraversalMode(b3TraversalMode traversalMode)
|
||||
{
|
||||
m_traversalMode = traversalMode;
|
||||
}
|
||||
|
||||
|
||||
B3_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray()
|
||||
{
|
||||
return m_quantizedContiguousNodes;
|
||||
B3_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray()
|
||||
{
|
||||
return m_quantizedContiguousNodes;
|
||||
}
|
||||
|
||||
|
||||
B3_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray()
|
||||
B3_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray()
|
||||
{
|
||||
return m_SubtreeHeaders;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////Calculate space needed to store BVH for serialization
|
||||
unsigned calculateSerializeBufferSize() const;
|
||||
|
||||
/// Data buffer MUST be 16 byte aligned
|
||||
virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const;
|
||||
virtual bool serialize(void* o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const;
|
||||
|
||||
///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
|
||||
static b3QuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
|
||||
static b3QuantizedBvh* deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
|
||||
|
||||
static unsigned int getAlignmentSerializationPadding();
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
virtual int calculateSerializeBufferSizeNew() const;
|
||||
virtual int calculateSerializeBufferSizeNew() const;
|
||||
|
||||
///fills the dataBuffer and returns the struct name (and 0 on failure)
|
||||
virtual const char* serialize(void* dataBuffer, b3Serializer* serializer) const;
|
||||
virtual const char* serialize(void* dataBuffer, b3Serializer* serializer) const;
|
||||
|
||||
virtual void deSerializeFloat(struct b3QuantizedBvhFloatData& quantizedBvhFloatData);
|
||||
virtual void deSerializeFloat(struct b3QuantizedBvhFloatData & quantizedBvhFloatData);
|
||||
|
||||
virtual void deSerializeDouble(struct b3QuantizedBvhDoubleData& quantizedBvhDoubleData);
|
||||
virtual void deSerializeDouble(struct b3QuantizedBvhDoubleData & quantizedBvhDoubleData);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
B3_FORCE_INLINE bool isQuantized()
|
||||
{
|
||||
@@ -483,74 +447,65 @@ private:
|
||||
// Special "copy" constructor that allows for in-place deserialization
|
||||
// Prevents b3Vector3's default constructor from being called, but doesn't inialize much else
|
||||
// ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need)
|
||||
b3QuantizedBvh(b3QuantizedBvh &other, bool ownsMemory);
|
||||
|
||||
}
|
||||
;
|
||||
|
||||
b3QuantizedBvh(b3QuantizedBvh & other, bool ownsMemory);
|
||||
};
|
||||
|
||||
struct b3OptimizedBvhNodeFloatData
|
||||
{
|
||||
b3Vector3FloatData m_aabbMinOrg;
|
||||
b3Vector3FloatData m_aabbMaxOrg;
|
||||
int m_escapeIndex;
|
||||
int m_subPart;
|
||||
int m_triangleIndex;
|
||||
b3Vector3FloatData m_aabbMinOrg;
|
||||
b3Vector3FloatData m_aabbMaxOrg;
|
||||
int m_escapeIndex;
|
||||
int m_subPart;
|
||||
int m_triangleIndex;
|
||||
char m_pad[4];
|
||||
};
|
||||
|
||||
struct b3OptimizedBvhNodeDoubleData
|
||||
{
|
||||
b3Vector3DoubleData m_aabbMinOrg;
|
||||
b3Vector3DoubleData m_aabbMaxOrg;
|
||||
int m_escapeIndex;
|
||||
int m_subPart;
|
||||
int m_triangleIndex;
|
||||
char m_pad[4];
|
||||
b3Vector3DoubleData m_aabbMinOrg;
|
||||
b3Vector3DoubleData m_aabbMaxOrg;
|
||||
int m_escapeIndex;
|
||||
int m_subPart;
|
||||
int m_triangleIndex;
|
||||
char m_pad[4];
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct b3QuantizedBvhFloatData
|
||||
struct b3QuantizedBvhFloatData
|
||||
{
|
||||
b3Vector3FloatData m_bvhAabbMin;
|
||||
b3Vector3FloatData m_bvhAabbMax;
|
||||
b3Vector3FloatData m_bvhQuantization;
|
||||
int m_curNodeIndex;
|
||||
int m_useQuantization;
|
||||
int m_numContiguousLeafNodes;
|
||||
int m_numQuantizedContiguousNodes;
|
||||
b3OptimizedBvhNodeFloatData *m_contiguousNodesPtr;
|
||||
b3QuantizedBvhNodeData *m_quantizedContiguousNodesPtr;
|
||||
b3BvhSubtreeInfoData *m_subTreeInfoPtr;
|
||||
int m_traversalMode;
|
||||
int m_numSubtreeHeaders;
|
||||
|
||||
b3Vector3FloatData m_bvhAabbMin;
|
||||
b3Vector3FloatData m_bvhAabbMax;
|
||||
b3Vector3FloatData m_bvhQuantization;
|
||||
int m_curNodeIndex;
|
||||
int m_useQuantization;
|
||||
int m_numContiguousLeafNodes;
|
||||
int m_numQuantizedContiguousNodes;
|
||||
b3OptimizedBvhNodeFloatData* m_contiguousNodesPtr;
|
||||
b3QuantizedBvhNodeData* m_quantizedContiguousNodesPtr;
|
||||
b3BvhSubtreeInfoData* m_subTreeInfoPtr;
|
||||
int m_traversalMode;
|
||||
int m_numSubtreeHeaders;
|
||||
};
|
||||
|
||||
struct b3QuantizedBvhDoubleData
|
||||
struct b3QuantizedBvhDoubleData
|
||||
{
|
||||
b3Vector3DoubleData m_bvhAabbMin;
|
||||
b3Vector3DoubleData m_bvhAabbMax;
|
||||
b3Vector3DoubleData m_bvhQuantization;
|
||||
int m_curNodeIndex;
|
||||
int m_useQuantization;
|
||||
int m_numContiguousLeafNodes;
|
||||
int m_numQuantizedContiguousNodes;
|
||||
b3OptimizedBvhNodeDoubleData *m_contiguousNodesPtr;
|
||||
b3QuantizedBvhNodeData *m_quantizedContiguousNodesPtr;
|
||||
b3Vector3DoubleData m_bvhAabbMin;
|
||||
b3Vector3DoubleData m_bvhAabbMax;
|
||||
b3Vector3DoubleData m_bvhQuantization;
|
||||
int m_curNodeIndex;
|
||||
int m_useQuantization;
|
||||
int m_numContiguousLeafNodes;
|
||||
int m_numQuantizedContiguousNodes;
|
||||
b3OptimizedBvhNodeDoubleData* m_contiguousNodesPtr;
|
||||
b3QuantizedBvhNodeData* m_quantizedContiguousNodesPtr;
|
||||
|
||||
int m_traversalMode;
|
||||
int m_numSubtreeHeaders;
|
||||
b3BvhSubtreeInfoData *m_subTreeInfoPtr;
|
||||
int m_traversalMode;
|
||||
int m_numSubtreeHeaders;
|
||||
b3BvhSubtreeInfoData* m_subTreeInfoPtr;
|
||||
};
|
||||
|
||||
|
||||
B3_FORCE_INLINE int b3QuantizedBvh::calculateSerializeBufferSizeNew() const
|
||||
B3_FORCE_INLINE int b3QuantizedBvh::calculateSerializeBufferSizeNew() const
|
||||
{
|
||||
return sizeof(b3QuantizedBvhData);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif //B3_QUANTIZED_BVH_H
|
||||
#endif //B3_QUANTIZED_BVH_H
|
||||
|
||||
@@ -15,35 +15,32 @@ subject to the following restrictions:
|
||||
|
||||
#include "b3StridingMeshInterface.h"
|
||||
|
||||
|
||||
b3StridingMeshInterface::~b3StridingMeshInterface()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void b3StridingMeshInterface::InternalProcessAllTriangles(b3InternalTriangleIndexCallback* callback,const b3Vector3& aabbMin,const b3Vector3& aabbMax) const
|
||||
void b3StridingMeshInterface::InternalProcessAllTriangles(b3InternalTriangleIndexCallback* callback, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const
|
||||
{
|
||||
(void)aabbMin;
|
||||
(void)aabbMax;
|
||||
int numtotalphysicsverts = 0;
|
||||
int part,graphicssubparts = getNumSubParts();
|
||||
const unsigned char * vertexbase;
|
||||
const unsigned char * indexbase;
|
||||
int part, graphicssubparts = getNumSubParts();
|
||||
const unsigned char* vertexbase;
|
||||
const unsigned char* indexbase;
|
||||
int indexstride;
|
||||
PHY_ScalarType type;
|
||||
PHY_ScalarType gfxindextype;
|
||||
int stride,numverts,numtriangles;
|
||||
int stride, numverts, numtriangles;
|
||||
int gfxindex;
|
||||
b3Vector3 triangle[3];
|
||||
|
||||
b3Vector3 meshScaling = getScaling();
|
||||
|
||||
///if the number of parts is big, the performance might drop due to the innerloop switch on indextype
|
||||
for (part=0;part<graphicssubparts ;part++)
|
||||
for (part = 0; part < graphicssubparts; part++)
|
||||
{
|
||||
getLockedReadOnlyVertexIndexBase(&vertexbase,numverts,type,stride,&indexbase,indexstride,numtriangles,gfxindextype,part);
|
||||
numtotalphysicsverts+=numtriangles*3; //upper bound
|
||||
getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numtriangles, gfxindextype, part);
|
||||
numtotalphysicsverts += numtriangles * 3; //upper bound
|
||||
|
||||
///unlike that developers want to pass in double-precision meshes in single-precision Bullet build
|
||||
///so disable this feature by default
|
||||
@@ -51,143 +48,141 @@ void b3StridingMeshInterface::InternalProcessAllTriangles(b3InternalTriangleInde
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case PHY_FLOAT:
|
||||
{
|
||||
case PHY_FLOAT:
|
||||
{
|
||||
float* graphicsbase;
|
||||
|
||||
float* graphicsbase;
|
||||
switch (gfxindextype)
|
||||
{
|
||||
case PHY_INTEGER:
|
||||
{
|
||||
for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
|
||||
{
|
||||
unsigned int* tri_indices = (unsigned int*)(indexbase + gfxindex * indexstride);
|
||||
graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
|
||||
triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
|
||||
graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
|
||||
triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
|
||||
graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
|
||||
triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
|
||||
callback->internalProcessTriangleIndex(triangle, part, gfxindex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PHY_SHORT:
|
||||
{
|
||||
for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
|
||||
{
|
||||
unsigned short int* tri_indices = (unsigned short int*)(indexbase + gfxindex * indexstride);
|
||||
graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
|
||||
triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
|
||||
graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
|
||||
triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
|
||||
graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
|
||||
triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
|
||||
callback->internalProcessTriangleIndex(triangle, part, gfxindex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PHY_UCHAR:
|
||||
{
|
||||
for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
|
||||
{
|
||||
unsigned char* tri_indices = (unsigned char*)(indexbase + gfxindex * indexstride);
|
||||
graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
|
||||
triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
|
||||
graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
|
||||
triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
|
||||
graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
|
||||
triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
|
||||
callback->internalProcessTriangleIndex(triangle, part, gfxindex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
b3Assert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (gfxindextype)
|
||||
{
|
||||
case PHY_INTEGER:
|
||||
{
|
||||
for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
|
||||
{
|
||||
unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride);
|
||||
graphicsbase = (float*)(vertexbase+tri_indices[0]*stride);
|
||||
triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
|
||||
graphicsbase = (float*)(vertexbase+tri_indices[1]*stride);
|
||||
triangle[1].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
|
||||
graphicsbase = (float*)(vertexbase+tri_indices[2]*stride);
|
||||
triangle[2].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
|
||||
callback->internalProcessTriangleIndex(triangle,part,gfxindex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PHY_SHORT:
|
||||
{
|
||||
for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
|
||||
{
|
||||
unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride);
|
||||
graphicsbase = (float*)(vertexbase+tri_indices[0]*stride);
|
||||
triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
|
||||
graphicsbase = (float*)(vertexbase+tri_indices[1]*stride);
|
||||
triangle[1].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
|
||||
graphicsbase = (float*)(vertexbase+tri_indices[2]*stride);
|
||||
triangle[2].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
|
||||
callback->internalProcessTriangleIndex(triangle,part,gfxindex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PHY_UCHAR:
|
||||
{
|
||||
for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
|
||||
{
|
||||
unsigned char* tri_indices= (unsigned char*)(indexbase+gfxindex*indexstride);
|
||||
graphicsbase = (float*)(vertexbase+tri_indices[0]*stride);
|
||||
triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
|
||||
graphicsbase = (float*)(vertexbase+tri_indices[1]*stride);
|
||||
triangle[1].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
|
||||
graphicsbase = (float*)(vertexbase+tri_indices[2]*stride);
|
||||
triangle[2].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(), graphicsbase[2]*meshScaling.getZ());
|
||||
callback->internalProcessTriangleIndex(triangle,part,gfxindex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
b3Assert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PHY_DOUBLE:
|
||||
case PHY_DOUBLE:
|
||||
{
|
||||
double* graphicsbase;
|
||||
|
||||
switch (gfxindextype)
|
||||
{
|
||||
case PHY_INTEGER:
|
||||
case PHY_INTEGER:
|
||||
{
|
||||
for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
|
||||
for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
|
||||
{
|
||||
unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride);
|
||||
graphicsbase = (double*)(vertexbase+tri_indices[0]*stride);
|
||||
triangle[0].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(),(b3Scalar)graphicsbase[2]*meshScaling.getZ());
|
||||
graphicsbase = (double*)(vertexbase+tri_indices[1]*stride);
|
||||
triangle[1].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(), (b3Scalar)graphicsbase[2]*meshScaling.getZ());
|
||||
graphicsbase = (double*)(vertexbase+tri_indices[2]*stride);
|
||||
triangle[2].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(), (b3Scalar)graphicsbase[2]*meshScaling.getZ());
|
||||
callback->internalProcessTriangleIndex(triangle,part,gfxindex);
|
||||
unsigned int* tri_indices = (unsigned int*)(indexbase + gfxindex * indexstride);
|
||||
graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
|
||||
triangle[0].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
|
||||
graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
|
||||
triangle[1].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
|
||||
graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
|
||||
triangle[2].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
|
||||
callback->internalProcessTriangleIndex(triangle, part, gfxindex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PHY_SHORT:
|
||||
case PHY_SHORT:
|
||||
{
|
||||
for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
|
||||
for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
|
||||
{
|
||||
unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride);
|
||||
graphicsbase = (double*)(vertexbase+tri_indices[0]*stride);
|
||||
triangle[0].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(),(b3Scalar)graphicsbase[2]*meshScaling.getZ());
|
||||
graphicsbase = (double*)(vertexbase+tri_indices[1]*stride);
|
||||
triangle[1].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(), (b3Scalar)graphicsbase[2]*meshScaling.getZ());
|
||||
graphicsbase = (double*)(vertexbase+tri_indices[2]*stride);
|
||||
triangle[2].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(), (b3Scalar)graphicsbase[2]*meshScaling.getZ());
|
||||
callback->internalProcessTriangleIndex(triangle,part,gfxindex);
|
||||
unsigned short int* tri_indices = (unsigned short int*)(indexbase + gfxindex * indexstride);
|
||||
graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
|
||||
triangle[0].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
|
||||
graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
|
||||
triangle[1].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
|
||||
graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
|
||||
triangle[2].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
|
||||
callback->internalProcessTriangleIndex(triangle, part, gfxindex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PHY_UCHAR:
|
||||
case PHY_UCHAR:
|
||||
{
|
||||
for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
|
||||
for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
|
||||
{
|
||||
unsigned char* tri_indices= (unsigned char*)(indexbase+gfxindex*indexstride);
|
||||
graphicsbase = (double*)(vertexbase+tri_indices[0]*stride);
|
||||
triangle[0].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(),(b3Scalar)graphicsbase[2]*meshScaling.getZ());
|
||||
graphicsbase = (double*)(vertexbase+tri_indices[1]*stride);
|
||||
triangle[1].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(), (b3Scalar)graphicsbase[2]*meshScaling.getZ());
|
||||
graphicsbase = (double*)(vertexbase+tri_indices[2]*stride);
|
||||
triangle[2].setValue((b3Scalar)graphicsbase[0]*meshScaling.getX(),(b3Scalar)graphicsbase[1]*meshScaling.getY(), (b3Scalar)graphicsbase[2]*meshScaling.getZ());
|
||||
callback->internalProcessTriangleIndex(triangle,part,gfxindex);
|
||||
unsigned char* tri_indices = (unsigned char*)(indexbase + gfxindex * indexstride);
|
||||
graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
|
||||
triangle[0].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
|
||||
graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
|
||||
triangle[1].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
|
||||
graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
|
||||
triangle[2].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
|
||||
callback->internalProcessTriangleIndex(triangle, part, gfxindex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
b3Assert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
|
||||
default:
|
||||
b3Assert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
b3Assert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
|
||||
default:
|
||||
b3Assert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
|
||||
}
|
||||
|
||||
unLockReadOnlyVertexBase(part);
|
||||
}
|
||||
}
|
||||
|
||||
void b3StridingMeshInterface::calculateAabbBruteForce(b3Vector3& aabbMin,b3Vector3& aabbMax)
|
||||
void b3StridingMeshInterface::calculateAabbBruteForce(b3Vector3& aabbMin, b3Vector3& aabbMax)
|
||||
{
|
||||
|
||||
struct AabbCalculationCallback : public b3InternalTriangleIndexCallback
|
||||
struct AabbCalculationCallback : public b3InternalTriangleIndexCallback
|
||||
{
|
||||
b3Vector3 m_aabbMin;
|
||||
b3Vector3 m_aabbMax;
|
||||
b3Vector3 m_aabbMin;
|
||||
b3Vector3 m_aabbMax;
|
||||
|
||||
AabbCalculationCallback()
|
||||
{
|
||||
m_aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT));
|
||||
m_aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT));
|
||||
m_aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
|
||||
m_aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
|
||||
}
|
||||
|
||||
virtual void internalProcessTriangleIndex(b3Vector3* triangle,int partId,int triangleIndex)
|
||||
virtual void internalProcessTriangleIndex(b3Vector3* triangle, int partId, int triangleIndex)
|
||||
{
|
||||
(void)partId;
|
||||
(void)triangleIndex;
|
||||
@@ -202,13 +197,11 @@ void b3StridingMeshInterface::calculateAabbBruteForce(b3Vector3& aabbMin,b3Vecto
|
||||
};
|
||||
|
||||
//first calculate the total aabb for all triangles
|
||||
AabbCalculationCallback aabbCallback;
|
||||
aabbMin.setValue(b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT),b3Scalar(-B3_LARGE_FLOAT));
|
||||
aabbMax.setValue(b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT));
|
||||
InternalProcessAllTriangles(&aabbCallback,aabbMin,aabbMax);
|
||||
AabbCalculationCallback aabbCallback;
|
||||
aabbMin.setValue(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
|
||||
aabbMax.setValue(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
|
||||
InternalProcessAllTriangles(&aabbCallback, aabbMin, aabbMax);
|
||||
|
||||
aabbMin = aabbCallback.m_aabbMin;
|
||||
aabbMax = aabbCallback.m_aabbMax;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -20,148 +20,139 @@ subject to the following restrictions:
|
||||
#include "b3TriangleCallback.h"
|
||||
//#include "b3ConcaveShape.h"
|
||||
|
||||
|
||||
enum PHY_ScalarType {
|
||||
PHY_FLOAT, PHY_DOUBLE, PHY_INTEGER, PHY_SHORT,
|
||||
PHY_FIXEDPOINT88, PHY_UCHAR
|
||||
enum PHY_ScalarType
|
||||
{
|
||||
PHY_FLOAT,
|
||||
PHY_DOUBLE,
|
||||
PHY_INTEGER,
|
||||
PHY_SHORT,
|
||||
PHY_FIXEDPOINT88,
|
||||
PHY_UCHAR
|
||||
};
|
||||
|
||||
|
||||
/// The b3StridingMeshInterface is the interface class for high performance generic access to triangle meshes, used in combination with b3BvhTriangleMeshShape and some other collision shapes.
|
||||
/// Using index striding of 3*sizeof(integer) it can use triangle arrays, using index striding of 1*sizeof(integer) it can handle triangle strips.
|
||||
/// It allows for sharing graphics and collision meshes. Also it provides locking/unlocking of graphics meshes that are in gpu memory.
|
||||
B3_ATTRIBUTE_ALIGNED16(class ) b3StridingMeshInterface
|
||||
B3_ATTRIBUTE_ALIGNED16(class)
|
||||
b3StridingMeshInterface
|
||||
{
|
||||
protected:
|
||||
|
||||
b3Vector3 m_scaling;
|
||||
protected:
|
||||
b3Vector3 m_scaling;
|
||||
|
||||
public:
|
||||
B3_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
b3StridingMeshInterface() :m_scaling(b3MakeVector3(b3Scalar(1.),b3Scalar(1.),b3Scalar(1.)))
|
||||
{
|
||||
public:
|
||||
B3_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
}
|
||||
b3StridingMeshInterface() : m_scaling(b3MakeVector3(b3Scalar(1.), b3Scalar(1.), b3Scalar(1.)))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~b3StridingMeshInterface();
|
||||
virtual ~b3StridingMeshInterface();
|
||||
|
||||
virtual void InternalProcessAllTriangles(b3InternalTriangleIndexCallback * callback, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const;
|
||||
|
||||
///brute force method to calculate aabb
|
||||
void calculateAabbBruteForce(b3Vector3 & aabbMin, b3Vector3 & aabbMax);
|
||||
|
||||
virtual void InternalProcessAllTriangles(b3InternalTriangleIndexCallback* callback,const b3Vector3& aabbMin,const b3Vector3& aabbMax) const;
|
||||
/// get read and write access to a subpart of a triangle mesh
|
||||
/// this subpart has a continuous array of vertices and indices
|
||||
/// in this way the mesh can be handled as chunks of memory with striding
|
||||
/// very similar to OpenGL vertexarray support
|
||||
/// make a call to unLockVertexBase when the read and write access is finished
|
||||
virtual void getLockedVertexIndexBase(unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& stride, unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0) = 0;
|
||||
|
||||
///brute force method to calculate aabb
|
||||
void calculateAabbBruteForce(b3Vector3& aabbMin,b3Vector3& aabbMax);
|
||||
virtual void getLockedReadOnlyVertexIndexBase(const unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& stride, const unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0) const = 0;
|
||||
|
||||
/// get read and write access to a subpart of a triangle mesh
|
||||
/// this subpart has a continuous array of vertices and indices
|
||||
/// in this way the mesh can be handled as chunks of memory with striding
|
||||
/// very similar to OpenGL vertexarray support
|
||||
/// make a call to unLockVertexBase when the read and write access is finished
|
||||
virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0)=0;
|
||||
|
||||
virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const=0;
|
||||
|
||||
/// unLockVertexBase finishes the access to a subpart of the triangle mesh
|
||||
/// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
|
||||
virtual void unLockVertexBase(int subpart)=0;
|
||||
/// unLockVertexBase finishes the access to a subpart of the triangle mesh
|
||||
/// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
|
||||
virtual void unLockVertexBase(int subpart) = 0;
|
||||
|
||||
virtual void unLockReadOnlyVertexBase(int subpart) const=0;
|
||||
virtual void unLockReadOnlyVertexBase(int subpart) const = 0;
|
||||
|
||||
/// getNumSubParts returns the number of seperate subparts
|
||||
/// each subpart has a continuous array of vertices and indices
|
||||
virtual int getNumSubParts() const = 0;
|
||||
|
||||
/// getNumSubParts returns the number of seperate subparts
|
||||
/// each subpart has a continuous array of vertices and indices
|
||||
virtual int getNumSubParts() const=0;
|
||||
virtual void preallocateVertices(int numverts) = 0;
|
||||
virtual void preallocateIndices(int numindices) = 0;
|
||||
|
||||
virtual void preallocateVertices(int numverts)=0;
|
||||
virtual void preallocateIndices(int numindices)=0;
|
||||
virtual bool hasPremadeAabb() const { return false; }
|
||||
virtual void setPremadeAabb(const b3Vector3& aabbMin, const b3Vector3& aabbMax) const
|
||||
{
|
||||
(void)aabbMin;
|
||||
(void)aabbMax;
|
||||
}
|
||||
virtual void getPremadeAabb(b3Vector3 * aabbMin, b3Vector3 * aabbMax) const
|
||||
{
|
||||
(void)aabbMin;
|
||||
(void)aabbMax;
|
||||
}
|
||||
|
||||
virtual bool hasPremadeAabb() const { return false; }
|
||||
virtual void setPremadeAabb(const b3Vector3& aabbMin, const b3Vector3& aabbMax ) const
|
||||
{
|
||||
(void) aabbMin;
|
||||
(void) aabbMax;
|
||||
}
|
||||
virtual void getPremadeAabb(b3Vector3* aabbMin, b3Vector3* aabbMax ) const
|
||||
{
|
||||
(void) aabbMin;
|
||||
(void) aabbMax;
|
||||
}
|
||||
|
||||
const b3Vector3& getScaling() const {
|
||||
return m_scaling;
|
||||
}
|
||||
void setScaling(const b3Vector3& scaling)
|
||||
{
|
||||
m_scaling = scaling;
|
||||
}
|
||||
|
||||
virtual int calculateSerializeBufferSize() const;
|
||||
|
||||
///fills the dataBuffer and returns the struct name (and 0 on failure)
|
||||
//virtual const char* serialize(void* dataBuffer, b3Serializer* serializer) const;
|
||||
const b3Vector3& getScaling() const
|
||||
{
|
||||
return m_scaling;
|
||||
}
|
||||
void setScaling(const b3Vector3& scaling)
|
||||
{
|
||||
m_scaling = scaling;
|
||||
}
|
||||
|
||||
virtual int calculateSerializeBufferSize() const;
|
||||
|
||||
///fills the dataBuffer and returns the struct name (and 0 on failure)
|
||||
//virtual const char* serialize(void* dataBuffer, b3Serializer* serializer) const;
|
||||
};
|
||||
|
||||
struct b3IntIndexData
|
||||
struct b3IntIndexData
|
||||
{
|
||||
int m_value;
|
||||
int m_value;
|
||||
};
|
||||
|
||||
struct b3ShortIntIndexData
|
||||
struct b3ShortIntIndexData
|
||||
{
|
||||
short m_value;
|
||||
char m_pad[2];
|
||||
};
|
||||
|
||||
struct b3ShortIntIndexTripletData
|
||||
struct b3ShortIntIndexTripletData
|
||||
{
|
||||
short m_values[3];
|
||||
char m_pad[2];
|
||||
short m_values[3];
|
||||
char m_pad[2];
|
||||
};
|
||||
|
||||
struct b3CharIndexTripletData
|
||||
struct b3CharIndexTripletData
|
||||
{
|
||||
unsigned char m_values[3];
|
||||
char m_pad;
|
||||
char m_pad;
|
||||
};
|
||||
|
||||
|
||||
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
|
||||
struct b3MeshPartData
|
||||
struct b3MeshPartData
|
||||
{
|
||||
b3Vector3FloatData *m_vertices3f;
|
||||
b3Vector3DoubleData *m_vertices3d;
|
||||
b3Vector3FloatData* m_vertices3f;
|
||||
b3Vector3DoubleData* m_vertices3d;
|
||||
|
||||
b3IntIndexData *m_indices32;
|
||||
b3ShortIntIndexTripletData *m_3indices16;
|
||||
b3CharIndexTripletData *m_3indices8;
|
||||
b3IntIndexData* m_indices32;
|
||||
b3ShortIntIndexTripletData* m_3indices16;
|
||||
b3CharIndexTripletData* m_3indices8;
|
||||
|
||||
b3ShortIntIndexData *m_indices16;//backwards compatibility
|
||||
b3ShortIntIndexData* m_indices16; //backwards compatibility
|
||||
|
||||
int m_numTriangles;//length of m_indices = m_numTriangles
|
||||
int m_numVertices;
|
||||
int m_numTriangles; //length of m_indices = m_numTriangles
|
||||
int m_numVertices;
|
||||
};
|
||||
|
||||
|
||||
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
|
||||
struct b3StridingMeshInterfaceData
|
||||
struct b3StridingMeshInterfaceData
|
||||
{
|
||||
b3MeshPartData *m_meshPartsPtr;
|
||||
b3Vector3FloatData m_scaling;
|
||||
int m_numMeshParts;
|
||||
b3MeshPartData* m_meshPartsPtr;
|
||||
b3Vector3FloatData m_scaling;
|
||||
int m_numMeshParts;
|
||||
char m_padding[4];
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
B3_FORCE_INLINE int b3StridingMeshInterface::calculateSerializeBufferSize() const
|
||||
B3_FORCE_INLINE int b3StridingMeshInterface::calculateSerializeBufferSize() const
|
||||
{
|
||||
return sizeof(b3StridingMeshInterfaceData);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif //B3_STRIDING_MESHINTERFACE_H
|
||||
#endif //B3_STRIDING_MESHINTERFACE_H
|
||||
|
||||
@@ -6,33 +6,29 @@
|
||||
#include "Bullet3Common/b3AlignedObjectArray.h"
|
||||
#include "b3VectorFloat4.h"
|
||||
|
||||
|
||||
struct b3GjkPairDetector;
|
||||
|
||||
|
||||
|
||||
inline b3Vector3 localGetSupportVertexWithMargin(const float4& supportVec,const struct b3ConvexPolyhedronData* hull,
|
||||
const b3AlignedObjectArray<b3Vector3>& verticesA, b3Scalar margin)
|
||||
inline b3Vector3 localGetSupportVertexWithMargin(const float4& supportVec, const struct b3ConvexPolyhedronData* hull,
|
||||
const b3AlignedObjectArray<b3Vector3>& verticesA, b3Scalar margin)
|
||||
{
|
||||
b3Vector3 supVec = b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
|
||||
b3Vector3 supVec = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
|
||||
b3Scalar maxDot = b3Scalar(-B3_LARGE_FLOAT);
|
||||
|
||||
// Here we take advantage of dot(a, b*c) = dot(a*b, c). Note: This is true mathematically, but not numerically.
|
||||
if( 0 < hull->m_numVertices )
|
||||
{
|
||||
const b3Vector3 scaled = supportVec;
|
||||
int index = (int) scaled.maxDot( &verticesA[hull->m_vertexOffset], hull->m_numVertices, maxDot);
|
||||
return verticesA[hull->m_vertexOffset+index];
|
||||
}
|
||||
|
||||
return supVec;
|
||||
// Here we take advantage of dot(a, b*c) = dot(a*b, c). Note: This is true mathematically, but not numerically.
|
||||
if (0 < hull->m_numVertices)
|
||||
{
|
||||
const b3Vector3 scaled = supportVec;
|
||||
int index = (int)scaled.maxDot(&verticesA[hull->m_vertexOffset], hull->m_numVertices, maxDot);
|
||||
return verticesA[hull->m_vertexOffset + index];
|
||||
}
|
||||
|
||||
return supVec;
|
||||
}
|
||||
|
||||
inline b3Vector3 localGetSupportVertexWithoutMargin(const float4& supportVec,const struct b3ConvexPolyhedronData* hull,
|
||||
const b3AlignedObjectArray<b3Vector3>& verticesA)
|
||||
inline b3Vector3 localGetSupportVertexWithoutMargin(const float4& supportVec, const struct b3ConvexPolyhedronData* hull,
|
||||
const b3AlignedObjectArray<b3Vector3>& verticesA)
|
||||
{
|
||||
return localGetSupportVertexWithMargin(supportVec,hull,verticesA,0.f);
|
||||
return localGetSupportVertexWithMargin(supportVec, hull, verticesA, 0.f);
|
||||
}
|
||||
|
||||
#endif //B3_SUPPORT_MAPPINGS_H
|
||||
#endif //B3_SUPPORT_MAPPINGS_H
|
||||
|
||||
@@ -17,12 +17,8 @@ subject to the following restrictions:
|
||||
|
||||
b3TriangleCallback::~b3TriangleCallback()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
b3InternalTriangleIndexCallback::~b3InternalTriangleIndexCallback()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -18,13 +18,11 @@ subject to the following restrictions:
|
||||
|
||||
#include "Bullet3Common/b3Vector3.h"
|
||||
|
||||
|
||||
///The b3TriangleCallback provides a callback for each overlapping triangle when calling processAllTriangles.
|
||||
///This callback is called by processAllTriangles for all b3ConcaveShape derived class, such as b3BvhTriangleMeshShape, b3StaticPlaneShape and b3HeightfieldTerrainShape.
|
||||
class b3TriangleCallback
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~b3TriangleCallback();
|
||||
virtual void processTriangle(b3Vector3* triangle, int partId, int triangleIndex) = 0;
|
||||
};
|
||||
@@ -32,11 +30,8 @@ public:
|
||||
class b3InternalTriangleIndexCallback
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~b3InternalTriangleIndexCallback();
|
||||
virtual void internalProcessTriangleIndex(b3Vector3* triangle,int partId,int triangleIndex) = 0;
|
||||
virtual void internalProcessTriangleIndex(b3Vector3* triangle, int partId, int triangleIndex) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //B3_TRIANGLE_CALLBACK_H
|
||||
#endif //B3_TRIANGLE_CALLBACK_H
|
||||
|
||||
@@ -15,81 +15,76 @@ subject to the following restrictions:
|
||||
|
||||
#include "b3TriangleIndexVertexArray.h"
|
||||
|
||||
b3TriangleIndexVertexArray::b3TriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,b3Scalar* vertexBase,int vertexStride)
|
||||
: m_hasAabb(0)
|
||||
b3TriangleIndexVertexArray::b3TriangleIndexVertexArray(int numTriangles, int* triangleIndexBase, int triangleIndexStride, int numVertices, b3Scalar* vertexBase, int vertexStride)
|
||||
: m_hasAabb(0)
|
||||
{
|
||||
b3IndexedMesh mesh;
|
||||
|
||||
mesh.m_numTriangles = numTriangles;
|
||||
mesh.m_triangleIndexBase = (const unsigned char *)triangleIndexBase;
|
||||
mesh.m_triangleIndexBase = (const unsigned char*)triangleIndexBase;
|
||||
mesh.m_triangleIndexStride = triangleIndexStride;
|
||||
mesh.m_numVertices = numVertices;
|
||||
mesh.m_vertexBase = (const unsigned char *)vertexBase;
|
||||
mesh.m_vertexBase = (const unsigned char*)vertexBase;
|
||||
mesh.m_vertexStride = vertexStride;
|
||||
|
||||
addIndexedMesh(mesh);
|
||||
|
||||
}
|
||||
|
||||
b3TriangleIndexVertexArray::~b3TriangleIndexVertexArray()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void b3TriangleIndexVertexArray::getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart)
|
||||
void b3TriangleIndexVertexArray::getLockedVertexIndexBase(unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart)
|
||||
{
|
||||
b3Assert(subpart< getNumSubParts() );
|
||||
b3Assert(subpart < getNumSubParts());
|
||||
|
||||
b3IndexedMesh& mesh = m_indexedMeshes[subpart];
|
||||
|
||||
numverts = mesh.m_numVertices;
|
||||
(*vertexbase) = (unsigned char *) mesh.m_vertexBase;
|
||||
(*vertexbase) = (unsigned char*)mesh.m_vertexBase;
|
||||
|
||||
type = mesh.m_vertexType;
|
||||
type = mesh.m_vertexType;
|
||||
|
||||
vertexStride = mesh.m_vertexStride;
|
||||
|
||||
numfaces = mesh.m_numTriangles;
|
||||
|
||||
(*indexbase) = (unsigned char *)mesh.m_triangleIndexBase;
|
||||
(*indexbase) = (unsigned char*)mesh.m_triangleIndexBase;
|
||||
indexstride = mesh.m_triangleIndexStride;
|
||||
indicestype = mesh.m_indexType;
|
||||
}
|
||||
|
||||
void b3TriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) const
|
||||
void b3TriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, const unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart) const
|
||||
{
|
||||
const b3IndexedMesh& mesh = m_indexedMeshes[subpart];
|
||||
|
||||
numverts = mesh.m_numVertices;
|
||||
(*vertexbase) = (const unsigned char *)mesh.m_vertexBase;
|
||||
(*vertexbase) = (const unsigned char*)mesh.m_vertexBase;
|
||||
|
||||
type = mesh.m_vertexType;
|
||||
|
||||
type = mesh.m_vertexType;
|
||||
|
||||
vertexStride = mesh.m_vertexStride;
|
||||
|
||||
numfaces = mesh.m_numTriangles;
|
||||
(*indexbase) = (const unsigned char *)mesh.m_triangleIndexBase;
|
||||
(*indexbase) = (const unsigned char*)mesh.m_triangleIndexBase;
|
||||
indexstride = mesh.m_triangleIndexStride;
|
||||
indicestype = mesh.m_indexType;
|
||||
}
|
||||
|
||||
bool b3TriangleIndexVertexArray::hasPremadeAabb() const
|
||||
bool b3TriangleIndexVertexArray::hasPremadeAabb() const
|
||||
{
|
||||
return (m_hasAabb == 1);
|
||||
}
|
||||
|
||||
|
||||
void b3TriangleIndexVertexArray::setPremadeAabb(const b3Vector3& aabbMin, const b3Vector3& aabbMax ) const
|
||||
void b3TriangleIndexVertexArray::setPremadeAabb(const b3Vector3& aabbMin, const b3Vector3& aabbMax) const
|
||||
{
|
||||
m_aabbMin = aabbMin;
|
||||
m_aabbMax = aabbMax;
|
||||
m_hasAabb = 1; // this is intentionally an int see notes in header
|
||||
m_hasAabb = 1; // this is intentionally an int see notes in header
|
||||
}
|
||||
|
||||
void b3TriangleIndexVertexArray::getPremadeAabb(b3Vector3* aabbMin, b3Vector3* aabbMax ) const
|
||||
void b3TriangleIndexVertexArray::getPremadeAabb(b3Vector3* aabbMin, b3Vector3* aabbMax) const
|
||||
{
|
||||
*aabbMin = m_aabbMin;
|
||||
*aabbMax = m_aabbMax;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -20,62 +20,59 @@ subject to the following restrictions:
|
||||
#include "Bullet3Common/b3AlignedObjectArray.h"
|
||||
#include "Bullet3Common/b3Scalar.h"
|
||||
|
||||
|
||||
///The b3IndexedMesh indexes a single vertex and index array. Multiple b3IndexedMesh objects can be passed into a b3TriangleIndexVertexArray using addIndexedMesh.
|
||||
///Instead of the number of indices, we pass the number of triangles.
|
||||
B3_ATTRIBUTE_ALIGNED16( struct) b3IndexedMesh
|
||||
B3_ATTRIBUTE_ALIGNED16(struct)
|
||||
b3IndexedMesh
|
||||
{
|
||||
B3_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
int m_numTriangles;
|
||||
const unsigned char * m_triangleIndexBase;
|
||||
// Size in byte of the indices for one triangle (3*sizeof(index_type) if the indices are tightly packed)
|
||||
int m_triangleIndexStride;
|
||||
int m_numVertices;
|
||||
const unsigned char * m_vertexBase;
|
||||
// Size of a vertex, in bytes
|
||||
int m_vertexStride;
|
||||
int m_numTriangles;
|
||||
const unsigned char* m_triangleIndexBase;
|
||||
// Size in byte of the indices for one triangle (3*sizeof(index_type) if the indices are tightly packed)
|
||||
int m_triangleIndexStride;
|
||||
int m_numVertices;
|
||||
const unsigned char* m_vertexBase;
|
||||
// Size of a vertex, in bytes
|
||||
int m_vertexStride;
|
||||
|
||||
// The index type is set when adding an indexed mesh to the
|
||||
// b3TriangleIndexVertexArray, do not set it manually
|
||||
PHY_ScalarType m_indexType;
|
||||
// The index type is set when adding an indexed mesh to the
|
||||
// b3TriangleIndexVertexArray, do not set it manually
|
||||
PHY_ScalarType m_indexType;
|
||||
|
||||
// The vertex type has a default type similar to Bullet's precision mode (float or double)
|
||||
// but can be set manually if you for example run Bullet with double precision but have
|
||||
// mesh data in single precision..
|
||||
PHY_ScalarType m_vertexType;
|
||||
// The vertex type has a default type similar to Bullet's precision mode (float or double)
|
||||
// but can be set manually if you for example run Bullet with double precision but have
|
||||
// mesh data in single precision..
|
||||
PHY_ScalarType m_vertexType;
|
||||
|
||||
|
||||
b3IndexedMesh()
|
||||
:m_indexType(PHY_INTEGER),
|
||||
b3IndexedMesh()
|
||||
: m_indexType(PHY_INTEGER),
|
||||
#ifdef B3_USE_DOUBLE_PRECISION
|
||||
m_vertexType(PHY_DOUBLE)
|
||||
#else // B3_USE_DOUBLE_PRECISION
|
||||
m_vertexType(PHY_FLOAT)
|
||||
#endif // B3_USE_DOUBLE_PRECISION
|
||||
{
|
||||
}
|
||||
}
|
||||
;
|
||||
m_vertexType(PHY_DOUBLE)
|
||||
#else // B3_USE_DOUBLE_PRECISION
|
||||
m_vertexType(PHY_FLOAT)
|
||||
#endif // B3_USE_DOUBLE_PRECISION
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef b3AlignedObjectArray<b3IndexedMesh> IndexedMeshArray;
|
||||
typedef b3AlignedObjectArray<b3IndexedMesh> IndexedMeshArray;
|
||||
|
||||
///The b3TriangleIndexVertexArray allows to access multiple triangle meshes, by indexing into existing triangle/index arrays.
|
||||
///Additional meshes can be added using addIndexedMesh
|
||||
///No duplcate is made of the vertex/index data, it only indexes into external vertex/index arrays.
|
||||
///So keep those arrays around during the lifetime of this b3TriangleIndexVertexArray.
|
||||
B3_ATTRIBUTE_ALIGNED16( class) b3TriangleIndexVertexArray : public b3StridingMeshInterface
|
||||
B3_ATTRIBUTE_ALIGNED16(class)
|
||||
b3TriangleIndexVertexArray : public b3StridingMeshInterface
|
||||
{
|
||||
protected:
|
||||
IndexedMeshArray m_indexedMeshes;
|
||||
IndexedMeshArray m_indexedMeshes;
|
||||
int m_pad[2];
|
||||
mutable int m_hasAabb; // using int instead of bool to maintain alignment
|
||||
mutable int m_hasAabb; // using int instead of bool to maintain alignment
|
||||
mutable b3Vector3 m_aabbMin;
|
||||
mutable b3Vector3 m_aabbMax;
|
||||
|
||||
public:
|
||||
|
||||
B3_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
b3TriangleIndexVertexArray() : m_hasAabb(0)
|
||||
@@ -85,49 +82,47 @@ public:
|
||||
virtual ~b3TriangleIndexVertexArray();
|
||||
|
||||
//just to be backwards compatible
|
||||
b3TriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,b3Scalar* vertexBase,int vertexStride);
|
||||
|
||||
void addIndexedMesh(const b3IndexedMesh& mesh, PHY_ScalarType indexType = PHY_INTEGER)
|
||||
b3TriangleIndexVertexArray(int numTriangles, int* triangleIndexBase, int triangleIndexStride, int numVertices, b3Scalar* vertexBase, int vertexStride);
|
||||
|
||||
void addIndexedMesh(const b3IndexedMesh& mesh, PHY_ScalarType indexType = PHY_INTEGER)
|
||||
{
|
||||
m_indexedMeshes.push_back(mesh);
|
||||
m_indexedMeshes[m_indexedMeshes.size()-1].m_indexType = indexType;
|
||||
m_indexedMeshes[m_indexedMeshes.size() - 1].m_indexType = indexType;
|
||||
}
|
||||
|
||||
|
||||
virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0);
|
||||
|
||||
virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const;
|
||||
virtual void getLockedVertexIndexBase(unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0);
|
||||
|
||||
virtual void getLockedReadOnlyVertexIndexBase(const unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, const unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0) const;
|
||||
|
||||
/// unLockVertexBase finishes the access to a subpart of the triangle mesh
|
||||
/// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
|
||||
virtual void unLockVertexBase(int subpart) {(void)subpart;}
|
||||
virtual void unLockVertexBase(int subpart) { (void)subpart; }
|
||||
|
||||
virtual void unLockReadOnlyVertexBase(int subpart) const {(void)subpart;}
|
||||
virtual void unLockReadOnlyVertexBase(int subpart) const { (void)subpart; }
|
||||
|
||||
/// getNumSubParts returns the number of seperate subparts
|
||||
/// each subpart has a continuous array of vertices and indices
|
||||
virtual int getNumSubParts() const {
|
||||
virtual int getNumSubParts() const
|
||||
{
|
||||
return (int)m_indexedMeshes.size();
|
||||
}
|
||||
|
||||
IndexedMeshArray& getIndexedMeshArray()
|
||||
IndexedMeshArray& getIndexedMeshArray()
|
||||
{
|
||||
return m_indexedMeshes;
|
||||
}
|
||||
|
||||
const IndexedMeshArray& getIndexedMeshArray() const
|
||||
const IndexedMeshArray& getIndexedMeshArray() const
|
||||
{
|
||||
return m_indexedMeshes;
|
||||
}
|
||||
|
||||
virtual void preallocateVertices(int numverts){(void) numverts;}
|
||||
virtual void preallocateIndices(int numindices){(void) numindices;}
|
||||
virtual void preallocateVertices(int numverts) { (void)numverts; }
|
||||
virtual void preallocateIndices(int numindices) { (void)numindices; }
|
||||
|
||||
virtual bool hasPremadeAabb() const;
|
||||
virtual void setPremadeAabb(const b3Vector3& aabbMin, const b3Vector3& aabbMax ) const;
|
||||
virtual void getPremadeAabb(b3Vector3* aabbMin, b3Vector3* aabbMax ) const;
|
||||
virtual bool hasPremadeAabb() const;
|
||||
virtual void setPremadeAabb(const b3Vector3& aabbMin, const b3Vector3& aabbMax) const;
|
||||
virtual void getPremadeAabb(b3Vector3 * aabbMin, b3Vector3 * aabbMax) const;
|
||||
};
|
||||
|
||||
}
|
||||
;
|
||||
|
||||
#endif //B3_TRIANGLE_INDEX_VERTEX_ARRAY_H
|
||||
#endif //B3_TRIANGLE_INDEX_VERTEX_ARRAY_H
|
||||
|
||||
@@ -7,5 +7,4 @@
|
||||
#define float4 b3Vector3
|
||||
//#define make_float4(x,y,z,w) b3Vector4(x,y,z,w)
|
||||
|
||||
|
||||
#endif //B3_VECTOR_FLOAT4_H
|
||||
#endif //B3_VECTOR_FLOAT4_H
|
||||
|
||||
@@ -23,26 +23,24 @@ subject to the following restrictions:
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "b3VoronoiSimplexSolver.h"
|
||||
|
||||
#define VERTA 0
|
||||
#define VERTB 1
|
||||
#define VERTC 2
|
||||
#define VERTD 3
|
||||
#define VERTA 0
|
||||
#define VERTB 1
|
||||
#define VERTC 2
|
||||
#define VERTD 3
|
||||
|
||||
#define B3_CATCH_DEGENERATE_TETRAHEDRON 1
|
||||
void b3VoronoiSimplexSolver::removeVertex(int index)
|
||||
void b3VoronoiSimplexSolver::removeVertex(int index)
|
||||
{
|
||||
|
||||
b3Assert(m_numVertices>0);
|
||||
b3Assert(m_numVertices > 0);
|
||||
m_numVertices--;
|
||||
m_simplexVectorW[index] = m_simplexVectorW[m_numVertices];
|
||||
m_simplexPointsP[index] = m_simplexPointsP[m_numVertices];
|
||||
m_simplexPointsQ[index] = m_simplexPointsQ[m_numVertices];
|
||||
}
|
||||
|
||||
void b3VoronoiSimplexSolver::reduceVertices (const b3UsageBitfield& usedVerts)
|
||||
void b3VoronoiSimplexSolver::reduceVertices(const b3UsageBitfield& usedVerts)
|
||||
{
|
||||
if ((numVertices() >= 4) && (!usedVerts.usedVertexD))
|
||||
removeVertex(3);
|
||||
@@ -52,29 +50,22 @@ void b3VoronoiSimplexSolver::reduceVertices (const b3UsageBitfield& usedVerts)
|
||||
|
||||
if ((numVertices() >= 2) && (!usedVerts.usedVertexB))
|
||||
removeVertex(1);
|
||||
|
||||
|
||||
if ((numVertices() >= 1) && (!usedVerts.usedVertexA))
|
||||
removeVertex(0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//clear the simplex, remove all the vertices
|
||||
void b3VoronoiSimplexSolver::reset()
|
||||
{
|
||||
m_cachedValidClosest = false;
|
||||
m_numVertices = 0;
|
||||
m_needsUpdate = true;
|
||||
m_lastW = b3MakeVector3(b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT),b3Scalar(B3_LARGE_FLOAT));
|
||||
m_lastW = b3MakeVector3(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
|
||||
m_cachedBC.reset();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//add a vertex
|
||||
//add a vertex
|
||||
void b3VoronoiSimplexSolver::addVertex(const b3Vector3& w, const b3Vector3& p, const b3Vector3& q)
|
||||
{
|
||||
m_lastW = w;
|
||||
@@ -87,9 +78,8 @@ void b3VoronoiSimplexSolver::addVertex(const b3Vector3& w, const b3Vector3& p, c
|
||||
m_numVertices++;
|
||||
}
|
||||
|
||||
bool b3VoronoiSimplexSolver::updateClosestVectorAndPoints()
|
||||
bool b3VoronoiSimplexSolver::updateClosestVectorAndPoints()
|
||||
{
|
||||
|
||||
if (m_needsUpdate)
|
||||
{
|
||||
m_cachedBC.reset();
|
||||
@@ -98,127 +88,131 @@ bool b3VoronoiSimplexSolver::updateClosestVectorAndPoints()
|
||||
|
||||
switch (numVertices())
|
||||
{
|
||||
case 0:
|
||||
case 0:
|
||||
m_cachedValidClosest = false;
|
||||
break;
|
||||
case 1:
|
||||
case 1:
|
||||
{
|
||||
m_cachedP1 = m_simplexPointsP[0];
|
||||
m_cachedP2 = m_simplexPointsQ[0];
|
||||
m_cachedV = m_cachedP1-m_cachedP2; //== m_simplexVectorW[0]
|
||||
m_cachedV = m_cachedP1 - m_cachedP2; //== m_simplexVectorW[0]
|
||||
m_cachedBC.reset();
|
||||
m_cachedBC.setBarycentricCoordinates(b3Scalar(1.),b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
|
||||
m_cachedBC.setBarycentricCoordinates(b3Scalar(1.), b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
|
||||
m_cachedValidClosest = m_cachedBC.isValid();
|
||||
break;
|
||||
};
|
||||
case 2:
|
||||
case 2:
|
||||
{
|
||||
//closest point origin from line segment
|
||||
const b3Vector3& from = m_simplexVectorW[0];
|
||||
const b3Vector3& to = m_simplexVectorW[1];
|
||||
b3Vector3 nearest;
|
||||
//closest point origin from line segment
|
||||
const b3Vector3& from = m_simplexVectorW[0];
|
||||
const b3Vector3& to = m_simplexVectorW[1];
|
||||
b3Vector3 nearest;
|
||||
|
||||
b3Vector3 p =b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
|
||||
b3Vector3 diff = p - from;
|
||||
b3Vector3 v = to - from;
|
||||
b3Scalar t = v.dot(diff);
|
||||
|
||||
if (t > 0) {
|
||||
b3Scalar dotVV = v.dot(v);
|
||||
if (t < dotVV) {
|
||||
t /= dotVV;
|
||||
diff -= t*v;
|
||||
m_cachedBC.m_usedVertices.usedVertexA = true;
|
||||
m_cachedBC.m_usedVertices.usedVertexB = true;
|
||||
} else {
|
||||
t = 1;
|
||||
diff -= v;
|
||||
//reduce to 1 point
|
||||
m_cachedBC.m_usedVertices.usedVertexB = true;
|
||||
}
|
||||
} else
|
||||
b3Vector3 p = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
|
||||
b3Vector3 diff = p - from;
|
||||
b3Vector3 v = to - from;
|
||||
b3Scalar t = v.dot(diff);
|
||||
|
||||
if (t > 0)
|
||||
{
|
||||
b3Scalar dotVV = v.dot(v);
|
||||
if (t < dotVV)
|
||||
{
|
||||
t = 0;
|
||||
//reduce to 1 point
|
||||
t /= dotVV;
|
||||
diff -= t * v;
|
||||
m_cachedBC.m_usedVertices.usedVertexA = true;
|
||||
m_cachedBC.m_usedVertices.usedVertexB = true;
|
||||
}
|
||||
m_cachedBC.setBarycentricCoordinates(1-t,t);
|
||||
nearest = from + t*v;
|
||||
else
|
||||
{
|
||||
t = 1;
|
||||
diff -= v;
|
||||
//reduce to 1 point
|
||||
m_cachedBC.m_usedVertices.usedVertexB = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
t = 0;
|
||||
//reduce to 1 point
|
||||
m_cachedBC.m_usedVertices.usedVertexA = true;
|
||||
}
|
||||
m_cachedBC.setBarycentricCoordinates(1 - t, t);
|
||||
nearest = from + t * v;
|
||||
|
||||
m_cachedP1 = m_simplexPointsP[0] + t * (m_simplexPointsP[1] - m_simplexPointsP[0]);
|
||||
m_cachedP2 = m_simplexPointsQ[0] + t * (m_simplexPointsQ[1] - m_simplexPointsQ[0]);
|
||||
m_cachedV = m_cachedP1 - m_cachedP2;
|
||||
|
||||
reduceVertices(m_cachedBC.m_usedVertices);
|
||||
m_cachedP1 = m_simplexPointsP[0] + t * (m_simplexPointsP[1] - m_simplexPointsP[0]);
|
||||
m_cachedP2 = m_simplexPointsQ[0] + t * (m_simplexPointsQ[1] - m_simplexPointsQ[0]);
|
||||
m_cachedV = m_cachedP1 - m_cachedP2;
|
||||
|
||||
m_cachedValidClosest = m_cachedBC.isValid();
|
||||
break;
|
||||
reduceVertices(m_cachedBC.m_usedVertices);
|
||||
|
||||
m_cachedValidClosest = m_cachedBC.isValid();
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
//closest point origin from triangle
|
||||
b3Vector3 p =b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
|
||||
|
||||
const b3Vector3& a = m_simplexVectorW[0];
|
||||
const b3Vector3& b = m_simplexVectorW[1];
|
||||
const b3Vector3& c = m_simplexVectorW[2];
|
||||
|
||||
closestPtPointTriangle(p,a,b,c,m_cachedBC);
|
||||
m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
|
||||
m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
|
||||
m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2];
|
||||
|
||||
m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
|
||||
m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
|
||||
m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2];
|
||||
|
||||
m_cachedV = m_cachedP1-m_cachedP2;
|
||||
|
||||
reduceVertices (m_cachedBC.m_usedVertices);
|
||||
m_cachedValidClosest = m_cachedBC.isValid();
|
||||
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
case 3:
|
||||
{
|
||||
//closest point origin from triangle
|
||||
b3Vector3 p = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
|
||||
|
||||
const b3Vector3& a = m_simplexVectorW[0];
|
||||
const b3Vector3& b = m_simplexVectorW[1];
|
||||
const b3Vector3& c = m_simplexVectorW[2];
|
||||
|
||||
closestPtPointTriangle(p, a, b, c, m_cachedBC);
|
||||
m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
|
||||
m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
|
||||
m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2];
|
||||
|
||||
m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
|
||||
m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
|
||||
m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2];
|
||||
|
||||
m_cachedV = m_cachedP1 - m_cachedP2;
|
||||
|
||||
reduceVertices(m_cachedBC.m_usedVertices);
|
||||
m_cachedValidClosest = m_cachedBC.isValid();
|
||||
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
b3Vector3 p = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
|
||||
|
||||
|
||||
b3Vector3 p =b3MakeVector3(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
|
||||
|
||||
const b3Vector3& a = m_simplexVectorW[0];
|
||||
const b3Vector3& b = m_simplexVectorW[1];
|
||||
const b3Vector3& c = m_simplexVectorW[2];
|
||||
const b3Vector3& d = m_simplexVectorW[3];
|
||||
|
||||
bool hasSeperation = closestPtPointTetrahedron(p,a,b,c,d,m_cachedBC);
|
||||
bool hasSeperation = closestPtPointTetrahedron(p, a, b, c, d, m_cachedBC);
|
||||
|
||||
if (hasSeperation)
|
||||
{
|
||||
|
||||
m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
|
||||
m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
|
||||
m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2] +
|
||||
m_simplexPointsP[3] * m_cachedBC.m_barycentricCoords[3];
|
||||
m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
|
||||
m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2] +
|
||||
m_simplexPointsP[3] * m_cachedBC.m_barycentricCoords[3];
|
||||
|
||||
m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
|
||||
m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
|
||||
m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2] +
|
||||
m_simplexPointsQ[3] * m_cachedBC.m_barycentricCoords[3];
|
||||
m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
|
||||
m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2] +
|
||||
m_simplexPointsQ[3] * m_cachedBC.m_barycentricCoords[3];
|
||||
|
||||
m_cachedV = m_cachedP1-m_cachedP2;
|
||||
reduceVertices (m_cachedBC.m_usedVertices);
|
||||
} else
|
||||
m_cachedV = m_cachedP1 - m_cachedP2;
|
||||
reduceVertices(m_cachedBC.m_usedVertices);
|
||||
}
|
||||
else
|
||||
{
|
||||
// printf("sub distance got penetration\n");
|
||||
// printf("sub distance got penetration\n");
|
||||
|
||||
if (m_cachedBC.m_degenerate)
|
||||
{
|
||||
m_cachedValidClosest = false;
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cachedValidClosest = true;
|
||||
//degenerate case == false, penetration = true + zero
|
||||
m_cachedV.setValue(b3Scalar(0.),b3Scalar(0.),b3Scalar(0.));
|
||||
m_cachedV.setValue(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -228,7 +222,7 @@ bool b3VoronoiSimplexSolver::updateClosestVectorAndPoints()
|
||||
//closest point origin from tetrahedron
|
||||
break;
|
||||
}
|
||||
default:
|
||||
default:
|
||||
{
|
||||
m_cachedValidClosest = false;
|
||||
}
|
||||
@@ -236,7 +230,6 @@ bool b3VoronoiSimplexSolver::updateClosestVectorAndPoints()
|
||||
}
|
||||
|
||||
return m_cachedValidClosest;
|
||||
|
||||
}
|
||||
|
||||
//return/calculate the closest vertex
|
||||
@@ -247,13 +240,11 @@ bool b3VoronoiSimplexSolver::closest(b3Vector3& v)
|
||||
return succes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
b3Scalar b3VoronoiSimplexSolver::maxVertex()
|
||||
{
|
||||
int i, numverts = numVertices();
|
||||
b3Scalar maxV = b3Scalar(0.);
|
||||
for (i=0;i<numverts;i++)
|
||||
for (i = 0; i < numverts; i++)
|
||||
{
|
||||
b3Scalar curLen2 = m_simplexVectorW[i].length2();
|
||||
if (maxV < curLen2)
|
||||
@@ -262,13 +253,11 @@ b3Scalar b3VoronoiSimplexSolver::maxVertex()
|
||||
return maxV;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//return the current simplex
|
||||
int b3VoronoiSimplexSolver::getSimplex(b3Vector3 *pBuf, b3Vector3 *qBuf, b3Vector3 *yBuf) const
|
||||
//return the current simplex
|
||||
int b3VoronoiSimplexSolver::getSimplex(b3Vector3* pBuf, b3Vector3* qBuf, b3Vector3* yBuf) const
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<numVertices();i++)
|
||||
for (i = 0; i < numVertices(); i++)
|
||||
{
|
||||
yBuf[i] = m_simplexVectorW[i];
|
||||
pBuf[i] = m_simplexPointsP[i];
|
||||
@@ -277,20 +266,17 @@ int b3VoronoiSimplexSolver::getSimplex(b3Vector3 *pBuf, b3Vector3 *qBuf, b3Vecto
|
||||
return numVertices();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool b3VoronoiSimplexSolver::inSimplex(const b3Vector3& w)
|
||||
{
|
||||
bool found = false;
|
||||
int i, numverts = numVertices();
|
||||
//b3Scalar maxV = b3Scalar(0.);
|
||||
|
||||
|
||||
//w is in the current (reduced) simplex
|
||||
for (i=0;i<numverts;i++)
|
||||
for (i = 0; i < numverts; i++)
|
||||
{
|
||||
#ifdef BT_USE_EQUAL_VERTEX_THRESHOLD
|
||||
if ( m_simplexVectorW[i].distance2(w) <= m_equalVertexThreshold)
|
||||
if (m_simplexVectorW[i].distance2(w) <= m_equalVertexThreshold)
|
||||
#else
|
||||
if (m_simplexVectorW[i] == w)
|
||||
#endif
|
||||
@@ -300,199 +286,190 @@ bool b3VoronoiSimplexSolver::inSimplex(const b3Vector3& w)
|
||||
//check in case lastW is already removed
|
||||
if (w == m_lastW)
|
||||
return true;
|
||||
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
void b3VoronoiSimplexSolver::backup_closest(b3Vector3& v)
|
||||
void b3VoronoiSimplexSolver::backup_closest(b3Vector3& v)
|
||||
{
|
||||
v = m_cachedV;
|
||||
}
|
||||
|
||||
|
||||
bool b3VoronoiSimplexSolver::emptySimplex() const
|
||||
bool b3VoronoiSimplexSolver::emptySimplex() const
|
||||
{
|
||||
return (numVertices() == 0);
|
||||
|
||||
}
|
||||
|
||||
void b3VoronoiSimplexSolver::compute_points(b3Vector3& p1, b3Vector3& p2)
|
||||
void b3VoronoiSimplexSolver::compute_points(b3Vector3& p1, b3Vector3& p2)
|
||||
{
|
||||
updateClosestVectorAndPoints();
|
||||
p1 = m_cachedP1;
|
||||
p2 = m_cachedP2;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool b3VoronoiSimplexSolver::closestPtPointTriangle(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c,b3SubSimplexClosestResult& result)
|
||||
bool b3VoronoiSimplexSolver::closestPtPointTriangle(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, b3SubSimplexClosestResult& result)
|
||||
{
|
||||
result.m_usedVertices.reset();
|
||||
|
||||
// Check if P in vertex region outside A
|
||||
b3Vector3 ab = b - a;
|
||||
b3Vector3 ac = c - a;
|
||||
b3Vector3 ap = p - a;
|
||||
b3Scalar d1 = ab.dot(ap);
|
||||
b3Scalar d2 = ac.dot(ap);
|
||||
if (d1 <= b3Scalar(0.0) && d2 <= b3Scalar(0.0))
|
||||
// Check if P in vertex region outside A
|
||||
b3Vector3 ab = b - a;
|
||||
b3Vector3 ac = c - a;
|
||||
b3Vector3 ap = p - a;
|
||||
b3Scalar d1 = ab.dot(ap);
|
||||
b3Scalar d2 = ac.dot(ap);
|
||||
if (d1 <= b3Scalar(0.0) && d2 <= b3Scalar(0.0))
|
||||
{
|
||||
result.m_closestPointOnSimplex = a;
|
||||
result.m_usedVertices.usedVertexA = true;
|
||||
result.setBarycentricCoordinates(1,0,0);
|
||||
return true;// a; // barycentric coordinates (1,0,0)
|
||||
result.setBarycentricCoordinates(1, 0, 0);
|
||||
return true; // a; // barycentric coordinates (1,0,0)
|
||||
}
|
||||
|
||||
// Check if P in vertex region outside B
|
||||
b3Vector3 bp = p - b;
|
||||
b3Scalar d3 = ab.dot(bp);
|
||||
b3Scalar d4 = ac.dot(bp);
|
||||
if (d3 >= b3Scalar(0.0) && d4 <= d3)
|
||||
// Check if P in vertex region outside B
|
||||
b3Vector3 bp = p - b;
|
||||
b3Scalar d3 = ab.dot(bp);
|
||||
b3Scalar d4 = ac.dot(bp);
|
||||
if (d3 >= b3Scalar(0.0) && d4 <= d3)
|
||||
{
|
||||
result.m_closestPointOnSimplex = b;
|
||||
result.m_usedVertices.usedVertexB = true;
|
||||
result.setBarycentricCoordinates(0,1,0);
|
||||
result.setBarycentricCoordinates(0, 1, 0);
|
||||
|
||||
return true; // b; // barycentric coordinates (0,1,0)
|
||||
return true; // b; // barycentric coordinates (0,1,0)
|
||||
}
|
||||
// Check if P in edge region of AB, if so return projection of P onto AB
|
||||
b3Scalar vc = d1*d4 - d3*d2;
|
||||
if (vc <= b3Scalar(0.0) && d1 >= b3Scalar(0.0) && d3 <= b3Scalar(0.0)) {
|
||||
b3Scalar v = d1 / (d1 - d3);
|
||||
// Check if P in edge region of AB, if so return projection of P onto AB
|
||||
b3Scalar vc = d1 * d4 - d3 * d2;
|
||||
if (vc <= b3Scalar(0.0) && d1 >= b3Scalar(0.0) && d3 <= b3Scalar(0.0))
|
||||
{
|
||||
b3Scalar v = d1 / (d1 - d3);
|
||||
result.m_closestPointOnSimplex = a + v * ab;
|
||||
result.m_usedVertices.usedVertexA = true;
|
||||
result.m_usedVertices.usedVertexB = true;
|
||||
result.setBarycentricCoordinates(1-v,v,0);
|
||||
result.setBarycentricCoordinates(1 - v, v, 0);
|
||||
return true;
|
||||
//return a + v * ab; // barycentric coordinates (1-v,v,0)
|
||||
}
|
||||
//return a + v * ab; // barycentric coordinates (1-v,v,0)
|
||||
}
|
||||
|
||||
// Check if P in vertex region outside C
|
||||
b3Vector3 cp = p - c;
|
||||
b3Scalar d5 = ab.dot(cp);
|
||||
b3Scalar d6 = ac.dot(cp);
|
||||
if (d6 >= b3Scalar(0.0) && d5 <= d6)
|
||||
// Check if P in vertex region outside C
|
||||
b3Vector3 cp = p - c;
|
||||
b3Scalar d5 = ab.dot(cp);
|
||||
b3Scalar d6 = ac.dot(cp);
|
||||
if (d6 >= b3Scalar(0.0) && d5 <= d6)
|
||||
{
|
||||
result.m_closestPointOnSimplex = c;
|
||||
result.m_usedVertices.usedVertexC = true;
|
||||
result.setBarycentricCoordinates(0,0,1);
|
||||
return true;//c; // barycentric coordinates (0,0,1)
|
||||
result.setBarycentricCoordinates(0, 0, 1);
|
||||
return true; //c; // barycentric coordinates (0,0,1)
|
||||
}
|
||||
|
||||
// Check if P in edge region of AC, if so return projection of P onto AC
|
||||
b3Scalar vb = d5*d2 - d1*d6;
|
||||
if (vb <= b3Scalar(0.0) && d2 >= b3Scalar(0.0) && d6 <= b3Scalar(0.0)) {
|
||||
b3Scalar w = d2 / (d2 - d6);
|
||||
// Check if P in edge region of AC, if so return projection of P onto AC
|
||||
b3Scalar vb = d5 * d2 - d1 * d6;
|
||||
if (vb <= b3Scalar(0.0) && d2 >= b3Scalar(0.0) && d6 <= b3Scalar(0.0))
|
||||
{
|
||||
b3Scalar w = d2 / (d2 - d6);
|
||||
result.m_closestPointOnSimplex = a + w * ac;
|
||||
result.m_usedVertices.usedVertexA = true;
|
||||
result.m_usedVertices.usedVertexC = true;
|
||||
result.setBarycentricCoordinates(1-w,0,w);
|
||||
result.setBarycentricCoordinates(1 - w, 0, w);
|
||||
return true;
|
||||
//return a + w * ac; // barycentric coordinates (1-w,0,w)
|
||||
}
|
||||
//return a + w * ac; // barycentric coordinates (1-w,0,w)
|
||||
}
|
||||
|
||||
// Check if P in edge region of BC, if so return projection of P onto BC
|
||||
b3Scalar va = d3 * d6 - d5 * d4;
|
||||
if (va <= b3Scalar(0.0) && (d4 - d3) >= b3Scalar(0.0) && (d5 - d6) >= b3Scalar(0.0))
|
||||
{
|
||||
b3Scalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
|
||||
|
||||
// Check if P in edge region of BC, if so return projection of P onto BC
|
||||
b3Scalar va = d3*d6 - d5*d4;
|
||||
if (va <= b3Scalar(0.0) && (d4 - d3) >= b3Scalar(0.0) && (d5 - d6) >= b3Scalar(0.0)) {
|
||||
b3Scalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
|
||||
|
||||
result.m_closestPointOnSimplex = b + w * (c - b);
|
||||
result.m_usedVertices.usedVertexB = true;
|
||||
result.m_usedVertices.usedVertexC = true;
|
||||
result.setBarycentricCoordinates(0,1-w,w);
|
||||
return true;
|
||||
// return b + w * (c - b); // barycentric coordinates (0,1-w,w)
|
||||
}
|
||||
result.setBarycentricCoordinates(0, 1 - w, w);
|
||||
return true;
|
||||
// return b + w * (c - b); // barycentric coordinates (0,1-w,w)
|
||||
}
|
||||
|
||||
// P inside face region. Compute Q through its barycentric coordinates (u,v,w)
|
||||
b3Scalar denom = b3Scalar(1.0) / (va + vb + vc);
|
||||
b3Scalar v = vb * denom;
|
||||
b3Scalar w = vc * denom;
|
||||
|
||||
// P inside face region. Compute Q through its barycentric coordinates (u,v,w)
|
||||
b3Scalar denom = b3Scalar(1.0) / (va + vb + vc);
|
||||
b3Scalar v = vb * denom;
|
||||
b3Scalar w = vc * denom;
|
||||
|
||||
result.m_closestPointOnSimplex = a + ab * v + ac * w;
|
||||
result.m_usedVertices.usedVertexA = true;
|
||||
result.m_usedVertices.usedVertexB = true;
|
||||
result.m_usedVertices.usedVertexC = true;
|
||||
result.setBarycentricCoordinates(1-v-w,v,w);
|
||||
|
||||
result.setBarycentricCoordinates(1 - v - w, v, w);
|
||||
|
||||
return true;
|
||||
// return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = b3Scalar(1.0) - v - w
|
||||
|
||||
// return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = b3Scalar(1.0) - v - w
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// Test if point p and d lie on opposite sides of plane through abc
|
||||
int b3VoronoiSimplexSolver::pointOutsideOfPlane(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d)
|
||||
{
|
||||
b3Vector3 normal = (b-a).cross(c-a);
|
||||
b3Vector3 normal = (b - a).cross(c - a);
|
||||
|
||||
b3Scalar signp = (p - a).dot(normal); // [AP AB AC]
|
||||
b3Scalar signd = (d - a).dot( normal); // [AD AB AC]
|
||||
b3Scalar signp = (p - a).dot(normal); // [AP AB AC]
|
||||
b3Scalar signd = (d - a).dot(normal); // [AD AB AC]
|
||||
|
||||
#ifdef B3_CATCH_DEGENERATE_TETRAHEDRON
|
||||
#ifdef BT_USE_DOUBLE_PRECISION
|
||||
if (signd * signd < (b3Scalar(1e-8) * b3Scalar(1e-8)))
|
||||
if (signd * signd < (b3Scalar(1e-8) * b3Scalar(1e-8)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
if (signd * signd < (b3Scalar(1e-4) * b3Scalar(1e-4)))
|
||||
{
|
||||
// printf("affine dependent/degenerate\n");//
|
||||
// printf("affine dependent/degenerate\n");//
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
// Points on opposite sides if expression signs are opposite
|
||||
return signp * signd < b3Scalar(0.);
|
||||
return signp * signd < b3Scalar(0.);
|
||||
}
|
||||
|
||||
|
||||
bool b3VoronoiSimplexSolver::closestPtPointTetrahedron(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d, b3SubSimplexClosestResult& finalResult)
|
||||
bool b3VoronoiSimplexSolver::closestPtPointTetrahedron(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d, b3SubSimplexClosestResult& finalResult)
|
||||
{
|
||||
b3SubSimplexClosestResult tempResult;
|
||||
|
||||
// Start out assuming point inside all halfspaces, so closest to itself
|
||||
// Start out assuming point inside all halfspaces, so closest to itself
|
||||
finalResult.m_closestPointOnSimplex = p;
|
||||
finalResult.m_usedVertices.reset();
|
||||
finalResult.m_usedVertices.usedVertexA = true;
|
||||
finalResult.m_usedVertices.usedVertexA = true;
|
||||
finalResult.m_usedVertices.usedVertexB = true;
|
||||
finalResult.m_usedVertices.usedVertexC = true;
|
||||
finalResult.m_usedVertices.usedVertexD = true;
|
||||
|
||||
int pointOutsideABC = pointOutsideOfPlane(p, a, b, c, d);
|
||||
int pointOutsideABC = pointOutsideOfPlane(p, a, b, c, d);
|
||||
int pointOutsideACD = pointOutsideOfPlane(p, a, c, d, b);
|
||||
int pointOutsideADB = pointOutsideOfPlane(p, a, d, b, c);
|
||||
int pointOutsideBDC = pointOutsideOfPlane(p, b, d, c, a);
|
||||
int pointOutsideADB = pointOutsideOfPlane(p, a, d, b, c);
|
||||
int pointOutsideBDC = pointOutsideOfPlane(p, b, d, c, a);
|
||||
|
||||
if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0)
|
||||
{
|
||||
finalResult.m_degenerate = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!pointOutsideABC && !pointOutsideACD && !pointOutsideADB && !pointOutsideBDC)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
b3Scalar bestSqDist = FLT_MAX;
|
||||
// If point outside face abc then compute closest point on abc
|
||||
if (pointOutsideABC)
|
||||
if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0)
|
||||
{
|
||||
closestPtPointTriangle(p, a, b, c,tempResult);
|
||||
finalResult.m_degenerate = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!pointOutsideABC && !pointOutsideACD && !pointOutsideADB && !pointOutsideBDC)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
b3Scalar bestSqDist = FLT_MAX;
|
||||
// If point outside face abc then compute closest point on abc
|
||||
if (pointOutsideABC)
|
||||
{
|
||||
closestPtPointTriangle(p, a, b, c, tempResult);
|
||||
b3Vector3 q = tempResult.m_closestPointOnSimplex;
|
||||
|
||||
b3Scalar sqDist = (q - p).dot( q - p);
|
||||
// Update best closest point if (squared) distance is less than current best
|
||||
if (sqDist < bestSqDist) {
|
||||
|
||||
b3Scalar sqDist = (q - p).dot(q - p);
|
||||
// Update best closest point if (squared) distance is less than current best
|
||||
if (sqDist < bestSqDist)
|
||||
{
|
||||
bestSqDist = sqDist;
|
||||
finalResult.m_closestPointOnSimplex = q;
|
||||
//convert result bitmask!
|
||||
@@ -501,25 +478,22 @@ bool b3VoronoiSimplexSolver::closestPtPointTetrahedron(const b3Vector3& p, const
|
||||
finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexB;
|
||||
finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
|
||||
finalResult.setBarycentricCoordinates(
|
||||
tempResult.m_barycentricCoords[VERTA],
|
||||
tempResult.m_barycentricCoords[VERTB],
|
||||
tempResult.m_barycentricCoords[VERTC],
|
||||
0
|
||||
);
|
||||
|
||||
tempResult.m_barycentricCoords[VERTA],
|
||||
tempResult.m_barycentricCoords[VERTB],
|
||||
tempResult.m_barycentricCoords[VERTC],
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Repeat test for face acd
|
||||
if (pointOutsideACD)
|
||||
if (pointOutsideACD)
|
||||
{
|
||||
closestPtPointTriangle(p, a, c, d,tempResult);
|
||||
closestPtPointTriangle(p, a, c, d, tempResult);
|
||||
b3Vector3 q = tempResult.m_closestPointOnSimplex;
|
||||
//convert result bitmask!
|
||||
|
||||
b3Scalar sqDist = (q - p).dot( q - p);
|
||||
if (sqDist < bestSqDist)
|
||||
b3Scalar sqDist = (q - p).dot(q - p);
|
||||
if (sqDist < bestSqDist)
|
||||
{
|
||||
bestSqDist = sqDist;
|
||||
finalResult.m_closestPointOnSimplex = q;
|
||||
@@ -529,52 +503,46 @@ bool b3VoronoiSimplexSolver::closestPtPointTetrahedron(const b3Vector3& p, const
|
||||
finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexB;
|
||||
finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexC;
|
||||
finalResult.setBarycentricCoordinates(
|
||||
tempResult.m_barycentricCoords[VERTA],
|
||||
0,
|
||||
tempResult.m_barycentricCoords[VERTB],
|
||||
tempResult.m_barycentricCoords[VERTC]
|
||||
);
|
||||
|
||||
tempResult.m_barycentricCoords[VERTA],
|
||||
0,
|
||||
tempResult.m_barycentricCoords[VERTB],
|
||||
tempResult.m_barycentricCoords[VERTC]);
|
||||
}
|
||||
}
|
||||
// Repeat test for face adb
|
||||
}
|
||||
// Repeat test for face adb
|
||||
|
||||
|
||||
if (pointOutsideADB)
|
||||
{
|
||||
closestPtPointTriangle(p, a, d, b,tempResult);
|
||||
closestPtPointTriangle(p, a, d, b, tempResult);
|
||||
b3Vector3 q = tempResult.m_closestPointOnSimplex;
|
||||
//convert result bitmask!
|
||||
|
||||
b3Scalar sqDist = (q - p).dot( q - p);
|
||||
if (sqDist < bestSqDist)
|
||||
b3Scalar sqDist = (q - p).dot(q - p);
|
||||
if (sqDist < bestSqDist)
|
||||
{
|
||||
bestSqDist = sqDist;
|
||||
finalResult.m_closestPointOnSimplex = q;
|
||||
finalResult.m_usedVertices.reset();
|
||||
finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
|
||||
finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexC;
|
||||
|
||||
|
||||
finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
|
||||
finalResult.setBarycentricCoordinates(
|
||||
tempResult.m_barycentricCoords[VERTA],
|
||||
tempResult.m_barycentricCoords[VERTC],
|
||||
0,
|
||||
tempResult.m_barycentricCoords[VERTB]
|
||||
);
|
||||
|
||||
tempResult.m_barycentricCoords[VERTA],
|
||||
tempResult.m_barycentricCoords[VERTC],
|
||||
0,
|
||||
tempResult.m_barycentricCoords[VERTB]);
|
||||
}
|
||||
}
|
||||
// Repeat test for face bdc
|
||||
|
||||
}
|
||||
// Repeat test for face bdc
|
||||
|
||||
if (pointOutsideBDC)
|
||||
{
|
||||
closestPtPointTriangle(p, b, d, c,tempResult);
|
||||
closestPtPointTriangle(p, b, d, c, tempResult);
|
||||
b3Vector3 q = tempResult.m_closestPointOnSimplex;
|
||||
//convert result bitmask!
|
||||
b3Scalar sqDist = (q - p).dot( q - p);
|
||||
if (sqDist < bestSqDist)
|
||||
b3Scalar sqDist = (q - p).dot(q - p);
|
||||
if (sqDist < bestSqDist)
|
||||
{
|
||||
bestSqDist = sqDist;
|
||||
finalResult.m_closestPointOnSimplex = q;
|
||||
@@ -585,25 +553,22 @@ bool b3VoronoiSimplexSolver::closestPtPointTetrahedron(const b3Vector3& p, const
|
||||
finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
|
||||
|
||||
finalResult.setBarycentricCoordinates(
|
||||
0,
|
||||
tempResult.m_barycentricCoords[VERTA],
|
||||
tempResult.m_barycentricCoords[VERTC],
|
||||
tempResult.m_barycentricCoords[VERTB]
|
||||
);
|
||||
|
||||
0,
|
||||
tempResult.m_barycentricCoords[VERTA],
|
||||
tempResult.m_barycentricCoords[VERTC],
|
||||
tempResult.m_barycentricCoords[VERTB]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//help! we ended up full !
|
||||
|
||||
|
||||
if (finalResult.m_usedVertices.usedVertexA &&
|
||||
finalResult.m_usedVertices.usedVertexB &&
|
||||
finalResult.m_usedVertices.usedVertexC &&
|
||||
finalResult.m_usedVertices.usedVertexD)
|
||||
finalResult.m_usedVertices.usedVertexD)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,22 +13,19 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef B3_VORONOI_SIMPLEX_SOLVER_H
|
||||
#define B3_VORONOI_SIMPLEX_SOLVER_H
|
||||
|
||||
#include "Bullet3Common/b3Vector3.h"
|
||||
|
||||
|
||||
#define VORONOI_SIMPLEX_MAX_VERTS 5
|
||||
|
||||
///disable next define, or use defaultCollisionConfiguration->getSimplexSolver()->setEqualVertexThreshold(0.f) to disable/configure
|
||||
//#define BT_USE_EQUAL_VERTEX_THRESHOLD
|
||||
#define VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD 0.0001f
|
||||
|
||||
|
||||
struct b3UsageBitfield{
|
||||
struct b3UsageBitfield
|
||||
{
|
||||
b3UsageBitfield()
|
||||
{
|
||||
reset();
|
||||
@@ -41,137 +38,127 @@ struct b3UsageBitfield{
|
||||
usedVertexC = false;
|
||||
usedVertexD = false;
|
||||
}
|
||||
unsigned short usedVertexA : 1;
|
||||
unsigned short usedVertexB : 1;
|
||||
unsigned short usedVertexC : 1;
|
||||
unsigned short usedVertexD : 1;
|
||||
unsigned short unused1 : 1;
|
||||
unsigned short unused2 : 1;
|
||||
unsigned short unused3 : 1;
|
||||
unsigned short unused4 : 1;
|
||||
unsigned short usedVertexA : 1;
|
||||
unsigned short usedVertexB : 1;
|
||||
unsigned short usedVertexC : 1;
|
||||
unsigned short usedVertexD : 1;
|
||||
unsigned short unused1 : 1;
|
||||
unsigned short unused2 : 1;
|
||||
unsigned short unused3 : 1;
|
||||
unsigned short unused4 : 1;
|
||||
};
|
||||
|
||||
|
||||
struct b3SubSimplexClosestResult
|
||||
struct b3SubSimplexClosestResult
|
||||
{
|
||||
b3Vector3 m_closestPointOnSimplex;
|
||||
b3Vector3 m_closestPointOnSimplex;
|
||||
//MASK for m_usedVertices
|
||||
//stores the simplex vertex-usage, using the MASK,
|
||||
//stores the simplex vertex-usage, using the MASK,
|
||||
// if m_usedVertices & MASK then the related vertex is used
|
||||
b3UsageBitfield m_usedVertices;
|
||||
b3Scalar m_barycentricCoords[4];
|
||||
b3UsageBitfield m_usedVertices;
|
||||
b3Scalar m_barycentricCoords[4];
|
||||
bool m_degenerate;
|
||||
|
||||
void reset()
|
||||
void reset()
|
||||
{
|
||||
m_degenerate = false;
|
||||
setBarycentricCoordinates();
|
||||
m_usedVertices.reset();
|
||||
}
|
||||
bool isValid()
|
||||
bool isValid()
|
||||
{
|
||||
bool valid = (m_barycentricCoords[0] >= b3Scalar(0.)) &&
|
||||
(m_barycentricCoords[1] >= b3Scalar(0.)) &&
|
||||
(m_barycentricCoords[2] >= b3Scalar(0.)) &&
|
||||
(m_barycentricCoords[3] >= b3Scalar(0.));
|
||||
|
||||
(m_barycentricCoords[1] >= b3Scalar(0.)) &&
|
||||
(m_barycentricCoords[2] >= b3Scalar(0.)) &&
|
||||
(m_barycentricCoords[3] >= b3Scalar(0.));
|
||||
|
||||
return valid;
|
||||
}
|
||||
void setBarycentricCoordinates(b3Scalar a=b3Scalar(0.),b3Scalar b=b3Scalar(0.),b3Scalar c=b3Scalar(0.),b3Scalar d=b3Scalar(0.))
|
||||
void setBarycentricCoordinates(b3Scalar a = b3Scalar(0.), b3Scalar b = b3Scalar(0.), b3Scalar c = b3Scalar(0.), b3Scalar d = b3Scalar(0.))
|
||||
{
|
||||
m_barycentricCoords[0] = a;
|
||||
m_barycentricCoords[1] = b;
|
||||
m_barycentricCoords[2] = c;
|
||||
m_barycentricCoords[3] = d;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/// b3VoronoiSimplexSolver is an implementation of the closest point distance algorithm from a 1-4 points simplex to the origin.
|
||||
/// Can be used with GJK, as an alternative to Johnson distance algorithm.
|
||||
|
||||
B3_ATTRIBUTE_ALIGNED16(class) b3VoronoiSimplexSolver
|
||||
B3_ATTRIBUTE_ALIGNED16(class)
|
||||
b3VoronoiSimplexSolver
|
||||
{
|
||||
public:
|
||||
|
||||
B3_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
int m_numVertices;
|
||||
int m_numVertices;
|
||||
|
||||
b3Vector3 m_simplexVectorW[VORONOI_SIMPLEX_MAX_VERTS];
|
||||
b3Vector3 m_simplexPointsP[VORONOI_SIMPLEX_MAX_VERTS];
|
||||
b3Vector3 m_simplexPointsQ[VORONOI_SIMPLEX_MAX_VERTS];
|
||||
b3Vector3 m_simplexVectorW[VORONOI_SIMPLEX_MAX_VERTS];
|
||||
b3Vector3 m_simplexPointsP[VORONOI_SIMPLEX_MAX_VERTS];
|
||||
b3Vector3 m_simplexPointsQ[VORONOI_SIMPLEX_MAX_VERTS];
|
||||
|
||||
|
||||
|
||||
b3Vector3 m_cachedP1;
|
||||
b3Vector3 m_cachedP2;
|
||||
b3Vector3 m_cachedV;
|
||||
b3Vector3 m_lastW;
|
||||
|
||||
b3Scalar m_equalVertexThreshold;
|
||||
bool m_cachedValidClosest;
|
||||
b3Vector3 m_cachedP1;
|
||||
b3Vector3 m_cachedP2;
|
||||
b3Vector3 m_cachedV;
|
||||
b3Vector3 m_lastW;
|
||||
|
||||
b3Scalar m_equalVertexThreshold;
|
||||
bool m_cachedValidClosest;
|
||||
|
||||
b3SubSimplexClosestResult m_cachedBC;
|
||||
|
||||
bool m_needsUpdate;
|
||||
|
||||
void removeVertex(int index);
|
||||
void reduceVertices (const b3UsageBitfield& usedVerts);
|
||||
bool updateClosestVectorAndPoints();
|
||||
bool m_needsUpdate;
|
||||
|
||||
bool closestPtPointTetrahedron(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d, b3SubSimplexClosestResult& finalResult);
|
||||
int pointOutsideOfPlane(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d);
|
||||
bool closestPtPointTriangle(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c,b3SubSimplexClosestResult& result);
|
||||
void removeVertex(int index);
|
||||
void reduceVertices(const b3UsageBitfield& usedVerts);
|
||||
bool updateClosestVectorAndPoints();
|
||||
|
||||
bool closestPtPointTetrahedron(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d, b3SubSimplexClosestResult& finalResult);
|
||||
int pointOutsideOfPlane(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d);
|
||||
bool closestPtPointTriangle(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, b3SubSimplexClosestResult& result);
|
||||
|
||||
public:
|
||||
|
||||
b3VoronoiSimplexSolver()
|
||||
: m_equalVertexThreshold(VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD)
|
||||
: m_equalVertexThreshold(VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD)
|
||||
{
|
||||
}
|
||||
void reset();
|
||||
void reset();
|
||||
|
||||
void addVertex(const b3Vector3& w, const b3Vector3& p, const b3Vector3& q);
|
||||
void addVertex(const b3Vector3& w, const b3Vector3& p, const b3Vector3& q);
|
||||
|
||||
void setEqualVertexThreshold(b3Scalar threshold)
|
||||
{
|
||||
m_equalVertexThreshold = threshold;
|
||||
}
|
||||
void setEqualVertexThreshold(b3Scalar threshold)
|
||||
{
|
||||
m_equalVertexThreshold = threshold;
|
||||
}
|
||||
|
||||
b3Scalar getEqualVertexThreshold() const
|
||||
{
|
||||
return m_equalVertexThreshold;
|
||||
}
|
||||
b3Scalar getEqualVertexThreshold() const
|
||||
{
|
||||
return m_equalVertexThreshold;
|
||||
}
|
||||
|
||||
bool closest(b3Vector3& v);
|
||||
bool closest(b3Vector3 & v);
|
||||
|
||||
b3Scalar maxVertex();
|
||||
b3Scalar maxVertex();
|
||||
|
||||
bool fullSimplex() const
|
||||
{
|
||||
return (m_numVertices == 4);
|
||||
}
|
||||
bool fullSimplex() const
|
||||
{
|
||||
return (m_numVertices == 4);
|
||||
}
|
||||
|
||||
int getSimplex(b3Vector3 *pBuf, b3Vector3 *qBuf, b3Vector3 *yBuf) const;
|
||||
int getSimplex(b3Vector3 * pBuf, b3Vector3 * qBuf, b3Vector3 * yBuf) const;
|
||||
|
||||
bool inSimplex(const b3Vector3& w);
|
||||
|
||||
void backup_closest(b3Vector3& v) ;
|
||||
bool inSimplex(const b3Vector3& w);
|
||||
|
||||
bool emptySimplex() const ;
|
||||
void backup_closest(b3Vector3 & v);
|
||||
|
||||
void compute_points(b3Vector3& p1, b3Vector3& p2) ;
|
||||
|
||||
int numVertices() const
|
||||
{
|
||||
return m_numVertices;
|
||||
}
|
||||
bool emptySimplex() const;
|
||||
|
||||
void compute_points(b3Vector3 & p1, b3Vector3 & p2);
|
||||
|
||||
int numVertices() const
|
||||
{
|
||||
return m_numVertices;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //B3_VORONOI_SIMPLEX_SOLVER_H
|
||||
|
||||
#endif //B3_VORONOI_SIMPLEX_SOLVER_H
|
||||
|
||||
@@ -1,258 +1,257 @@
|
||||
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
|
||||
static const char* bvhTraversalKernelCL= \
|
||||
"//keep this enum in sync with the CPU version (in btCollidable.h)\n"
|
||||
"//written by Erwin Coumans\n"
|
||||
"#define SHAPE_CONVEX_HULL 3\n"
|
||||
"#define SHAPE_CONCAVE_TRIMESH 5\n"
|
||||
"#define TRIANGLE_NUM_CONVEX_FACES 5\n"
|
||||
"#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
|
||||
"#define SHAPE_SPHERE 7\n"
|
||||
"typedef unsigned int u32;\n"
|
||||
"#define MAX_NUM_PARTS_IN_BITS 10\n"
|
||||
"///btQuantizedBvhNode is a compressed aabb node, 16 bytes.\n"
|
||||
"///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" //12 bytes\n"
|
||||
" unsigned short int m_quantizedAabbMin[3];\n"
|
||||
" unsigned short int m_quantizedAabbMax[3];\n"
|
||||
" //4 bytes\n"
|
||||
" int m_escapeIndexOrTriangleIndex;\n"
|
||||
"} btQuantizedBvhNode;\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_aabbMin;\n"
|
||||
" float4 m_aabbMax;\n"
|
||||
" float4 m_quantization;\n"
|
||||
" int m_numNodes;\n"
|
||||
" int m_numSubTrees;\n"
|
||||
" int m_nodeOffset;\n"
|
||||
" int m_subTreeOffset;\n"
|
||||
"} b3BvhInfo;\n"
|
||||
"int getTriangleIndex(const btQuantizedBvhNode* rootNode)\n"
|
||||
"{\n"
|
||||
" unsigned int x=0;\n"
|
||||
" unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
|
||||
" // Get only the lower bits where the triangle index is stored\n"
|
||||
" return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
|
||||
"}\n"
|
||||
"int isLeaf(const btQuantizedBvhNode* rootNode)\n"
|
||||
"{\n"
|
||||
" //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
|
||||
" return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
|
||||
"}\n"
|
||||
" \n"
|
||||
"int getEscapeIndex(const btQuantizedBvhNode* rootNode)\n"
|
||||
"{\n"
|
||||
" return -rootNode->m_escapeIndexOrTriangleIndex;\n"
|
||||
"}\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" //12 bytes\n"
|
||||
" unsigned short int m_quantizedAabbMin[3];\n"
|
||||
" unsigned short int m_quantizedAabbMax[3];\n"
|
||||
" //4 bytes, points to the root of the subtree\n"
|
||||
" int m_rootNodeIndex;\n"
|
||||
" //4 bytes\n"
|
||||
" int m_subtreeSize;\n"
|
||||
" int m_padding[3];\n"
|
||||
"} btBvhSubtreeInfo;\n"
|
||||
"///keep this in sync with btCollidable.h\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" int m_numChildShapes;\n"
|
||||
" int blaat2;\n"
|
||||
" int m_shapeType;\n"
|
||||
" int m_shapeIndex;\n"
|
||||
" \n"
|
||||
"} btCollidableGpu;\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_childPosition;\n"
|
||||
" float4 m_childOrientation;\n"
|
||||
" int m_shapeIndex;\n"
|
||||
" int m_unused0;\n"
|
||||
" int m_unused1;\n"
|
||||
" int m_unused2;\n"
|
||||
"} btGpuChildShape;\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_pos;\n"
|
||||
" float4 m_quat;\n"
|
||||
" float4 m_linVel;\n"
|
||||
" float4 m_angVel;\n"
|
||||
" u32 m_collidableIdx;\n"
|
||||
" float m_invMass;\n"
|
||||
" float m_restituitionCoeff;\n"
|
||||
" float m_frictionCoeff;\n"
|
||||
"} BodyData;\n"
|
||||
"typedef struct \n"
|
||||
"{\n"
|
||||
" union\n"
|
||||
" {\n"
|
||||
" float4 m_min;\n"
|
||||
" float m_minElems[4];\n"
|
||||
" int m_minIndices[4];\n"
|
||||
" };\n"
|
||||
" union\n"
|
||||
" {\n"
|
||||
" float4 m_max;\n"
|
||||
" float m_maxElems[4];\n"
|
||||
" int m_maxIndices[4];\n"
|
||||
" };\n"
|
||||
"} btAabbCL;\n"
|
||||
"int testQuantizedAabbAgainstQuantizedAabb(\n"
|
||||
" const unsigned short int* aabbMin1,\n"
|
||||
" const unsigned short int* aabbMax1,\n"
|
||||
" const unsigned short int* aabbMin2,\n"
|
||||
" const unsigned short int* aabbMax2)\n"
|
||||
"{\n"
|
||||
" //int overlap = 1;\n"
|
||||
" if (aabbMin1[0] > aabbMax2[0])\n"
|
||||
" return 0;\n"
|
||||
" if (aabbMax1[0] < aabbMin2[0])\n"
|
||||
" return 0;\n"
|
||||
" if (aabbMin1[1] > aabbMax2[1])\n"
|
||||
" return 0;\n"
|
||||
" if (aabbMax1[1] < aabbMin2[1])\n"
|
||||
" return 0;\n"
|
||||
" if (aabbMin1[2] > aabbMax2[2])\n"
|
||||
" return 0;\n"
|
||||
" if (aabbMax1[2] < aabbMin2[2])\n"
|
||||
" return 0;\n"
|
||||
" return 1;\n"
|
||||
" //overlap = ((aabbMin1[0] > aabbMax2[0]) || (aabbMax1[0] < aabbMin2[0])) ? 0 : overlap;\n"
|
||||
" //overlap = ((aabbMin1[2] > aabbMax2[2]) || (aabbMax1[2] < aabbMin2[2])) ? 0 : overlap;\n"
|
||||
" //overlap = ((aabbMin1[1] > aabbMax2[1]) || (aabbMax1[1] < aabbMin2[1])) ? 0 : overlap;\n"
|
||||
" //return overlap;\n"
|
||||
"}\n"
|
||||
"void quantizeWithClamp(unsigned short* out, float4 point2,int isMax, float4 bvhAabbMin, float4 bvhAabbMax, float4 bvhQuantization)\n"
|
||||
"{\n"
|
||||
" float4 clampedPoint = max(point2,bvhAabbMin);\n"
|
||||
" clampedPoint = min (clampedPoint, bvhAabbMax);\n"
|
||||
" float4 v = (clampedPoint - bvhAabbMin) * bvhQuantization;\n"
|
||||
" if (isMax)\n"
|
||||
" {\n"
|
||||
" out[0] = (unsigned short) (((unsigned short)(v.x+1.f) | 1));\n"
|
||||
" out[1] = (unsigned short) (((unsigned short)(v.y+1.f) | 1));\n"
|
||||
" out[2] = (unsigned short) (((unsigned short)(v.z+1.f) | 1));\n"
|
||||
" } else\n"
|
||||
" {\n"
|
||||
" out[0] = (unsigned short) (((unsigned short)(v.x) & 0xfffe));\n"
|
||||
" out[1] = (unsigned short) (((unsigned short)(v.y) & 0xfffe));\n"
|
||||
" out[2] = (unsigned short) (((unsigned short)(v.z) & 0xfffe));\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"// work-in-progress\n"
|
||||
"__kernel void bvhTraversalKernel( __global const int4* pairs, \n"
|
||||
" __global const BodyData* rigidBodies, \n"
|
||||
" __global const btCollidableGpu* collidables,\n"
|
||||
" __global btAabbCL* aabbs,\n"
|
||||
" __global int4* concavePairsOut,\n"
|
||||
" __global volatile int* numConcavePairsOut,\n"
|
||||
" __global const btBvhSubtreeInfo* subtreeHeadersRoot,\n"
|
||||
" __global const btQuantizedBvhNode* quantizedNodesRoot,\n"
|
||||
" __global const b3BvhInfo* bvhInfos,\n"
|
||||
" int numPairs,\n"
|
||||
" int maxNumConcavePairsCapacity)\n"
|
||||
"{\n"
|
||||
" int id = get_global_id(0);\n"
|
||||
" if (id>=numPairs)\n"
|
||||
" return;\n"
|
||||
" \n"
|
||||
" int bodyIndexA = pairs[id].x;\n"
|
||||
" int bodyIndexB = pairs[id].y;\n"
|
||||
" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
|
||||
" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
|
||||
" \n"
|
||||
" //once the broadphase avoids static-static pairs, we can remove this test\n"
|
||||
" if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
|
||||
" {\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
" if (collidables[collidableIndexA].m_shapeType!=SHAPE_CONCAVE_TRIMESH)\n"
|
||||
" return;\n"
|
||||
" int shapeTypeB = collidables[collidableIndexB].m_shapeType;\n"
|
||||
" \n"
|
||||
" if (shapeTypeB!=SHAPE_CONVEX_HULL &&\n"
|
||||
" shapeTypeB!=SHAPE_SPHERE &&\n"
|
||||
" shapeTypeB!=SHAPE_COMPOUND_OF_CONVEX_HULLS\n"
|
||||
" )\n"
|
||||
" return;\n"
|
||||
" b3BvhInfo bvhInfo = bvhInfos[collidables[collidableIndexA].m_numChildShapes];\n"
|
||||
" float4 bvhAabbMin = bvhInfo.m_aabbMin;\n"
|
||||
" float4 bvhAabbMax = bvhInfo.m_aabbMax;\n"
|
||||
" float4 bvhQuantization = bvhInfo.m_quantization;\n"
|
||||
" int numSubtreeHeaders = bvhInfo.m_numSubTrees;\n"
|
||||
" __global const btBvhSubtreeInfo* subtreeHeaders = &subtreeHeadersRoot[bvhInfo.m_subTreeOffset];\n"
|
||||
" __global const btQuantizedBvhNode* quantizedNodes = &quantizedNodesRoot[bvhInfo.m_nodeOffset];\n"
|
||||
" \n"
|
||||
" unsigned short int quantizedQueryAabbMin[3];\n"
|
||||
" unsigned short int quantizedQueryAabbMax[3];\n"
|
||||
" quantizeWithClamp(quantizedQueryAabbMin,aabbs[bodyIndexB].m_min,false,bvhAabbMin, bvhAabbMax,bvhQuantization);\n"
|
||||
" quantizeWithClamp(quantizedQueryAabbMax,aabbs[bodyIndexB].m_max,true ,bvhAabbMin, bvhAabbMax,bvhQuantization);\n"
|
||||
" \n"
|
||||
" for (int i=0;i<numSubtreeHeaders;i++)\n"
|
||||
" {\n"
|
||||
" btBvhSubtreeInfo subtree = subtreeHeaders[i];\n"
|
||||
" \n"
|
||||
" int overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);\n"
|
||||
" if (overlap != 0)\n"
|
||||
" {\n"
|
||||
" int startNodeIndex = subtree.m_rootNodeIndex;\n"
|
||||
" int endNodeIndex = subtree.m_rootNodeIndex+subtree.m_subtreeSize;\n"
|
||||
" int curIndex = startNodeIndex;\n"
|
||||
" int escapeIndex;\n"
|
||||
" int isLeafNode;\n"
|
||||
" int aabbOverlap;\n"
|
||||
" while (curIndex < endNodeIndex)\n"
|
||||
" {\n"
|
||||
" btQuantizedBvhNode rootNode = quantizedNodes[curIndex];\n"
|
||||
" aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode.m_quantizedAabbMin,rootNode.m_quantizedAabbMax);\n"
|
||||
" isLeafNode = isLeaf(&rootNode);\n"
|
||||
" if (aabbOverlap)\n"
|
||||
" {\n"
|
||||
" if (isLeafNode)\n"
|
||||
" {\n"
|
||||
" int triangleIndex = getTriangleIndex(&rootNode);\n"
|
||||
" if (shapeTypeB==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
|
||||
" {\n"
|
||||
" int numChildrenB = collidables[collidableIndexB].m_numChildShapes;\n"
|
||||
" int pairIdx = atomic_add(numConcavePairsOut,numChildrenB);\n"
|
||||
" for (int b=0;b<numChildrenB;b++)\n"
|
||||
" {\n"
|
||||
" if ((pairIdx+b)<maxNumConcavePairsCapacity)\n"
|
||||
" {\n"
|
||||
" int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;\n"
|
||||
" int4 newPair = (int4)(bodyIndexA,bodyIndexB,triangleIndex,childShapeIndexB);\n"
|
||||
" concavePairsOut[pairIdx+b] = newPair;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" } else\n"
|
||||
" {\n"
|
||||
" int pairIdx = atomic_inc(numConcavePairsOut);\n"
|
||||
" if (pairIdx<maxNumConcavePairsCapacity)\n"
|
||||
" {\n"
|
||||
" int4 newPair = (int4)(bodyIndexA,bodyIndexB,triangleIndex,0);\n"
|
||||
" concavePairsOut[pairIdx] = newPair;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" } \n"
|
||||
" curIndex++;\n"
|
||||
" } else\n"
|
||||
" {\n"
|
||||
" if (isLeafNode)\n"
|
||||
" {\n"
|
||||
" curIndex++;\n"
|
||||
" } else\n"
|
||||
" {\n"
|
||||
" escapeIndex = getEscapeIndex(&rootNode);\n"
|
||||
" curIndex += escapeIndex;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
;
|
||||
static const char* bvhTraversalKernelCL =
|
||||
"//keep this enum in sync with the CPU version (in btCollidable.h)\n"
|
||||
"//written by Erwin Coumans\n"
|
||||
"#define SHAPE_CONVEX_HULL 3\n"
|
||||
"#define SHAPE_CONCAVE_TRIMESH 5\n"
|
||||
"#define TRIANGLE_NUM_CONVEX_FACES 5\n"
|
||||
"#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
|
||||
"#define SHAPE_SPHERE 7\n"
|
||||
"typedef unsigned int u32;\n"
|
||||
"#define MAX_NUM_PARTS_IN_BITS 10\n"
|
||||
"///btQuantizedBvhNode is a compressed aabb node, 16 bytes.\n"
|
||||
"///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" //12 bytes\n"
|
||||
" unsigned short int m_quantizedAabbMin[3];\n"
|
||||
" unsigned short int m_quantizedAabbMax[3];\n"
|
||||
" //4 bytes\n"
|
||||
" int m_escapeIndexOrTriangleIndex;\n"
|
||||
"} btQuantizedBvhNode;\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_aabbMin;\n"
|
||||
" float4 m_aabbMax;\n"
|
||||
" float4 m_quantization;\n"
|
||||
" int m_numNodes;\n"
|
||||
" int m_numSubTrees;\n"
|
||||
" int m_nodeOffset;\n"
|
||||
" int m_subTreeOffset;\n"
|
||||
"} b3BvhInfo;\n"
|
||||
"int getTriangleIndex(const btQuantizedBvhNode* rootNode)\n"
|
||||
"{\n"
|
||||
" unsigned int x=0;\n"
|
||||
" unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
|
||||
" // Get only the lower bits where the triangle index is stored\n"
|
||||
" return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
|
||||
"}\n"
|
||||
"int isLeaf(const btQuantizedBvhNode* rootNode)\n"
|
||||
"{\n"
|
||||
" //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
|
||||
" return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
|
||||
"}\n"
|
||||
" \n"
|
||||
"int getEscapeIndex(const btQuantizedBvhNode* rootNode)\n"
|
||||
"{\n"
|
||||
" return -rootNode->m_escapeIndexOrTriangleIndex;\n"
|
||||
"}\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" //12 bytes\n"
|
||||
" unsigned short int m_quantizedAabbMin[3];\n"
|
||||
" unsigned short int m_quantizedAabbMax[3];\n"
|
||||
" //4 bytes, points to the root of the subtree\n"
|
||||
" int m_rootNodeIndex;\n"
|
||||
" //4 bytes\n"
|
||||
" int m_subtreeSize;\n"
|
||||
" int m_padding[3];\n"
|
||||
"} btBvhSubtreeInfo;\n"
|
||||
"///keep this in sync with btCollidable.h\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" int m_numChildShapes;\n"
|
||||
" int blaat2;\n"
|
||||
" int m_shapeType;\n"
|
||||
" int m_shapeIndex;\n"
|
||||
" \n"
|
||||
"} btCollidableGpu;\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_childPosition;\n"
|
||||
" float4 m_childOrientation;\n"
|
||||
" int m_shapeIndex;\n"
|
||||
" int m_unused0;\n"
|
||||
" int m_unused1;\n"
|
||||
" int m_unused2;\n"
|
||||
"} btGpuChildShape;\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_pos;\n"
|
||||
" float4 m_quat;\n"
|
||||
" float4 m_linVel;\n"
|
||||
" float4 m_angVel;\n"
|
||||
" u32 m_collidableIdx;\n"
|
||||
" float m_invMass;\n"
|
||||
" float m_restituitionCoeff;\n"
|
||||
" float m_frictionCoeff;\n"
|
||||
"} BodyData;\n"
|
||||
"typedef struct \n"
|
||||
"{\n"
|
||||
" union\n"
|
||||
" {\n"
|
||||
" float4 m_min;\n"
|
||||
" float m_minElems[4];\n"
|
||||
" int m_minIndices[4];\n"
|
||||
" };\n"
|
||||
" union\n"
|
||||
" {\n"
|
||||
" float4 m_max;\n"
|
||||
" float m_maxElems[4];\n"
|
||||
" int m_maxIndices[4];\n"
|
||||
" };\n"
|
||||
"} btAabbCL;\n"
|
||||
"int testQuantizedAabbAgainstQuantizedAabb(\n"
|
||||
" const unsigned short int* aabbMin1,\n"
|
||||
" const unsigned short int* aabbMax1,\n"
|
||||
" const unsigned short int* aabbMin2,\n"
|
||||
" const unsigned short int* aabbMax2)\n"
|
||||
"{\n"
|
||||
" //int overlap = 1;\n"
|
||||
" if (aabbMin1[0] > aabbMax2[0])\n"
|
||||
" return 0;\n"
|
||||
" if (aabbMax1[0] < aabbMin2[0])\n"
|
||||
" return 0;\n"
|
||||
" if (aabbMin1[1] > aabbMax2[1])\n"
|
||||
" return 0;\n"
|
||||
" if (aabbMax1[1] < aabbMin2[1])\n"
|
||||
" return 0;\n"
|
||||
" if (aabbMin1[2] > aabbMax2[2])\n"
|
||||
" return 0;\n"
|
||||
" if (aabbMax1[2] < aabbMin2[2])\n"
|
||||
" return 0;\n"
|
||||
" return 1;\n"
|
||||
" //overlap = ((aabbMin1[0] > aabbMax2[0]) || (aabbMax1[0] < aabbMin2[0])) ? 0 : overlap;\n"
|
||||
" //overlap = ((aabbMin1[2] > aabbMax2[2]) || (aabbMax1[2] < aabbMin2[2])) ? 0 : overlap;\n"
|
||||
" //overlap = ((aabbMin1[1] > aabbMax2[1]) || (aabbMax1[1] < aabbMin2[1])) ? 0 : overlap;\n"
|
||||
" //return overlap;\n"
|
||||
"}\n"
|
||||
"void quantizeWithClamp(unsigned short* out, float4 point2,int isMax, float4 bvhAabbMin, float4 bvhAabbMax, float4 bvhQuantization)\n"
|
||||
"{\n"
|
||||
" float4 clampedPoint = max(point2,bvhAabbMin);\n"
|
||||
" clampedPoint = min (clampedPoint, bvhAabbMax);\n"
|
||||
" float4 v = (clampedPoint - bvhAabbMin) * bvhQuantization;\n"
|
||||
" if (isMax)\n"
|
||||
" {\n"
|
||||
" out[0] = (unsigned short) (((unsigned short)(v.x+1.f) | 1));\n"
|
||||
" out[1] = (unsigned short) (((unsigned short)(v.y+1.f) | 1));\n"
|
||||
" out[2] = (unsigned short) (((unsigned short)(v.z+1.f) | 1));\n"
|
||||
" } else\n"
|
||||
" {\n"
|
||||
" out[0] = (unsigned short) (((unsigned short)(v.x) & 0xfffe));\n"
|
||||
" out[1] = (unsigned short) (((unsigned short)(v.y) & 0xfffe));\n"
|
||||
" out[2] = (unsigned short) (((unsigned short)(v.z) & 0xfffe));\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"// work-in-progress\n"
|
||||
"__kernel void bvhTraversalKernel( __global const int4* pairs, \n"
|
||||
" __global const BodyData* rigidBodies, \n"
|
||||
" __global const btCollidableGpu* collidables,\n"
|
||||
" __global btAabbCL* aabbs,\n"
|
||||
" __global int4* concavePairsOut,\n"
|
||||
" __global volatile int* numConcavePairsOut,\n"
|
||||
" __global const btBvhSubtreeInfo* subtreeHeadersRoot,\n"
|
||||
" __global const btQuantizedBvhNode* quantizedNodesRoot,\n"
|
||||
" __global const b3BvhInfo* bvhInfos,\n"
|
||||
" int numPairs,\n"
|
||||
" int maxNumConcavePairsCapacity)\n"
|
||||
"{\n"
|
||||
" int id = get_global_id(0);\n"
|
||||
" if (id>=numPairs)\n"
|
||||
" return;\n"
|
||||
" \n"
|
||||
" int bodyIndexA = pairs[id].x;\n"
|
||||
" int bodyIndexB = pairs[id].y;\n"
|
||||
" int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
|
||||
" int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
|
||||
" \n"
|
||||
" //once the broadphase avoids static-static pairs, we can remove this test\n"
|
||||
" if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
|
||||
" {\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
" if (collidables[collidableIndexA].m_shapeType!=SHAPE_CONCAVE_TRIMESH)\n"
|
||||
" return;\n"
|
||||
" int shapeTypeB = collidables[collidableIndexB].m_shapeType;\n"
|
||||
" \n"
|
||||
" if (shapeTypeB!=SHAPE_CONVEX_HULL &&\n"
|
||||
" shapeTypeB!=SHAPE_SPHERE &&\n"
|
||||
" shapeTypeB!=SHAPE_COMPOUND_OF_CONVEX_HULLS\n"
|
||||
" )\n"
|
||||
" return;\n"
|
||||
" b3BvhInfo bvhInfo = bvhInfos[collidables[collidableIndexA].m_numChildShapes];\n"
|
||||
" float4 bvhAabbMin = bvhInfo.m_aabbMin;\n"
|
||||
" float4 bvhAabbMax = bvhInfo.m_aabbMax;\n"
|
||||
" float4 bvhQuantization = bvhInfo.m_quantization;\n"
|
||||
" int numSubtreeHeaders = bvhInfo.m_numSubTrees;\n"
|
||||
" __global const btBvhSubtreeInfo* subtreeHeaders = &subtreeHeadersRoot[bvhInfo.m_subTreeOffset];\n"
|
||||
" __global const btQuantizedBvhNode* quantizedNodes = &quantizedNodesRoot[bvhInfo.m_nodeOffset];\n"
|
||||
" \n"
|
||||
" unsigned short int quantizedQueryAabbMin[3];\n"
|
||||
" unsigned short int quantizedQueryAabbMax[3];\n"
|
||||
" quantizeWithClamp(quantizedQueryAabbMin,aabbs[bodyIndexB].m_min,false,bvhAabbMin, bvhAabbMax,bvhQuantization);\n"
|
||||
" quantizeWithClamp(quantizedQueryAabbMax,aabbs[bodyIndexB].m_max,true ,bvhAabbMin, bvhAabbMax,bvhQuantization);\n"
|
||||
" \n"
|
||||
" for (int i=0;i<numSubtreeHeaders;i++)\n"
|
||||
" {\n"
|
||||
" btBvhSubtreeInfo subtree = subtreeHeaders[i];\n"
|
||||
" \n"
|
||||
" int overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);\n"
|
||||
" if (overlap != 0)\n"
|
||||
" {\n"
|
||||
" int startNodeIndex = subtree.m_rootNodeIndex;\n"
|
||||
" int endNodeIndex = subtree.m_rootNodeIndex+subtree.m_subtreeSize;\n"
|
||||
" int curIndex = startNodeIndex;\n"
|
||||
" int escapeIndex;\n"
|
||||
" int isLeafNode;\n"
|
||||
" int aabbOverlap;\n"
|
||||
" while (curIndex < endNodeIndex)\n"
|
||||
" {\n"
|
||||
" btQuantizedBvhNode rootNode = quantizedNodes[curIndex];\n"
|
||||
" aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode.m_quantizedAabbMin,rootNode.m_quantizedAabbMax);\n"
|
||||
" isLeafNode = isLeaf(&rootNode);\n"
|
||||
" if (aabbOverlap)\n"
|
||||
" {\n"
|
||||
" if (isLeafNode)\n"
|
||||
" {\n"
|
||||
" int triangleIndex = getTriangleIndex(&rootNode);\n"
|
||||
" if (shapeTypeB==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
|
||||
" {\n"
|
||||
" int numChildrenB = collidables[collidableIndexB].m_numChildShapes;\n"
|
||||
" int pairIdx = atomic_add(numConcavePairsOut,numChildrenB);\n"
|
||||
" for (int b=0;b<numChildrenB;b++)\n"
|
||||
" {\n"
|
||||
" if ((pairIdx+b)<maxNumConcavePairsCapacity)\n"
|
||||
" {\n"
|
||||
" int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;\n"
|
||||
" int4 newPair = (int4)(bodyIndexA,bodyIndexB,triangleIndex,childShapeIndexB);\n"
|
||||
" concavePairsOut[pairIdx+b] = newPair;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" } else\n"
|
||||
" {\n"
|
||||
" int pairIdx = atomic_inc(numConcavePairsOut);\n"
|
||||
" if (pairIdx<maxNumConcavePairsCapacity)\n"
|
||||
" {\n"
|
||||
" int4 newPair = (int4)(bodyIndexA,bodyIndexB,triangleIndex,0);\n"
|
||||
" concavePairsOut[pairIdx] = newPair;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" } \n"
|
||||
" curIndex++;\n"
|
||||
" } else\n"
|
||||
" {\n"
|
||||
" if (isLeafNode)\n"
|
||||
" {\n"
|
||||
" curIndex++;\n"
|
||||
" } else\n"
|
||||
" {\n"
|
||||
" escapeIndex = getEscapeIndex(&rootNode);\n"
|
||||
" curIndex += escapeIndex;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user