remove most clutter (todo)

This commit is contained in:
Erwin Coumans
2013-12-06 15:29:13 -07:00
parent 9e9b172b23
commit f06312c632
1417 changed files with 0 additions and 661038 deletions

View File

@@ -1,176 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/*
Draft high-level generic physics C-API. For low-level access, use the physics SDK native API's.
Work in progress, functionality will be added on demand.
If possible, use the richer Bullet C++ API, by including "btBulletDynamicsCommon.h"
*/
#ifndef BULLET_C_API_H
#define BULLET_C_API_H
#define PL_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
#ifdef BT_USE_DOUBLE_PRECISION
typedef double plReal;
#else
typedef float plReal;
#endif
typedef plReal plVector3[3];
typedef plReal plQuaternion[4];
#ifdef __cplusplus
extern "C" {
#endif
/** Particular physics SDK (C-API) */
PL_DECLARE_HANDLE(plPhysicsSdkHandle);
/** Dynamics world, belonging to some physics SDK (C-API)*/
PL_DECLARE_HANDLE(plDynamicsWorldHandle);
/** Rigid Body that can be part of a Dynamics World (C-API)*/
PL_DECLARE_HANDLE(plRigidBodyHandle);
/** Collision Shape/Geometry, property of a Rigid Body (C-API)*/
PL_DECLARE_HANDLE(plCollisionShapeHandle);
/** Constraint for Rigid Bodies (C-API)*/
PL_DECLARE_HANDLE(plConstraintHandle);
/** Triangle Mesh interface (C-API)*/
PL_DECLARE_HANDLE(plMeshInterfaceHandle);
/** Broadphase Scene/Proxy Handles (C-API)*/
PL_DECLARE_HANDLE(plCollisionBroadphaseHandle);
PL_DECLARE_HANDLE(plBroadphaseProxyHandle);
PL_DECLARE_HANDLE(plCollisionWorldHandle);
/**
Create and Delete a Physics SDK
*/
extern plPhysicsSdkHandle plNewBulletSdk(void); //this could be also another sdk, like ODE, PhysX etc.
extern void plDeletePhysicsSdk(plPhysicsSdkHandle physicsSdk);
/** Collision World, not strictly necessary, you can also just create a Dynamics World with Rigid Bodies which internally manages the Collision World with Collision Objects */
typedef void(*btBroadphaseCallback)(void* clientData, void* object1,void* object2);
extern plCollisionBroadphaseHandle plCreateSapBroadphase(btBroadphaseCallback beginCallback,btBroadphaseCallback endCallback);
extern void plDestroyBroadphase(plCollisionBroadphaseHandle bp);
extern plBroadphaseProxyHandle plCreateProxy(plCollisionBroadphaseHandle bp, void* clientData, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ);
extern void plDestroyProxy(plCollisionBroadphaseHandle bp, plBroadphaseProxyHandle proxyHandle);
extern void plSetBoundingBox(plBroadphaseProxyHandle proxyHandle, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ);
/* todo: add pair cache support with queries like add/remove/find pair */
extern plCollisionWorldHandle plCreateCollisionWorld(plPhysicsSdkHandle physicsSdk);
/* todo: add/remove objects */
/* Dynamics World */
extern plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdk);
extern void plDeleteDynamicsWorld(plDynamicsWorldHandle world);
extern void plStepSimulation(plDynamicsWorldHandle, plReal timeStep);
extern void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object);
extern void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object);
/* Rigid Body */
extern plRigidBodyHandle plCreateRigidBody( void* user_data, float mass, plCollisionShapeHandle cshape );
extern void plDeleteRigidBody(plRigidBodyHandle body);
/* Collision Shape definition */
extern plCollisionShapeHandle plNewSphereShape(plReal radius);
extern plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z);
extern plCollisionShapeHandle plNewCapsuleShape(plReal radius, plReal height);
extern plCollisionShapeHandle plNewConeShape(plReal radius, plReal height);
extern plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height);
extern plCollisionShapeHandle plNewCompoundShape(void);
extern void plAddChildShape(plCollisionShapeHandle compoundShape,plCollisionShapeHandle childShape, plVector3 childPos,plQuaternion childOrn);
extern void plDeleteShape(plCollisionShapeHandle shape);
/* Convex Meshes */
extern plCollisionShapeHandle plNewConvexHullShape(void);
extern void plAddVertex(plCollisionShapeHandle convexHull, plReal x,plReal y,plReal z);
/* Concave static triangle meshes */
extern plMeshInterfaceHandle plNewMeshInterface(void);
extern void plAddTriangle(plMeshInterfaceHandle meshHandle, plVector3 v0,plVector3 v1,plVector3 v2);
extern plCollisionShapeHandle plNewStaticTriangleMeshShape(plMeshInterfaceHandle);
extern void plSetScaling(plCollisionShapeHandle shape, plVector3 scaling);
/* SOLID has Response Callback/Table/Management */
/* PhysX has Triggers, User Callbacks and filtering */
/* ODE has the typedef void dNearCallback (void *data, dGeomID o1, dGeomID o2); */
/* typedef void plUpdatedPositionCallback(void* userData, plRigidBodyHandle rbHandle, plVector3 pos); */
/* typedef void plUpdatedOrientationCallback(void* userData, plRigidBodyHandle rbHandle, plQuaternion orientation); */
/* get world transform */
extern void plGetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix);
extern void plGetPosition(plRigidBodyHandle object,plVector3 position);
extern void plGetOrientation(plRigidBodyHandle object,plQuaternion orientation);
/* set world transform (position/orientation) */
extern void plSetPosition(plRigidBodyHandle object, const plVector3 position);
extern void plSetOrientation(plRigidBodyHandle object, const plQuaternion orientation);
extern void plSetEuler(plReal yaw,plReal pitch,plReal roll, plQuaternion orient);
extern void plSetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix);
typedef struct plRayCastResult {
plRigidBodyHandle m_body;
plCollisionShapeHandle m_shape;
plVector3 m_positionWorld;
plVector3 m_normalWorld;
} plRayCastResult;
extern int plRayCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plRayCastResult res);
/* Sweep API */
/* extern plRigidBodyHandle plObjectCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); */
/* Continuous Collision Detection API */
// needed for source/blender/blenkernel/intern/collision.c
double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]);
#ifdef __cplusplus
}
#endif
#endif //BULLET_C_API_H

View File

@@ -1,286 +0,0 @@
INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src )
SET(BulletCollision_SRCS
BroadphaseCollision/btAxisSweep3.cpp
BroadphaseCollision/btBroadphaseProxy.cpp
BroadphaseCollision/btCollisionAlgorithm.cpp
BroadphaseCollision/btDbvt.cpp
BroadphaseCollision/btDbvtBroadphase.cpp
BroadphaseCollision/btDispatcher.cpp
BroadphaseCollision/btMultiSapBroadphase.cpp
BroadphaseCollision/btOverlappingPairCache.cpp
BroadphaseCollision/btQuantizedBvh.cpp
BroadphaseCollision/btSimpleBroadphase.cpp
CollisionDispatch/btActivatingCollisionAlgorithm.cpp
CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp
CollisionDispatch/btBoxBoxDetector.cpp
CollisionDispatch/btCollisionDispatcher.cpp
CollisionDispatch/btCollisionObject.cpp
CollisionDispatch/btCollisionWorld.cpp
CollisionDispatch/btCompoundCollisionAlgorithm.cpp
CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp
CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp
CollisionDispatch/btConvexConvexAlgorithm.cpp
CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp
CollisionDispatch/btDefaultCollisionConfiguration.cpp
CollisionDispatch/btEmptyCollisionAlgorithm.cpp
CollisionDispatch/btGhostObject.cpp
CollisionDispatch/btHashedSimplePairCache.cpp
CollisionDispatch/btInternalEdgeUtility.cpp
CollisionDispatch/btInternalEdgeUtility.h
CollisionDispatch/btManifoldResult.cpp
CollisionDispatch/btSimulationIslandManager.cpp
CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp
CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp
CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp
CollisionDispatch/btUnionFind.cpp
CollisionDispatch/SphereTriangleDetector.cpp
CollisionShapes/btBoxShape.cpp
CollisionShapes/btBox2dShape.cpp
CollisionShapes/btBvhTriangleMeshShape.cpp
CollisionShapes/btCapsuleShape.cpp
CollisionShapes/btCollisionShape.cpp
CollisionShapes/btCompoundShape.cpp
CollisionShapes/btConcaveShape.cpp
CollisionShapes/btConeShape.cpp
CollisionShapes/btConvexHullShape.cpp
CollisionShapes/btConvexInternalShape.cpp
CollisionShapes/btConvexPointCloudShape.cpp
CollisionShapes/btConvexPolyhedron.cpp
CollisionShapes/btConvexShape.cpp
CollisionShapes/btConvex2dShape.cpp
CollisionShapes/btConvexTriangleMeshShape.cpp
CollisionShapes/btCylinderShape.cpp
CollisionShapes/btEmptyShape.cpp
CollisionShapes/btHeightfieldTerrainShape.cpp
CollisionShapes/btMinkowskiSumShape.cpp
CollisionShapes/btMultimaterialTriangleMeshShape.cpp
CollisionShapes/btMultiSphereShape.cpp
CollisionShapes/btOptimizedBvh.cpp
CollisionShapes/btPolyhedralConvexShape.cpp
CollisionShapes/btScaledBvhTriangleMeshShape.cpp
CollisionShapes/btShapeHull.cpp
CollisionShapes/btSphereShape.cpp
CollisionShapes/btStaticPlaneShape.cpp
CollisionShapes/btStridingMeshInterface.cpp
CollisionShapes/btTetrahedronShape.cpp
CollisionShapes/btTriangleBuffer.cpp
CollisionShapes/btTriangleCallback.cpp
CollisionShapes/btTriangleIndexVertexArray.cpp
CollisionShapes/btTriangleIndexVertexMaterialArray.cpp
CollisionShapes/btTriangleMesh.cpp
CollisionShapes/btTriangleMeshShape.cpp
CollisionShapes/btUniformScalingShape.cpp
Gimpact/btContactProcessing.cpp
Gimpact/btGenericPoolAllocator.cpp
Gimpact/btGImpactBvh.cpp
Gimpact/btGImpactCollisionAlgorithm.cpp
Gimpact/btGImpactQuantizedBvh.cpp
Gimpact/btGImpactShape.cpp
Gimpact/btTriangleShapeEx.cpp
Gimpact/gim_box_set.cpp
Gimpact/gim_contact.cpp
Gimpact/gim_memory.cpp
Gimpact/gim_tri_collision.cpp
NarrowPhaseCollision/btContinuousConvexCollision.cpp
NarrowPhaseCollision/btConvexCast.cpp
NarrowPhaseCollision/btGjkConvexCast.cpp
NarrowPhaseCollision/btGjkEpa2.cpp
NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp
NarrowPhaseCollision/btGjkPairDetector.cpp
NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
NarrowPhaseCollision/btPersistentManifold.cpp
NarrowPhaseCollision/btRaycastCallback.cpp
NarrowPhaseCollision/btSubSimplexConvexCast.cpp
NarrowPhaseCollision/btVoronoiSimplexSolver.cpp
NarrowPhaseCollision/btPolyhedralContactClipping.cpp
)
SET(Root_HDRS
../btBulletCollisionCommon.h
)
SET(BroadphaseCollision_HDRS
BroadphaseCollision/btAxisSweep3.h
BroadphaseCollision/btBroadphaseInterface.h
BroadphaseCollision/btBroadphaseProxy.h
BroadphaseCollision/btCollisionAlgorithm.h
BroadphaseCollision/btDbvt.h
BroadphaseCollision/btDbvtBroadphase.h
BroadphaseCollision/btDispatcher.h
BroadphaseCollision/btMultiSapBroadphase.h
BroadphaseCollision/btOverlappingPairCache.h
BroadphaseCollision/btOverlappingPairCallback.h
BroadphaseCollision/btQuantizedBvh.h
BroadphaseCollision/btSimpleBroadphase.h
)
SET(CollisionDispatch_HDRS
CollisionDispatch/btActivatingCollisionAlgorithm.h
CollisionDispatch/btBoxBoxCollisionAlgorithm.h
CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h
CollisionDispatch/btBoxBoxDetector.h
CollisionDispatch/btCollisionConfiguration.h
CollisionDispatch/btCollisionCreateFunc.h
CollisionDispatch/btCollisionDispatcher.h
CollisionDispatch/btCollisionObject.h
CollisionDispatch/btCollisionObjectWrapper.h
CollisionDispatch/btCollisionWorld.h
CollisionDispatch/btCompoundCollisionAlgorithm.h
CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h
CollisionDispatch/btConvexConcaveCollisionAlgorithm.h
CollisionDispatch/btConvexConvexAlgorithm.h
CollisionDispatch/btConvex2dConvex2dAlgorithm.h
CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
CollisionDispatch/btDefaultCollisionConfiguration.h
CollisionDispatch/btEmptyCollisionAlgorithm.h
CollisionDispatch/btGhostObject.h
CollisionDispatch/btHashedSimplePairCache.h
CollisionDispatch/btManifoldResult.h
CollisionDispatch/btSimulationIslandManager.h
CollisionDispatch/btSphereBoxCollisionAlgorithm.h
CollisionDispatch/btSphereSphereCollisionAlgorithm.h
CollisionDispatch/btSphereTriangleCollisionAlgorithm.h
CollisionDispatch/btUnionFind.h
CollisionDispatch/SphereTriangleDetector.h
)
SET(CollisionShapes_HDRS
CollisionShapes/btBoxShape.h
CollisionShapes/btBox2dShape.h
CollisionShapes/btBvhTriangleMeshShape.h
CollisionShapes/btCapsuleShape.h
CollisionShapes/btCollisionMargin.h
CollisionShapes/btCollisionShape.h
CollisionShapes/btCompoundShape.h
CollisionShapes/btConcaveShape.h
CollisionShapes/btConeShape.h
CollisionShapes/btConvexHullShape.h
CollisionShapes/btConvexInternalShape.h
CollisionShapes/btConvexPointCloudShape.h
CollisionShapes/btConvexPolyhedron.h
CollisionShapes/btConvexShape.h
CollisionShapes/btConvex2dShape.h
CollisionShapes/btConvexTriangleMeshShape.h
CollisionShapes/btCylinderShape.h
CollisionShapes/btEmptyShape.h
CollisionShapes/btHeightfieldTerrainShape.h
CollisionShapes/btMaterial.h
CollisionShapes/btMinkowskiSumShape.h
CollisionShapes/btMultimaterialTriangleMeshShape.h
CollisionShapes/btMultiSphereShape.h
CollisionShapes/btOptimizedBvh.h
CollisionShapes/btPolyhedralConvexShape.h
CollisionShapes/btScaledBvhTriangleMeshShape.h
CollisionShapes/btShapeHull.h
CollisionShapes/btSphereShape.h
CollisionShapes/btStaticPlaneShape.h
CollisionShapes/btStridingMeshInterface.h
CollisionShapes/btTetrahedronShape.h
CollisionShapes/btTriangleBuffer.h
CollisionShapes/btTriangleCallback.h
CollisionShapes/btTriangleIndexVertexArray.h
CollisionShapes/btTriangleIndexVertexMaterialArray.h
CollisionShapes/btTriangleInfoMap.h
CollisionShapes/btTriangleMesh.h
CollisionShapes/btTriangleMeshShape.h
CollisionShapes/btTriangleShape.h
CollisionShapes/btUniformScalingShape.h
)
SET(Gimpact_HDRS
Gimpact/btBoxCollision.h
Gimpact/btClipPolygon.h
Gimpact/btContactProcessing.h
Gimpact/btGenericPoolAllocator.h
Gimpact/btGeometryOperations.h
Gimpact/btGImpactBvh.h
Gimpact/btGImpactCollisionAlgorithm.h
Gimpact/btGImpactMassUtil.h
Gimpact/btGImpactQuantizedBvh.h
Gimpact/btGImpactShape.h
Gimpact/btQuantization.h
Gimpact/btTriangleShapeEx.h
Gimpact/gim_array.h
Gimpact/gim_basic_geometry_operations.h
Gimpact/gim_bitset.h
Gimpact/gim_box_collision.h
Gimpact/gim_box_set.h
Gimpact/gim_clip_polygon.h
Gimpact/gim_contact.h
Gimpact/gim_geom_types.h
Gimpact/gim_geometry.h
Gimpact/gim_hash_table.h
Gimpact/gim_linear_math.h
Gimpact/gim_math.h
Gimpact/gim_memory.h
Gimpact/gim_radixsort.h
Gimpact/gim_tri_collision.h
)
SET(NarrowPhaseCollision_HDRS
NarrowPhaseCollision/btContinuousConvexCollision.h
NarrowPhaseCollision/btConvexCast.h
NarrowPhaseCollision/btConvexPenetrationDepthSolver.h
NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h
NarrowPhaseCollision/btGjkConvexCast.h
NarrowPhaseCollision/btGjkEpa2.h
NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h
NarrowPhaseCollision/btGjkPairDetector.h
NarrowPhaseCollision/btManifoldPoint.h
NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h
NarrowPhaseCollision/btPersistentManifold.h
NarrowPhaseCollision/btPointCollector.h
NarrowPhaseCollision/btRaycastCallback.h
NarrowPhaseCollision/btSimplexSolverInterface.h
NarrowPhaseCollision/btSubSimplexConvexCast.h
NarrowPhaseCollision/btVoronoiSimplexSolver.h
NarrowPhaseCollision/btPolyhedralContactClipping.h
)
SET(BulletCollision_HDRS
${Root_HDRS}
${BroadphaseCollision_HDRS}
${CollisionDispatch_HDRS}
${CollisionShapes_HDRS}
${Gimpact_HDRS}
${NarrowPhaseCollision_HDRS}
)
ADD_LIBRARY(BulletCollision ${BulletCollision_SRCS} ${BulletCollision_HDRS})
SET_TARGET_PROPERTIES(BulletCollision PROPERTIES VERSION ${BULLET_VERSION})
SET_TARGET_PROPERTIES(BulletCollision PROPERTIES SOVERSION ${BULLET_VERSION})
IF (BUILD_SHARED_LIBS)
TARGET_LINK_LIBRARIES(BulletCollision LinearMath)
ENDIF (BUILD_SHARED_LIBS)
IF (INSTALL_LIBS)
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
#INSTALL of other files requires CMake 2.6
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS BulletCollision DESTINATION .)
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS BulletCollision RUNTIME DESTINATION bin
LIBRARY DESTINATION lib${LIB_SUFFIX}
ARCHIVE DESTINATION lib${LIB_SUFFIX})
INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN ".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
INSTALL(FILES ../btBulletCollisionCommon.h
DESTINATION ${INCLUDE_INSTALL_DIR}/BulletCollision)
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
SET_TARGET_PROPERTIES(BulletCollision PROPERTIES FRAMEWORK true)
SET_TARGET_PROPERTIES(BulletCollision PROPERTIES PUBLIC_HEADER "${Root_HDRS}")
# Have to list out sub-directories manually:
SET_PROPERTY(SOURCE ${BroadphaseCollision_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/BroadphaseCollision)
SET_PROPERTY(SOURCE ${CollisionDispatch_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/CollisionDispatch)
SET_PROPERTY(SOURCE ${CollisionShapes_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/CollisionShapes)
SET_PROPERTY(SOURCE ${Gimpact_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Gimpact)
SET_PROPERTY(SOURCE ${NarrowPhaseCollision_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/NarrowPhaseCollision)
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
ENDIF (INSTALL_LIBS)

View File

@@ -1,746 +0,0 @@
# Doxyfile 1.2.4
# This file describes the settings to be used by doxygen for a project
#
# All text after a hash (#) is considered a comment and will be ignored
# The format is:
# TAG = value [value, ...]
# For lists items can also be appended using:
# TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (" ")
#---------------------------------------------------------------------------
# General configuration options
#---------------------------------------------------------------------------
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
PROJECT_NAME = "Bullet Continuous Collision Detection Library"
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER =
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY =
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
# The default language is English, other supported languages are:
# Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese,
# Korean, Hungarian, Norwegian, Spanish, Romanian, Russian, Croatian,
# Polish, Portuguese and Slovene.
OUTPUT_LANGUAGE = English
# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
# documentation are documented, even if no documentation was available.
# Private class members and static file members will be hidden unless
# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
EXTRACT_ALL = YES
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
# will be included in the documentation.
EXTRACT_PRIVATE = YES
# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.
EXTRACT_STATIC = YES
# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
# undocumented members of documented classes, files or namespaces.
# If set to NO (the default) these members will be included in the
# various overviews, but no documentation section is generated.
# This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy.
# If set to NO (the default) these class will be included in the various
# overviews. This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_CLASSES = NO
# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
# include brief member descriptions after the members that are listed in
# the file and class documentation (similar to JavaDoc).
# Set to NO to disable this.
BRIEF_MEMBER_DESC = YES
# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
# the brief description of a member or function before the detailed description.
# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
REPEAT_BRIEF = YES
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# Doxygen will generate a detailed section even if there is only a brief
# description.
ALWAYS_DETAILED_SEC = NO
# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
# path before files name in the file list and in the header files. If set
# to NO the shortest path that makes the file name unique will be used.
FULL_PATH_NAMES = NO
# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
# can be used to strip a user defined part of the path. Stripping is
# only done if one of the specified strings matches the left-hand part of
# the path. It is allowed to use relative paths in the argument list.
STRIP_FROM_PATH =
# The INTERNAL_DOCS tag determines if documentation
# that is typed after a \internal command is included. If the tag is set
# to NO (the default) then the documentation will be excluded.
# Set it to YES to include the internal documentation.
INTERNAL_DOCS = NO
# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
# generate a class diagram (in Html and LaTeX) for classes with base or
# super classes. Setting the tag to NO turns the diagrams off.
CLASS_DIAGRAMS = YES
# If the SOURCE_BROWSER tag is set to YES then a list of source files will
# be generated. Documented entities will be cross-referenced with these sources.
SOURCE_BROWSER = YES
# Setting the INLINE_SOURCES tag to YES will include the body
# of functions and classes directly in the documentation.
INLINE_SOURCES = NO
# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
# doxygen to hide any special comment blocks from generated source code
# fragments. Normal C and C++ comments will always remain visible.
STRIP_CODE_COMMENTS = YES
# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
# file names in lower case letters. If set to YES upper case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# users are adviced to set this option to NO.
CASE_SENSE_NAMES = YES
# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
# will show members with their full class and namespace scopes in the
# documentation. If set to YES the scope will be hidden.
HIDE_SCOPE_NAMES = NO
# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
# will generate a verbatim copy of the header file for each class for
# which an include is specified. Set to NO to disable this.
VERBATIM_HEADERS = YES
# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
# will put list of the files that are included by a file in the documentation
# of that file.
SHOW_INCLUDE_FILES = YES
# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
# will interpret the first line (until the first dot) of a JavaDoc-style
# comment as the brief description. If set to NO, the JavaDoc
# comments will behave just like the Qt-style comments (thus requiring an
# explict @brief command for a brief description.
JAVADOC_AUTOBRIEF = YES
# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
# member inherits the documentation from any documented member that it
# reimplements.
INHERIT_DOCS = YES
# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
# is inserted in the documentation for inline members.
INLINE_INFO = YES
# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
# will sort the (detailed) documentation of file and class members
# alphabetically by member name. If set to NO the members will appear in
# declaration order.
SORT_MEMBER_DOCS = YES
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
# tag is set to YES, then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
DISTRIBUTE_GROUP_DOC = NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab.
# Doxygen uses this value to replace tabs by spaces in code fragments.
TAB_SIZE = 8
# The ENABLE_SECTIONS tag can be used to enable conditional
# documentation sections, marked by \if sectionname ... \endif.
ENABLED_SECTIONS =
# The GENERATE_TODOLIST tag can be used to enable (YES) or
# disable (NO) the todo list. This list is created by putting \todo
# commands in the documentation.
GENERATE_TODOLIST = YES
# The GENERATE_TESTLIST tag can be used to enable (YES) or
# disable (NO) the test list. This list is created by putting \test
# commands in the documentation.
GENERATE_TESTLIST = YES
# This tag can be used to specify a number of aliases that acts
# as commands in the documentation. An alias has the form "name=value".
# For example adding "sideeffect=\par Side Effects:\n" will allow you to
# put the command \sideeffect (or @sideeffect) in the documentation, which
# will result in a user defined paragraph with heading "Side Effects:".
# You can put \n's in the value part of an alias to insert newlines.
ALIASES =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
# The QUIET tag can be used to turn on/off the messages that are generated
# by doxygen. Possible values are YES and NO. If left blank NO is used.
QUIET = NO
# The WARNINGS tag can be used to turn on/off the warning messages that are
# generated by doxygen. Possible values are YES and NO. If left blank
# NO is used.
WARNINGS = YES
# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
# automatically be disabled.
WARN_IF_UNDOCUMENTED = YES
# The WARN_FORMAT tag determines the format of the warning messages that
# doxygen can produce. The string should contain the $file, $line, and $text
# tags, which will be replaced by the file and line number from which the
# warning originated and the warning text.
WARN_FORMAT = "$file:$line: $text"
# The WARN_LOGFILE tag can be used to specify a file to which warning
# and error messages should be written. If left blank the output is written
# to stderr.
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
# The INPUT tag can be used to specify the files and/or directories that contain
# documented source files. You may enter file names like "myfile.cpp" or
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = .
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank all files are included.
FILE_PATTERNS = *.h *.cpp *.c
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
# should be searched for input files as well. Possible values are YES and NO.
# If left blank NO is used.
RECURSIVE = YES
# The EXCLUDE tag can be used to specify files and/or directories that should
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
EXCLUDE =
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
# certain files from those directories.
EXCLUDE_PATTERNS =
# The EXAMPLE_PATH tag can be used to specify one or more files or
# directories that contain example code fragments that are included (see
# the \include command).
EXAMPLE_PATH =
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank all files are included.
EXAMPLE_PATTERNS =
# The IMAGE_PATH tag can be used to specify one or more files or
# directories that contain image that are included in the documentation (see
# the \image command).
IMAGE_PATH =
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
# by executing (via popen()) the command <filter> <input-file>, where <filter>
# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
# input file. Doxygen will then use the output that the filter program writes
# to standard output.
INPUT_FILTER =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER) will be used to filter the input files when producing source
# files to browse.
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
# of all compounds will be generated. Enable this if the project
# contains a lot of classes, structs, unions or interfaces.
ALPHABETICAL_INDEX = NO
# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
# in which this list will be split (can be a number in the range [1..20])
COLS_IN_ALPHA_INDEX = 5
# In case all classes in a project start with a common prefix, all
# classes will be put under the same header in the alphabetical index.
# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
# should be ignored while generating the index headers.
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
# generate HTML output.
GENERATE_HTML = YES
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `html' will be used as the default path.
HTML_OUTPUT = html
# The HTML_HEADER tag can be used to specify a personal HTML header for
# each generated HTML page. If it is left blank doxygen will generate a
# standard header.
HTML_HEADER =
# The HTML_FOOTER tag can be used to specify a personal HTML footer for
# each generated HTML page. If it is left blank doxygen will generate a
# standard footer.
HTML_FOOTER =
# The HTML_STYLESHEET tag can be used to specify a user defined cascading
# style sheet that is used by each HTML page. It can be used to
# fine-tune the look of the HTML output. If the tag is left blank doxygen
# will generate a default style sheet
HTML_STYLESHEET =
# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
# files or namespaces will be aligned in HTML using tables. If set to
# NO a bullet list will be used.
HTML_ALIGN_MEMBERS = YES
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
# will be generated that can be used as input for tools like the
# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
# of the generated HTML documentation.
GENERATE_HTMLHELP = NO
# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
# top of each HTML page. The value NO (the default) enables the index and
# the value YES disables it.
DISABLE_INDEX = NO
# This tag can be used to set the number of enum values (range [1..20])
# that doxygen will group on one line in the generated HTML documentation.
ENUM_VALUES_PER_LINE = 4
# If the GENERATE_TREEVIEW tag is set to YES, a side pannel will be
# generated containing a tree-like index structure (just like the one that
# is generated for HTML Help). For this to work a browser that supports
# JavaScript and frames is required (for instance Netscape 4.0+
# or Internet explorer 4.0+).
GENERATE_TREEVIEW = NO
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
# used to set the initial width (in pixels) of the frame in which the tree
# is shown.
TREEVIEW_WIDTH = 250
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output.
GENERATE_LATEX = NO
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `latex' will be used as the default path.
LATEX_OUTPUT = latex
# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
# LaTeX documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_LATEX = NO
# The PAPER_TYPE tag can be used to set the paper type that is used
# by the printer. Possible values are: a4, a4wide, letter, legal and
# executive. If left blank a4wide will be used.
PAPER_TYPE = a4wide
# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
# packages that should be included in the LaTeX output.
EXTRA_PACKAGES =
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
# the generated latex document. The header should contain everything until
# the first chapter. If it is left blank doxygen will generate a
# standard header. Notice: only use this tag if you know what you are doing!
LATEX_HEADER =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
# is prepared for conversion to pdf (using ps2pdf). The pdf file will
# contain links (just like the HTML output) instead of page references
# This makes the output suitable for online browsing using a pdf viewer.
PDF_HYPERLINKS = NO
# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
# plain latex in the generated Makefile. Set this option to YES to get a
# higher quality PDF documentation.
USE_PDFLATEX = NO
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
# command to the generated LaTeX files. This will instruct LaTeX to keep
# running if errors occur, instead of asking the user for help.
# This option is also used when generating formulas in HTML.
LATEX_BATCHMODE = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
# The RTF output is optimised for Word 97 and may not look very pretty with
# other RTF readers or editors.
GENERATE_RTF = NO
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `rtf' will be used as the default path.
RTF_OUTPUT = rtf
# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
# RTF documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_RTF = NO
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
# will contain hyperlink fields. The RTF file will
# contain links (just like the HTML output) instead of page references.
# This makes the output suitable for online browsing using a WORD or other.
# programs which support those fields.
# Note: wordpad (write) and others do not support links.
RTF_HYPERLINKS = NO
# Load stylesheet definitions from file. Syntax is similar to doxygen's
# config file, i.e. a series of assigments. You only have to provide
# replacements, missing definitions are set to their default value.
RTF_STYLESHEET_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
# generate man pages
GENERATE_MAN = NO
# The MAN_OUTPUT tag is used to specify where the man pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `man' will be used as the default path.
MAN_OUTPUT = man
# The MAN_EXTENSION tag determines the extension that is added to
# the generated man pages (default is the subroutine's section .3)
MAN_EXTENSION = .3
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
# If the GENERATE_XML tag is set to YES Doxygen will
# generate an XML file that captures the structure of
# the code including all documentation. Warning: This feature
# is still experimental and very incomplete.
GENERATE_XML = NO
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
# evaluate all C-preprocessor directives found in the sources and include
# files.
ENABLE_PREPROCESSING = YES
# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
# names in the source code. If set to NO (the default) only conditional
# compilation will be performed. Macro expansion can be done in a controlled
# way by setting EXPAND_ONLY_PREDEF to YES.
MACRO_EXPANSION = NO
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
# then the macro expansion is limited to the macros specified with the
# PREDEFINED and EXPAND_AS_PREDEFINED tags.
EXPAND_ONLY_PREDEF = NO
# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
# in the INCLUDE_PATH (see below) will be search if a #include is found.
SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by
# the preprocessor.
INCLUDE_PATH = ../../generic/extern
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
# directories. If left blank, the patterns specified with FILE_PATTERNS will
# be used.
INCLUDE_FILE_PATTERNS =
# The PREDEFINED tag can be used to specify one or more macro names that
# are defined before the preprocessor is started (similar to the -D option of
# gcc). The argument of the tag is a list of macros of the form: name
# or name=definition (no spaces). If the definition and the = are
# omitted =1 is assumed.
PREDEFINED =
# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
# The macro definition that is found in the sources will be used.
# Use the PREDEFINED tag if you want to use a different macro definition.
EXPAND_AS_DEFINED =
#---------------------------------------------------------------------------
# Configuration::addtions related to external references
#---------------------------------------------------------------------------
# The TAGFILES tag can be used to specify one or more tagfiles.
TAGFILES =
# When a file name is specified after GENERATE_TAGFILE, doxygen will create
# a tag file that is based on the input files it reads.
GENERATE_TAGFILE =
# If the ALLEXTERNALS tag is set to YES all external classes will be listed
# in the class index. If set to NO only the inherited external classes
# will be listed.
ALLEXTERNALS = NO
# The PERL_PATH should be the absolute path and name of the perl script
# interpreter (i.e. the result of `which perl').
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz, a graph visualization
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
# have no effect if this option is set to NO (the default)
HAVE_DOT = YES
# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect inheritance relations. Setting this tag to YES will force the
# the CLASS_DIAGRAMS tag to NO.
CLASS_GRAPH = YES
# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect implementation dependencies (inheritance, containment, and
# class references variables) of the class with other documented classes.
COLLABORATION_GRAPH = YES
# If the ENABLE_PREPROCESSING, INCLUDE_GRAPH, and HAVE_DOT tags are set to
# YES then doxygen will generate a graph for each documented file showing
# the direct and indirect include dependencies of the file with other
# documented files.
INCLUDE_GRAPH = YES
# If the ENABLE_PREPROCESSING, INCLUDED_BY_GRAPH, and HAVE_DOT tags are set to
# YES then doxygen will generate a graph for each documented header file showing
# the documented files that directly or indirectly include this file
INCLUDED_BY_GRAPH = YES
# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
# will graphical hierarchy of all classes instead of a textual one.
GRAPHICAL_HIERARCHY = YES
# The tag DOT_PATH can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found on the path.
DOT_PATH =
# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
# (in pixels) of the graphs generated by dot. If a graph becomes larger than
# this value, doxygen will try to truncate the graph, so that it fits within
# the specified constraint. Beware that most browsers cannot cope with very
# large images.
MAX_DOT_GRAPH_WIDTH = 1024
# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
# (in pixels) of the graphs generated by dot. If a graph becomes larger than
# this value, doxygen will try to truncate the graph, so that it fits within
# the specified constraint. Beware that most browsers cannot cope with very
# large images.
MAX_DOT_GRAPH_HEIGHT = 1024
# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
# generate a legend page explaining the meaning of the various boxes and
# arrows in the dot generated graphs.
GENERATE_LEGEND = YES
#---------------------------------------------------------------------------
# Configuration::addtions related to the search engine
#---------------------------------------------------------------------------
# The SEARCHENGINE tag specifies whether or not a search engine should be
# used. If set to NO the values of all tags below this one will be ignored.
SEARCHENGINE = NO
# The CGI_NAME tag should be the name of the CGI script that
# starts the search engine (doxysearch) with the correct parameters.
# A script with this name will be generated by doxygen.
CGI_NAME = search.cgi
# The CGI_URL tag should be the absolute URL to the directory where the
# cgi binaries are located. See the documentation of your http daemon for
# details.
CGI_URL =
# The DOC_URL tag should be the absolute URL to the directory where the
# documentation is located. If left blank the absolute path to the
# documentation, with file:// prepended to it, will be used.
DOC_URL =
# The DOC_ABSPATH tag should be the absolute path to the directory where the
# documentation is located. If left blank the directory on the local machine
# will be used.
DOC_ABSPATH =
# The BIN_ABSPATH tag must point to the directory where the doxysearch binary
# is installed.
BIN_ABSPATH = c:\program files\doxygen\bin
# The EXT_DOC_PATHS tag can be used to specify one or more paths to
# documentation generated for other projects. This allows doxysearch to search
# the documentation for these projects as well.
EXT_DOC_PATHS =

View File

@@ -1,645 +0,0 @@
#ifndef BT_BOX_COLLISION_H_INCLUDED
#define BT_BOX_COLLISION_H_INCLUDED
/*! \file gim_box_collision.h
\author Francisco Leon Najera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "LinearMath/btTransform.h"
///Swap numbers
#define BT_SWAP_NUMBERS(a,b){ \
a = a+b; \
b = a-b; \
a = a-b; \
}\
#define BT_MAX(a,b) (a<b?b:a)
#define BT_MIN(a,b) (a>b?b:a)
#define BT_GREATER(x, y) btFabs(x) > (y)
#define BT_MAX3(a,b,c) BT_MAX(a,BT_MAX(b,c))
#define BT_MIN3(a,b,c) BT_MIN(a,BT_MIN(b,c))
enum eBT_PLANE_INTERSECTION_TYPE
{
BT_CONST_BACK_PLANE = 0,
BT_CONST_COLLIDE_PLANE,
BT_CONST_FRONT_PLANE
};
//SIMD_FORCE_INLINE bool test_cross_edge_box(
// const btVector3 & edge,
// const btVector3 & absolute_edge,
// const btVector3 & pointa,
// const btVector3 & pointb, const btVector3 & extend,
// int dir_index0,
// int dir_index1
// int component_index0,
// int component_index1)
//{
// // dir coords are -z and y
//
// const btScalar dir0 = -edge[dir_index0];
// const btScalar dir1 = edge[dir_index1];
// btScalar pmin = pointa[component_index0]*dir0 + pointa[component_index1]*dir1;
// btScalar pmax = pointb[component_index0]*dir0 + pointb[component_index1]*dir1;
// //find minmax
// if(pmin>pmax)
// {
// BT_SWAP_NUMBERS(pmin,pmax);
// }
// //find extends
// const btScalar rad = extend[component_index0] * absolute_edge[dir_index0] +
// extend[component_index1] * absolute_edge[dir_index1];
//
// if(pmin>rad || -rad>pmax) return false;
// return true;
//}
//
//SIMD_FORCE_INLINE bool test_cross_edge_box_X_axis(
// const btVector3 & edge,
// const btVector3 & absolute_edge,
// const btVector3 & pointa,
// const btVector3 & pointb, btVector3 & extend)
//{
//
// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,2,1,1,2);
//}
//
//
//SIMD_FORCE_INLINE bool test_cross_edge_box_Y_axis(
// const btVector3 & edge,
// const btVector3 & absolute_edge,
// const btVector3 & pointa,
// const btVector3 & pointb, btVector3 & extend)
//{
//
// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,0,2,2,0);
//}
//
//SIMD_FORCE_INLINE bool test_cross_edge_box_Z_axis(
// const btVector3 & edge,
// const btVector3 & absolute_edge,
// const btVector3 & pointa,
// const btVector3 & pointb, btVector3 & extend)
//{
//
// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,1,0,0,1);
//}
#define TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,i_dir_0,i_dir_1,i_comp_0,i_comp_1)\
{\
const btScalar dir0 = -edge[i_dir_0];\
const btScalar dir1 = edge[i_dir_1];\
btScalar pmin = pointa[i_comp_0]*dir0 + pointa[i_comp_1]*dir1;\
btScalar pmax = pointb[i_comp_0]*dir0 + pointb[i_comp_1]*dir1;\
if(pmin>pmax)\
{\
BT_SWAP_NUMBERS(pmin,pmax); \
}\
const btScalar abs_dir0 = absolute_edge[i_dir_0];\
const btScalar abs_dir1 = absolute_edge[i_dir_1];\
const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1;\
if(pmin>rad || -rad>pmax) return false;\
}\
#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
{\
TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,2,1,1,2);\
}\
#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
{\
TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,0,2,2,0);\
}\
#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
{\
TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,1,0,0,1);\
}\
//! Returns the dot product between a vec3f and the col of a matrix
SIMD_FORCE_INLINE btScalar bt_mat3_dot_col(
const btMatrix3x3 & mat, const btVector3 & vec3, int colindex)
{
return vec3[0]*mat[0][colindex] + vec3[1]*mat[1][colindex] + vec3[2]*mat[2][colindex];
}
//! Class for transforming a model1 to the space of model0
ATTRIBUTE_ALIGNED16 (class) BT_BOX_BOX_TRANSFORM_CACHE
{
public:
btVector3 m_T1to0;//!< Transforms translation of model1 to model 0
btMatrix3x3 m_R1to0;//!< Transforms Rotation of model1 to model 0, equal to R0' * R1
btMatrix3x3 m_AR;//!< Absolute value of m_R1to0
SIMD_FORCE_INLINE void calc_absolute_matrix()
{
// static const btVector3 vepsi(1e-6f,1e-6f,1e-6f);
// m_AR[0] = vepsi + m_R1to0[0].absolute();
// m_AR[1] = vepsi + m_R1to0[1].absolute();
// m_AR[2] = vepsi + m_R1to0[2].absolute();
int i,j;
for(i=0;i<3;i++)
{
for(j=0;j<3;j++ )
{
m_AR[i][j] = 1e-6f + btFabs(m_R1to0[i][j]);
}
}
}
BT_BOX_BOX_TRANSFORM_CACHE()
{
}
//! Calc the transformation relative 1 to 0. Inverts matrics by transposing
SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform & trans0,const btTransform & trans1)
{
btTransform temp_trans = trans0.inverse();
temp_trans = temp_trans * trans1;
m_T1to0 = temp_trans.getOrigin();
m_R1to0 = temp_trans.getBasis();
calc_absolute_matrix();
}
//! Calcs the full invertion of the matrices. Useful for scaling matrices
SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform & trans0,const btTransform & trans1)
{
m_R1to0 = trans0.getBasis().inverse();
m_T1to0 = m_R1to0 * (-trans0.getOrigin());
m_T1to0 += m_R1to0*trans1.getOrigin();
m_R1to0 *= trans1.getBasis();
calc_absolute_matrix();
}
SIMD_FORCE_INLINE btVector3 transform(const btVector3 & point) const
{
return point.dot3( m_R1to0[0], m_R1to0[1], m_R1to0[2] ) + m_T1to0;
}
};
#define BOX_PLANE_EPSILON 0.000001f
//! Axis aligned box
ATTRIBUTE_ALIGNED16 (class) btAABB
{
public:
btVector3 m_min;
btVector3 m_max;
btAABB()
{}
btAABB(const btVector3 & V1,
const btVector3 & V2,
const btVector3 & V3)
{
m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
}
btAABB(const btVector3 & V1,
const btVector3 & V2,
const btVector3 & V3,
btScalar margin)
{
m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
m_min[0] -= margin;
m_min[1] -= margin;
m_min[2] -= margin;
m_max[0] += margin;
m_max[1] += margin;
m_max[2] += margin;
}
btAABB(const btAABB &other):
m_min(other.m_min),m_max(other.m_max)
{
}
btAABB(const btAABB &other,btScalar margin ):
m_min(other.m_min),m_max(other.m_max)
{
m_min[0] -= margin;
m_min[1] -= margin;
m_min[2] -= margin;
m_max[0] += margin;
m_max[1] += margin;
m_max[2] += margin;
}
SIMD_FORCE_INLINE void invalidate()
{
m_min[0] = SIMD_INFINITY;
m_min[1] = SIMD_INFINITY;
m_min[2] = SIMD_INFINITY;
m_max[0] = -SIMD_INFINITY;
m_max[1] = -SIMD_INFINITY;
m_max[2] = -SIMD_INFINITY;
}
SIMD_FORCE_INLINE void increment_margin(btScalar margin)
{
m_min[0] -= margin;
m_min[1] -= margin;
m_min[2] -= margin;
m_max[0] += margin;
m_max[1] += margin;
m_max[2] += margin;
}
SIMD_FORCE_INLINE void copy_with_margin(const btAABB &other, btScalar margin)
{
m_min[0] = other.m_min[0] - margin;
m_min[1] = other.m_min[1] - margin;
m_min[2] = other.m_min[2] - margin;
m_max[0] = other.m_max[0] + margin;
m_max[1] = other.m_max[1] + margin;
m_max[2] = other.m_max[2] + margin;
}
template<typename CLASS_POINT>
SIMD_FORCE_INLINE void calc_from_triangle(
const CLASS_POINT & V1,
const CLASS_POINT & V2,
const CLASS_POINT & V3)
{
m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
}
template<typename CLASS_POINT>
SIMD_FORCE_INLINE void calc_from_triangle_margin(
const CLASS_POINT & V1,
const CLASS_POINT & V2,
const CLASS_POINT & V3, btScalar margin)
{
m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
m_min[0] -= margin;
m_min[1] -= margin;
m_min[2] -= margin;
m_max[0] += margin;
m_max[1] += margin;
m_max[2] += margin;
}
//! Apply a transform to an AABB
SIMD_FORCE_INLINE void appy_transform(const btTransform & trans)
{
btVector3 center = (m_max+m_min)*0.5f;
btVector3 extends = m_max - center;
// Compute new center
center = trans(center);
btVector3 textends = extends.dot3(trans.getBasis().getRow(0).absolute(),
trans.getBasis().getRow(1).absolute(),
trans.getBasis().getRow(2).absolute());
m_min = center - textends;
m_max = center + textends;
}
//! Apply a transform to an AABB
SIMD_FORCE_INLINE void appy_transform_trans_cache(const BT_BOX_BOX_TRANSFORM_CACHE & trans)
{
btVector3 center = (m_max+m_min)*0.5f;
btVector3 extends = m_max - center;
// Compute new center
center = trans.transform(center);
btVector3 textends = extends.dot3(trans.m_R1to0.getRow(0).absolute(),
trans.m_R1to0.getRow(1).absolute(),
trans.m_R1to0.getRow(2).absolute());
m_min = center - textends;
m_max = center + textends;
}
//! Merges a Box
SIMD_FORCE_INLINE void merge(const btAABB & box)
{
m_min[0] = BT_MIN(m_min[0],box.m_min[0]);
m_min[1] = BT_MIN(m_min[1],box.m_min[1]);
m_min[2] = BT_MIN(m_min[2],box.m_min[2]);
m_max[0] = BT_MAX(m_max[0],box.m_max[0]);
m_max[1] = BT_MAX(m_max[1],box.m_max[1]);
m_max[2] = BT_MAX(m_max[2],box.m_max[2]);
}
//! Merges a point
template<typename CLASS_POINT>
SIMD_FORCE_INLINE void merge_point(const CLASS_POINT & point)
{
m_min[0] = BT_MIN(m_min[0],point[0]);
m_min[1] = BT_MIN(m_min[1],point[1]);
m_min[2] = BT_MIN(m_min[2],point[2]);
m_max[0] = BT_MAX(m_max[0],point[0]);
m_max[1] = BT_MAX(m_max[1],point[1]);
m_max[2] = BT_MAX(m_max[2],point[2]);
}
//! Gets the extend and center
SIMD_FORCE_INLINE void get_center_extend(btVector3 & center,btVector3 & extend) const
{
center = (m_max+m_min)*0.5f;
extend = m_max - center;
}
//! Finds the intersecting box between this box and the other.
SIMD_FORCE_INLINE void find_intersection(const btAABB & other, btAABB & intersection) const
{
intersection.m_min[0] = BT_MAX(other.m_min[0],m_min[0]);
intersection.m_min[1] = BT_MAX(other.m_min[1],m_min[1]);
intersection.m_min[2] = BT_MAX(other.m_min[2],m_min[2]);
intersection.m_max[0] = BT_MIN(other.m_max[0],m_max[0]);
intersection.m_max[1] = BT_MIN(other.m_max[1],m_max[1]);
intersection.m_max[2] = BT_MIN(other.m_max[2],m_max[2]);
}
SIMD_FORCE_INLINE bool has_collision(const btAABB & other) const
{
if(m_min[0] > other.m_max[0] ||
m_max[0] < other.m_min[0] ||
m_min[1] > other.m_max[1] ||
m_max[1] < other.m_min[1] ||
m_min[2] > other.m_max[2] ||
m_max[2] < other.m_min[2])
{
return false;
}
return true;
}
/*! \brief Finds the Ray intersection parameter.
\param aabb Aligned box
\param vorigin A vec3f with the origin of the ray
\param vdir A vec3f with the direction of the ray
*/
SIMD_FORCE_INLINE bool collide_ray(const btVector3 & vorigin,const btVector3 & vdir) const
{
btVector3 extents,center;
this->get_center_extend(center,extents);;
btScalar Dx = vorigin[0] - center[0];
if(BT_GREATER(Dx, extents[0]) && Dx*vdir[0]>=0.0f) return false;
btScalar Dy = vorigin[1] - center[1];
if(BT_GREATER(Dy, extents[1]) && Dy*vdir[1]>=0.0f) return false;
btScalar Dz = vorigin[2] - center[2];
if(BT_GREATER(Dz, extents[2]) && Dz*vdir[2]>=0.0f) return false;
btScalar f = vdir[1] * Dz - vdir[2] * Dy;
if(btFabs(f) > extents[1]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[1])) return false;
f = vdir[2] * Dx - vdir[0] * Dz;
if(btFabs(f) > extents[0]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[0]))return false;
f = vdir[0] * Dy - vdir[1] * Dx;
if(btFabs(f) > extents[0]*btFabs(vdir[1]) + extents[1]*btFabs(vdir[0]))return false;
return true;
}
SIMD_FORCE_INLINE void projection_interval(const btVector3 & direction, btScalar &vmin, btScalar &vmax) const
{
btVector3 center = (m_max+m_min)*0.5f;
btVector3 extend = m_max-center;
btScalar _fOrigin = direction.dot(center);
btScalar _fMaximumExtent = extend.dot(direction.absolute());
vmin = _fOrigin - _fMaximumExtent;
vmax = _fOrigin + _fMaximumExtent;
}
SIMD_FORCE_INLINE eBT_PLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const
{
btScalar _fmin,_fmax;
this->projection_interval(plane,_fmin,_fmax);
if(plane[3] > _fmax + BOX_PLANE_EPSILON)
{
return BT_CONST_BACK_PLANE; // 0
}
if(plane[3]+BOX_PLANE_EPSILON >=_fmin)
{
return BT_CONST_COLLIDE_PLANE; //1
}
return BT_CONST_FRONT_PLANE;//2
}
SIMD_FORCE_INLINE bool overlapping_trans_conservative(const btAABB & box, btTransform & trans1_to_0) const
{
btAABB tbox = box;
tbox.appy_transform(trans1_to_0);
return has_collision(tbox);
}
SIMD_FORCE_INLINE bool overlapping_trans_conservative2(const btAABB & box,
const BT_BOX_BOX_TRANSFORM_CACHE & trans1_to_0) const
{
btAABB tbox = box;
tbox.appy_transform_trans_cache(trans1_to_0);
return has_collision(tbox);
}
//! transcache is the transformation cache from box to this AABB
SIMD_FORCE_INLINE bool overlapping_trans_cache(
const btAABB & box,const BT_BOX_BOX_TRANSFORM_CACHE & transcache, bool fulltest) const
{
//Taken from OPCODE
btVector3 ea,eb;//extends
btVector3 ca,cb;//extends
get_center_extend(ca,ea);
box.get_center_extend(cb,eb);
btVector3 T;
btScalar t,t2;
int i;
// Class I : A's basis vectors
for(i=0;i<3;i++)
{
T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i];
t = transcache.m_AR[i].dot(eb) + ea[i];
if(BT_GREATER(T[i], t)) return false;
}
// Class II : B's basis vectors
for(i=0;i<3;i++)
{
t = bt_mat3_dot_col(transcache.m_R1to0,T,i);
t2 = bt_mat3_dot_col(transcache.m_AR,ea,i) + eb[i];
if(BT_GREATER(t,t2)) return false;
}
// Class III : 9 cross products
if(fulltest)
{
int j,m,n,o,p,q,r;
for(i=0;i<3;i++)
{
m = (i+1)%3;
n = (i+2)%3;
o = i==0?1:0;
p = i==2?1:2;
for(j=0;j<3;j++)
{
q = j==2?1:2;
r = j==0?1:0;
t = T[n]*transcache.m_R1to0[m][j] - T[m]*transcache.m_R1to0[n][j];
t2 = ea[o]*transcache.m_AR[p][j] + ea[p]*transcache.m_AR[o][j] +
eb[r]*transcache.m_AR[i][q] + eb[q]*transcache.m_AR[i][r];
if(BT_GREATER(t,t2)) return false;
}
}
}
return true;
}
//! Simple test for planes.
SIMD_FORCE_INLINE bool collide_plane(
const btVector4 & plane) const
{
eBT_PLANE_INTERSECTION_TYPE classify = plane_classify(plane);
return (classify == BT_CONST_COLLIDE_PLANE);
}
//! test for a triangle, with edges
SIMD_FORCE_INLINE bool collide_triangle_exact(
const btVector3 & p1,
const btVector3 & p2,
const btVector3 & p3,
const btVector4 & triangle_plane) const
{
if(!collide_plane(triangle_plane)) return false;
btVector3 center,extends;
this->get_center_extend(center,extends);
const btVector3 v1(p1 - center);
const btVector3 v2(p2 - center);
const btVector3 v3(p3 - center);
//First axis
btVector3 diff(v2 - v1);
btVector3 abs_diff = diff.absolute();
//Test With X axis
TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v1,v3,extends);
//Test With Y axis
TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v1,v3,extends);
//Test With Z axis
TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v1,v3,extends);
diff = v3 - v2;
abs_diff = diff.absolute();
//Test With X axis
TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v2,v1,extends);
//Test With Y axis
TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v2,v1,extends);
//Test With Z axis
TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v2,v1,extends);
diff = v1 - v3;
abs_diff = diff.absolute();
//Test With X axis
TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v3,v2,extends);
//Test With Y axis
TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v3,v2,extends);
//Test With Z axis
TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v3,v2,extends);
return true;
}
};
//! Compairison of transformation objects
SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btTransform & t2)
{
if(!(t1.getOrigin() == t2.getOrigin()) ) return false;
if(!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0)) ) return false;
if(!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1)) ) return false;
if(!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2)) ) return false;
return true;
}
#endif // GIM_BOX_COLLISION_H_INCLUDED

View File

@@ -1,182 +0,0 @@
#ifndef BT_CLIP_POLYGON_H_INCLUDED
#define BT_CLIP_POLYGON_H_INCLUDED
/*! \file btClipPolygon.h
\author Francisco Leon Najera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "LinearMath/btTransform.h"
#include "LinearMath/btGeometryUtil.h"
SIMD_FORCE_INLINE btScalar bt_distance_point_plane(const btVector4 & plane,const btVector3 &point)
{
return point.dot(plane) - plane[3];
}
/*! Vector blending
Takes two vectors a, b, blends them together*/
SIMD_FORCE_INLINE void bt_vec_blend(btVector3 &vr, const btVector3 &va,const btVector3 &vb, btScalar blend_factor)
{
vr = (1-blend_factor)*va + blend_factor*vb;
}
//! This function calcs the distance from a 3D plane
SIMD_FORCE_INLINE void bt_plane_clip_polygon_collect(
const btVector3 & point0,
const btVector3 & point1,
btScalar dist0,
btScalar dist1,
btVector3 * clipped,
int & clipped_count)
{
bool _prevclassif = (dist0>SIMD_EPSILON);
bool _classif = (dist1>SIMD_EPSILON);
if(_classif!=_prevclassif)
{
btScalar blendfactor = -dist0/(dist1-dist0);
bt_vec_blend(clipped[clipped_count],point0,point1,blendfactor);
clipped_count++;
}
if(!_classif)
{
clipped[clipped_count] = point1;
clipped_count++;
}
}
//! Clips a polygon by a plane
/*!
*\return The count of the clipped counts
*/
SIMD_FORCE_INLINE int bt_plane_clip_polygon(
const btVector4 & plane,
const btVector3 * polygon_points,
int polygon_point_count,
btVector3 * clipped)
{
int clipped_count = 0;
//clip first point
btScalar firstdist = bt_distance_point_plane(plane,polygon_points[0]);;
if(!(firstdist>SIMD_EPSILON))
{
clipped[clipped_count] = polygon_points[0];
clipped_count++;
}
btScalar olddist = firstdist;
for(int i=1;i<polygon_point_count;i++)
{
btScalar dist = bt_distance_point_plane(plane,polygon_points[i]);
bt_plane_clip_polygon_collect(
polygon_points[i-1],polygon_points[i],
olddist,
dist,
clipped,
clipped_count);
olddist = dist;
}
//RETURN TO FIRST point
bt_plane_clip_polygon_collect(
polygon_points[polygon_point_count-1],polygon_points[0],
olddist,
firstdist,
clipped,
clipped_count);
return clipped_count;
}
//! Clips a polygon by a plane
/*!
*\param clipped must be an array of 16 points.
*\return The count of the clipped counts
*/
SIMD_FORCE_INLINE int bt_plane_clip_triangle(
const btVector4 & plane,
const btVector3 & point0,
const btVector3 & point1,
const btVector3& point2,
btVector3 * clipped // an allocated array of 16 points at least
)
{
int clipped_count = 0;
//clip first point0
btScalar firstdist = bt_distance_point_plane(plane,point0);;
if(!(firstdist>SIMD_EPSILON))
{
clipped[clipped_count] = point0;
clipped_count++;
}
// point 1
btScalar olddist = firstdist;
btScalar dist = bt_distance_point_plane(plane,point1);
bt_plane_clip_polygon_collect(
point0,point1,
olddist,
dist,
clipped,
clipped_count);
olddist = dist;
// point 2
dist = bt_distance_point_plane(plane,point2);
bt_plane_clip_polygon_collect(
point1,point2,
olddist,
dist,
clipped,
clipped_count);
olddist = dist;
//RETURN TO FIRST point0
bt_plane_clip_polygon_collect(
point2,point0,
olddist,
firstdist,
clipped,
clipped_count);
return clipped_count;
}
#endif // GIM_TRI_COLLISION_H_INCLUDED

View File

@@ -1,93 +0,0 @@
#ifndef BT_COMPOUND_FROM_GIMPACT
#define BT_COMPOUND_FROM_GIMPACT
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
#include "btGImpactShape.h"
#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
struct MyCallback : public btTriangleRaycastCallback
{
int m_ignorePart;
int m_ignoreTriangleIndex;
MyCallback(const btVector3& from, const btVector3& to, int ignorePart, int ignoreTriangleIndex)
:btTriangleRaycastCallback(from,to),
m_ignorePart(ignorePart),
m_ignoreTriangleIndex(ignoreTriangleIndex)
{
}
virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex)
{
if (partId!=m_ignorePart || triangleIndex!=m_ignoreTriangleIndex)
{
if (hitFraction < m_hitFraction)
return hitFraction;
}
return m_hitFraction;
}
};
struct MyInternalTriangleIndexCallback :public btInternalTriangleIndexCallback
{
const btGImpactMeshShape* m_gimpactShape;
btCompoundShape* m_colShape;
btScalar m_depth;
MyInternalTriangleIndexCallback (btCompoundShape* colShape, const btGImpactMeshShape* meshShape, btScalar depth)
:m_colShape(colShape),
m_gimpactShape(meshShape),
m_depth(depth)
{
}
virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
{
btVector3 scale = m_gimpactShape->getLocalScaling();
btVector3 v0=triangle[0]*scale;
btVector3 v1=triangle[1]*scale;
btVector3 v2=triangle[2]*scale;
btVector3 centroid = (v0+v1+v2)/3;
btVector3 normal = (v1-v0).cross(v2-v0);
normal.normalize();
btVector3 rayFrom = centroid;
btVector3 rayTo = centroid-normal*m_depth;
MyCallback cb(rayFrom,rayTo,partId,triangleIndex);
m_gimpactShape->processAllTrianglesRay(&cb,rayFrom, rayTo);
if (cb.m_hitFraction<1)
{
rayTo.setInterpolate3(cb.m_from,cb.m_to,cb.m_hitFraction);
//rayTo = cb.m_from;
//rayTo = rayTo.lerp(cb.m_to,cb.m_hitFraction);
//gDebugDraw.drawLine(tr(centroid),tr(centroid+normal),btVector3(1,0,0));
}
btBU_Simplex1to4* tet = new btBU_Simplex1to4(v0,v1,v2,rayTo);
btTransform ident;
ident.setIdentity();
m_colShape->addChildShape(ident,tet);
}
};
btCompoundShape* btCreateCompoundFromGimpactShape(const btGImpactMeshShape* gimpactMesh, btScalar depth)
{
btCompoundShape* colShape = new btCompoundShape();
btTransform tr;
tr.setIdentity();
MyInternalTriangleIndexCallback cb(colShape,gimpactMesh, depth);
btVector3 aabbMin,aabbMax;
gimpactMesh->getAabb(tr,aabbMin,aabbMax);
gimpactMesh->getMeshInterface()->InternalProcessAllTriangles(&cb,aabbMin,aabbMax);
return colShape;
}
#endif //BT_COMPOUND_FROM_GIMPACT

View File

@@ -1,181 +0,0 @@
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "btContactProcessing.h"
#define MAX_COINCIDENT 8
struct CONTACT_KEY_TOKEN
{
unsigned int m_key;
int m_value;
CONTACT_KEY_TOKEN()
{
}
CONTACT_KEY_TOKEN(unsigned int key,int token)
{
m_key = key;
m_value = token;
}
CONTACT_KEY_TOKEN(const CONTACT_KEY_TOKEN& rtoken)
{
m_key = rtoken.m_key;
m_value = rtoken.m_value;
}
inline bool operator <(const CONTACT_KEY_TOKEN& other) const
{
return (m_key < other.m_key);
}
inline bool operator >(const CONTACT_KEY_TOKEN& other) const
{
return (m_key > other.m_key);
}
};
class CONTACT_KEY_TOKEN_COMP
{
public:
bool operator() ( const CONTACT_KEY_TOKEN& a, const CONTACT_KEY_TOKEN& b ) const
{
return ( a < b );
}
};
void btContactArray::merge_contacts(
const btContactArray & contacts, bool normal_contact_average)
{
clear();
int i;
if(contacts.size()==0) return;
if(contacts.size()==1)
{
push_back(contacts[0]);
return;
}
btAlignedObjectArray<CONTACT_KEY_TOKEN> keycontacts;
keycontacts.reserve(contacts.size());
//fill key contacts
for ( i = 0;i<contacts.size() ;i++ )
{
keycontacts.push_back(CONTACT_KEY_TOKEN(contacts[i].calc_key_contact(),i));
}
//sort keys
keycontacts.quickSort(CONTACT_KEY_TOKEN_COMP());
// Merge contacts
int coincident_count=0;
btVector3 coincident_normals[MAX_COINCIDENT];
unsigned int last_key = keycontacts[0].m_key;
unsigned int key = 0;
push_back(contacts[keycontacts[0].m_value]);
GIM_CONTACT * pcontact = &(*this)[0];
for( i=1;i<keycontacts.size();i++)
{
key = keycontacts[i].m_key;
const GIM_CONTACT * scontact = &contacts[keycontacts[i].m_value];
if(last_key == key)//same points
{
//merge contact
if(pcontact->m_depth - CONTACT_DIFF_EPSILON > scontact->m_depth)//)
{
*pcontact = *scontact;
coincident_count = 0;
}
else if(normal_contact_average)
{
if(btFabs(pcontact->m_depth - scontact->m_depth)<CONTACT_DIFF_EPSILON)
{
if(coincident_count<MAX_COINCIDENT)
{
coincident_normals[coincident_count] = scontact->m_normal;
coincident_count++;
}
}
}
}
else
{//add new contact
if(normal_contact_average && coincident_count>0)
{
pcontact->interpolate_normals(coincident_normals,coincident_count);
coincident_count = 0;
}
push_back(*scontact);
pcontact = &(*this)[this->size()-1];
}
last_key = key;
}
}
void btContactArray::merge_contacts_unique(const btContactArray & contacts)
{
clear();
if(contacts.size()==0) return;
if(contacts.size()==1)
{
push_back(contacts[0]);
return;
}
GIM_CONTACT average_contact = contacts[0];
for (int i=1;i<contacts.size() ;i++ )
{
average_contact.m_point += contacts[i].m_point;
average_contact.m_normal += contacts[i].m_normal * contacts[i].m_depth;
}
//divide
btScalar divide_average = 1.0f/((btScalar)contacts.size());
average_contact.m_point *= divide_average;
average_contact.m_normal *= divide_average;
average_contact.m_depth = average_contact.m_normal.length();
average_contact.m_normal /= average_contact.m_depth;
}

View File

@@ -1,145 +0,0 @@
#ifndef BT_CONTACT_H_INCLUDED
#define BT_CONTACT_H_INCLUDED
/*! \file gim_contact.h
\author Francisco Leon Najera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "LinearMath/btTransform.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "btTriangleShapeEx.h"
/**
Configuration var for applying interpolation of contact normals
*/
#define NORMAL_CONTACT_AVERAGE 1
#define CONTACT_DIFF_EPSILON 0.00001f
///The GIM_CONTACT is an internal GIMPACT structure, similar to btManifoldPoint.
///@todo: remove and replace GIM_CONTACT by btManifoldPoint.
class GIM_CONTACT
{
public:
btVector3 m_point;
btVector3 m_normal;
btScalar m_depth;//Positive value indicates interpenetration
btScalar m_distance;//Padding not for use
int m_feature1;//Face number
int m_feature2;//Face number
public:
GIM_CONTACT()
{
}
GIM_CONTACT(const GIM_CONTACT & contact):
m_point(contact.m_point),
m_normal(contact.m_normal),
m_depth(contact.m_depth),
m_feature1(contact.m_feature1),
m_feature2(contact.m_feature2)
{
}
GIM_CONTACT(const btVector3 &point,const btVector3 & normal,
btScalar depth, int feature1, int feature2):
m_point(point),
m_normal(normal),
m_depth(depth),
m_feature1(feature1),
m_feature2(feature2)
{
}
//! Calcs key for coord classification
SIMD_FORCE_INLINE unsigned int calc_key_contact() const
{
int _coords[] = {
(int)(m_point[0]*1000.0f+1.0f),
(int)(m_point[1]*1333.0f),
(int)(m_point[2]*2133.0f+3.0f)};
unsigned int _hash=0;
unsigned int *_uitmp = (unsigned int *)(&_coords[0]);
_hash = *_uitmp;
_uitmp++;
_hash += (*_uitmp)<<4;
_uitmp++;
_hash += (*_uitmp)<<8;
return _hash;
}
SIMD_FORCE_INLINE void interpolate_normals( btVector3 * normals,int normal_count)
{
btVector3 vec_sum(m_normal);
for(int i=0;i<normal_count;i++)
{
vec_sum += normals[i];
}
btScalar vec_sum_len = vec_sum.length2();
if(vec_sum_len <CONTACT_DIFF_EPSILON) return;
//GIM_INV_SQRT(vec_sum_len,vec_sum_len); // 1/sqrt(vec_sum_len)
m_normal = vec_sum/btSqrt(vec_sum_len);
}
};
class btContactArray:public btAlignedObjectArray<GIM_CONTACT>
{
public:
btContactArray()
{
reserve(64);
}
SIMD_FORCE_INLINE void push_contact(
const btVector3 &point,const btVector3 & normal,
btScalar depth, int feature1, int feature2)
{
push_back( GIM_CONTACT(point,normal,depth,feature1,feature2) );
}
SIMD_FORCE_INLINE void push_triangle_contacts(
const GIM_TRIANGLE_CONTACT & tricontact,
int feature1,int feature2)
{
for(int i = 0;i<tricontact.m_point_count ;i++ )
{
push_contact(
tricontact.m_points[i],
tricontact.m_separating_normal,
tricontact.m_penetration_depth,feature1,feature2);
}
}
void merge_contacts(const btContactArray & contacts, bool normal_contact_average = true);
void merge_contacts_unique(const btContactArray & contacts);
};
#endif // GIM_CONTACT_H_INCLUDED

View File

@@ -1,498 +0,0 @@
/*! \file gim_box_set.h
\author Francisco Leon Najera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "btGImpactBvh.h"
#include "LinearMath/btQuickprof.h"
#ifdef TRI_COLLISION_PROFILING
btClock g_tree_clock;
float g_accum_tree_collision_time = 0;
int g_count_traversing = 0;
void bt_begin_gim02_tree_time()
{
g_tree_clock.reset();
}
void bt_end_gim02_tree_time()
{
g_accum_tree_collision_time += g_tree_clock.getTimeMicroseconds();
g_count_traversing++;
}
//! Gets the average time in miliseconds of tree collisions
float btGImpactBvh::getAverageTreeCollisionTime()
{
if(g_count_traversing == 0) return 0;
float avgtime = g_accum_tree_collision_time;
avgtime /= (float)g_count_traversing;
g_accum_tree_collision_time = 0;
g_count_traversing = 0;
return avgtime;
// float avgtime = g_count_traversing;
// g_count_traversing = 0;
// return avgtime;
}
#endif //TRI_COLLISION_PROFILING
/////////////////////// btBvhTree /////////////////////////////////
int btBvhTree::_calc_splitting_axis(
GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex)
{
int i;
btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.));
int numIndices = endIndex-startIndex;
for (i=startIndex;i<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
primitive_boxes[i].m_bound.m_min);
means+=center;
}
means *= (btScalar(1.)/(btScalar)numIndices);
for (i=startIndex;i<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
primitive_boxes[i].m_bound.m_min);
btVector3 diff2 = center-means;
diff2 = diff2 * diff2;
variance += diff2;
}
variance *= (btScalar(1.)/ ((btScalar)numIndices-1) );
return variance.maxAxis();
}
int btBvhTree::_sort_and_calc_splitting_index(
GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex,
int endIndex, int splitAxis)
{
int i;
int splitIndex =startIndex;
int numIndices = endIndex - startIndex;
// average of centers
btScalar splitValue = 0.0f;
btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
for (i=startIndex;i<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
primitive_boxes[i].m_bound.m_min);
means+=center;
}
means *= (btScalar(1.)/(btScalar)numIndices);
splitValue = means[splitAxis];
//sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
for (i=startIndex;i<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
primitive_boxes[i].m_bound.m_min);
if (center[splitAxis] > splitValue)
{
//swap
primitive_boxes.swap(i,splitIndex);
//swapLeafNodes(i,splitIndex);
splitIndex++;
}
}
//if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
//otherwise the tree-building might fail due to stack-overflows in certain cases.
//unbalanced1 is unsafe: it can cause stack overflows
//bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
//unbalanced2 should work too: always use center (perfect balanced trees)
//bool unbalanced2 = true;
//this should be safe too:
int rangeBalancedIndices = numIndices/3;
bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
if (unbalanced)
{
splitIndex = startIndex+ (numIndices>>1);
}
btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex))));
return splitIndex;
}
void btBvhTree::_build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex)
{
int curIndex = m_num_nodes;
m_num_nodes++;
btAssert((endIndex-startIndex)>0);
if ((endIndex-startIndex)==1)
{
//We have a leaf node
setNodeBound(curIndex,primitive_boxes[startIndex].m_bound);
m_node_array[curIndex].setDataIndex(primitive_boxes[startIndex].m_data);
return;
}
//calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
//split axis
int splitIndex = _calc_splitting_axis(primitive_boxes,startIndex,endIndex);
splitIndex = _sort_and_calc_splitting_index(
primitive_boxes,startIndex,endIndex,
splitIndex//split axis
);
//calc this node bounding box
btAABB node_bound;
node_bound.invalidate();
for (int i=startIndex;i<endIndex;i++)
{
node_bound.merge(primitive_boxes[i].m_bound);
}
setNodeBound(curIndex,node_bound);
//build left branch
_build_sub_tree(primitive_boxes, startIndex, splitIndex );
//build right branch
_build_sub_tree(primitive_boxes, splitIndex ,endIndex);
m_node_array[curIndex].setEscapeIndex(m_num_nodes - curIndex);
}
//! stackless build tree
void btBvhTree::build_tree(
GIM_BVH_DATA_ARRAY & primitive_boxes)
{
// initialize node count to 0
m_num_nodes = 0;
// allocate nodes
m_node_array.resize(primitive_boxes.size()*2);
_build_sub_tree(primitive_boxes, 0, primitive_boxes.size());
}
////////////////////////////////////class btGImpactBvh
void btGImpactBvh::refit()
{
int nodecount = getNodeCount();
while(nodecount--)
{
if(isLeafNode(nodecount))
{
btAABB leafbox;
m_primitive_manager->get_primitive_box(getNodeData(nodecount),leafbox);
setNodeBound(nodecount,leafbox);
}
else
{
//const GIM_BVH_TREE_NODE * nodepointer = get_node_pointer(nodecount);
//get left bound
btAABB bound;
bound.invalidate();
btAABB temp_box;
int child_node = getLeftNode(nodecount);
if(child_node)
{
getNodeBound(child_node,temp_box);
bound.merge(temp_box);
}
child_node = getRightNode(nodecount);
if(child_node)
{
getNodeBound(child_node,temp_box);
bound.merge(temp_box);
}
setNodeBound(nodecount,bound);
}
}
}
//! this rebuild the entire set
void btGImpactBvh::buildSet()
{
//obtain primitive boxes
GIM_BVH_DATA_ARRAY primitive_boxes;
primitive_boxes.resize(m_primitive_manager->get_primitive_count());
for (int i = 0;i<primitive_boxes.size() ;i++ )
{
m_primitive_manager->get_primitive_box(i,primitive_boxes[i].m_bound);
primitive_boxes[i].m_data = i;
}
m_box_tree.build_tree(primitive_boxes);
}
//! returns the indices of the primitives in the m_primitive_manager
bool btGImpactBvh::boxQuery(const btAABB & box, btAlignedObjectArray<int> & collided_results) const
{
int curIndex = 0;
int numNodes = getNodeCount();
while (curIndex < numNodes)
{
btAABB bound;
getNodeBound(curIndex,bound);
//catch bugs in tree data
bool aabbOverlap = bound.has_collision(box);
bool isleafnode = isLeafNode(curIndex);
if (isleafnode && aabbOverlap)
{
collided_results.push_back(getNodeData(curIndex));
}
if (aabbOverlap || isleafnode)
{
//next subnode
curIndex++;
}
else
{
//skip node
curIndex+= getEscapeNodeIndex(curIndex);
}
}
if(collided_results.size()>0) return true;
return false;
}
//! returns the indices of the primitives in the m_primitive_manager
bool btGImpactBvh::rayQuery(
const btVector3 & ray_dir,const btVector3 & ray_origin ,
btAlignedObjectArray<int> & collided_results) const
{
int curIndex = 0;
int numNodes = getNodeCount();
while (curIndex < numNodes)
{
btAABB bound;
getNodeBound(curIndex,bound);
//catch bugs in tree data
bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir);
bool isleafnode = isLeafNode(curIndex);
if (isleafnode && aabbOverlap)
{
collided_results.push_back(getNodeData( curIndex));
}
if (aabbOverlap || isleafnode)
{
//next subnode
curIndex++;
}
else
{
//skip node
curIndex+= getEscapeNodeIndex(curIndex);
}
}
if(collided_results.size()>0) return true;
return false;
}
SIMD_FORCE_INLINE bool _node_collision(
btGImpactBvh * boxset0, btGImpactBvh * boxset1,
const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0,
int node0 ,int node1, bool complete_primitive_tests)
{
btAABB box0;
boxset0->getNodeBound(node0,box0);
btAABB box1;
boxset1->getNodeBound(node1,box1);
return box0.overlapping_trans_cache(box1,trans_cache_1to0,complete_primitive_tests );
// box1.appy_transform_trans_cache(trans_cache_1to0);
// return box0.has_collision(box1);
}
//stackless recursive collision routine
static void _find_collision_pairs_recursive(
btGImpactBvh * boxset0, btGImpactBvh * boxset1,
btPairSet * collision_pairs,
const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0,
int node0, int node1, bool complete_primitive_tests)
{
if( _node_collision(
boxset0,boxset1,trans_cache_1to0,
node0,node1,complete_primitive_tests) ==false) return;//avoid colliding internal nodes
if(boxset0->isLeafNode(node0))
{
if(boxset1->isLeafNode(node1))
{
// collision result
collision_pairs->push_pair(
boxset0->getNodeData(node0),boxset1->getNodeData(node1));
return;
}
else
{
//collide left recursive
_find_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
node0,boxset1->getLeftNode(node1),false);
//collide right recursive
_find_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
node0,boxset1->getRightNode(node1),false);
}
}
else
{
if(boxset1->isLeafNode(node1))
{
//collide left recursive
_find_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getLeftNode(node0),node1,false);
//collide right recursive
_find_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getRightNode(node0),node1,false);
}
else
{
//collide left0 left1
_find_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getLeftNode(node0),boxset1->getLeftNode(node1),false);
//collide left0 right1
_find_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getLeftNode(node0),boxset1->getRightNode(node1),false);
//collide right0 left1
_find_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getRightNode(node0),boxset1->getLeftNode(node1),false);
//collide right0 right1
_find_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getRightNode(node0),boxset1->getRightNode(node1),false);
}// else if node1 is not a leaf
}// else if node0 is not a leaf
}
void btGImpactBvh::find_collision(btGImpactBvh * boxset0, const btTransform & trans0,
btGImpactBvh * boxset1, const btTransform & trans1,
btPairSet & collision_pairs)
{
if(boxset0->getNodeCount()==0 || boxset1->getNodeCount()==0 ) return;
BT_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0;
trans_cache_1to0.calc_from_homogenic(trans0,trans1);
#ifdef TRI_COLLISION_PROFILING
bt_begin_gim02_tree_time();
#endif //TRI_COLLISION_PROFILING
_find_collision_pairs_recursive(
boxset0,boxset1,
&collision_pairs,trans_cache_1to0,0,0,true);
#ifdef TRI_COLLISION_PROFILING
bt_end_gim02_tree_time();
#endif //TRI_COLLISION_PROFILING
}

View File

@@ -1,396 +0,0 @@
#ifndef GIM_BOX_SET_H_INCLUDED
#define GIM_BOX_SET_H_INCLUDED
/*! \file gim_box_set.h
\author Francisco Leon Najera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "LinearMath/btAlignedObjectArray.h"
#include "btBoxCollision.h"
#include "btTriangleShapeEx.h"
//! Overlapping pair
struct GIM_PAIR
{
int m_index1;
int m_index2;
GIM_PAIR()
{}
GIM_PAIR(const GIM_PAIR & p)
{
m_index1 = p.m_index1;
m_index2 = p.m_index2;
}
GIM_PAIR(int index1, int index2)
{
m_index1 = index1;
m_index2 = index2;
}
};
//! A pairset array
class btPairSet: public btAlignedObjectArray<GIM_PAIR>
{
public:
btPairSet()
{
reserve(32);
}
inline void push_pair(int index1,int index2)
{
push_back(GIM_PAIR(index1,index2));
}
inline void push_pair_inv(int index1,int index2)
{
push_back(GIM_PAIR(index2,index1));
}
};
///GIM_BVH_DATA is an internal GIMPACT collision structure to contain axis aligned bounding box
struct GIM_BVH_DATA
{
btAABB m_bound;
int m_data;
};
//! Node Structure for trees
class GIM_BVH_TREE_NODE
{
public:
btAABB m_bound;
protected:
int m_escapeIndexOrDataIndex;
public:
GIM_BVH_TREE_NODE()
{
m_escapeIndexOrDataIndex = 0;
}
SIMD_FORCE_INLINE bool isLeafNode() const
{
//skipindex is negative (internal node), triangleindex >=0 (leafnode)
return (m_escapeIndexOrDataIndex>=0);
}
SIMD_FORCE_INLINE int getEscapeIndex() const
{
//btAssert(m_escapeIndexOrDataIndex < 0);
return -m_escapeIndexOrDataIndex;
}
SIMD_FORCE_INLINE void setEscapeIndex(int index)
{
m_escapeIndexOrDataIndex = -index;
}
SIMD_FORCE_INLINE int getDataIndex() const
{
//btAssert(m_escapeIndexOrDataIndex >= 0);
return m_escapeIndexOrDataIndex;
}
SIMD_FORCE_INLINE void setDataIndex(int index)
{
m_escapeIndexOrDataIndex = index;
}
};
class GIM_BVH_DATA_ARRAY:public btAlignedObjectArray<GIM_BVH_DATA>
{
};
class GIM_BVH_TREE_NODE_ARRAY:public btAlignedObjectArray<GIM_BVH_TREE_NODE>
{
};
//! Basic Box tree structure
class btBvhTree
{
protected:
int m_num_nodes;
GIM_BVH_TREE_NODE_ARRAY m_node_array;
protected:
int _sort_and_calc_splitting_index(
GIM_BVH_DATA_ARRAY & primitive_boxes,
int startIndex, int endIndex, int splitAxis);
int _calc_splitting_axis(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex);
void _build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex);
public:
btBvhTree()
{
m_num_nodes = 0;
}
//! prototype functions for box tree management
//!@{
void build_tree(GIM_BVH_DATA_ARRAY & primitive_boxes);
SIMD_FORCE_INLINE void clearNodes()
{
m_node_array.clear();
m_num_nodes = 0;
}
//! node count
SIMD_FORCE_INLINE int getNodeCount() const
{
return m_num_nodes;
}
//! tells if the node is a leaf
SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
{
return m_node_array[nodeindex].isLeafNode();
}
SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
{
return m_node_array[nodeindex].getDataIndex();
}
SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const
{
bound = m_node_array[nodeindex].m_bound;
}
SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound)
{
m_node_array[nodeindex].m_bound = bound;
}
SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
{
return nodeindex+1;
}
SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
{
if(m_node_array[nodeindex+1].isLeafNode()) return nodeindex+2;
return nodeindex+1 + m_node_array[nodeindex+1].getEscapeIndex();
}
SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
{
return m_node_array[nodeindex].getEscapeIndex();
}
SIMD_FORCE_INLINE const GIM_BVH_TREE_NODE * get_node_pointer(int index = 0) const
{
return &m_node_array[index];
}
//!@}
};
//! Prototype Base class for primitive classification
/*!
This class is a wrapper for primitive collections.
This tells relevant info for the Bounding Box set classes, which take care of space classification.
This class can manage Compound shapes and trimeshes, and if it is managing trimesh then the Hierarchy Bounding Box classes will take advantage of primitive Vs Box overlapping tests for getting optimal results and less Per Box compairisons.
*/
class btPrimitiveManagerBase
{
public:
virtual ~btPrimitiveManagerBase() {}
//! determines if this manager consist on only triangles, which special case will be optimized
virtual bool is_trimesh() const = 0;
virtual int get_primitive_count() const = 0;
virtual void get_primitive_box(int prim_index ,btAABB & primbox) const = 0;
//! retrieves only the points of the triangle, and the collision margin
virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const= 0;
};
//! Structure for containing Boxes
/*!
This class offers an structure for managing a box tree of primitives.
Requires a Primitive prototype (like btPrimitiveManagerBase )
*/
class btGImpactBvh
{
protected:
btBvhTree m_box_tree;
btPrimitiveManagerBase * m_primitive_manager;
protected:
//stackless refit
void refit();
public:
//! this constructor doesn't build the tree. you must call buildSet
btGImpactBvh()
{
m_primitive_manager = NULL;
}
//! this constructor doesn't build the tree. you must call buildSet
btGImpactBvh(btPrimitiveManagerBase * primitive_manager)
{
m_primitive_manager = primitive_manager;
}
SIMD_FORCE_INLINE btAABB getGlobalBox() const
{
btAABB totalbox;
getNodeBound(0, totalbox);
return totalbox;
}
SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase * primitive_manager)
{
m_primitive_manager = primitive_manager;
}
SIMD_FORCE_INLINE btPrimitiveManagerBase * getPrimitiveManager() const
{
return m_primitive_manager;
}
//! node manager prototype functions
///@{
//! this attemps to refit the box set.
SIMD_FORCE_INLINE void update()
{
refit();
}
//! this rebuild the entire set
void buildSet();
//! returns the indices of the primitives in the m_primitive_manager
bool boxQuery(const btAABB & box, btAlignedObjectArray<int> & collided_results) const;
//! returns the indices of the primitives in the m_primitive_manager
SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB & box,
const btTransform & transform, btAlignedObjectArray<int> & collided_results) const
{
btAABB transbox=box;
transbox.appy_transform(transform);
return boxQuery(transbox,collided_results);
}
//! returns the indices of the primitives in the m_primitive_manager
bool rayQuery(
const btVector3 & ray_dir,const btVector3 & ray_origin ,
btAlignedObjectArray<int> & collided_results) const;
//! tells if this set has hierarcht
SIMD_FORCE_INLINE bool hasHierarchy() const
{
return true;
}
//! tells if this set is a trimesh
SIMD_FORCE_INLINE bool isTrimesh() const
{
return m_primitive_manager->is_trimesh();
}
//! node count
SIMD_FORCE_INLINE int getNodeCount() const
{
return m_box_tree.getNodeCount();
}
//! tells if the node is a leaf
SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
{
return m_box_tree.isLeafNode(nodeindex);
}
SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
{
return m_box_tree.getNodeData(nodeindex);
}
SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const
{
m_box_tree.getNodeBound(nodeindex, bound);
}
SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound)
{
m_box_tree.setNodeBound(nodeindex, bound);
}
SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
{
return m_box_tree.getLeftNode(nodeindex);
}
SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
{
return m_box_tree.getRightNode(nodeindex);
}
SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
{
return m_box_tree.getEscapeNodeIndex(nodeindex);
}
SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex,btPrimitiveTriangle & triangle) const
{
m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex),triangle);
}
SIMD_FORCE_INLINE const GIM_BVH_TREE_NODE * get_node_pointer(int index = 0) const
{
return m_box_tree.get_node_pointer(index);
}
#ifdef TRI_COLLISION_PROFILING
static float getAverageTreeCollisionTime();
#endif //TRI_COLLISION_PROFILING
static void find_collision(btGImpactBvh * boxset1, const btTransform & trans1,
btGImpactBvh * boxset2, const btTransform & trans2,
btPairSet & collision_pairs);
};
#endif // GIM_BOXPRUNING_H_INCLUDED

View File

@@ -1,932 +0,0 @@
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/*
Author: Francisco Len N<>jera
Concave-Concave Collision
*/
#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
#include "LinearMath/btIDebugDraw.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btBoxShape.h"
#include "btGImpactCollisionAlgorithm.h"
#include "btContactProcessing.h"
#include "LinearMath/btQuickprof.h"
//! Class for accessing the plane equation
class btPlaneShape : public btStaticPlaneShape
{
public:
btPlaneShape(const btVector3& v, float f)
:btStaticPlaneShape(v,f)
{
}
void get_plane_equation(btVector4 &equation)
{
equation[0] = m_planeNormal[0];
equation[1] = m_planeNormal[1];
equation[2] = m_planeNormal[2];
equation[3] = m_planeConstant;
}
void get_plane_equation_transformed(const btTransform & trans,btVector4 &equation) const
{
equation[0] = trans.getBasis().getRow(0).dot(m_planeNormal);
equation[1] = trans.getBasis().getRow(1).dot(m_planeNormal);
equation[2] = trans.getBasis().getRow(2).dot(m_planeNormal);
equation[3] = trans.getOrigin().dot(m_planeNormal) + m_planeConstant;
}
};
//////////////////////////////////////////////////////////////////////////////////////////////
#ifdef TRI_COLLISION_PROFILING
btClock g_triangle_clock;
float g_accum_triangle_collision_time = 0;
int g_count_triangle_collision = 0;
void bt_begin_gim02_tri_time()
{
g_triangle_clock.reset();
}
void bt_end_gim02_tri_time()
{
g_accum_triangle_collision_time += g_triangle_clock.getTimeMicroseconds();
g_count_triangle_collision++;
}
#endif //TRI_COLLISION_PROFILING
//! Retrieving shapes shapes
/*!
Declared here due of insuficent space on Pool allocators
*/
//!@{
class GIM_ShapeRetriever
{
public:
const btGImpactShapeInterface * m_gim_shape;
btTriangleShapeEx m_trishape;
btTetrahedronShapeEx m_tetrashape;
public:
class ChildShapeRetriever
{
public:
GIM_ShapeRetriever * m_parent;
virtual const btCollisionShape * getChildShape(int index)
{
return m_parent->m_gim_shape->getChildShape(index);
}
virtual ~ChildShapeRetriever() {}
};
class TriangleShapeRetriever:public ChildShapeRetriever
{
public:
virtual btCollisionShape * getChildShape(int index)
{
m_parent->m_gim_shape->getBulletTriangle(index,m_parent->m_trishape);
return &m_parent->m_trishape;
}
virtual ~TriangleShapeRetriever() {}
};
class TetraShapeRetriever:public ChildShapeRetriever
{
public:
virtual btCollisionShape * getChildShape(int index)
{
m_parent->m_gim_shape->getBulletTetrahedron(index,m_parent->m_tetrashape);
return &m_parent->m_tetrashape;
}
};
public:
ChildShapeRetriever m_child_retriever;
TriangleShapeRetriever m_tri_retriever;
TetraShapeRetriever m_tetra_retriever;
ChildShapeRetriever * m_current_retriever;
GIM_ShapeRetriever(const btGImpactShapeInterface * gim_shape)
{
m_gim_shape = gim_shape;
//select retriever
if(m_gim_shape->needsRetrieveTriangles())
{
m_current_retriever = &m_tri_retriever;
}
else if(m_gim_shape->needsRetrieveTetrahedrons())
{
m_current_retriever = &m_tetra_retriever;
}
else
{
m_current_retriever = &m_child_retriever;
}
m_current_retriever->m_parent = this;
}
const btCollisionShape * getChildShape(int index)
{
return m_current_retriever->getChildShape(index);
}
};
//!@}
#ifdef TRI_COLLISION_PROFILING
//! Gets the average time in miliseconds of tree collisions
float btGImpactCollisionAlgorithm::getAverageTreeCollisionTime()
{
return btGImpactBoxSet::getAverageTreeCollisionTime();
}
//! Gets the average time in miliseconds of triangle collisions
float btGImpactCollisionAlgorithm::getAverageTriangleCollisionTime()
{
if(g_count_triangle_collision == 0) return 0;
float avgtime = g_accum_triangle_collision_time;
avgtime /= (float)g_count_triangle_collision;
g_accum_triangle_collision_time = 0;
g_count_triangle_collision = 0;
return avgtime;
}
#endif //TRI_COLLISION_PROFILING
btGImpactCollisionAlgorithm::btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap)
{
m_manifoldPtr = NULL;
m_convex_algorithm = NULL;
}
btGImpactCollisionAlgorithm::~btGImpactCollisionAlgorithm()
{
clearCache();
}
void btGImpactCollisionAlgorithm::addContactPoint(const btCollisionObjectWrapper * body0Wrap,
const btCollisionObjectWrapper * body1Wrap,
const btVector3 & point,
const btVector3 & normal,
btScalar distance)
{
m_resultOut->setShapeIdentifiersA(m_part0,m_triface0);
m_resultOut->setShapeIdentifiersB(m_part1,m_triface1);
checkManifold(body0Wrap,body1Wrap);
m_resultOut->addContactPoint(normal,point,distance);
}
void btGImpactCollisionAlgorithm::shape_vs_shape_collision(
const btCollisionObjectWrapper * body0Wrap,
const btCollisionObjectWrapper* body1Wrap,
const btCollisionShape * shape0,
const btCollisionShape * shape1)
{
{
btCollisionAlgorithm* algor = newAlgorithm(body0Wrap,body1Wrap);
// post : checkManifold is called
m_resultOut->setShapeIdentifiersA(m_part0,m_triface0);
m_resultOut->setShapeIdentifiersB(m_part1,m_triface1);
algor->processCollision(body0Wrap,body1Wrap,*m_dispatchInfo,m_resultOut);
algor->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm(algor);
}
}
void btGImpactCollisionAlgorithm::convex_vs_convex_collision(
const btCollisionObjectWrapper* body0Wrap,
const btCollisionObjectWrapper* body1Wrap,
const btCollisionShape* shape0,
const btCollisionShape* shape1)
{
m_resultOut->setShapeIdentifiersA(m_part0,m_triface0);
m_resultOut->setShapeIdentifiersB(m_part1,m_triface1);
btCollisionObjectWrapper ob0(body0Wrap,shape0,body0Wrap->getCollisionObject(),body0Wrap->getWorldTransform(),m_part0,m_triface0);
btCollisionObjectWrapper ob1(body1Wrap,shape1,body1Wrap->getCollisionObject(),body1Wrap->getWorldTransform(),m_part1,m_triface1);
checkConvexAlgorithm(&ob0,&ob1);
m_convex_algorithm->processCollision(&ob0,&ob1,*m_dispatchInfo,m_resultOut);
}
void btGImpactCollisionAlgorithm::gimpact_vs_gimpact_find_pairs(
const btTransform & trans0,
const btTransform & trans1,
const btGImpactShapeInterface * shape0,
const btGImpactShapeInterface * shape1,btPairSet & pairset)
{
if(shape0->hasBoxSet() && shape1->hasBoxSet())
{
btGImpactBoxSet::find_collision(shape0->getBoxSet(),trans0,shape1->getBoxSet(),trans1,pairset);
}
else
{
btAABB boxshape0;
btAABB boxshape1;
int i = shape0->getNumChildShapes();
while(i--)
{
shape0->getChildAabb(i,trans0,boxshape0.m_min,boxshape0.m_max);
int j = shape1->getNumChildShapes();
while(j--)
{
shape1->getChildAabb(i,trans1,boxshape1.m_min,boxshape1.m_max);
if(boxshape1.has_collision(boxshape0))
{
pairset.push_pair(i,j);
}
}
}
}
}
void btGImpactCollisionAlgorithm::gimpact_vs_shape_find_pairs(
const btTransform & trans0,
const btTransform & trans1,
const btGImpactShapeInterface * shape0,
const btCollisionShape * shape1,
btAlignedObjectArray<int> & collided_primitives)
{
btAABB boxshape;
if(shape0->hasBoxSet())
{
btTransform trans1to0 = trans0.inverse();
trans1to0 *= trans1;
shape1->getAabb(trans1to0,boxshape.m_min,boxshape.m_max);
shape0->getBoxSet()->boxQuery(boxshape, collided_primitives);
}
else
{
shape1->getAabb(trans1,boxshape.m_min,boxshape.m_max);
btAABB boxshape0;
int i = shape0->getNumChildShapes();
while(i--)
{
shape0->getChildAabb(i,trans0,boxshape0.m_min,boxshape0.m_max);
if(boxshape.has_collision(boxshape0))
{
collided_primitives.push_back(i);
}
}
}
}
void btGImpactCollisionAlgorithm::collide_gjk_triangles(const btCollisionObjectWrapper * body0Wrap,
const btCollisionObjectWrapper * body1Wrap,
const btGImpactMeshShapePart * shape0,
const btGImpactMeshShapePart * shape1,
const int * pairs, int pair_count)
{
btTriangleShapeEx tri0;
btTriangleShapeEx tri1;
shape0->lockChildShapes();
shape1->lockChildShapes();
const int * pair_pointer = pairs;
while(pair_count--)
{
m_triface0 = *(pair_pointer);
m_triface1 = *(pair_pointer+1);
pair_pointer+=2;
shape0->getBulletTriangle(m_triface0,tri0);
shape1->getBulletTriangle(m_triface1,tri1);
//collide two convex shapes
if(tri0.overlap_test_conservative(tri1))
{
convex_vs_convex_collision(body0Wrap,body1Wrap,&tri0,&tri1);
}
}
shape0->unlockChildShapes();
shape1->unlockChildShapes();
}
void btGImpactCollisionAlgorithm::collide_sat_triangles(const btCollisionObjectWrapper* body0Wrap,
const btCollisionObjectWrapper* body1Wrap,
const btGImpactMeshShapePart * shape0,
const btGImpactMeshShapePart * shape1,
const int * pairs, int pair_count)
{
btTransform orgtrans0 = body0Wrap->getWorldTransform();
btTransform orgtrans1 = body1Wrap->getWorldTransform();
btPrimitiveTriangle ptri0;
btPrimitiveTriangle ptri1;
GIM_TRIANGLE_CONTACT contact_data;
shape0->lockChildShapes();
shape1->lockChildShapes();
const int * pair_pointer = pairs;
while(pair_count--)
{
m_triface0 = *(pair_pointer);
m_triface1 = *(pair_pointer+1);
pair_pointer+=2;
shape0->getPrimitiveTriangle(m_triface0,ptri0);
shape1->getPrimitiveTriangle(m_triface1,ptri1);
#ifdef TRI_COLLISION_PROFILING
bt_begin_gim02_tri_time();
#endif
ptri0.applyTransform(orgtrans0);
ptri1.applyTransform(orgtrans1);
//build planes
ptri0.buildTriPlane();
ptri1.buildTriPlane();
// test conservative
if(ptri0.overlap_test_conservative(ptri1))
{
if(ptri0.find_triangle_collision_clip_method(ptri1,contact_data))
{
int j = contact_data.m_point_count;
while(j--)
{
addContactPoint(body0Wrap, body1Wrap,
contact_data.m_points[j],
contact_data.m_separating_normal,
-contact_data.m_penetration_depth);
}
}
}
#ifdef TRI_COLLISION_PROFILING
bt_end_gim02_tri_time();
#endif
}
shape0->unlockChildShapes();
shape1->unlockChildShapes();
}
void btGImpactCollisionAlgorithm::gimpact_vs_gimpact(
const btCollisionObjectWrapper* body0Wrap,
const btCollisionObjectWrapper * body1Wrap,
const btGImpactShapeInterface * shape0,
const btGImpactShapeInterface * shape1)
{
if(shape0->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
{
const btGImpactMeshShape * meshshape0 = static_cast<const btGImpactMeshShape *>(shape0);
m_part0 = meshshape0->getMeshPartCount();
while(m_part0--)
{
gimpact_vs_gimpact(body0Wrap,body1Wrap,meshshape0->getMeshPart(m_part0),shape1);
}
return;
}
if(shape1->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
{
const btGImpactMeshShape * meshshape1 = static_cast<const btGImpactMeshShape *>(shape1);
m_part1 = meshshape1->getMeshPartCount();
while(m_part1--)
{
gimpact_vs_gimpact(body0Wrap,body1Wrap,shape0,meshshape1->getMeshPart(m_part1));
}
return;
}
btTransform orgtrans0 = body0Wrap->getWorldTransform();
btTransform orgtrans1 = body1Wrap->getWorldTransform();
btPairSet pairset;
gimpact_vs_gimpact_find_pairs(orgtrans0,orgtrans1,shape0,shape1,pairset);
if(pairset.size()== 0) return;
if(shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
shape1->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART)
{
const btGImpactMeshShapePart * shapepart0 = static_cast<const btGImpactMeshShapePart * >(shape0);
const btGImpactMeshShapePart * shapepart1 = static_cast<const btGImpactMeshShapePart * >(shape1);
//specialized function
#ifdef BULLET_TRIANGLE_COLLISION
collide_gjk_triangles(body0Wrap,body1Wrap,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size());
#else
collide_sat_triangles(body0Wrap,body1Wrap,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size());
#endif
return;
}
//general function
shape0->lockChildShapes();
shape1->lockChildShapes();
GIM_ShapeRetriever retriever0(shape0);
GIM_ShapeRetriever retriever1(shape1);
bool child_has_transform0 = shape0->childrenHasTransform();
bool child_has_transform1 = shape1->childrenHasTransform();
int i = pairset.size();
while(i--)
{
GIM_PAIR * pair = &pairset[i];
m_triface0 = pair->m_index1;
m_triface1 = pair->m_index2;
const btCollisionShape * colshape0 = retriever0.getChildShape(m_triface0);
const btCollisionShape * colshape1 = retriever1.getChildShape(m_triface1);
btTransform tr0 = body0Wrap->getWorldTransform();
btTransform tr1 = body1Wrap->getWorldTransform();
if(child_has_transform0)
{
tr0 = orgtrans0*shape0->getChildTransform(m_triface0);
}
if(child_has_transform1)
{
tr1 = orgtrans1*shape1->getChildTransform(m_triface1);
}
btCollisionObjectWrapper ob0(body0Wrap,colshape0,body0Wrap->getCollisionObject(),tr0,m_part0,m_triface0);
btCollisionObjectWrapper ob1(body1Wrap,colshape1,body1Wrap->getCollisionObject(),tr1,m_part1,m_triface1);
//collide two convex shapes
convex_vs_convex_collision(&ob0,&ob1,colshape0,colshape1);
}
shape0->unlockChildShapes();
shape1->unlockChildShapes();
}
void btGImpactCollisionAlgorithm::gimpact_vs_shape(const btCollisionObjectWrapper* body0Wrap,
const btCollisionObjectWrapper * body1Wrap,
const btGImpactShapeInterface * shape0,
const btCollisionShape * shape1,bool swapped)
{
if(shape0->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
{
const btGImpactMeshShape * meshshape0 = static_cast<const btGImpactMeshShape *>(shape0);
int& part = swapped ? m_part1 : m_part0;
part = meshshape0->getMeshPartCount();
while(part--)
{
gimpact_vs_shape(body0Wrap,
body1Wrap,
meshshape0->getMeshPart(part),
shape1,swapped);
}
return;
}
#ifdef GIMPACT_VS_PLANE_COLLISION
if(shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
shape1->getShapeType() == STATIC_PLANE_PROXYTYPE)
{
const btGImpactMeshShapePart * shapepart = static_cast<const btGImpactMeshShapePart *>(shape0);
const btStaticPlaneShape * planeshape = static_cast<const btStaticPlaneShape * >(shape1);
gimpacttrimeshpart_vs_plane_collision(body0Wrap,body1Wrap,shapepart,planeshape,swapped);
return;
}
#endif
if(shape1->isCompound())
{
const btCompoundShape * compoundshape = static_cast<const btCompoundShape *>(shape1);
gimpact_vs_compoundshape(body0Wrap,body1Wrap,shape0,compoundshape,swapped);
return;
}
else if(shape1->isConcave())
{
const btConcaveShape * concaveshape = static_cast<const btConcaveShape *>(shape1);
gimpact_vs_concave(body0Wrap,body1Wrap,shape0,concaveshape,swapped);
return;
}
btTransform orgtrans0 = body0Wrap->getWorldTransform();
btTransform orgtrans1 = body1Wrap->getWorldTransform();
btAlignedObjectArray<int> collided_results;
gimpact_vs_shape_find_pairs(orgtrans0,orgtrans1,shape0,shape1,collided_results);
if(collided_results.size() == 0) return;
shape0->lockChildShapes();
GIM_ShapeRetriever retriever0(shape0);
bool child_has_transform0 = shape0->childrenHasTransform();
int i = collided_results.size();
while(i--)
{
int child_index = collided_results[i];
if(swapped)
m_triface1 = child_index;
else
m_triface0 = child_index;
const btCollisionShape * colshape0 = retriever0.getChildShape(child_index);
btTransform tr0 = body0Wrap->getWorldTransform();
if(child_has_transform0)
{
tr0 = orgtrans0*shape0->getChildTransform(child_index);
}
btCollisionObjectWrapper ob0(body0Wrap,colshape0,body0Wrap->getCollisionObject(),body0Wrap->getWorldTransform(),m_part0,m_triface0);
const btCollisionObjectWrapper* prevObj0 = m_resultOut->getBody0Wrap();
if (m_resultOut->getBody0Wrap()->getCollisionObject()==ob0.getCollisionObject())
{
m_resultOut->setBody0Wrap(&ob0);
} else
{
m_resultOut->setBody1Wrap(&ob0);
}
//collide two shapes
if(swapped)
{
shape_vs_shape_collision(body1Wrap,&ob0,shape1,colshape0);
}
else
{
shape_vs_shape_collision(&ob0,body1Wrap,colshape0,shape1);
}
m_resultOut->setBody0Wrap(prevObj0);
}
shape0->unlockChildShapes();
}
void btGImpactCollisionAlgorithm::gimpact_vs_compoundshape(const btCollisionObjectWrapper* body0Wrap,
const btCollisionObjectWrapper* body1Wrap,
const btGImpactShapeInterface * shape0,
const btCompoundShape * shape1,bool swapped)
{
btTransform orgtrans1 = body1Wrap->getWorldTransform();
int i = shape1->getNumChildShapes();
while(i--)
{
const btCollisionShape * colshape1 = shape1->getChildShape(i);
btTransform childtrans1 = orgtrans1*shape1->getChildTransform(i);
btCollisionObjectWrapper ob1(body1Wrap,colshape1,body1Wrap->getCollisionObject(),childtrans1,-1,i);
const btCollisionObjectWrapper* tmp = 0;
if (m_resultOut->getBody0Wrap()->getCollisionObject()==ob1.getCollisionObject())
{
tmp = m_resultOut->getBody0Wrap();
m_resultOut->setBody0Wrap(&ob1);
} else
{
tmp = m_resultOut->getBody1Wrap();
m_resultOut->setBody1Wrap(&ob1);
}
//collide child shape
gimpact_vs_shape(body0Wrap, &ob1,
shape0,colshape1,swapped);
if (m_resultOut->getBody0Wrap()->getCollisionObject()==ob1.getCollisionObject())
{
m_resultOut->setBody0Wrap(tmp);
} else
{
m_resultOut->setBody1Wrap(tmp);
}
}
}
void btGImpactCollisionAlgorithm::gimpacttrimeshpart_vs_plane_collision(
const btCollisionObjectWrapper * body0Wrap,
const btCollisionObjectWrapper * body1Wrap,
const btGImpactMeshShapePart * shape0,
const btStaticPlaneShape * shape1,bool swapped)
{
btTransform orgtrans0 = body0Wrap->getWorldTransform();
btTransform orgtrans1 = body1Wrap->getWorldTransform();
const btPlaneShape * planeshape = static_cast<const btPlaneShape *>(shape1);
btVector4 plane;
planeshape->get_plane_equation_transformed(orgtrans1,plane);
//test box against plane
btAABB tribox;
shape0->getAabb(orgtrans0,tribox.m_min,tribox.m_max);
tribox.increment_margin(planeshape->getMargin());
if( tribox.plane_classify(plane)!= BT_CONST_COLLIDE_PLANE) return;
shape0->lockChildShapes();
btScalar margin = shape0->getMargin() + planeshape->getMargin();
btVector3 vertex;
int vi = shape0->getVertexCount();
while(vi--)
{
shape0->getVertex(vi,vertex);
vertex = orgtrans0(vertex);
btScalar distance = vertex.dot(plane) - plane[3] - margin;
if(distance<0.0)//add contact
{
if(swapped)
{
addContactPoint(body1Wrap, body0Wrap,
vertex,
-plane,
distance);
}
else
{
addContactPoint(body0Wrap, body1Wrap,
vertex,
plane,
distance);
}
}
}
shape0->unlockChildShapes();
}
class btGImpactTriangleCallback: public btTriangleCallback
{
public:
btGImpactCollisionAlgorithm * algorithm;
const btCollisionObjectWrapper * body0Wrap;
const btCollisionObjectWrapper * body1Wrap;
const btGImpactShapeInterface * gimpactshape0;
bool swapped;
btScalar margin;
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
{
btTriangleShapeEx tri1(triangle[0],triangle[1],triangle[2]);
tri1.setMargin(margin);
if(swapped)
{
algorithm->setPart0(partId);
algorithm->setFace0(triangleIndex);
}
else
{
algorithm->setPart1(partId);
algorithm->setFace1(triangleIndex);
}
btCollisionObjectWrapper ob1Wrap(body1Wrap,&tri1,body1Wrap->getCollisionObject(),body1Wrap->getWorldTransform(),partId,triangleIndex);
const btCollisionObjectWrapper * tmp = 0;
if (algorithm->internalGetResultOut()->getBody0Wrap()->getCollisionObject()==ob1Wrap.getCollisionObject())
{
tmp = algorithm->internalGetResultOut()->getBody0Wrap();
algorithm->internalGetResultOut()->setBody0Wrap(&ob1Wrap);
} else
{
tmp = algorithm->internalGetResultOut()->getBody1Wrap();
algorithm->internalGetResultOut()->setBody1Wrap(&ob1Wrap);
}
algorithm->gimpact_vs_shape(
body0Wrap,&ob1Wrap,gimpactshape0,&tri1,swapped);
if (algorithm->internalGetResultOut()->getBody0Wrap()->getCollisionObject()==ob1Wrap.getCollisionObject())
{
algorithm->internalGetResultOut()->setBody0Wrap(tmp);
} else
{
algorithm->internalGetResultOut()->setBody1Wrap(tmp);
}
}
};
void btGImpactCollisionAlgorithm::gimpact_vs_concave(
const btCollisionObjectWrapper* body0Wrap,
const btCollisionObjectWrapper * body1Wrap,
const btGImpactShapeInterface * shape0,
const btConcaveShape * shape1,bool swapped)
{
//create the callback
btGImpactTriangleCallback tricallback;
tricallback.algorithm = this;
tricallback.body0Wrap = body0Wrap;
tricallback.body1Wrap = body1Wrap;
tricallback.gimpactshape0 = shape0;
tricallback.swapped = swapped;
tricallback.margin = shape1->getMargin();
//getting the trimesh AABB
btTransform gimpactInConcaveSpace;
gimpactInConcaveSpace = body1Wrap->getWorldTransform().inverse() * body0Wrap->getWorldTransform();
btVector3 minAABB,maxAABB;
shape0->getAabb(gimpactInConcaveSpace,minAABB,maxAABB);
shape1->processAllTriangles(&tricallback,minAABB,maxAABB);
}
void btGImpactCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
clearCache();
m_resultOut = resultOut;
m_dispatchInfo = &dispatchInfo;
const btGImpactShapeInterface * gimpactshape0;
const btGImpactShapeInterface * gimpactshape1;
if (body0Wrap->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE)
{
gimpactshape0 = static_cast<const btGImpactShapeInterface *>(body0Wrap->getCollisionShape());
if( body1Wrap->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE )
{
gimpactshape1 = static_cast<const btGImpactShapeInterface *>(body1Wrap->getCollisionShape());
gimpact_vs_gimpact(body0Wrap,body1Wrap,gimpactshape0,gimpactshape1);
}
else
{
gimpact_vs_shape(body0Wrap,body1Wrap,gimpactshape0,body1Wrap->getCollisionShape(),false);
}
}
else if (body1Wrap->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE )
{
gimpactshape1 = static_cast<const btGImpactShapeInterface *>(body1Wrap->getCollisionShape());
gimpact_vs_shape(body1Wrap,body0Wrap,gimpactshape1,body0Wrap->getCollisionShape(),true);
}
}
btScalar btGImpactCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
return 1.f;
}
///////////////////////////////////// REGISTERING ALGORITHM //////////////////////////////////////////////
//! Use this function for register the algorithm externally
void btGImpactCollisionAlgorithm::registerAlgorithm(btCollisionDispatcher * dispatcher)
{
static btGImpactCollisionAlgorithm::CreateFunc s_gimpact_cf;
int i;
for ( i = 0;i < MAX_BROADPHASE_COLLISION_TYPES ;i++ )
{
dispatcher->registerCollisionCreateFunc(GIMPACT_SHAPE_PROXYTYPE,i ,&s_gimpact_cf);
}
for ( i = 0;i < MAX_BROADPHASE_COLLISION_TYPES ;i++ )
{
dispatcher->registerCollisionCreateFunc(i,GIMPACT_SHAPE_PROXYTYPE ,&s_gimpact_cf);
}
}

View File

@@ -1,310 +0,0 @@
/*! \file btGImpactShape.h
\author Francisco Leon Najera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_GIMPACT_BVH_CONCAVE_COLLISION_ALGORITHM_H
#define BT_GIMPACT_BVH_CONCAVE_COLLISION_ALGORITHM_H
#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h"
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
class btDispatcher;
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "btGImpactShape.h"
#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h"
#include "LinearMath/btIDebugDraw.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
//! Collision Algorithm for GImpact Shapes
/*!
For register this algorithm in Bullet, proceed as following:
\code
btCollisionDispatcher * dispatcher = static_cast<btCollisionDispatcher *>(m_dynamicsWorld ->getDispatcher());
btGImpactCollisionAlgorithm::registerAlgorithm(dispatcher);
\endcode
*/
class btGImpactCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
protected:
btCollisionAlgorithm * m_convex_algorithm;
btPersistentManifold * m_manifoldPtr;
btManifoldResult* m_resultOut;
const btDispatcherInfo * m_dispatchInfo;
int m_triface0;
int m_part0;
int m_triface1;
int m_part1;
//! Creates a new contact point
SIMD_FORCE_INLINE btPersistentManifold* newContactManifold(const btCollisionObject* body0,const btCollisionObject* body1)
{
m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1);
return m_manifoldPtr;
}
SIMD_FORCE_INLINE void destroyConvexAlgorithm()
{
if(m_convex_algorithm)
{
m_convex_algorithm->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm( m_convex_algorithm);
m_convex_algorithm = NULL;
}
}
SIMD_FORCE_INLINE void destroyContactManifolds()
{
if(m_manifoldPtr == NULL) return;
m_dispatcher->releaseManifold(m_manifoldPtr);
m_manifoldPtr = NULL;
}
SIMD_FORCE_INLINE void clearCache()
{
destroyContactManifolds();
destroyConvexAlgorithm();
m_triface0 = -1;
m_part0 = -1;
m_triface1 = -1;
m_part1 = -1;
}
SIMD_FORCE_INLINE btPersistentManifold* getLastManifold()
{
return m_manifoldPtr;
}
// Call before process collision
SIMD_FORCE_INLINE void checkManifold(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
if(getLastManifold() == 0)
{
newContactManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject());
}
m_resultOut->setPersistentManifold(getLastManifold());
}
// Call before process collision
SIMD_FORCE_INLINE btCollisionAlgorithm * newAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
checkManifold(body0Wrap,body1Wrap);
btCollisionAlgorithm * convex_algorithm = m_dispatcher->findAlgorithm(
body0Wrap,body1Wrap,getLastManifold());
return convex_algorithm ;
}
// Call before process collision
SIMD_FORCE_INLINE void checkConvexAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
if(m_convex_algorithm) return;
m_convex_algorithm = newAlgorithm(body0Wrap,body1Wrap);
}
void addContactPoint(const btCollisionObjectWrapper * body0Wrap,
const btCollisionObjectWrapper * body1Wrap,
const btVector3 & point,
const btVector3 & normal,
btScalar distance);
//! Collision routines
//!@{
void collide_gjk_triangles(const btCollisionObjectWrapper* body0Wrap,
const btCollisionObjectWrapper* body1Wrap,
const btGImpactMeshShapePart * shape0,
const btGImpactMeshShapePart * shape1,
const int * pairs, int pair_count);
void collide_sat_triangles(const btCollisionObjectWrapper* body0Wrap,
const btCollisionObjectWrapper* body1Wrap,
const btGImpactMeshShapePart * shape0,
const btGImpactMeshShapePart * shape1,
const int * pairs, int pair_count);
void shape_vs_shape_collision(
const btCollisionObjectWrapper* body0,
const btCollisionObjectWrapper* body1,
const btCollisionShape * shape0,
const btCollisionShape * shape1);
void convex_vs_convex_collision(const btCollisionObjectWrapper* body0Wrap,
const btCollisionObjectWrapper* body1Wrap,
const btCollisionShape* shape0,
const btCollisionShape* shape1);
void gimpact_vs_gimpact_find_pairs(
const btTransform & trans0,
const btTransform & trans1,
const btGImpactShapeInterface * shape0,
const btGImpactShapeInterface * shape1,btPairSet & pairset);
void gimpact_vs_shape_find_pairs(
const btTransform & trans0,
const btTransform & trans1,
const btGImpactShapeInterface * shape0,
const btCollisionShape * shape1,
btAlignedObjectArray<int> & collided_primitives);
void gimpacttrimeshpart_vs_plane_collision(
const btCollisionObjectWrapper * body0Wrap,
const btCollisionObjectWrapper * body1Wrap,
const btGImpactMeshShapePart * shape0,
const btStaticPlaneShape * shape1,bool swapped);
public:
btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
virtual ~btGImpactCollisionAlgorithm();
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr)
manifoldArray.push_back(m_manifoldPtr);
}
btManifoldResult* internalGetResultOut()
{
return m_resultOut;
}
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btGImpactCollisionAlgorithm));
return new(mem) btGImpactCollisionAlgorithm(ci,body0Wrap,body1Wrap);
}
};
//! Use this function for register the algorithm externally
static void registerAlgorithm(btCollisionDispatcher * dispatcher);
#ifdef TRI_COLLISION_PROFILING
//! Gets the average time in miliseconds of tree collisions
static float getAverageTreeCollisionTime();
//! Gets the average time in miliseconds of triangle collisions
static float getAverageTriangleCollisionTime();
#endif //TRI_COLLISION_PROFILING
//! Collides two gimpact shapes
/*!
\pre shape0 and shape1 couldn't be btGImpactMeshShape objects
*/
void gimpact_vs_gimpact(const btCollisionObjectWrapper* body0Wrap,
const btCollisionObjectWrapper * body1Wrap,
const btGImpactShapeInterface * shape0,
const btGImpactShapeInterface * shape1);
void gimpact_vs_shape(const btCollisionObjectWrapper* body0Wrap,
const btCollisionObjectWrapper* body1Wrap,
const btGImpactShapeInterface * shape0,
const btCollisionShape * shape1,bool swapped);
void gimpact_vs_compoundshape(const btCollisionObjectWrapper * body0Wrap,
const btCollisionObjectWrapper * body1Wrap,
const btGImpactShapeInterface * shape0,
const btCompoundShape * shape1,bool swapped);
void gimpact_vs_concave(
const btCollisionObjectWrapper * body0Wrap,
const btCollisionObjectWrapper * body1Wrap,
const btGImpactShapeInterface * shape0,
const btConcaveShape * shape1,bool swapped);
/// Accessor/Mutator pairs for Part and triangleID
void setFace0(int value)
{
m_triface0 = value;
}
int getFace0()
{
return m_triface0;
}
void setFace1(int value)
{
m_triface1 = value;
}
int getFace1()
{
return m_triface1;
}
void setPart0(int value)
{
m_part0 = value;
}
int getPart0()
{
return m_part0;
}
void setPart1(int value)
{
m_part1 = value;
}
int getPart1()
{
return m_part1;
}
};
//algorithm details
//#define BULLET_TRIANGLE_COLLISION 1
#define GIMPACT_VS_PLANE_COLLISION 1
#endif //BT_GIMPACT_BVH_CONCAVE_COLLISION_ALGORITHM_H

View File

@@ -1,60 +0,0 @@
/*! \file btGImpactMassUtil.h
\author Francisco Leon Najera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef GIMPACT_MASS_UTIL_H
#define GIMPACT_MASS_UTIL_H
#include "LinearMath/btTransform.h"
SIMD_FORCE_INLINE btVector3 gim_inertia_add_transformed(
const btVector3 & source_inertia, const btVector3 & added_inertia, const btTransform & transform)
{
btMatrix3x3 rotatedTensor = transform.getBasis().scaled(added_inertia) * transform.getBasis().transpose();
btScalar x2 = transform.getOrigin()[0];
x2*= x2;
btScalar y2 = transform.getOrigin()[1];
y2*= y2;
btScalar z2 = transform.getOrigin()[2];
z2*= z2;
btScalar ix = rotatedTensor[0][0]*(y2+z2);
btScalar iy = rotatedTensor[1][1]*(x2+z2);
btScalar iz = rotatedTensor[2][2]*(x2+y2);
return btVector3(source_inertia[0]+ix,source_inertia[1]+iy,source_inertia[2] + iz);
}
SIMD_FORCE_INLINE btVector3 gim_get_point_inertia(const btVector3 & point, btScalar mass)
{
btScalar x2 = point[0]*point[0];
btScalar y2 = point[1]*point[1];
btScalar z2 = point[2]*point[2];
return btVector3(mass*(y2+z2),mass*(x2+z2),mass*(x2+y2));
}
#endif //GIMPACT_MESH_SHAPE_H

View File

@@ -1,528 +0,0 @@
/*! \file gim_box_set.h
\author Francisco Leon Najera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "btGImpactQuantizedBvh.h"
#include "LinearMath/btQuickprof.h"
#ifdef TRI_COLLISION_PROFILING
btClock g_q_tree_clock;
float g_q_accum_tree_collision_time = 0;
int g_q_count_traversing = 0;
void bt_begin_gim02_q_tree_time()
{
g_q_tree_clock.reset();
}
void bt_end_gim02_q_tree_time()
{
g_q_accum_tree_collision_time += g_q_tree_clock.getTimeMicroseconds();
g_q_count_traversing++;
}
//! Gets the average time in miliseconds of tree collisions
float btGImpactQuantizedBvh::getAverageTreeCollisionTime()
{
if(g_q_count_traversing == 0) return 0;
float avgtime = g_q_accum_tree_collision_time;
avgtime /= (float)g_q_count_traversing;
g_q_accum_tree_collision_time = 0;
g_q_count_traversing = 0;
return avgtime;
// float avgtime = g_q_count_traversing;
// g_q_count_traversing = 0;
// return avgtime;
}
#endif //TRI_COLLISION_PROFILING
/////////////////////// btQuantizedBvhTree /////////////////////////////////
void btQuantizedBvhTree::calc_quantization(
GIM_BVH_DATA_ARRAY & primitive_boxes, btScalar boundMargin)
{
//calc globa box
btAABB global_bound;
global_bound.invalidate();
for (int i=0;i<primitive_boxes.size() ;i++ )
{
global_bound.merge(primitive_boxes[i].m_bound);
}
bt_calc_quantization_parameters(
m_global_bound.m_min,m_global_bound.m_max,m_bvhQuantization,global_bound.m_min,global_bound.m_max,boundMargin);
}
int btQuantizedBvhTree::_calc_splitting_axis(
GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex)
{
int i;
btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.));
int numIndices = endIndex-startIndex;
for (i=startIndex;i<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
primitive_boxes[i].m_bound.m_min);
means+=center;
}
means *= (btScalar(1.)/(btScalar)numIndices);
for (i=startIndex;i<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
primitive_boxes[i].m_bound.m_min);
btVector3 diff2 = center-means;
diff2 = diff2 * diff2;
variance += diff2;
}
variance *= (btScalar(1.)/ ((btScalar)numIndices-1) );
return variance.maxAxis();
}
int btQuantizedBvhTree::_sort_and_calc_splitting_index(
GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex,
int endIndex, int splitAxis)
{
int i;
int splitIndex =startIndex;
int numIndices = endIndex - startIndex;
// average of centers
btScalar splitValue = 0.0f;
btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
for (i=startIndex;i<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
primitive_boxes[i].m_bound.m_min);
means+=center;
}
means *= (btScalar(1.)/(btScalar)numIndices);
splitValue = means[splitAxis];
//sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
for (i=startIndex;i<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
primitive_boxes[i].m_bound.m_min);
if (center[splitAxis] > splitValue)
{
//swap
primitive_boxes.swap(i,splitIndex);
//swapLeafNodes(i,splitIndex);
splitIndex++;
}
}
//if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
//otherwise the tree-building might fail due to stack-overflows in certain cases.
//unbalanced1 is unsafe: it can cause stack overflows
//bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
//unbalanced2 should work too: always use center (perfect balanced trees)
//bool unbalanced2 = true;
//this should be safe too:
int rangeBalancedIndices = numIndices/3;
bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
if (unbalanced)
{
splitIndex = startIndex+ (numIndices>>1);
}
btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex))));
return splitIndex;
}
void btQuantizedBvhTree::_build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex)
{
int curIndex = m_num_nodes;
m_num_nodes++;
btAssert((endIndex-startIndex)>0);
if ((endIndex-startIndex)==1)
{
//We have a leaf node
setNodeBound(curIndex,primitive_boxes[startIndex].m_bound);
m_node_array[curIndex].setDataIndex(primitive_boxes[startIndex].m_data);
return;
}
//calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
//split axis
int splitIndex = _calc_splitting_axis(primitive_boxes,startIndex,endIndex);
splitIndex = _sort_and_calc_splitting_index(
primitive_boxes,startIndex,endIndex,
splitIndex//split axis
);
//calc this node bounding box
btAABB node_bound;
node_bound.invalidate();
for (int i=startIndex;i<endIndex;i++)
{
node_bound.merge(primitive_boxes[i].m_bound);
}
setNodeBound(curIndex,node_bound);
//build left branch
_build_sub_tree(primitive_boxes, startIndex, splitIndex );
//build right branch
_build_sub_tree(primitive_boxes, splitIndex ,endIndex);
m_node_array[curIndex].setEscapeIndex(m_num_nodes - curIndex);
}
//! stackless build tree
void btQuantizedBvhTree::build_tree(
GIM_BVH_DATA_ARRAY & primitive_boxes)
{
calc_quantization(primitive_boxes);
// initialize node count to 0
m_num_nodes = 0;
// allocate nodes
m_node_array.resize(primitive_boxes.size()*2);
_build_sub_tree(primitive_boxes, 0, primitive_boxes.size());
}
////////////////////////////////////class btGImpactQuantizedBvh
void btGImpactQuantizedBvh::refit()
{
int nodecount = getNodeCount();
while(nodecount--)
{
if(isLeafNode(nodecount))
{
btAABB leafbox;
m_primitive_manager->get_primitive_box(getNodeData(nodecount),leafbox);
setNodeBound(nodecount,leafbox);
}
else
{
//const GIM_BVH_TREE_NODE * nodepointer = get_node_pointer(nodecount);
//get left bound
btAABB bound;
bound.invalidate();
btAABB temp_box;
int child_node = getLeftNode(nodecount);
if(child_node)
{
getNodeBound(child_node,temp_box);
bound.merge(temp_box);
}
child_node = getRightNode(nodecount);
if(child_node)
{
getNodeBound(child_node,temp_box);
bound.merge(temp_box);
}
setNodeBound(nodecount,bound);
}
}
}
//! this rebuild the entire set
void btGImpactQuantizedBvh::buildSet()
{
//obtain primitive boxes
GIM_BVH_DATA_ARRAY primitive_boxes;
primitive_boxes.resize(m_primitive_manager->get_primitive_count());
for (int i = 0;i<primitive_boxes.size() ;i++ )
{
m_primitive_manager->get_primitive_box(i,primitive_boxes[i].m_bound);
primitive_boxes[i].m_data = i;
}
m_box_tree.build_tree(primitive_boxes);
}
//! returns the indices of the primitives in the m_primitive_manager
bool btGImpactQuantizedBvh::boxQuery(const btAABB & box, btAlignedObjectArray<int> & collided_results) const
{
int curIndex = 0;
int numNodes = getNodeCount();
//quantize box
unsigned short quantizedMin[3];
unsigned short quantizedMax[3];
m_box_tree.quantizePoint(quantizedMin,box.m_min);
m_box_tree.quantizePoint(quantizedMax,box.m_max);
while (curIndex < numNodes)
{
//catch bugs in tree data
bool aabbOverlap = m_box_tree.testQuantizedBoxOverlapp(curIndex, quantizedMin,quantizedMax);
bool isleafnode = isLeafNode(curIndex);
if (isleafnode && aabbOverlap)
{
collided_results.push_back(getNodeData(curIndex));
}
if (aabbOverlap || isleafnode)
{
//next subnode
curIndex++;
}
else
{
//skip node
curIndex+= getEscapeNodeIndex(curIndex);
}
}
if(collided_results.size()>0) return true;
return false;
}
//! returns the indices of the primitives in the m_primitive_manager
bool btGImpactQuantizedBvh::rayQuery(
const btVector3 & ray_dir,const btVector3 & ray_origin ,
btAlignedObjectArray<int> & collided_results) const
{
int curIndex = 0;
int numNodes = getNodeCount();
while (curIndex < numNodes)
{
btAABB bound;
getNodeBound(curIndex,bound);
//catch bugs in tree data
bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir);
bool isleafnode = isLeafNode(curIndex);
if (isleafnode && aabbOverlap)
{
collided_results.push_back(getNodeData( curIndex));
}
if (aabbOverlap || isleafnode)
{
//next subnode
curIndex++;
}
else
{
//skip node
curIndex+= getEscapeNodeIndex(curIndex);
}
}
if(collided_results.size()>0) return true;
return false;
}
SIMD_FORCE_INLINE bool _quantized_node_collision(
const btGImpactQuantizedBvh * boxset0, const btGImpactQuantizedBvh * boxset1,
const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0,
int node0 ,int node1, bool complete_primitive_tests)
{
btAABB box0;
boxset0->getNodeBound(node0,box0);
btAABB box1;
boxset1->getNodeBound(node1,box1);
return box0.overlapping_trans_cache(box1,trans_cache_1to0,complete_primitive_tests );
// box1.appy_transform_trans_cache(trans_cache_1to0);
// return box0.has_collision(box1);
}
//stackless recursive collision routine
static void _find_quantized_collision_pairs_recursive(
const btGImpactQuantizedBvh * boxset0, const btGImpactQuantizedBvh * boxset1,
btPairSet * collision_pairs,
const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0,
int node0, int node1, bool complete_primitive_tests)
{
if( _quantized_node_collision(
boxset0,boxset1,trans_cache_1to0,
node0,node1,complete_primitive_tests) ==false) return;//avoid colliding internal nodes
if(boxset0->isLeafNode(node0))
{
if(boxset1->isLeafNode(node1))
{
// collision result
collision_pairs->push_pair(
boxset0->getNodeData(node0),boxset1->getNodeData(node1));
return;
}
else
{
//collide left recursive
_find_quantized_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
node0,boxset1->getLeftNode(node1),false);
//collide right recursive
_find_quantized_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
node0,boxset1->getRightNode(node1),false);
}
}
else
{
if(boxset1->isLeafNode(node1))
{
//collide left recursive
_find_quantized_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getLeftNode(node0),node1,false);
//collide right recursive
_find_quantized_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getRightNode(node0),node1,false);
}
else
{
//collide left0 left1
_find_quantized_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getLeftNode(node0),boxset1->getLeftNode(node1),false);
//collide left0 right1
_find_quantized_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getLeftNode(node0),boxset1->getRightNode(node1),false);
//collide right0 left1
_find_quantized_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getRightNode(node0),boxset1->getLeftNode(node1),false);
//collide right0 right1
_find_quantized_collision_pairs_recursive(
boxset0,boxset1,
collision_pairs,trans_cache_1to0,
boxset0->getRightNode(node0),boxset1->getRightNode(node1),false);
}// else if node1 is not a leaf
}// else if node0 is not a leaf
}
void btGImpactQuantizedBvh::find_collision(const btGImpactQuantizedBvh * boxset0, const btTransform & trans0,
const btGImpactQuantizedBvh * boxset1, const btTransform & trans1,
btPairSet & collision_pairs)
{
if(boxset0->getNodeCount()==0 || boxset1->getNodeCount()==0 ) return;
BT_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0;
trans_cache_1to0.calc_from_homogenic(trans0,trans1);
#ifdef TRI_COLLISION_PROFILING
bt_begin_gim02_q_tree_time();
#endif //TRI_COLLISION_PROFILING
_find_quantized_collision_pairs_recursive(
boxset0,boxset1,
&collision_pairs,trans_cache_1to0,0,0,true);
#ifdef TRI_COLLISION_PROFILING
bt_end_gim02_q_tree_time();
#endif //TRI_COLLISION_PROFILING
}

View File

@@ -1,372 +0,0 @@
#ifndef GIM_QUANTIZED_SET_H_INCLUDED
#define GIM_QUANTIZED_SET_H_INCLUDED
/*! \file btGImpactQuantizedBvh.h
\author Francisco Leon Najera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "btGImpactBvh.h"
#include "btQuantization.h"
///btQuantizedBvhNode 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).
ATTRIBUTE_ALIGNED16 (struct) BT_QUANTIZED_BVH_NODE
{
//12 bytes
unsigned short int m_quantizedAabbMin[3];
unsigned short int m_quantizedAabbMax[3];
//4 bytes
int m_escapeIndexOrDataIndex;
BT_QUANTIZED_BVH_NODE()
{
m_escapeIndexOrDataIndex = 0;
}
SIMD_FORCE_INLINE bool isLeafNode() const
{
//skipindex is negative (internal node), triangleindex >=0 (leafnode)
return (m_escapeIndexOrDataIndex>=0);
}
SIMD_FORCE_INLINE int getEscapeIndex() const
{
//btAssert(m_escapeIndexOrDataIndex < 0);
return -m_escapeIndexOrDataIndex;
}
SIMD_FORCE_INLINE void setEscapeIndex(int index)
{
m_escapeIndexOrDataIndex = -index;
}
SIMD_FORCE_INLINE int getDataIndex() const
{
//btAssert(m_escapeIndexOrDataIndex >= 0);
return m_escapeIndexOrDataIndex;
}
SIMD_FORCE_INLINE void setDataIndex(int index)
{
m_escapeIndexOrDataIndex = index;
}
SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp(
unsigned short * quantizedMin,unsigned short * quantizedMax) const
{
if(m_quantizedAabbMin[0] > quantizedMax[0] ||
m_quantizedAabbMax[0] < quantizedMin[0] ||
m_quantizedAabbMin[1] > quantizedMax[1] ||
m_quantizedAabbMax[1] < quantizedMin[1] ||
m_quantizedAabbMin[2] > quantizedMax[2] ||
m_quantizedAabbMax[2] < quantizedMin[2])
{
return false;
}
return true;
}
};
class GIM_QUANTIZED_BVH_NODE_ARRAY:public btAlignedObjectArray<BT_QUANTIZED_BVH_NODE>
{
};
//! Basic Box tree structure
class btQuantizedBvhTree
{
protected:
int m_num_nodes;
GIM_QUANTIZED_BVH_NODE_ARRAY m_node_array;
btAABB m_global_bound;
btVector3 m_bvhQuantization;
protected:
void calc_quantization(GIM_BVH_DATA_ARRAY & primitive_boxes, btScalar boundMargin = btScalar(1.0) );
int _sort_and_calc_splitting_index(
GIM_BVH_DATA_ARRAY & primitive_boxes,
int startIndex, int endIndex, int splitAxis);
int _calc_splitting_axis(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex);
void _build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex);
public:
btQuantizedBvhTree()
{
m_num_nodes = 0;
}
//! prototype functions for box tree management
//!@{
void build_tree(GIM_BVH_DATA_ARRAY & primitive_boxes);
SIMD_FORCE_INLINE void quantizePoint(
unsigned short * quantizedpoint, const btVector3 & point) const
{
bt_quantize_clamp(quantizedpoint,point,m_global_bound.m_min,m_global_bound.m_max,m_bvhQuantization);
}
SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp(
int node_index,
unsigned short * quantizedMin,unsigned short * quantizedMax) const
{
return m_node_array[node_index].testQuantizedBoxOverlapp(quantizedMin,quantizedMax);
}
SIMD_FORCE_INLINE void clearNodes()
{
m_node_array.clear();
m_num_nodes = 0;
}
//! node count
SIMD_FORCE_INLINE int getNodeCount() const
{
return m_num_nodes;
}
//! tells if the node is a leaf
SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
{
return m_node_array[nodeindex].isLeafNode();
}
SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
{
return m_node_array[nodeindex].getDataIndex();
}
SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const
{
bound.m_min = bt_unquantize(
m_node_array[nodeindex].m_quantizedAabbMin,
m_global_bound.m_min,m_bvhQuantization);
bound.m_max = bt_unquantize(
m_node_array[nodeindex].m_quantizedAabbMax,
m_global_bound.m_min,m_bvhQuantization);
}
SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound)
{
bt_quantize_clamp( m_node_array[nodeindex].m_quantizedAabbMin,
bound.m_min,
m_global_bound.m_min,
m_global_bound.m_max,
m_bvhQuantization);
bt_quantize_clamp( m_node_array[nodeindex].m_quantizedAabbMax,
bound.m_max,
m_global_bound.m_min,
m_global_bound.m_max,
m_bvhQuantization);
}
SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
{
return nodeindex+1;
}
SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
{
if(m_node_array[nodeindex+1].isLeafNode()) return nodeindex+2;
return nodeindex+1 + m_node_array[nodeindex+1].getEscapeIndex();
}
SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
{
return m_node_array[nodeindex].getEscapeIndex();
}
SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE * get_node_pointer(int index = 0) const
{
return &m_node_array[index];
}
//!@}
};
//! Structure for containing Boxes
/*!
This class offers an structure for managing a box tree of primitives.
Requires a Primitive prototype (like btPrimitiveManagerBase )
*/
class btGImpactQuantizedBvh
{
protected:
btQuantizedBvhTree m_box_tree;
btPrimitiveManagerBase * m_primitive_manager;
protected:
//stackless refit
void refit();
public:
//! this constructor doesn't build the tree. you must call buildSet
btGImpactQuantizedBvh()
{
m_primitive_manager = NULL;
}
//! this constructor doesn't build the tree. you must call buildSet
btGImpactQuantizedBvh(btPrimitiveManagerBase * primitive_manager)
{
m_primitive_manager = primitive_manager;
}
SIMD_FORCE_INLINE btAABB getGlobalBox() const
{
btAABB totalbox;
getNodeBound(0, totalbox);
return totalbox;
}
SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase * primitive_manager)
{
m_primitive_manager = primitive_manager;
}
SIMD_FORCE_INLINE btPrimitiveManagerBase * getPrimitiveManager() const
{
return m_primitive_manager;
}
//! node manager prototype functions
///@{
//! this attemps to refit the box set.
SIMD_FORCE_INLINE void update()
{
refit();
}
//! this rebuild the entire set
void buildSet();
//! returns the indices of the primitives in the m_primitive_manager
bool boxQuery(const btAABB & box, btAlignedObjectArray<int> & collided_results) const;
//! returns the indices of the primitives in the m_primitive_manager
SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB & box,
const btTransform & transform, btAlignedObjectArray<int> & collided_results) const
{
btAABB transbox=box;
transbox.appy_transform(transform);
return boxQuery(transbox,collided_results);
}
//! returns the indices of the primitives in the m_primitive_manager
bool rayQuery(
const btVector3 & ray_dir,const btVector3 & ray_origin ,
btAlignedObjectArray<int> & collided_results) const;
//! tells if this set has hierarcht
SIMD_FORCE_INLINE bool hasHierarchy() const
{
return true;
}
//! tells if this set is a trimesh
SIMD_FORCE_INLINE bool isTrimesh() const
{
return m_primitive_manager->is_trimesh();
}
//! node count
SIMD_FORCE_INLINE int getNodeCount() const
{
return m_box_tree.getNodeCount();
}
//! tells if the node is a leaf
SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
{
return m_box_tree.isLeafNode(nodeindex);
}
SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
{
return m_box_tree.getNodeData(nodeindex);
}
SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const
{
m_box_tree.getNodeBound(nodeindex, bound);
}
SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound)
{
m_box_tree.setNodeBound(nodeindex, bound);
}
SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
{
return m_box_tree.getLeftNode(nodeindex);
}
SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
{
return m_box_tree.getRightNode(nodeindex);
}
SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
{
return m_box_tree.getEscapeNodeIndex(nodeindex);
}
SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex,btPrimitiveTriangle & triangle) const
{
m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex),triangle);
}
SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE * get_node_pointer(int index = 0) const
{
return m_box_tree.get_node_pointer(index);
}
#ifdef TRI_COLLISION_PROFILING
static float getAverageTreeCollisionTime();
#endif //TRI_COLLISION_PROFILING
static void find_collision(const btGImpactQuantizedBvh * boxset1, const btTransform & trans1,
const btGImpactQuantizedBvh * boxset2, const btTransform & trans2,
btPairSet & collision_pairs);
};
#endif // GIM_BOXPRUNING_H_INCLUDED

View File

@@ -1,238 +0,0 @@
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "btGImpactShape.h"
#include "btGImpactMassUtil.h"
#define CALC_EXACT_INERTIA 1
void btGImpactCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
lockChildShapes();
#ifdef CALC_EXACT_INERTIA
inertia.setValue(0.f,0.f,0.f);
int i = this->getNumChildShapes();
btScalar shapemass = mass/btScalar(i);
while(i--)
{
btVector3 temp_inertia;
m_childShapes[i]->calculateLocalInertia(shapemass,temp_inertia);
if(childrenHasTransform())
{
inertia = gim_inertia_add_transformed( inertia,temp_inertia,m_childTransforms[i]);
}
else
{
inertia = gim_inertia_add_transformed( inertia,temp_inertia,btTransform::getIdentity());
}
}
#else
// Calc box inertia
btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0];
btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1];
btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2];
const btScalar x2 = lx*lx;
const btScalar y2 = ly*ly;
const btScalar z2 = lz*lz;
const btScalar scaledmass = mass * btScalar(0.08333333);
inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
#endif
unlockChildShapes();
}
void btGImpactMeshShapePart::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
lockChildShapes();
#ifdef CALC_EXACT_INERTIA
inertia.setValue(0.f,0.f,0.f);
int i = this->getVertexCount();
btScalar pointmass = mass/btScalar(i);
while(i--)
{
btVector3 pointintertia;
this->getVertex(i,pointintertia);
pointintertia = gim_get_point_inertia(pointintertia,pointmass);
inertia+=pointintertia;
}
#else
// Calc box inertia
btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0];
btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1];
btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2];
const btScalar x2 = lx*lx;
const btScalar y2 = ly*ly;
const btScalar z2 = lz*lz;
const btScalar scaledmass = mass * btScalar(0.08333333);
inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
#endif
unlockChildShapes();
}
void btGImpactMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
#ifdef CALC_EXACT_INERTIA
inertia.setValue(0.f,0.f,0.f);
int i = this->getMeshPartCount();
btScalar partmass = mass/btScalar(i);
while(i--)
{
btVector3 partinertia;
getMeshPart(i)->calculateLocalInertia(partmass,partinertia);
inertia+=partinertia;
}
#else
// Calc box inertia
btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0];
btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1];
btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2];
const btScalar x2 = lx*lx;
const btScalar y2 = ly*ly;
const btScalar z2 = lz*lz;
const btScalar scaledmass = mass * btScalar(0.08333333);
inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
#endif
}
void btGImpactMeshShape::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const
{
}
void btGImpactMeshShapePart::processAllTrianglesRay(btTriangleCallback* callback,const btVector3& rayFrom, const btVector3& rayTo) const
{
lockChildShapes();
btAlignedObjectArray<int> collided;
btVector3 rayDir(rayTo - rayFrom);
rayDir.normalize();
m_box_set.rayQuery(rayDir, rayFrom, collided);
if(collided.size()==0)
{
unlockChildShapes();
return;
}
int part = (int)getPart();
btPrimitiveTriangle triangle;
int i = collided.size();
while(i--)
{
getPrimitiveTriangle(collided[i],triangle);
callback->processTriangle(triangle.m_vertices,part,collided[i]);
}
unlockChildShapes();
}
void btGImpactMeshShapePart::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
{
lockChildShapes();
btAABB box;
box.m_min = aabbMin;
box.m_max = aabbMax;
btAlignedObjectArray<int> collided;
m_box_set.boxQuery(box,collided);
if(collided.size()==0)
{
unlockChildShapes();
return;
}
int part = (int)getPart();
btPrimitiveTriangle triangle;
int i = collided.size();
while(i--)
{
this->getPrimitiveTriangle(collided[i],triangle);
callback->processTriangle(triangle.m_vertices,part,collided[i]);
}
unlockChildShapes();
}
void btGImpactMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
{
int i = m_mesh_parts.size();
while(i--)
{
m_mesh_parts[i]->processAllTriangles(callback,aabbMin,aabbMax);
}
}
void btGImpactMeshShape::processAllTrianglesRay(btTriangleCallback* callback,const btVector3& rayFrom, const btVector3& rayTo) const
{
int i = m_mesh_parts.size();
while(i--)
{
m_mesh_parts[i]->processAllTrianglesRay(callback, rayFrom, rayTo);
}
}
///fills the dataBuffer and returns the struct name (and 0 on failure)
const char* btGImpactMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
{
btGImpactMeshShapeData* trimeshData = (btGImpactMeshShapeData*) dataBuffer;
btCollisionShape::serialize(&trimeshData->m_collisionShapeData,serializer);
m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer);
trimeshData->m_collisionMargin = float(m_collisionMargin);
localScaling.serializeFloat(trimeshData->m_localScaling);
trimeshData->m_gimpactSubType = int(getGImpactShapeType());
return "btGImpactMeshShapeData";
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,283 +0,0 @@
/*! \file btGenericPoolAllocator.cpp
\author Francisco Leon Najera. email projectileman@yahoo.com
General purpose allocator class
*/
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "btGenericPoolAllocator.h"
/// *************** btGenericMemoryPool ******************///////////
size_t btGenericMemoryPool::allocate_from_free_nodes(size_t num_elements)
{
size_t ptr = BT_UINT_MAX;
if(m_free_nodes_count == 0) return BT_UINT_MAX;
// find an avaliable free node with the correct size
size_t revindex = m_free_nodes_count;
while(revindex-- && ptr == BT_UINT_MAX)
{
if(m_allocated_sizes[m_free_nodes[revindex]]>=num_elements)
{
ptr = revindex;
}
}
if(ptr == BT_UINT_MAX) return BT_UINT_MAX; // not found
revindex = ptr;
ptr = m_free_nodes[revindex];
// post: ptr contains the node index, and revindex the index in m_free_nodes
size_t finalsize = m_allocated_sizes[ptr];
finalsize -= num_elements;
m_allocated_sizes[ptr] = num_elements;
// post: finalsize>=0, m_allocated_sizes[ptr] has the requested size
if(finalsize>0) // preserve free node, there are some free memory
{
m_free_nodes[revindex] = ptr + num_elements;
m_allocated_sizes[ptr + num_elements] = finalsize;
}
else // delete free node
{
// swap with end
m_free_nodes[revindex] = m_free_nodes[m_free_nodes_count-1];
m_free_nodes_count--;
}
return ptr;
}
size_t btGenericMemoryPool::allocate_from_pool(size_t num_elements)
{
if(m_allocated_count+num_elements>m_max_element_count) return BT_UINT_MAX;
size_t ptr = m_allocated_count;
m_allocated_sizes[m_allocated_count] = num_elements;
m_allocated_count+=num_elements;
return ptr;
}
void btGenericMemoryPool::init_pool(size_t element_size, size_t element_count)
{
m_allocated_count = 0;
m_free_nodes_count = 0;
m_element_size = element_size;
m_max_element_count = element_count;
m_pool = (unsigned char *) btAlignedAlloc(m_element_size*m_max_element_count,16);
m_free_nodes = (size_t *) btAlignedAlloc(sizeof(size_t)*m_max_element_count,16);
m_allocated_sizes = (size_t *) btAlignedAlloc(sizeof(size_t)*m_max_element_count,16);
for (size_t i = 0;i< m_max_element_count;i++ )
{
m_allocated_sizes[i] = 0;
}
}
void btGenericMemoryPool::end_pool()
{
btAlignedFree(m_pool);
btAlignedFree(m_free_nodes);
btAlignedFree(m_allocated_sizes);
m_allocated_count = 0;
m_free_nodes_count = 0;
}
//! Allocates memory in pool
/*!
\param size_bytes size in bytes of the buffer
*/
void * btGenericMemoryPool::allocate(size_t size_bytes)
{
size_t module = size_bytes%m_element_size;
size_t element_count = size_bytes/m_element_size;
if(module>0) element_count++;
size_t alloc_pos = allocate_from_free_nodes(element_count);
// a free node is found
if(alloc_pos != BT_UINT_MAX)
{
return get_element_data(alloc_pos);
}
// allocate directly on pool
alloc_pos = allocate_from_pool(element_count);
if(alloc_pos == BT_UINT_MAX) return NULL; // not space
return get_element_data(alloc_pos);
}
bool btGenericMemoryPool::freeMemory(void * pointer)
{
unsigned char * pointer_pos = (unsigned char *)pointer;
unsigned char * pool_pos = (unsigned char *)m_pool;
// calc offset
if(pointer_pos<pool_pos) return false;//other pool
size_t offset = size_t(pointer_pos - pool_pos);
if(offset>=get_pool_capacity()) return false;// far away
// find free position
m_free_nodes[m_free_nodes_count] = offset/m_element_size;
m_free_nodes_count++;
return true;
}
/// *******************! btGenericPoolAllocator *******************!///
btGenericPoolAllocator::~btGenericPoolAllocator()
{
// destroy pools
size_t i;
for (i=0;i<m_pool_count;i++)
{
m_pools[i]->end_pool();
btAlignedFree(m_pools[i]);
}
}
// creates a pool
btGenericMemoryPool * btGenericPoolAllocator::push_new_pool()
{
if(m_pool_count >= BT_DEFAULT_MAX_POOLS) return NULL;
btGenericMemoryPool * newptr = (btGenericMemoryPool *)btAlignedAlloc(sizeof(btGenericMemoryPool),16);
m_pools[m_pool_count] = newptr;
m_pools[m_pool_count]->init_pool(m_pool_element_size,m_pool_element_count);
m_pool_count++;
return newptr;
}
void * btGenericPoolAllocator::failback_alloc(size_t size_bytes)
{
btGenericMemoryPool * pool = NULL;
if(size_bytes<=get_pool_capacity())
{
pool = push_new_pool();
}
if(pool==NULL) // failback
{
return btAlignedAlloc(size_bytes,16);
}
return pool->allocate(size_bytes);
}
bool btGenericPoolAllocator::failback_free(void * pointer)
{
btAlignedFree(pointer);
return true;
}
//! Allocates memory in pool
/*!
\param size_bytes size in bytes of the buffer
*/
void * btGenericPoolAllocator::allocate(size_t size_bytes)
{
void * ptr = NULL;
size_t i = 0;
while(i<m_pool_count && ptr == NULL)
{
ptr = m_pools[i]->allocate(size_bytes);
++i;
}
if(ptr) return ptr;
return failback_alloc(size_bytes);
}
bool btGenericPoolAllocator::freeMemory(void * pointer)
{
bool result = false;
size_t i = 0;
while(i<m_pool_count && result == false)
{
result = m_pools[i]->freeMemory(pointer);
++i;
}
if(result) return true;
return failback_free(pointer);
}
/// ************** STANDARD ALLOCATOR ***************************///
#define BT_DEFAULT_POOL_SIZE 32768
#define BT_DEFAULT_POOL_ELEMENT_SIZE 8
// main allocator
class GIM_STANDARD_ALLOCATOR: public btGenericPoolAllocator
{
public:
GIM_STANDARD_ALLOCATOR():btGenericPoolAllocator(BT_DEFAULT_POOL_ELEMENT_SIZE,BT_DEFAULT_POOL_SIZE)
{
}
};
// global allocator
GIM_STANDARD_ALLOCATOR g_main_allocator;
void * btPoolAlloc(size_t size)
{
return g_main_allocator.allocate(size);
}
void * btPoolRealloc(void *ptr, size_t oldsize, size_t newsize)
{
void * newptr = btPoolAlloc(newsize);
size_t copysize = oldsize<newsize?oldsize:newsize;
memcpy(newptr,ptr,copysize);
btPoolFree(ptr);
return newptr;
}
void btPoolFree(void *ptr)
{
g_main_allocator.freeMemory(ptr);
}

View File

@@ -1,163 +0,0 @@
/*! \file btGenericPoolAllocator.h
\author Francisco Leon Najera. email projectileman@yahoo.com
General purpose allocator class
*/
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_GENERIC_POOL_ALLOCATOR_H
#define BT_GENERIC_POOL_ALLOCATOR_H
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include "LinearMath/btAlignedAllocator.h"
#define BT_UINT_MAX UINT_MAX
#define BT_DEFAULT_MAX_POOLS 16
//! Generic Pool class
class btGenericMemoryPool
{
public:
unsigned char * m_pool; //[m_element_size*m_max_element_count];
size_t * m_free_nodes; //[m_max_element_count];//! free nodes
size_t * m_allocated_sizes;//[m_max_element_count];//! Number of elements allocated per node
size_t m_allocated_count;
size_t m_free_nodes_count;
protected:
size_t m_element_size;
size_t m_max_element_count;
size_t allocate_from_free_nodes(size_t num_elements);
size_t allocate_from_pool(size_t num_elements);
public:
void init_pool(size_t element_size, size_t element_count);
void end_pool();
btGenericMemoryPool(size_t element_size, size_t element_count)
{
init_pool(element_size, element_count);
}
~btGenericMemoryPool()
{
end_pool();
}
inline size_t get_pool_capacity()
{
return m_element_size*m_max_element_count;
}
inline size_t gem_element_size()
{
return m_element_size;
}
inline size_t get_max_element_count()
{
return m_max_element_count;
}
inline size_t get_allocated_count()
{
return m_allocated_count;
}
inline size_t get_free_positions_count()
{
return m_free_nodes_count;
}
inline void * get_element_data(size_t element_index)
{
return &m_pool[element_index*m_element_size];
}
//! Allocates memory in pool
/*!
\param size_bytes size in bytes of the buffer
*/
void * allocate(size_t size_bytes);
bool freeMemory(void * pointer);
};
//! Generic Allocator with pools
/*!
General purpose Allocator which can create Memory Pools dynamiacally as needed.
*/
class btGenericPoolAllocator
{
protected:
size_t m_pool_element_size;
size_t m_pool_element_count;
public:
btGenericMemoryPool * m_pools[BT_DEFAULT_MAX_POOLS];
size_t m_pool_count;
inline size_t get_pool_capacity()
{
return m_pool_element_size*m_pool_element_count;
}
protected:
// creates a pool
btGenericMemoryPool * push_new_pool();
void * failback_alloc(size_t size_bytes);
bool failback_free(void * pointer);
public:
btGenericPoolAllocator(size_t pool_element_size, size_t pool_element_count)
{
m_pool_count = 0;
m_pool_element_size = pool_element_size;
m_pool_element_count = pool_element_count;
}
virtual ~btGenericPoolAllocator();
//! Allocates memory in pool
/*!
\param size_bytes size in bytes of the buffer
*/
void * allocate(size_t size_bytes);
bool freeMemory(void * pointer);
};
void * btPoolAlloc(size_t size);
void * btPoolRealloc(void *ptr, size_t oldsize, size_t newsize);
void btPoolFree(void *ptr);
#endif

View File

@@ -1,212 +0,0 @@
#ifndef BT_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
#define BT_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
/*! \file btGeometryOperations.h
*\author Francisco Leon Najera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "btBoxCollision.h"
#define PLANEDIREPSILON 0.0000001f
#define PARALELENORMALS 0.000001f
#define BT_CLAMP(number,minval,maxval) (number<minval?minval:(number>maxval?maxval:number))
/// Calc a plane from a triangle edge an a normal. plane is a vec4f
SIMD_FORCE_INLINE void bt_edge_plane(const btVector3 & e1,const btVector3 & e2, const btVector3 & normal,btVector4 & plane)
{
btVector3 planenormal = (e2-e1).cross(normal);
planenormal.normalize();
plane.setValue(planenormal[0],planenormal[1],planenormal[2],e2.dot(planenormal));
}
//***************** SEGMENT and LINE FUNCTIONS **********************************///
/*! Finds the closest point(cp) to (v) on a segment (e1,e2)
*/
SIMD_FORCE_INLINE void bt_closest_point_on_segment(
btVector3 & cp, const btVector3 & v,
const btVector3 &e1,const btVector3 &e2)
{
btVector3 n = e2-e1;
cp = v - e1;
btScalar _scalar = cp.dot(n)/n.dot(n);
if(_scalar <0.0f)
{
cp = e1;
}
else if(_scalar >1.0f)
{
cp = e2;
}
else
{
cp = _scalar*n + e1;
}
}
//! line plane collision
/*!
*\return
-0 if the ray never intersects
-1 if the ray collides in front
-2 if the ray collides in back
*/
SIMD_FORCE_INLINE int bt_line_plane_collision(
const btVector4 & plane,
const btVector3 & vDir,
const btVector3 & vPoint,
btVector3 & pout,
btScalar &tparam,
btScalar tmin, btScalar tmax)
{
btScalar _dotdir = vDir.dot(plane);
if(btFabs(_dotdir)<PLANEDIREPSILON)
{
tparam = tmax;
return 0;
}
btScalar _dis = bt_distance_point_plane(plane,vPoint);
char returnvalue = _dis<0.0f? 2:1;
tparam = -_dis/_dotdir;
if(tparam<tmin)
{
returnvalue = 0;
tparam = tmin;
}
else if(tparam>tmax)
{
returnvalue = 0;
tparam = tmax;
}
pout = tparam*vDir + vPoint;
return returnvalue;
}
//! Find closest points on segments
SIMD_FORCE_INLINE void bt_segment_collision(
const btVector3 & vA1,
const btVector3 & vA2,
const btVector3 & vB1,
const btVector3 & vB2,
btVector3 & vPointA,
btVector3 & vPointB)
{
btVector3 AD = vA2 - vA1;
btVector3 BD = vB2 - vB1;
btVector3 N = AD.cross(BD);
btScalar tp = N.length2();
btVector4 _M;//plane
if(tp<SIMD_EPSILON)//ARE PARALELE
{
//project B over A
bool invert_b_order = false;
_M[0] = vB1.dot(AD);
_M[1] = vB2.dot(AD);
if(_M[0]>_M[1])
{
invert_b_order = true;
BT_SWAP_NUMBERS(_M[0],_M[1]);
}
_M[2] = vA1.dot(AD);
_M[3] = vA2.dot(AD);
//mid points
N[0] = (_M[0]+_M[1])*0.5f;
N[1] = (_M[2]+_M[3])*0.5f;
if(N[0]<N[1])
{
if(_M[1]<_M[2])
{
vPointB = invert_b_order?vB1:vB2;
vPointA = vA1;
}
else if(_M[1]<_M[3])
{
vPointB = invert_b_order?vB1:vB2;
bt_closest_point_on_segment(vPointA,vPointB,vA1,vA2);
}
else
{
vPointA = vA2;
bt_closest_point_on_segment(vPointB,vPointA,vB1,vB2);
}
}
else
{
if(_M[3]<_M[0])
{
vPointB = invert_b_order?vB2:vB1;
vPointA = vA2;
}
else if(_M[3]<_M[1])
{
vPointA = vA2;
bt_closest_point_on_segment(vPointB,vPointA,vB1,vB2);
}
else
{
vPointB = invert_b_order?vB1:vB2;
bt_closest_point_on_segment(vPointA,vPointB,vA1,vA2);
}
}
return;
}
N = N.cross(BD);
_M.setValue(N[0],N[1],N[2],vB1.dot(N));
// get point A as the plane collision point
bt_line_plane_collision(_M,AD,vA1,vPointA,tp,btScalar(0), btScalar(1));
/*Closest point on segment*/
vPointB = vPointA - vB1;
tp = vPointB.dot(BD);
tp/= BD.dot(BD);
tp = BT_CLAMP(tp,0.0f,1.0f);
vPointB = tp*BD + vB1;
}
#endif // GIM_VECTOR_H_INCLUDED

View File

@@ -1,88 +0,0 @@
#ifndef BT_GIMPACT_QUANTIZATION_H_INCLUDED
#define BT_GIMPACT_QUANTIZATION_H_INCLUDED
/*! \file btQuantization.h
*\author Francisco Leon Najera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "LinearMath/btTransform.h"
SIMD_FORCE_INLINE void bt_calc_quantization_parameters(
btVector3 & outMinBound,
btVector3 & outMaxBound,
btVector3 & bvhQuantization,
const btVector3& srcMinBound,const btVector3& srcMaxBound,
btScalar quantizationMargin)
{
//enlarge the AABB to avoid division by zero when initializing the quantization values
btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin);
outMinBound = srcMinBound - clampValue;
outMaxBound = srcMaxBound + clampValue;
btVector3 aabbSize = outMaxBound - outMinBound;
bvhQuantization = btVector3(btScalar(65535.0),
btScalar(65535.0),
btScalar(65535.0)) / aabbSize;
}
SIMD_FORCE_INLINE void bt_quantize_clamp(
unsigned short* out,
const btVector3& point,
const btVector3 & min_bound,
const btVector3 & max_bound,
const btVector3 & bvhQuantization)
{
btVector3 clampedPoint(point);
clampedPoint.setMax(min_bound);
clampedPoint.setMin(max_bound);
btVector3 v = (clampedPoint - min_bound) * bvhQuantization;
out[0] = (unsigned short)(v.getX()+0.5f);
out[1] = (unsigned short)(v.getY()+0.5f);
out[2] = (unsigned short)(v.getZ()+0.5f);
}
SIMD_FORCE_INLINE btVector3 bt_unquantize(
const unsigned short* vecIn,
const btVector3 & offset,
const btVector3 & bvhQuantization)
{
btVector3 vecOut;
vecOut.setValue(
(btScalar)(vecIn[0]) / (bvhQuantization.getX()),
(btScalar)(vecIn[1]) / (bvhQuantization.getY()),
(btScalar)(vecIn[2]) / (bvhQuantization.getZ()));
vecOut += offset;
return vecOut;
}
#endif // BT_GIMPACT_QUANTIZATION_H_INCLUDED

View File

@@ -1,218 +0,0 @@
/*! \file btGImpactTriangleShape.h
\author Francisco Leon Najera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "btTriangleShapeEx.h"
void GIM_TRIANGLE_CONTACT::merge_points(const btVector4 & plane,
btScalar margin, const btVector3 * points, int point_count)
{
m_point_count = 0;
m_penetration_depth= -1000.0f;
int point_indices[MAX_TRI_CLIPPING];
int _k;
for ( _k=0;_k<point_count;_k++)
{
btScalar _dist = - bt_distance_point_plane(plane,points[_k]) + margin;
if (_dist>=0.0f)
{
if (_dist>m_penetration_depth)
{
m_penetration_depth = _dist;
point_indices[0] = _k;
m_point_count=1;
}
else if ((_dist+SIMD_EPSILON)>=m_penetration_depth)
{
point_indices[m_point_count] = _k;
m_point_count++;
}
}
}
for ( _k=0;_k<m_point_count;_k++)
{
m_points[_k] = points[point_indices[_k]];
}
}
///class btPrimitiveTriangle
bool btPrimitiveTriangle::overlap_test_conservative(const btPrimitiveTriangle& other)
{
btScalar total_margin = m_margin + other.m_margin;
// classify points on other triangle
btScalar dis0 = bt_distance_point_plane(m_plane,other.m_vertices[0]) - total_margin;
btScalar dis1 = bt_distance_point_plane(m_plane,other.m_vertices[1]) - total_margin;
btScalar dis2 = bt_distance_point_plane(m_plane,other.m_vertices[2]) - total_margin;
if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false;
// classify points on this triangle
dis0 = bt_distance_point_plane(other.m_plane,m_vertices[0]) - total_margin;
dis1 = bt_distance_point_plane(other.m_plane,m_vertices[1]) - total_margin;
dis2 = bt_distance_point_plane(other.m_plane,m_vertices[2]) - total_margin;
if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false;
return true;
}
int btPrimitiveTriangle::clip_triangle(btPrimitiveTriangle & other, btVector3 * clipped_points )
{
// edge 0
btVector3 temp_points[MAX_TRI_CLIPPING];
btVector4 edgeplane;
get_edge_plane(0,edgeplane);
int clipped_count = bt_plane_clip_triangle(
edgeplane,other.m_vertices[0],other.m_vertices[1],other.m_vertices[2],temp_points);
if (clipped_count == 0) return 0;
btVector3 temp_points1[MAX_TRI_CLIPPING];
// edge 1
get_edge_plane(1,edgeplane);
clipped_count = bt_plane_clip_polygon(edgeplane,temp_points,clipped_count,temp_points1);
if (clipped_count == 0) return 0;
// edge 2
get_edge_plane(2,edgeplane);
clipped_count = bt_plane_clip_polygon(
edgeplane,temp_points1,clipped_count,clipped_points);
return clipped_count;
}
bool btPrimitiveTriangle::find_triangle_collision_clip_method(btPrimitiveTriangle & other, GIM_TRIANGLE_CONTACT & contacts)
{
btScalar margin = m_margin + other.m_margin;
btVector3 clipped_points[MAX_TRI_CLIPPING];
int clipped_count;
//create planes
// plane v vs U points
GIM_TRIANGLE_CONTACT contacts1;
contacts1.m_separating_normal = m_plane;
clipped_count = clip_triangle(other,clipped_points);
if (clipped_count == 0 )
{
return false;//Reject
}
//find most deep interval face1
contacts1.merge_points(contacts1.m_separating_normal,margin,clipped_points,clipped_count);
if (contacts1.m_point_count == 0) return false; // too far
//Normal pointing to this triangle
contacts1.m_separating_normal *= -1.f;
//Clip tri1 by tri2 edges
GIM_TRIANGLE_CONTACT contacts2;
contacts2.m_separating_normal = other.m_plane;
clipped_count = other.clip_triangle(*this,clipped_points);
if (clipped_count == 0 )
{
return false;//Reject
}
//find most deep interval face1
contacts2.merge_points(contacts2.m_separating_normal,margin,clipped_points,clipped_count);
if (contacts2.m_point_count == 0) return false; // too far
////check most dir for contacts
if (contacts2.m_penetration_depth<contacts1.m_penetration_depth)
{
contacts.copy_from(contacts2);
}
else
{
contacts.copy_from(contacts1);
}
return true;
}
///class btTriangleShapeEx: public btTriangleShape
bool btTriangleShapeEx::overlap_test_conservative(const btTriangleShapeEx& other)
{
btScalar total_margin = getMargin() + other.getMargin();
btVector4 plane0;
buildTriPlane(plane0);
btVector4 plane1;
other.buildTriPlane(plane1);
// classify points on other triangle
btScalar dis0 = bt_distance_point_plane(plane0,other.m_vertices1[0]) - total_margin;
btScalar dis1 = bt_distance_point_plane(plane0,other.m_vertices1[1]) - total_margin;
btScalar dis2 = bt_distance_point_plane(plane0,other.m_vertices1[2]) - total_margin;
if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false;
// classify points on this triangle
dis0 = bt_distance_point_plane(plane1,m_vertices1[0]) - total_margin;
dis1 = bt_distance_point_plane(plane1,m_vertices1[1]) - total_margin;
dis2 = bt_distance_point_plane(plane1,m_vertices1[2]) - total_margin;
if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false;
return true;
}

View File

@@ -1,180 +0,0 @@
/*! \file btGImpactShape.h
\author Francisco Leon Najera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef GIMPACT_TRIANGLE_SHAPE_EX_H
#define GIMPACT_TRIANGLE_SHAPE_EX_H
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "BulletCollision/CollisionShapes/btTriangleShape.h"
#include "btBoxCollision.h"
#include "btClipPolygon.h"
#include "btGeometryOperations.h"
#define MAX_TRI_CLIPPING 16
//! Structure for collision
struct GIM_TRIANGLE_CONTACT
{
btScalar m_penetration_depth;
int m_point_count;
btVector4 m_separating_normal;
btVector3 m_points[MAX_TRI_CLIPPING];
SIMD_FORCE_INLINE void copy_from(const GIM_TRIANGLE_CONTACT& other)
{
m_penetration_depth = other.m_penetration_depth;
m_separating_normal = other.m_separating_normal;
m_point_count = other.m_point_count;
int i = m_point_count;
while(i--)
{
m_points[i] = other.m_points[i];
}
}
GIM_TRIANGLE_CONTACT()
{
}
GIM_TRIANGLE_CONTACT(const GIM_TRIANGLE_CONTACT& other)
{
copy_from(other);
}
//! classify points that are closer
void merge_points(const btVector4 & plane,
btScalar margin, const btVector3 * points, int point_count);
};
class btPrimitiveTriangle
{
public:
btVector3 m_vertices[3];
btVector4 m_plane;
btScalar m_margin;
btScalar m_dummy;
btPrimitiveTriangle():m_margin(0.01f)
{
}
SIMD_FORCE_INLINE void buildTriPlane()
{
btVector3 normal = (m_vertices[1]-m_vertices[0]).cross(m_vertices[2]-m_vertices[0]);
normal.normalize();
m_plane.setValue(normal[0],normal[1],normal[2],m_vertices[0].dot(normal));
}
//! Test if triangles could collide
bool overlap_test_conservative(const btPrimitiveTriangle& other);
//! Calcs the plane which is paralele to the edge and perpendicular to the triangle plane
/*!
\pre this triangle must have its plane calculated.
*/
SIMD_FORCE_INLINE void get_edge_plane(int edge_index, btVector4 &plane) const
{
const btVector3 & e0 = m_vertices[edge_index];
const btVector3 & e1 = m_vertices[(edge_index+1)%3];
bt_edge_plane(e0,e1,m_plane,plane);
}
void applyTransform(const btTransform& t)
{
m_vertices[0] = t(m_vertices[0]);
m_vertices[1] = t(m_vertices[1]);
m_vertices[2] = t(m_vertices[2]);
}
//! Clips the triangle against this
/*!
\pre clipped_points must have MAX_TRI_CLIPPING size, and this triangle must have its plane calculated.
\return the number of clipped points
*/
int clip_triangle(btPrimitiveTriangle & other, btVector3 * clipped_points );
//! Find collision using the clipping method
/*!
\pre this triangle and other must have their triangles calculated
*/
bool find_triangle_collision_clip_method(btPrimitiveTriangle & other, GIM_TRIANGLE_CONTACT & contacts);
};
//! Helper class for colliding Bullet Triangle Shapes
/*!
This class implements a better getAabb method than the previous btTriangleShape class
*/
class btTriangleShapeEx: public btTriangleShape
{
public:
btTriangleShapeEx():btTriangleShape(btVector3(0,0,0),btVector3(0,0,0),btVector3(0,0,0))
{
}
btTriangleShapeEx(const btVector3& p0,const btVector3& p1,const btVector3& p2): btTriangleShape(p0,p1,p2)
{
}
btTriangleShapeEx(const btTriangleShapeEx & other): btTriangleShape(other.m_vertices1[0],other.m_vertices1[1],other.m_vertices1[2])
{
}
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax)const
{
btVector3 tv0 = t(m_vertices1[0]);
btVector3 tv1 = t(m_vertices1[1]);
btVector3 tv2 = t(m_vertices1[2]);
btAABB trianglebox(tv0,tv1,tv2,m_collisionMargin);
aabbMin = trianglebox.m_min;
aabbMax = trianglebox.m_max;
}
void applyTransform(const btTransform& t)
{
m_vertices1[0] = t(m_vertices1[0]);
m_vertices1[1] = t(m_vertices1[1]);
m_vertices1[2] = t(m_vertices1[2]);
}
SIMD_FORCE_INLINE void buildTriPlane(btVector4 & plane) const
{
btVector3 normal = (m_vertices1[1]-m_vertices1[0]).cross(m_vertices1[2]-m_vertices1[0]);
normal.normalize();
plane.setValue(normal[0],normal[1],normal[2],m_vertices1[0].dot(normal));
}
bool overlap_test_conservative(const btTriangleShapeEx& other);
};
#endif //GIMPACT_TRIANGLE_MESH_SHAPE_H

View File

@@ -1,324 +0,0 @@
#ifndef GIM_ARRAY_H_INCLUDED
#define GIM_ARRAY_H_INCLUDED
/*! \file gim_array.h
\author Francisco Leon Najera
*/
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This library is free software; you can redistribute it and/or
modify it under the terms of EITHER:
(1) The GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at
your option) any later version. The text of the GNU Lesser
General Public License is included with this library in the
file GIMPACT-LICENSE-LGPL.TXT.
(2) The BSD-style license that is included with this library in
the file GIMPACT-LICENSE-BSD.TXT.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.TXT.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "gim_memory.h"
#define GIM_ARRAY_GROW_INCREMENT 2
#define GIM_ARRAY_GROW_FACTOR 2
//! Very simple array container with fast access and simd memory
template<typename T>
class gim_array
{
public:
//! properties
//!@{
T *m_data;
GUINT m_size;
GUINT m_allocated_size;
//!@}
//! protected operations
//!@{
inline void destroyData()
{
m_allocated_size = 0;
if(m_data==NULL) return;
gim_free(m_data);
m_data = NULL;
}
inline bool resizeData(GUINT newsize)
{
if(newsize==0)
{
destroyData();
return true;
}
if(m_size>0)
{
m_data = (T*)gim_realloc(m_data,m_size*sizeof(T),newsize*sizeof(T));
}
else
{
m_data = (T*)gim_alloc(newsize*sizeof(T));
}
m_allocated_size = newsize;
return true;
}
inline bool growingCheck()
{
if(m_allocated_size<=m_size)
{
GUINT requestsize = m_size;
m_size = m_allocated_size;
if(resizeData((requestsize+GIM_ARRAY_GROW_INCREMENT)*GIM_ARRAY_GROW_FACTOR)==false) return false;
}
return true;
}
//!@}
//! public operations
//!@{
inline bool reserve(GUINT size)
{
if(m_allocated_size>=size) return false;
return resizeData(size);
}
inline void clear_range(GUINT start_range)
{
while(m_size>start_range)
{
m_data[--m_size].~T();
}
}
inline void clear()
{
if(m_size==0)return;
clear_range(0);
}
inline void clear_memory()
{
clear();
destroyData();
}
gim_array()
{
m_data = 0;
m_size = 0;
m_allocated_size = 0;
}
gim_array(GUINT reservesize)
{
m_data = 0;
m_size = 0;
m_allocated_size = 0;
reserve(reservesize);
}
~gim_array()
{
clear_memory();
}
inline GUINT size() const
{
return m_size;
}
inline GUINT max_size() const
{
return m_allocated_size;
}
inline T & operator[](size_t i)
{
return m_data[i];
}
inline const T & operator[](size_t i) const
{
return m_data[i];
}
inline T * pointer(){ return m_data;}
inline const T * pointer() const
{ return m_data;}
inline T * get_pointer_at(GUINT i)
{
return m_data + i;
}
inline const T * get_pointer_at(GUINT i) const
{
return m_data + i;
}
inline T & at(GUINT i)
{
return m_data[i];
}
inline const T & at(GUINT i) const
{
return m_data[i];
}
inline T & front()
{
return *m_data;
}
inline const T & front() const
{
return *m_data;
}
inline T & back()
{
return m_data[m_size-1];
}
inline const T & back() const
{
return m_data[m_size-1];
}
inline void swap(GUINT i, GUINT j)
{
gim_swap_elements(m_data,i,j);
}
inline void push_back(const T & obj)
{
this->growingCheck();
m_data[m_size] = obj;
m_size++;
}
//!Simply increase the m_size, doesn't call the new element constructor
inline void push_back_mem()
{
this->growingCheck();
m_size++;
}
inline void push_back_memcpy(const T & obj)
{
this->growingCheck();
irr_simd_memcpy(&m_data[m_size],&obj,sizeof(T));
m_size++;
}
inline void pop_back()
{
m_size--;
m_data[m_size].~T();
}
//!Simply decrease the m_size, doesn't call the deleted element destructor
inline void pop_back_mem()
{
m_size--;
}
//! fast erase
inline void erase(GUINT index)
{
if(index<m_size-1)
{
swap(index,m_size-1);
}
pop_back();
}
inline void erase_sorted_mem(GUINT index)
{
m_size--;
for(GUINT i = index;i<m_size;i++)
{
gim_simd_memcpy(m_data+i,m_data+i+1,sizeof(T));
}
}
inline void erase_sorted(GUINT index)
{
m_data[index].~T();
erase_sorted_mem(index);
}
inline void insert_mem(GUINT index)
{
this->growingCheck();
for(GUINT i = m_size;i>index;i--)
{
gim_simd_memcpy(m_data+i,m_data+i-1,sizeof(T));
}
m_size++;
}
inline void insert(const T & obj,GUINT index)
{
insert_mem(index);
m_data[index] = obj;
}
inline void resize(GUINT size, bool call_constructor = true, const T& fillData=T())
{
if(size>m_size)
{
reserve(size);
if(call_constructor)
{
while(m_size<size)
{
m_data[m_size] = fillData;
m_size++;
}
}
else
{
m_size = size;
}
}
else if(size<m_size)
{
if(call_constructor) clear_range(size);
m_size = size;
}
}
inline void refit()
{
resizeData(m_size);
}
};
#endif // GIM_CONTAINERS_H_INCLUDED

View File

@@ -1,543 +0,0 @@
#ifndef GIM_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
#define GIM_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
/*! \file gim_basic_geometry_operations.h
*\author Francisco Leon Najera
type independant geometry routines
*/
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This library is free software; you can redistribute it and/or
modify it under the terms of EITHER:
(1) The GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at
your option) any later version. The text of the GNU Lesser
General Public License is included with this library in the
file GIMPACT-LICENSE-LGPL.TXT.
(2) The BSD-style license that is included with this library in
the file GIMPACT-LICENSE-BSD.TXT.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.TXT.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "gim_linear_math.h"
#define PLANEDIREPSILON 0.0000001f
#define PARALELENORMALS 0.000001f
#define TRIANGLE_NORMAL(v1,v2,v3,n)\
{\
vec3f _dif1,_dif2;\
VEC_DIFF(_dif1,v2,v1);\
VEC_DIFF(_dif2,v3,v1);\
VEC_CROSS(n,_dif1,_dif2);\
VEC_NORMALIZE(n);\
}\
#define TRIANGLE_NORMAL_FAST(v1,v2,v3,n){\
vec3f _dif1,_dif2; \
VEC_DIFF(_dif1,v2,v1); \
VEC_DIFF(_dif2,v3,v1); \
VEC_CROSS(n,_dif1,_dif2); \
}\
/// plane is a vec4f
#define TRIANGLE_PLANE(v1,v2,v3,plane) {\
TRIANGLE_NORMAL(v1,v2,v3,plane);\
plane[3] = VEC_DOT(v1,plane);\
}\
/// plane is a vec4f
#define TRIANGLE_PLANE_FAST(v1,v2,v3,plane) {\
TRIANGLE_NORMAL_FAST(v1,v2,v3,plane);\
plane[3] = VEC_DOT(v1,plane);\
}\
/// Calc a plane from an edge an a normal. plane is a vec4f
#define EDGE_PLANE(e1,e2,n,plane) {\
vec3f _dif; \
VEC_DIFF(_dif,e2,e1); \
VEC_CROSS(plane,_dif,n); \
VEC_NORMALIZE(plane); \
plane[3] = VEC_DOT(e1,plane);\
}\
#define DISTANCE_PLANE_POINT(plane,point) (VEC_DOT(plane,point) - plane[3])
#define PROJECT_POINT_PLANE(point,plane,projected) {\
GREAL _dis;\
_dis = DISTANCE_PLANE_POINT(plane,point);\
VEC_SCALE(projected,-_dis,plane);\
VEC_SUM(projected,projected,point); \
}\
//! Verifies if a point is in the plane hull
template<typename CLASS_POINT,typename CLASS_PLANE>
SIMD_FORCE_INLINE bool POINT_IN_HULL(
const CLASS_POINT& point,const CLASS_PLANE * planes,GUINT plane_count)
{
GREAL _dis;
for (GUINT _i = 0;_i< plane_count;++_i)
{
_dis = DISTANCE_PLANE_POINT(planes[_i],point);
if(_dis>0.0f) return false;
}
return true;
}
template<typename CLASS_POINT,typename CLASS_PLANE>
SIMD_FORCE_INLINE void PLANE_CLIP_SEGMENT(
const CLASS_POINT& s1,
const CLASS_POINT &s2,const CLASS_PLANE &plane,CLASS_POINT &clipped)
{
GREAL _dis1,_dis2;
_dis1 = DISTANCE_PLANE_POINT(plane,s1);
VEC_DIFF(clipped,s2,s1);
_dis2 = VEC_DOT(clipped,plane);
VEC_SCALE(clipped,-_dis1/_dis2,clipped);
VEC_SUM(clipped,clipped,s1);
}
enum ePLANE_INTERSECTION_TYPE
{
G_BACK_PLANE = 0,
G_COLLIDE_PLANE,
G_FRONT_PLANE
};
enum eLINE_PLANE_INTERSECTION_TYPE
{
G_FRONT_PLANE_S1 = 0,
G_FRONT_PLANE_S2,
G_BACK_PLANE_S1,
G_BACK_PLANE_S2,
G_COLLIDE_PLANE_S1,
G_COLLIDE_PLANE_S2
};
//! Confirms if the plane intersect the edge or nor
/*!
intersection type must have the following values
<ul>
<li> 0 : Segment in front of plane, s1 closest
<li> 1 : Segment in front of plane, s2 closest
<li> 2 : Segment in back of plane, s1 closest
<li> 3 : Segment in back of plane, s2 closest
<li> 4 : Segment collides plane, s1 in back
<li> 5 : Segment collides plane, s2 in back
</ul>
*/
template<typename CLASS_POINT,typename CLASS_PLANE>
SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT2(
const CLASS_POINT& s1,
const CLASS_POINT &s2,
const CLASS_PLANE &plane,CLASS_POINT &clipped)
{
GREAL _dis1 = DISTANCE_PLANE_POINT(plane,s1);
GREAL _dis2 = DISTANCE_PLANE_POINT(plane,s2);
if(_dis1 >-G_EPSILON && _dis2 >-G_EPSILON)
{
if(_dis1<_dis2) return G_FRONT_PLANE_S1;
return G_FRONT_PLANE_S2;
}
else if(_dis1 <G_EPSILON && _dis2 <G_EPSILON)
{
if(_dis1>_dis2) return G_BACK_PLANE_S1;
return G_BACK_PLANE_S2;
}
VEC_DIFF(clipped,s2,s1);
_dis2 = VEC_DOT(clipped,plane);
VEC_SCALE(clipped,-_dis1/_dis2,clipped);
VEC_SUM(clipped,clipped,s1);
if(_dis1<_dis2) return G_COLLIDE_PLANE_S1;
return G_COLLIDE_PLANE_S2;
}
//! Confirms if the plane intersect the edge or not
/*!
clipped1 and clipped2 are the vertices behind the plane.
clipped1 is the closest
intersection_type must have the following values
<ul>
<li> 0 : Segment in front of plane, s1 closest
<li> 1 : Segment in front of plane, s2 closest
<li> 2 : Segment in back of plane, s1 closest
<li> 3 : Segment in back of plane, s2 closest
<li> 4 : Segment collides plane, s1 in back
<li> 5 : Segment collides plane, s2 in back
</ul>
*/
template<typename CLASS_POINT,typename CLASS_PLANE>
SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT_CLOSEST(
const CLASS_POINT& s1,
const CLASS_POINT &s2,
const CLASS_PLANE &plane,
CLASS_POINT &clipped1,CLASS_POINT &clipped2)
{
eLINE_PLANE_INTERSECTION_TYPE intersection_type = PLANE_CLIP_SEGMENT2(s1,s2,plane,clipped1);
switch(intersection_type)
{
case G_FRONT_PLANE_S1:
VEC_COPY(clipped1,s1);
VEC_COPY(clipped2,s2);
break;
case G_FRONT_PLANE_S2:
VEC_COPY(clipped1,s2);
VEC_COPY(clipped2,s1);
break;
case G_BACK_PLANE_S1:
VEC_COPY(clipped1,s1);
VEC_COPY(clipped2,s2);
break;
case G_BACK_PLANE_S2:
VEC_COPY(clipped1,s2);
VEC_COPY(clipped2,s1);
break;
case G_COLLIDE_PLANE_S1:
VEC_COPY(clipped2,s1);
break;
case G_COLLIDE_PLANE_S2:
VEC_COPY(clipped2,s2);
break;
}
return intersection_type;
}
//! Finds the 2 smallest cartesian coordinates of a plane normal
#define PLANE_MINOR_AXES(plane, i0, i1) VEC_MINOR_AXES(plane, i0, i1)
//! Ray plane collision in one way
/*!
Intersects plane in one way only. The ray must face the plane (normals must be in opossite directions).<br/>
It uses the PLANEDIREPSILON constant.
*/
template<typename T,typename CLASS_POINT,typename CLASS_PLANE>
SIMD_FORCE_INLINE bool RAY_PLANE_COLLISION(
const CLASS_PLANE & plane,
const CLASS_POINT & vDir,
const CLASS_POINT & vPoint,
CLASS_POINT & pout,T &tparam)
{
GREAL _dis,_dotdir;
_dotdir = VEC_DOT(plane,vDir);
if(_dotdir<PLANEDIREPSILON)
{
return false;
}
_dis = DISTANCE_PLANE_POINT(plane,vPoint);
tparam = -_dis/_dotdir;
VEC_SCALE(pout,tparam,vDir);
VEC_SUM(pout,vPoint,pout);
return true;
}
//! line collision
/*!
*\return
-0 if the ray never intersects
-1 if the ray collides in front
-2 if the ray collides in back
*/
template<typename T,typename CLASS_POINT,typename CLASS_PLANE>
SIMD_FORCE_INLINE GUINT LINE_PLANE_COLLISION(
const CLASS_PLANE & plane,
const CLASS_POINT & vDir,
const CLASS_POINT & vPoint,
CLASS_POINT & pout,
T &tparam,
T tmin, T tmax)
{
GREAL _dis,_dotdir;
_dotdir = VEC_DOT(plane,vDir);
if(btFabs(_dotdir)<PLANEDIREPSILON)
{
tparam = tmax;
return 0;
}
_dis = DISTANCE_PLANE_POINT(plane,vPoint);
char returnvalue = _dis<0.0f?2:1;
tparam = -_dis/_dotdir;
if(tparam<tmin)
{
returnvalue = 0;
tparam = tmin;
}
else if(tparam>tmax)
{
returnvalue = 0;
tparam = tmax;
}
VEC_SCALE(pout,tparam,vDir);
VEC_SUM(pout,vPoint,pout);
return returnvalue;
}
/*! \brief Returns the Ray on which 2 planes intersect if they do.
Written by Rodrigo Hernandez on ODE convex collision
\param p1 Plane 1
\param p2 Plane 2
\param p Contains the origin of the ray upon returning if planes intersect
\param d Contains the direction of the ray upon returning if planes intersect
\return true if the planes intersect, 0 if paralell.
*/
template<typename CLASS_POINT,typename CLASS_PLANE>
SIMD_FORCE_INLINE bool INTERSECT_PLANES(
const CLASS_PLANE &p1,
const CLASS_PLANE &p2,
CLASS_POINT &p,
CLASS_POINT &d)
{
VEC_CROSS(d,p1,p2);
GREAL denom = VEC_DOT(d, d);
if(GIM_IS_ZERO(denom)) return false;
vec3f _n;
_n[0]=p1[3]*p2[0] - p2[3]*p1[0];
_n[1]=p1[3]*p2[1] - p2[3]*p1[1];
_n[2]=p1[3]*p2[2] - p2[3]*p1[2];
VEC_CROSS(p,_n,d);
p[0]/=denom;
p[1]/=denom;
p[2]/=denom;
return true;
}
//***************** SEGMENT and LINE FUNCTIONS **********************************///
/*! Finds the closest point(cp) to (v) on a segment (e1,e2)
*/
template<typename CLASS_POINT>
SIMD_FORCE_INLINE void CLOSEST_POINT_ON_SEGMENT(
CLASS_POINT & cp, const CLASS_POINT & v,
const CLASS_POINT &e1,const CLASS_POINT &e2)
{
vec3f _n;
VEC_DIFF(_n,e2,e1);
VEC_DIFF(cp,v,e1);
GREAL _scalar = VEC_DOT(cp, _n);
_scalar/= VEC_DOT(_n, _n);
if(_scalar <0.0f)
{
VEC_COPY(cp,e1);
}
else if(_scalar >1.0f)
{
VEC_COPY(cp,e2);
}
else
{
VEC_SCALE(cp,_scalar,_n);
VEC_SUM(cp,cp,e1);
}
}
/*! \brief Finds the line params where these lines intersect.
\param dir1 Direction of line 1
\param point1 Point of line 1
\param dir2 Direction of line 2
\param point2 Point of line 2
\param t1 Result Parameter for line 1
\param t2 Result Parameter for line 2
\param dointersect 0 if the lines won't intersect, else 1
*/
template<typename T,typename CLASS_POINT>
SIMD_FORCE_INLINE bool LINE_INTERSECTION_PARAMS(
const CLASS_POINT & dir1,
CLASS_POINT & point1,
const CLASS_POINT & dir2,
CLASS_POINT & point2,
T& t1,T& t2)
{
GREAL det;
GREAL e1e1 = VEC_DOT(dir1,dir1);
GREAL e1e2 = VEC_DOT(dir1,dir2);
GREAL e2e2 = VEC_DOT(dir2,dir2);
vec3f p1p2;
VEC_DIFF(p1p2,point1,point2);
GREAL p1p2e1 = VEC_DOT(p1p2,dir1);
GREAL p1p2e2 = VEC_DOT(p1p2,dir2);
det = e1e2*e1e2 - e1e1*e2e2;
if(GIM_IS_ZERO(det)) return false;
t1 = (e1e2*p1p2e2 - e2e2*p1p2e1)/det;
t2 = (e1e1*p1p2e2 - e1e2*p1p2e1)/det;
return true;
}
//! Find closest points on segments
template<typename CLASS_POINT>
SIMD_FORCE_INLINE void SEGMENT_COLLISION(
const CLASS_POINT & vA1,
const CLASS_POINT & vA2,
const CLASS_POINT & vB1,
const CLASS_POINT & vB2,
CLASS_POINT & vPointA,
CLASS_POINT & vPointB)
{
CLASS_POINT _AD,_BD,_N;
vec4f _M;//plane
VEC_DIFF(_AD,vA2,vA1);
VEC_DIFF(_BD,vB2,vB1);
VEC_CROSS(_N,_AD,_BD);
GREAL _tp = VEC_DOT(_N,_N);
if(_tp<G_EPSILON)//ARE PARALELE
{
//project B over A
bool invert_b_order = false;
_M[0] = VEC_DOT(vB1,_AD);
_M[1] = VEC_DOT(vB2,_AD);
if(_M[0]>_M[1])
{
invert_b_order = true;
GIM_SWAP_NUMBERS(_M[0],_M[1]);
}
_M[2] = VEC_DOT(vA1,_AD);
_M[3] = VEC_DOT(vA2,_AD);
//mid points
_N[0] = (_M[0]+_M[1])*0.5f;
_N[1] = (_M[2]+_M[3])*0.5f;
if(_N[0]<_N[1])
{
if(_M[1]<_M[2])
{
vPointB = invert_b_order?vB1:vB2;
vPointA = vA1;
}
else if(_M[1]<_M[3])
{
vPointB = invert_b_order?vB1:vB2;
CLOSEST_POINT_ON_SEGMENT(vPointA,vPointB,vA1,vA2);
}
else
{
vPointA = vA2;
CLOSEST_POINT_ON_SEGMENT(vPointB,vPointA,vB1,vB2);
}
}
else
{
if(_M[3]<_M[0])
{
vPointB = invert_b_order?vB2:vB1;
vPointA = vA2;
}
else if(_M[3]<_M[1])
{
vPointA = vA2;
CLOSEST_POINT_ON_SEGMENT(vPointB,vPointA,vB1,vB2);
}
else
{
vPointB = invert_b_order?vB1:vB2;
CLOSEST_POINT_ON_SEGMENT(vPointA,vPointB,vA1,vA2);
}
}
return;
}
VEC_CROSS(_M,_N,_BD);
_M[3] = VEC_DOT(_M,vB1);
LINE_PLANE_COLLISION(_M,_AD,vA1,vPointA,_tp,btScalar(0), btScalar(1));
/*Closest point on segment*/
VEC_DIFF(vPointB,vPointA,vB1);
_tp = VEC_DOT(vPointB, _BD);
_tp/= VEC_DOT(_BD, _BD);
_tp = GIM_CLAMP(_tp,0.0f,1.0f);
VEC_SCALE(vPointB,_tp,_BD);
VEC_SUM(vPointB,vPointB,vB1);
}
//! Line box intersection in one dimension
/*!
*\param pos Position of the ray
*\param dir Projection of the Direction of the ray
*\param bmin Minimum bound of the box
*\param bmax Maximum bound of the box
*\param tfirst the minimum projection. Assign to 0 at first.
*\param tlast the maximum projection. Assign to INFINITY at first.
*\return true if there is an intersection.
*/
template<typename T>
SIMD_FORCE_INLINE bool BOX_AXIS_INTERSECT(T pos, T dir,T bmin, T bmax, T & tfirst, T & tlast)
{
if(GIM_IS_ZERO(dir))
{
return !(pos < bmin || pos > bmax);
}
GREAL a0 = (bmin - pos) / dir;
GREAL a1 = (bmax - pos) / dir;
if(a0 > a1) GIM_SWAP_NUMBERS(a0, a1);
tfirst = GIM_MAX(a0, tfirst);
tlast = GIM_MIN(a1, tlast);
if (tlast < tfirst) return false;
return true;
}
//! Sorts 3 componets
template<typename T>
SIMD_FORCE_INLINE void SORT_3_INDICES(
const T * values,
GUINT * order_indices)
{
//get minimum
order_indices[0] = values[0] < values[1] ? (values[0] < values[2] ? 0 : 2) : (values[1] < values[2] ? 1 : 2);
//get second and third
GUINT i0 = (order_indices[0] + 1)%3;
GUINT i1 = (i0 + 1)%3;
if(values[i0] < values[i1])
{
order_indices[1] = i0;
order_indices[2] = i1;
}
else
{
order_indices[1] = i1;
order_indices[2] = i0;
}
}
#endif // GIM_VECTOR_H_INCLUDED

View File

@@ -1,123 +0,0 @@
#ifndef GIM_BITSET_H_INCLUDED
#define GIM_BITSET_H_INCLUDED
/*! \file gim_bitset.h
\author Francisco Leon Najera
*/
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This library is free software; you can redistribute it and/or
modify it under the terms of EITHER:
(1) The GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at
your option) any later version. The text of the GNU Lesser
General Public License is included with this library in the
file GIMPACT-LICENSE-LGPL.TXT.
(2) The BSD-style license that is included with this library in
the file GIMPACT-LICENSE-BSD.TXT.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.TXT.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "gim_array.h"
#define GUINT_BIT_COUNT 32
#define GUINT_EXPONENT 5
class gim_bitset
{
public:
gim_array<GUINT> m_container;
gim_bitset()
{
}
gim_bitset(GUINT bits_count)
{
resize(bits_count);
}
~gim_bitset()
{
}
inline bool resize(GUINT newsize)
{
GUINT oldsize = m_container.size();
m_container.resize(newsize/GUINT_BIT_COUNT + 1,false);
while(oldsize<m_container.size())
{
m_container[oldsize] = 0;
}
return true;
}
inline GUINT size()
{
return m_container.size()*GUINT_BIT_COUNT;
}
inline void set_all()
{
for(GUINT i = 0;i<m_container.size();++i)
{
m_container[i] = 0xffffffff;
}
}
inline void clear_all()
{
for(GUINT i = 0;i<m_container.size();++i)
{
m_container[i] = 0;
}
}
inline void set(GUINT bit_index)
{
if(bit_index>=size())
{
resize(bit_index);
}
m_container[bit_index >> GUINT_EXPONENT] |= (1 << (bit_index & (GUINT_BIT_COUNT-1)));
}
///Return 0 or 1
inline char get(GUINT bit_index)
{
if(bit_index>=size())
{
return 0;
}
char value = m_container[bit_index >> GUINT_EXPONENT] &
(1 << (bit_index & (GUINT_BIT_COUNT-1)));
return value;
}
inline void clear(GUINT bit_index)
{
m_container[bit_index >> GUINT_EXPONENT] &= ~(1 << (bit_index & (GUINT_BIT_COUNT-1)));
}
};
#endif // GIM_CONTAINERS_H_INCLUDED

View File

@@ -1,588 +0,0 @@
#ifndef GIM_BOX_COLLISION_H_INCLUDED
#define GIM_BOX_COLLISION_H_INCLUDED
/*! \file gim_box_collision.h
\author Francisco Leon Najera
*/
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This library is free software; you can redistribute it and/or
modify it under the terms of EITHER:
(1) The GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at
your option) any later version. The text of the GNU Lesser
General Public License is included with this library in the
file GIMPACT-LICENSE-LGPL.TXT.
(2) The BSD-style license that is included with this library in
the file GIMPACT-LICENSE-BSD.TXT.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.TXT.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "gim_basic_geometry_operations.h"
#include "LinearMath/btTransform.h"
//SIMD_FORCE_INLINE bool test_cross_edge_box(
// const btVector3 & edge,
// const btVector3 & absolute_edge,
// const btVector3 & pointa,
// const btVector3 & pointb, const btVector3 & extend,
// int dir_index0,
// int dir_index1
// int component_index0,
// int component_index1)
//{
// // dir coords are -z and y
//
// const btScalar dir0 = -edge[dir_index0];
// const btScalar dir1 = edge[dir_index1];
// btScalar pmin = pointa[component_index0]*dir0 + pointa[component_index1]*dir1;
// btScalar pmax = pointb[component_index0]*dir0 + pointb[component_index1]*dir1;
// //find minmax
// if(pmin>pmax)
// {
// GIM_SWAP_NUMBERS(pmin,pmax);
// }
// //find extends
// const btScalar rad = extend[component_index0] * absolute_edge[dir_index0] +
// extend[component_index1] * absolute_edge[dir_index1];
//
// if(pmin>rad || -rad>pmax) return false;
// return true;
//}
//
//SIMD_FORCE_INLINE bool test_cross_edge_box_X_axis(
// const btVector3 & edge,
// const btVector3 & absolute_edge,
// const btVector3 & pointa,
// const btVector3 & pointb, btVector3 & extend)
//{
//
// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,2,1,1,2);
//}
//
//
//SIMD_FORCE_INLINE bool test_cross_edge_box_Y_axis(
// const btVector3 & edge,
// const btVector3 & absolute_edge,
// const btVector3 & pointa,
// const btVector3 & pointb, btVector3 & extend)
//{
//
// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,0,2,2,0);
//}
//
//SIMD_FORCE_INLINE bool test_cross_edge_box_Z_axis(
// const btVector3 & edge,
// const btVector3 & absolute_edge,
// const btVector3 & pointa,
// const btVector3 & pointb, btVector3 & extend)
//{
//
// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,1,0,0,1);
//}
#define TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,i_dir_0,i_dir_1,i_comp_0,i_comp_1)\
{\
const btScalar dir0 = -edge[i_dir_0];\
const btScalar dir1 = edge[i_dir_1];\
btScalar pmin = pointa[i_comp_0]*dir0 + pointa[i_comp_1]*dir1;\
btScalar pmax = pointb[i_comp_0]*dir0 + pointb[i_comp_1]*dir1;\
if(pmin>pmax)\
{\
GIM_SWAP_NUMBERS(pmin,pmax); \
}\
const btScalar abs_dir0 = absolute_edge[i_dir_0];\
const btScalar abs_dir1 = absolute_edge[i_dir_1];\
const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1;\
if(pmin>rad || -rad>pmax) return false;\
}\
#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
{\
TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,2,1,1,2);\
}\
#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
{\
TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,0,2,2,0);\
}\
#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
{\
TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,1,0,0,1);\
}\
//! Class for transforming a model1 to the space of model0
class GIM_BOX_BOX_TRANSFORM_CACHE
{
public:
btVector3 m_T1to0;//!< Transforms translation of model1 to model 0
btMatrix3x3 m_R1to0;//!< Transforms Rotation of model1 to model 0, equal to R0' * R1
btMatrix3x3 m_AR;//!< Absolute value of m_R1to0
SIMD_FORCE_INLINE void calc_absolute_matrix()
{
static const btVector3 vepsi(1e-6f,1e-6f,1e-6f);
m_AR[0] = vepsi + m_R1to0[0].absolute();
m_AR[1] = vepsi + m_R1to0[1].absolute();
m_AR[2] = vepsi + m_R1to0[2].absolute();
}
GIM_BOX_BOX_TRANSFORM_CACHE()
{
}
GIM_BOX_BOX_TRANSFORM_CACHE(mat4f trans1_to_0)
{
COPY_MATRIX_3X3(m_R1to0,trans1_to_0)
MAT_GET_TRANSLATION(trans1_to_0,m_T1to0)
calc_absolute_matrix();
}
//! Calc the transformation relative 1 to 0. Inverts matrics by transposing
SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform & trans0,const btTransform & trans1)
{
m_R1to0 = trans0.getBasis().transpose();
m_T1to0 = m_R1to0 * (-trans0.getOrigin());
m_T1to0 += m_R1to0*trans1.getOrigin();
m_R1to0 *= trans1.getBasis();
calc_absolute_matrix();
}
//! Calcs the full invertion of the matrices. Useful for scaling matrices
SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform & trans0,const btTransform & trans1)
{
m_R1to0 = trans0.getBasis().inverse();
m_T1to0 = m_R1to0 * (-trans0.getOrigin());
m_T1to0 += m_R1to0*trans1.getOrigin();
m_R1to0 *= trans1.getBasis();
calc_absolute_matrix();
}
SIMD_FORCE_INLINE btVector3 transform(const btVector3 & point)
{
return point.dot3(m_R1to0[0], m_R1to0[1], m_R1to0[2]) + m_T1to0;
}
};
#define BOX_PLANE_EPSILON 0.000001f
//! Axis aligned box
class GIM_AABB
{
public:
btVector3 m_min;
btVector3 m_max;
GIM_AABB()
{}
GIM_AABB(const btVector3 & V1,
const btVector3 & V2,
const btVector3 & V3)
{
m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
}
GIM_AABB(const btVector3 & V1,
const btVector3 & V2,
const btVector3 & V3,
GREAL margin)
{
m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
m_min[0] -= margin;
m_min[1] -= margin;
m_min[2] -= margin;
m_max[0] += margin;
m_max[1] += margin;
m_max[2] += margin;
}
GIM_AABB(const GIM_AABB &other):
m_min(other.m_min),m_max(other.m_max)
{
}
GIM_AABB(const GIM_AABB &other,btScalar margin ):
m_min(other.m_min),m_max(other.m_max)
{
m_min[0] -= margin;
m_min[1] -= margin;
m_min[2] -= margin;
m_max[0] += margin;
m_max[1] += margin;
m_max[2] += margin;
}
SIMD_FORCE_INLINE void invalidate()
{
m_min[0] = G_REAL_INFINITY;
m_min[1] = G_REAL_INFINITY;
m_min[2] = G_REAL_INFINITY;
m_max[0] = -G_REAL_INFINITY;
m_max[1] = -G_REAL_INFINITY;
m_max[2] = -G_REAL_INFINITY;
}
SIMD_FORCE_INLINE void increment_margin(btScalar margin)
{
m_min[0] -= margin;
m_min[1] -= margin;
m_min[2] -= margin;
m_max[0] += margin;
m_max[1] += margin;
m_max[2] += margin;
}
SIMD_FORCE_INLINE void copy_with_margin(const GIM_AABB &other, btScalar margin)
{
m_min[0] = other.m_min[0] - margin;
m_min[1] = other.m_min[1] - margin;
m_min[2] = other.m_min[2] - margin;
m_max[0] = other.m_max[0] + margin;
m_max[1] = other.m_max[1] + margin;
m_max[2] = other.m_max[2] + margin;
}
template<typename CLASS_POINT>
SIMD_FORCE_INLINE void calc_from_triangle(
const CLASS_POINT & V1,
const CLASS_POINT & V2,
const CLASS_POINT & V3)
{
m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
}
template<typename CLASS_POINT>
SIMD_FORCE_INLINE void calc_from_triangle_margin(
const CLASS_POINT & V1,
const CLASS_POINT & V2,
const CLASS_POINT & V3, btScalar margin)
{
m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
m_min[0] -= margin;
m_min[1] -= margin;
m_min[2] -= margin;
m_max[0] += margin;
m_max[1] += margin;
m_max[2] += margin;
}
//! Apply a transform to an AABB
SIMD_FORCE_INLINE void appy_transform(const btTransform & trans)
{
btVector3 center = (m_max+m_min)*0.5f;
btVector3 extends = m_max - center;
// Compute new center
center = trans(center);
btVector3 textends = extends.dot3(trans.getBasis().getRow(0).absolute(),
trans.getBasis().getRow(1).absolute(),
trans.getBasis().getRow(2).absolute());
m_min = center - textends;
m_max = center + textends;
}
//! Merges a Box
SIMD_FORCE_INLINE void merge(const GIM_AABB & box)
{
m_min[0] = GIM_MIN(m_min[0],box.m_min[0]);
m_min[1] = GIM_MIN(m_min[1],box.m_min[1]);
m_min[2] = GIM_MIN(m_min[2],box.m_min[2]);
m_max[0] = GIM_MAX(m_max[0],box.m_max[0]);
m_max[1] = GIM_MAX(m_max[1],box.m_max[1]);
m_max[2] = GIM_MAX(m_max[2],box.m_max[2]);
}
//! Merges a point
template<typename CLASS_POINT>
SIMD_FORCE_INLINE void merge_point(const CLASS_POINT & point)
{
m_min[0] = GIM_MIN(m_min[0],point[0]);
m_min[1] = GIM_MIN(m_min[1],point[1]);
m_min[2] = GIM_MIN(m_min[2],point[2]);
m_max[0] = GIM_MAX(m_max[0],point[0]);
m_max[1] = GIM_MAX(m_max[1],point[1]);
m_max[2] = GIM_MAX(m_max[2],point[2]);
}
//! Gets the extend and center
SIMD_FORCE_INLINE void get_center_extend(btVector3 & center,btVector3 & extend) const
{
center = (m_max+m_min)*0.5f;
extend = m_max - center;
}
//! Finds the intersecting box between this box and the other.
SIMD_FORCE_INLINE void find_intersection(const GIM_AABB & other, GIM_AABB & intersection) const
{
intersection.m_min[0] = GIM_MAX(other.m_min[0],m_min[0]);
intersection.m_min[1] = GIM_MAX(other.m_min[1],m_min[1]);
intersection.m_min[2] = GIM_MAX(other.m_min[2],m_min[2]);
intersection.m_max[0] = GIM_MIN(other.m_max[0],m_max[0]);
intersection.m_max[1] = GIM_MIN(other.m_max[1],m_max[1]);
intersection.m_max[2] = GIM_MIN(other.m_max[2],m_max[2]);
}
SIMD_FORCE_INLINE bool has_collision(const GIM_AABB & other) const
{
if(m_min[0] > other.m_max[0] ||
m_max[0] < other.m_min[0] ||
m_min[1] > other.m_max[1] ||
m_max[1] < other.m_min[1] ||
m_min[2] > other.m_max[2] ||
m_max[2] < other.m_min[2])
{
return false;
}
return true;
}
/*! \brief Finds the Ray intersection parameter.
\param aabb Aligned box
\param vorigin A vec3f with the origin of the ray
\param vdir A vec3f with the direction of the ray
*/
SIMD_FORCE_INLINE bool collide_ray(const btVector3 & vorigin,const btVector3 & vdir)
{
btVector3 extents,center;
this->get_center_extend(center,extents);;
btScalar Dx = vorigin[0] - center[0];
if(GIM_GREATER(Dx, extents[0]) && Dx*vdir[0]>=0.0f) return false;
btScalar Dy = vorigin[1] - center[1];
if(GIM_GREATER(Dy, extents[1]) && Dy*vdir[1]>=0.0f) return false;
btScalar Dz = vorigin[2] - center[2];
if(GIM_GREATER(Dz, extents[2]) && Dz*vdir[2]>=0.0f) return false;
btScalar f = vdir[1] * Dz - vdir[2] * Dy;
if(btFabs(f) > extents[1]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[1])) return false;
f = vdir[2] * Dx - vdir[0] * Dz;
if(btFabs(f) > extents[0]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[0]))return false;
f = vdir[0] * Dy - vdir[1] * Dx;
if(btFabs(f) > extents[0]*btFabs(vdir[1]) + extents[1]*btFabs(vdir[0]))return false;
return true;
}
SIMD_FORCE_INLINE void projection_interval(const btVector3 & direction, btScalar &vmin, btScalar &vmax) const
{
btVector3 center = (m_max+m_min)*0.5f;
btVector3 extend = m_max-center;
btScalar _fOrigin = direction.dot(center);
btScalar _fMaximumExtent = extend.dot(direction.absolute());
vmin = _fOrigin - _fMaximumExtent;
vmax = _fOrigin + _fMaximumExtent;
}
SIMD_FORCE_INLINE ePLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const
{
btScalar _fmin,_fmax;
this->projection_interval(plane,_fmin,_fmax);
if(plane[3] > _fmax + BOX_PLANE_EPSILON)
{
return G_BACK_PLANE; // 0
}
if(plane[3]+BOX_PLANE_EPSILON >=_fmin)
{
return G_COLLIDE_PLANE; //1
}
return G_FRONT_PLANE;//2
}
SIMD_FORCE_INLINE bool overlapping_trans_conservative(const GIM_AABB & box, btTransform & trans1_to_0)
{
GIM_AABB tbox = box;
tbox.appy_transform(trans1_to_0);
return has_collision(tbox);
}
//! transcache is the transformation cache from box to this AABB
SIMD_FORCE_INLINE bool overlapping_trans_cache(
const GIM_AABB & box,const GIM_BOX_BOX_TRANSFORM_CACHE & transcache, bool fulltest)
{
//Taken from OPCODE
btVector3 ea,eb;//extends
btVector3 ca,cb;//extends
get_center_extend(ca,ea);
box.get_center_extend(cb,eb);
btVector3 T;
btScalar t,t2;
int i;
// Class I : A's basis vectors
for(i=0;i<3;i++)
{
T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i];
t = transcache.m_AR[i].dot(eb) + ea[i];
if(GIM_GREATER(T[i], t)) return false;
}
// Class II : B's basis vectors
for(i=0;i<3;i++)
{
t = MAT_DOT_COL(transcache.m_R1to0,T,i);
t2 = MAT_DOT_COL(transcache.m_AR,ea,i) + eb[i];
if(GIM_GREATER(t,t2)) return false;
}
// Class III : 9 cross products
if(fulltest)
{
int j,m,n,o,p,q,r;
for(i=0;i<3;i++)
{
m = (i+1)%3;
n = (i+2)%3;
o = i==0?1:0;
p = i==2?1:2;
for(j=0;j<3;j++)
{
q = j==2?1:2;
r = j==0?1:0;
t = T[n]*transcache.m_R1to0[m][j] - T[m]*transcache.m_R1to0[n][j];
t2 = ea[o]*transcache.m_AR[p][j] + ea[p]*transcache.m_AR[o][j] +
eb[r]*transcache.m_AR[i][q] + eb[q]*transcache.m_AR[i][r];
if(GIM_GREATER(t,t2)) return false;
}
}
}
return true;
}
//! Simple test for planes.
SIMD_FORCE_INLINE bool collide_plane(
const btVector4 & plane)
{
ePLANE_INTERSECTION_TYPE classify = plane_classify(plane);
return (classify == G_COLLIDE_PLANE);
}
//! test for a triangle, with edges
SIMD_FORCE_INLINE bool collide_triangle_exact(
const btVector3 & p1,
const btVector3 & p2,
const btVector3 & p3,
const btVector4 & triangle_plane)
{
if(!collide_plane(triangle_plane)) return false;
btVector3 center,extends;
this->get_center_extend(center,extends);
const btVector3 v1(p1 - center);
const btVector3 v2(p2 - center);
const btVector3 v3(p3 - center);
//First axis
btVector3 diff(v2 - v1);
btVector3 abs_diff = diff.absolute();
//Test With X axis
TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v1,v3,extends);
//Test With Y axis
TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v1,v3,extends);
//Test With Z axis
TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v1,v3,extends);
diff = v3 - v2;
abs_diff = diff.absolute();
//Test With X axis
TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v2,v1,extends);
//Test With Y axis
TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v2,v1,extends);
//Test With Z axis
TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v2,v1,extends);
diff = v1 - v3;
abs_diff = diff.absolute();
//Test With X axis
TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v3,v2,extends);
//Test With Y axis
TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v3,v2,extends);
//Test With Z axis
TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v3,v2,extends);
return true;
}
};
//! Compairison of transformation objects
SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btTransform & t2)
{
if(!(t1.getOrigin() == t2.getOrigin()) ) return false;
if(!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0)) ) return false;
if(!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1)) ) return false;
if(!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2)) ) return false;
return true;
}
#endif // GIM_BOX_COLLISION_H_INCLUDED

View File

@@ -1,182 +0,0 @@
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This library is free software; you can redistribute it and/or
modify it under the terms of EITHER:
(1) The GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at
your option) any later version. The text of the GNU Lesser
General Public License is included with this library in the
file GIMPACT-LICENSE-LGPL.TXT.
(2) The BSD-style license that is included with this library in
the file GIMPACT-LICENSE-BSD.TXT.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.TXT.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "gim_box_set.h"
GUINT GIM_BOX_TREE::_calc_splitting_axis(
gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex, GUINT endIndex)
{
GUINT i;
btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.));
GUINT numIndices = endIndex-startIndex;
for (i=startIndex;i<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
primitive_boxes[i].m_bound.m_min);
means+=center;
}
means *= (btScalar(1.)/(btScalar)numIndices);
for (i=startIndex;i<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
primitive_boxes[i].m_bound.m_min);
btVector3 diff2 = center-means;
diff2 = diff2 * diff2;
variance += diff2;
}
variance *= (btScalar(1.)/ ((btScalar)numIndices-1) );
return variance.maxAxis();
}
GUINT GIM_BOX_TREE::_sort_and_calc_splitting_index(
gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex,
GUINT endIndex, GUINT splitAxis)
{
GUINT i;
GUINT splitIndex =startIndex;
GUINT numIndices = endIndex - startIndex;
// average of centers
btScalar splitValue = 0.0f;
for (i=startIndex;i<endIndex;i++)
{
splitValue+= 0.5f*(primitive_boxes[i].m_bound.m_max[splitAxis] +
primitive_boxes[i].m_bound.m_min[splitAxis]);
}
splitValue /= (btScalar)numIndices;
//sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
for (i=startIndex;i<endIndex;i++)
{
btScalar center = 0.5f*(primitive_boxes[i].m_bound.m_max[splitAxis] +
primitive_boxes[i].m_bound.m_min[splitAxis]);
if (center > splitValue)
{
//swap
primitive_boxes.swap(i,splitIndex);
splitIndex++;
}
}
//if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
//otherwise the tree-building might fail due to stack-overflows in certain cases.
//unbalanced1 is unsafe: it can cause stack overflows
//bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
//unbalanced2 should work too: always use center (perfect balanced trees)
//bool unbalanced2 = true;
//this should be safe too:
GUINT rangeBalancedIndices = numIndices/3;
bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
if (unbalanced)
{
splitIndex = startIndex+ (numIndices>>1);
}
btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex))));
return splitIndex;
}
void GIM_BOX_TREE::_build_sub_tree(gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex, GUINT endIndex)
{
GUINT current_index = m_num_nodes++;
btAssert((endIndex-startIndex)>0);
if((endIndex-startIndex) == 1) //we got a leaf
{
m_node_array[current_index].m_left = 0;
m_node_array[current_index].m_right = 0;
m_node_array[current_index].m_escapeIndex = 0;
m_node_array[current_index].m_bound = primitive_boxes[startIndex].m_bound;
m_node_array[current_index].m_data = primitive_boxes[startIndex].m_data;
return;
}
//configure inner node
GUINT splitIndex;
//calc this node bounding box
m_node_array[current_index].m_bound.invalidate();
for (splitIndex=startIndex;splitIndex<endIndex;splitIndex++)
{
m_node_array[current_index].m_bound.merge(primitive_boxes[splitIndex].m_bound);
}
//calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
//split axis
splitIndex = _calc_splitting_axis(primitive_boxes,startIndex,endIndex);
splitIndex = _sort_and_calc_splitting_index(
primitive_boxes,startIndex,endIndex,splitIndex);
//configure this inner node : the left node index
m_node_array[current_index].m_left = m_num_nodes;
//build left child tree
_build_sub_tree(primitive_boxes, startIndex, splitIndex );
//configure this inner node : the right node index
m_node_array[current_index].m_right = m_num_nodes;
//build right child tree
_build_sub_tree(primitive_boxes, splitIndex ,endIndex);
//configure this inner node : the escape index
m_node_array[current_index].m_escapeIndex = m_num_nodes - current_index;
}
//! stackless build tree
void GIM_BOX_TREE::build_tree(
gim_array<GIM_AABB_DATA> & primitive_boxes)
{
// initialize node count to 0
m_num_nodes = 0;
// allocate nodes
m_node_array.resize(primitive_boxes.size()*2);
_build_sub_tree(primitive_boxes, 0, primitive_boxes.size());
}

View File

@@ -1,674 +0,0 @@
#ifndef GIM_BOX_SET_H_INCLUDED
#define GIM_BOX_SET_H_INCLUDED
/*! \file gim_box_set.h
\author Francisco Leon Najera
*/
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This library is free software; you can redistribute it and/or
modify it under the terms of EITHER:
(1) The GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at
your option) any later version. The text of the GNU Lesser
General Public License is included with this library in the
file GIMPACT-LICENSE-LGPL.TXT.
(2) The BSD-style license that is included with this library in
the file GIMPACT-LICENSE-BSD.TXT.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.TXT.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "gim_array.h"
#include "gim_radixsort.h"
#include "gim_box_collision.h"
#include "gim_tri_collision.h"
//! Overlapping pair
struct GIM_PAIR
{
GUINT m_index1;
GUINT m_index2;
GIM_PAIR()
{}
GIM_PAIR(const GIM_PAIR & p)
{
m_index1 = p.m_index1;
m_index2 = p.m_index2;
}
GIM_PAIR(GUINT index1, GUINT index2)
{
m_index1 = index1;
m_index2 = index2;
}
};
//! A pairset array
class gim_pair_set: public gim_array<GIM_PAIR>
{
public:
gim_pair_set():gim_array<GIM_PAIR>(32)
{
}
inline void push_pair(GUINT index1,GUINT index2)
{
push_back(GIM_PAIR(index1,index2));
}
inline void push_pair_inv(GUINT index1,GUINT index2)
{
push_back(GIM_PAIR(index2,index1));
}
};
//! Prototype Base class for primitive classification
/*!
This class is a wrapper for primitive collections.
This tells relevant info for the Bounding Box set classes, which take care of space classification.
This class can manage Compound shapes and trimeshes, and if it is managing trimesh then the Hierarchy Bounding Box classes will take advantage of primitive Vs Box overlapping tests for getting optimal results and less Per Box compairisons.
*/
class GIM_PRIMITIVE_MANAGER_PROTOTYPE
{
public:
virtual ~GIM_PRIMITIVE_MANAGER_PROTOTYPE() {}
//! determines if this manager consist on only triangles, which special case will be optimized
virtual bool is_trimesh() = 0;
virtual GUINT get_primitive_count() = 0;
virtual void get_primitive_box(GUINT prim_index ,GIM_AABB & primbox) = 0;
virtual void get_primitive_triangle(GUINT prim_index,GIM_TRIANGLE & triangle) = 0;
};
struct GIM_AABB_DATA
{
GIM_AABB m_bound;
GUINT m_data;
};
//! Node Structure for trees
struct GIM_BOX_TREE_NODE
{
GIM_AABB m_bound;
GUINT m_left;//!< Left subtree
GUINT m_right;//!< Right subtree
GUINT m_escapeIndex;//!< Scape index for traversing
GUINT m_data;//!< primitive index if apply
GIM_BOX_TREE_NODE()
{
m_left = 0;
m_right = 0;
m_escapeIndex = 0;
m_data = 0;
}
SIMD_FORCE_INLINE bool is_leaf_node() const
{
return (!m_left && !m_right);
}
};
//! Basic Box tree structure
class GIM_BOX_TREE
{
protected:
GUINT m_num_nodes;
gim_array<GIM_BOX_TREE_NODE> m_node_array;
protected:
GUINT _sort_and_calc_splitting_index(
gim_array<GIM_AABB_DATA> & primitive_boxes,
GUINT startIndex, GUINT endIndex, GUINT splitAxis);
GUINT _calc_splitting_axis(gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex, GUINT endIndex);
void _build_sub_tree(gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex, GUINT endIndex);
public:
GIM_BOX_TREE()
{
m_num_nodes = 0;
}
//! prototype functions for box tree management
//!@{
void build_tree(gim_array<GIM_AABB_DATA> & primitive_boxes);
SIMD_FORCE_INLINE void clearNodes()
{
m_node_array.clear();
m_num_nodes = 0;
}
//! node count
SIMD_FORCE_INLINE GUINT getNodeCount() const
{
return m_num_nodes;
}
//! tells if the node is a leaf
SIMD_FORCE_INLINE bool isLeafNode(GUINT nodeindex) const
{
return m_node_array[nodeindex].is_leaf_node();
}
SIMD_FORCE_INLINE GUINT getNodeData(GUINT nodeindex) const
{
return m_node_array[nodeindex].m_data;
}
SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB & bound) const
{
bound = m_node_array[nodeindex].m_bound;
}
SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB & bound)
{
m_node_array[nodeindex].m_bound = bound;
}
SIMD_FORCE_INLINE GUINT getLeftNodeIndex(GUINT nodeindex) const
{
return m_node_array[nodeindex].m_left;
}
SIMD_FORCE_INLINE GUINT getRightNodeIndex(GUINT nodeindex) const
{
return m_node_array[nodeindex].m_right;
}
SIMD_FORCE_INLINE GUINT getScapeNodeIndex(GUINT nodeindex) const
{
return m_node_array[nodeindex].m_escapeIndex;
}
//!@}
};
//! Generic Box Tree Template
/*!
This class offers an structure for managing a box tree of primitives.
Requires a Primitive prototype (like GIM_PRIMITIVE_MANAGER_PROTOTYPE ) and
a Box tree structure ( like GIM_BOX_TREE).
*/
template<typename _GIM_PRIMITIVE_MANAGER_PROTOTYPE, typename _GIM_BOX_TREE_PROTOTYPE>
class GIM_BOX_TREE_TEMPLATE_SET
{
protected:
_GIM_PRIMITIVE_MANAGER_PROTOTYPE m_primitive_manager;
_GIM_BOX_TREE_PROTOTYPE m_box_tree;
protected:
//stackless refit
SIMD_FORCE_INLINE void refit()
{
GUINT nodecount = getNodeCount();
while(nodecount--)
{
if(isLeafNode(nodecount))
{
GIM_AABB leafbox;
m_primitive_manager.get_primitive_box(getNodeData(nodecount),leafbox);
setNodeBound(nodecount,leafbox);
}
else
{
//get left bound
GUINT childindex = getLeftNodeIndex(nodecount);
GIM_AABB bound;
getNodeBound(childindex,bound);
//get right bound
childindex = getRightNodeIndex(nodecount);
GIM_AABB bound2;
getNodeBound(childindex,bound2);
bound.merge(bound2);
setNodeBound(nodecount,bound);
}
}
}
public:
GIM_BOX_TREE_TEMPLATE_SET()
{
}
SIMD_FORCE_INLINE GIM_AABB getGlobalBox() const
{
GIM_AABB totalbox;
getNodeBound(0, totalbox);
return totalbox;
}
SIMD_FORCE_INLINE void setPrimitiveManager(const _GIM_PRIMITIVE_MANAGER_PROTOTYPE & primitive_manager)
{
m_primitive_manager = primitive_manager;
}
const _GIM_PRIMITIVE_MANAGER_PROTOTYPE & getPrimitiveManager() const
{
return m_primitive_manager;
}
_GIM_PRIMITIVE_MANAGER_PROTOTYPE & getPrimitiveManager()
{
return m_primitive_manager;
}
//! node manager prototype functions
///@{
//! this attemps to refit the box set.
SIMD_FORCE_INLINE void update()
{
refit();
}
//! this rebuild the entire set
SIMD_FORCE_INLINE void buildSet()
{
//obtain primitive boxes
gim_array<GIM_AABB_DATA> primitive_boxes;
primitive_boxes.resize(m_primitive_manager.get_primitive_count(),false);
for (GUINT i = 0;i<primitive_boxes.size() ;i++ )
{
m_primitive_manager.get_primitive_box(i,primitive_boxes[i].m_bound);
primitive_boxes[i].m_data = i;
}
m_box_tree.build_tree(primitive_boxes);
}
//! returns the indices of the primitives in the m_primitive_manager
SIMD_FORCE_INLINE bool boxQuery(const GIM_AABB & box, gim_array<GUINT> & collided_results) const
{
GUINT curIndex = 0;
GUINT numNodes = getNodeCount();
while (curIndex < numNodes)
{
GIM_AABB bound;
getNodeBound(curIndex,bound);
//catch bugs in tree data
bool aabbOverlap = bound.has_collision(box);
bool isleafnode = isLeafNode(curIndex);
if (isleafnode && aabbOverlap)
{
collided_results.push_back(getNodeData(curIndex));
}
if (aabbOverlap || isleafnode)
{
//next subnode
curIndex++;
}
else
{
//skip node
curIndex+= getScapeNodeIndex(curIndex);
}
}
if(collided_results.size()>0) return true;
return false;
}
//! returns the indices of the primitives in the m_primitive_manager
SIMD_FORCE_INLINE bool boxQueryTrans(const GIM_AABB & box,
const btTransform & transform, gim_array<GUINT> & collided_results) const
{
GIM_AABB transbox=box;
transbox.appy_transform(transform);
return boxQuery(transbox,collided_results);
}
//! returns the indices of the primitives in the m_primitive_manager
SIMD_FORCE_INLINE bool rayQuery(
const btVector3 & ray_dir,const btVector3 & ray_origin ,
gim_array<GUINT> & collided_results) const
{
GUINT curIndex = 0;
GUINT numNodes = getNodeCount();
while (curIndex < numNodes)
{
GIM_AABB bound;
getNodeBound(curIndex,bound);
//catch bugs in tree data
bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir);
bool isleafnode = isLeafNode(curIndex);
if (isleafnode && aabbOverlap)
{
collided_results.push_back(getNodeData( curIndex));
}
if (aabbOverlap || isleafnode)
{
//next subnode
curIndex++;
}
else
{
//skip node
curIndex+= getScapeNodeIndex(curIndex);
}
}
if(collided_results.size()>0) return true;
return false;
}
//! tells if this set has hierarcht
SIMD_FORCE_INLINE bool hasHierarchy() const
{
return true;
}
//! tells if this set is a trimesh
SIMD_FORCE_INLINE bool isTrimesh() const
{
return m_primitive_manager.is_trimesh();
}
//! node count
SIMD_FORCE_INLINE GUINT getNodeCount() const
{
return m_box_tree.getNodeCount();
}
//! tells if the node is a leaf
SIMD_FORCE_INLINE bool isLeafNode(GUINT nodeindex) const
{
return m_box_tree.isLeafNode(nodeindex);
}
SIMD_FORCE_INLINE GUINT getNodeData(GUINT nodeindex) const
{
return m_box_tree.getNodeData(nodeindex);
}
SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB & bound) const
{
m_box_tree.getNodeBound(nodeindex, bound);
}
SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB & bound)
{
m_box_tree.setNodeBound(nodeindex, bound);
}
SIMD_FORCE_INLINE GUINT getLeftNodeIndex(GUINT nodeindex) const
{
return m_box_tree.getLeftNodeIndex(nodeindex);
}
SIMD_FORCE_INLINE GUINT getRightNodeIndex(GUINT nodeindex) const
{
return m_box_tree.getRightNodeIndex(nodeindex);
}
SIMD_FORCE_INLINE GUINT getScapeNodeIndex(GUINT nodeindex) const
{
return m_box_tree.getScapeNodeIndex(nodeindex);
}
SIMD_FORCE_INLINE void getNodeTriangle(GUINT nodeindex,GIM_TRIANGLE & triangle) const
{
m_primitive_manager.get_primitive_triangle(getNodeData(nodeindex),triangle);
}
};
//! Class for Box Tree Sets
/*!
this has the GIM_BOX_TREE implementation for bounding boxes.
*/
template<typename _GIM_PRIMITIVE_MANAGER_PROTOTYPE>
class GIM_BOX_TREE_SET: public GIM_BOX_TREE_TEMPLATE_SET< _GIM_PRIMITIVE_MANAGER_PROTOTYPE, GIM_BOX_TREE>
{
public:
};
/// GIM_BOX_SET collision methods
template<typename BOX_SET_CLASS0,typename BOX_SET_CLASS1>
class GIM_TREE_TREE_COLLIDER
{
public:
gim_pair_set * m_collision_pairs;
BOX_SET_CLASS0 * m_boxset0;
BOX_SET_CLASS1 * m_boxset1;
GUINT current_node0;
GUINT current_node1;
bool node0_is_leaf;
bool node1_is_leaf;
bool t0_is_trimesh;
bool t1_is_trimesh;
bool node0_has_triangle;
bool node1_has_triangle;
GIM_AABB m_box0;
GIM_AABB m_box1;
GIM_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0;
btTransform trans_cache_0to1;
GIM_TRIANGLE m_tri0;
btVector4 m_tri0_plane;
GIM_TRIANGLE m_tri1;
btVector4 m_tri1_plane;
public:
GIM_TREE_TREE_COLLIDER()
{
current_node0 = G_UINT_INFINITY;
current_node1 = G_UINT_INFINITY;
}
protected:
SIMD_FORCE_INLINE void retrieve_node0_triangle(GUINT node0)
{
if(node0_has_triangle) return;
m_boxset0->getNodeTriangle(node0,m_tri0);
//transform triangle
m_tri0.m_vertices[0] = trans_cache_0to1(m_tri0.m_vertices[0]);
m_tri0.m_vertices[1] = trans_cache_0to1(m_tri0.m_vertices[1]);
m_tri0.m_vertices[2] = trans_cache_0to1(m_tri0.m_vertices[2]);
m_tri0.get_plane(m_tri0_plane);
node0_has_triangle = true;
}
SIMD_FORCE_INLINE void retrieve_node1_triangle(GUINT node1)
{
if(node1_has_triangle) return;
m_boxset1->getNodeTriangle(node1,m_tri1);
//transform triangle
m_tri1.m_vertices[0] = trans_cache_1to0.transform(m_tri1.m_vertices[0]);
m_tri1.m_vertices[1] = trans_cache_1to0.transform(m_tri1.m_vertices[1]);
m_tri1.m_vertices[2] = trans_cache_1to0.transform(m_tri1.m_vertices[2]);
m_tri1.get_plane(m_tri1_plane);
node1_has_triangle = true;
}
SIMD_FORCE_INLINE void retrieve_node0_info(GUINT node0)
{
if(node0 == current_node0) return;
m_boxset0->getNodeBound(node0,m_box0);
node0_is_leaf = m_boxset0->isLeafNode(node0);
node0_has_triangle = false;
current_node0 = node0;
}
SIMD_FORCE_INLINE void retrieve_node1_info(GUINT node1)
{
if(node1 == current_node1) return;
m_boxset1->getNodeBound(node1,m_box1);
node1_is_leaf = m_boxset1->isLeafNode(node1);
node1_has_triangle = false;
current_node1 = node1;
}
SIMD_FORCE_INLINE bool node_collision(GUINT node0 ,GUINT node1)
{
retrieve_node0_info(node0);
retrieve_node1_info(node1);
bool result = m_box0.overlapping_trans_cache(m_box1,trans_cache_1to0,true);
if(!result) return false;
if(t0_is_trimesh && node0_is_leaf)
{
//perform primitive vs box collision
retrieve_node0_triangle(node0);
//do triangle vs box collision
m_box1.increment_margin(m_tri0.m_margin);
result = m_box1.collide_triangle_exact(
m_tri0.m_vertices[0],m_tri0.m_vertices[1],m_tri0.m_vertices[2],m_tri0_plane);
m_box1.increment_margin(-m_tri0.m_margin);
if(!result) return false;
return true;
}
else if(t1_is_trimesh && node1_is_leaf)
{
//perform primitive vs box collision
retrieve_node1_triangle(node1);
//do triangle vs box collision
m_box0.increment_margin(m_tri1.m_margin);
result = m_box0.collide_triangle_exact(
m_tri1.m_vertices[0],m_tri1.m_vertices[1],m_tri1.m_vertices[2],m_tri1_plane);
m_box0.increment_margin(-m_tri1.m_margin);
if(!result) return false;
return true;
}
return true;
}
//stackless collision routine
void find_collision_pairs()
{
gim_pair_set stack_collisions;
stack_collisions.reserve(32);
//add the first pair
stack_collisions.push_pair(0,0);
while(stack_collisions.size())
{
//retrieve the last pair and pop
GUINT node0 = stack_collisions.back().m_index1;
GUINT node1 = stack_collisions.back().m_index2;
stack_collisions.pop_back();
if(node_collision(node0,node1)) // a collision is found
{
if(node0_is_leaf)
{
if(node1_is_leaf)
{
m_collision_pairs->push_pair(m_boxset0->getNodeData(node0),m_boxset1->getNodeData(node1));
}
else
{
//collide left
stack_collisions.push_pair(node0,m_boxset1->getLeftNodeIndex(node1));
//collide right
stack_collisions.push_pair(node0,m_boxset1->getRightNodeIndex(node1));
}
}
else
{
if(node1_is_leaf)
{
//collide left
stack_collisions.push_pair(m_boxset0->getLeftNodeIndex(node0),node1);
//collide right
stack_collisions.push_pair(m_boxset0->getRightNodeIndex(node0),node1);
}
else
{
GUINT left0 = m_boxset0->getLeftNodeIndex(node0);
GUINT right0 = m_boxset0->getRightNodeIndex(node0);
GUINT left1 = m_boxset1->getLeftNodeIndex(node1);
GUINT right1 = m_boxset1->getRightNodeIndex(node1);
//collide left
stack_collisions.push_pair(left0,left1);
//collide right
stack_collisions.push_pair(left0,right1);
//collide left
stack_collisions.push_pair(right0,left1);
//collide right
stack_collisions.push_pair(right0,right1);
}// else if node1 is not a leaf
}// else if node0 is not a leaf
}// if(node_collision(node0,node1))
}//while(stack_collisions.size())
}
public:
void find_collision(BOX_SET_CLASS0 * boxset1, const btTransform & trans1,
BOX_SET_CLASS1 * boxset2, const btTransform & trans2,
gim_pair_set & collision_pairs, bool complete_primitive_tests = true)
{
m_collision_pairs = &collision_pairs;
m_boxset0 = boxset1;
m_boxset1 = boxset2;
trans_cache_1to0.calc_from_homogenic(trans1,trans2);
trans_cache_0to1 = trans2.inverse();
trans_cache_0to1 *= trans1;
if(complete_primitive_tests)
{
t0_is_trimesh = boxset1->getPrimitiveManager().is_trimesh();
t1_is_trimesh = boxset2->getPrimitiveManager().is_trimesh();
}
else
{
t0_is_trimesh = false;
t1_is_trimesh = false;
}
find_collision_pairs();
}
};
#endif // GIM_BOXPRUNING_H_INCLUDED

View File

@@ -1,210 +0,0 @@
#ifndef GIM_CLIP_POLYGON_H_INCLUDED
#define GIM_CLIP_POLYGON_H_INCLUDED
/*! \file gim_tri_collision.h
\author Francisco Leon Najera
*/
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This library is free software; you can redistribute it and/or
modify it under the terms of EITHER:
(1) The GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at
your option) any later version. The text of the GNU Lesser
General Public License is included with this library in the
file GIMPACT-LICENSE-LGPL.TXT.
(2) The BSD-style license that is included with this library in
the file GIMPACT-LICENSE-BSD.TXT.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.TXT.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
//! This function calcs the distance from a 3D plane
class DISTANCE_PLANE_3D_FUNC
{
public:
template<typename CLASS_POINT,typename CLASS_PLANE>
inline GREAL operator()(const CLASS_PLANE & plane, const CLASS_POINT & point)
{
return DISTANCE_PLANE_POINT(plane, point);
}
};
template<typename CLASS_POINT>
SIMD_FORCE_INLINE void PLANE_CLIP_POLYGON_COLLECT(
const CLASS_POINT & point0,
const CLASS_POINT & point1,
GREAL dist0,
GREAL dist1,
CLASS_POINT * clipped,
GUINT & clipped_count)
{
GUINT _prevclassif = (dist0>G_EPSILON);
GUINT _classif = (dist1>G_EPSILON);
if(_classif!=_prevclassif)
{
GREAL blendfactor = -dist0/(dist1-dist0);
VEC_BLEND(clipped[clipped_count],point0,point1,blendfactor);
clipped_count++;
}
if(!_classif)
{
VEC_COPY(clipped[clipped_count],point1);
clipped_count++;
}
}
//! Clips a polygon by a plane
/*!
*\return The count of the clipped counts
*/
template<typename CLASS_POINT,typename CLASS_PLANE, typename DISTANCE_PLANE_FUNC>
SIMD_FORCE_INLINE GUINT PLANE_CLIP_POLYGON_GENERIC(
const CLASS_PLANE & plane,
const CLASS_POINT * polygon_points,
GUINT polygon_point_count,
CLASS_POINT * clipped,DISTANCE_PLANE_FUNC distance_func)
{
GUINT clipped_count = 0;
//clip first point
GREAL firstdist = distance_func(plane,polygon_points[0]);;
if(!(firstdist>G_EPSILON))
{
VEC_COPY(clipped[clipped_count],polygon_points[0]);
clipped_count++;
}
GREAL olddist = firstdist;
for(GUINT _i=1;_i<polygon_point_count;_i++)
{
GREAL dist = distance_func(plane,polygon_points[_i]);
PLANE_CLIP_POLYGON_COLLECT(
polygon_points[_i-1],polygon_points[_i],
olddist,
dist,
clipped,
clipped_count);
olddist = dist;
}
//RETURN TO FIRST point
PLANE_CLIP_POLYGON_COLLECT(
polygon_points[polygon_point_count-1],polygon_points[0],
olddist,
firstdist,
clipped,
clipped_count);
return clipped_count;
}
//! Clips a polygon by a plane
/*!
*\return The count of the clipped counts
*/
template<typename CLASS_POINT,typename CLASS_PLANE, typename DISTANCE_PLANE_FUNC>
SIMD_FORCE_INLINE GUINT PLANE_CLIP_TRIANGLE_GENERIC(
const CLASS_PLANE & plane,
const CLASS_POINT & point0,
const CLASS_POINT & point1,
const CLASS_POINT & point2,
CLASS_POINT * clipped,DISTANCE_PLANE_FUNC distance_func)
{
GUINT clipped_count = 0;
//clip first point
GREAL firstdist = distance_func(plane,point0);;
if(!(firstdist>G_EPSILON))
{
VEC_COPY(clipped[clipped_count],point0);
clipped_count++;
}
// point 1
GREAL olddist = firstdist;
GREAL dist = distance_func(plane,point1);
PLANE_CLIP_POLYGON_COLLECT(
point0,point1,
olddist,
dist,
clipped,
clipped_count);
olddist = dist;
// point 2
dist = distance_func(plane,point2);
PLANE_CLIP_POLYGON_COLLECT(
point1,point2,
olddist,
dist,
clipped,
clipped_count);
olddist = dist;
//RETURN TO FIRST point
PLANE_CLIP_POLYGON_COLLECT(
point2,point0,
olddist,
firstdist,
clipped,
clipped_count);
return clipped_count;
}
template<typename CLASS_POINT,typename CLASS_PLANE>
SIMD_FORCE_INLINE GUINT PLANE_CLIP_POLYGON3D(
const CLASS_PLANE & plane,
const CLASS_POINT * polygon_points,
GUINT polygon_point_count,
CLASS_POINT * clipped)
{
return PLANE_CLIP_POLYGON_GENERIC<CLASS_POINT,CLASS_PLANE>(plane,polygon_points,polygon_point_count,clipped,DISTANCE_PLANE_3D_FUNC());
}
template<typename CLASS_POINT,typename CLASS_PLANE>
SIMD_FORCE_INLINE GUINT PLANE_CLIP_TRIANGLE3D(
const CLASS_PLANE & plane,
const CLASS_POINT & point0,
const CLASS_POINT & point1,
const CLASS_POINT & point2,
CLASS_POINT * clipped)
{
return PLANE_CLIP_TRIANGLE_GENERIC<CLASS_POINT,CLASS_PLANE>(plane,point0,point1,point2,clipped,DISTANCE_PLANE_3D_FUNC());
}
#endif // GIM_TRI_COLLISION_H_INCLUDED

View File

@@ -1,146 +0,0 @@
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This library is free software; you can redistribute it and/or
modify it under the terms of EITHER:
(1) The GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at
your option) any later version. The text of the GNU Lesser
General Public License is included with this library in the
file GIMPACT-LICENSE-LGPL.TXT.
(2) The BSD-style license that is included with this library in
the file GIMPACT-LICENSE-BSD.TXT.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.TXT.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "gim_contact.h"
#define MAX_COINCIDENT 8
void gim_contact_array::merge_contacts(
const gim_contact_array & contacts, bool normal_contact_average)
{
clear();
if(contacts.size()==1)
{
push_back(contacts.back());
return;
}
gim_array<GIM_RSORT_TOKEN> keycontacts(contacts.size());
keycontacts.resize(contacts.size(),false);
//fill key contacts
GUINT i;
for (i = 0;i<contacts.size() ;i++ )
{
keycontacts[i].m_key = contacts[i].calc_key_contact();
keycontacts[i].m_value = i;
}
//sort keys
gim_heap_sort(keycontacts.pointer(),keycontacts.size(),GIM_RSORT_TOKEN_COMPARATOR());
// Merge contacts
GUINT coincident_count=0;
btVector3 coincident_normals[MAX_COINCIDENT];
GUINT last_key = keycontacts[0].m_key;
GUINT key = 0;
push_back(contacts[keycontacts[0].m_value]);
GIM_CONTACT * pcontact = &back();
for( i=1;i<keycontacts.size();i++)
{
key = keycontacts[i].m_key;
const GIM_CONTACT * scontact = &contacts[keycontacts[i].m_value];
if(last_key == key)//same points
{
//merge contact
if(pcontact->m_depth - CONTACT_DIFF_EPSILON > scontact->m_depth)//)
{
*pcontact = *scontact;
coincident_count = 0;
}
else if(normal_contact_average)
{
if(btFabs(pcontact->m_depth - scontact->m_depth)<CONTACT_DIFF_EPSILON)
{
if(coincident_count<MAX_COINCIDENT)
{
coincident_normals[coincident_count] = scontact->m_normal;
coincident_count++;
}
}
}
}
else
{//add new contact
if(normal_contact_average && coincident_count>0)
{
pcontact->interpolate_normals(coincident_normals,coincident_count);
coincident_count = 0;
}
push_back(*scontact);
pcontact = &back();
}
last_key = key;
}
}
void gim_contact_array::merge_contacts_unique(const gim_contact_array & contacts)
{
clear();
if(contacts.size()==1)
{
push_back(contacts.back());
return;
}
GIM_CONTACT average_contact = contacts.back();
for (GUINT i=1;i<contacts.size() ;i++ )
{
average_contact.m_point += contacts[i].m_point;
average_contact.m_normal += contacts[i].m_normal * contacts[i].m_depth;
}
//divide
GREAL divide_average = 1.0f/((GREAL)contacts.size());
average_contact.m_point *= divide_average;
average_contact.m_normal *= divide_average;
average_contact.m_depth = average_contact.m_normal.length();
average_contact.m_normal /= average_contact.m_depth;
}

View File

@@ -1,164 +0,0 @@
#ifndef GIM_CONTACT_H_INCLUDED
#define GIM_CONTACT_H_INCLUDED
/*! \file gim_contact.h
\author Francisco Leon Najera
*/
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This library is free software; you can redistribute it and/or
modify it under the terms of EITHER:
(1) The GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at
your option) any later version. The text of the GNU Lesser
General Public License is included with this library in the
file GIMPACT-LICENSE-LGPL.TXT.
(2) The BSD-style license that is included with this library in
the file GIMPACT-LICENSE-BSD.TXT.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.TXT.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "gim_geometry.h"
#include "gim_radixsort.h"
#include "gim_array.h"
/**
Configuration var for applying interpolation of contact normals
*/
#define NORMAL_CONTACT_AVERAGE 1
#define CONTACT_DIFF_EPSILON 0.00001f
/// Structure for collision results
///Functions for managing and sorting contacts resulting from a collision query.
///Contact lists must be create by calling \ref GIM_CREATE_CONTACT_LIST
///After querys, contact lists must be destroy by calling \ref GIM_DYNARRAY_DESTROY
///Contacts can be merge for avoid duplicate results by calling \ref gim_merge_contacts
class GIM_CONTACT
{
public:
btVector3 m_point;
btVector3 m_normal;
GREAL m_depth;//Positive value indicates interpenetration
GREAL m_distance;//Padding not for use
GUINT m_feature1;//Face number
GUINT m_feature2;//Face number
public:
GIM_CONTACT()
{
}
GIM_CONTACT(const GIM_CONTACT & contact):
m_point(contact.m_point),
m_normal(contact.m_normal),
m_depth(contact.m_depth),
m_feature1(contact.m_feature1),
m_feature2(contact.m_feature2)
{
m_point = contact.m_point;
m_normal = contact.m_normal;
m_depth = contact.m_depth;
m_feature1 = contact.m_feature1;
m_feature2 = contact.m_feature2;
}
GIM_CONTACT(const btVector3 &point,const btVector3 & normal,
GREAL depth, GUINT feature1, GUINT feature2):
m_point(point),
m_normal(normal),
m_depth(depth),
m_feature1(feature1),
m_feature2(feature2)
{
}
//! Calcs key for coord classification
SIMD_FORCE_INLINE GUINT calc_key_contact() const
{
GINT _coords[] = {
(GINT)(m_point[0]*1000.0f+1.0f),
(GINT)(m_point[1]*1333.0f),
(GINT)(m_point[2]*2133.0f+3.0f)};
GUINT _hash=0;
GUINT *_uitmp = (GUINT *)(&_coords[0]);
_hash = *_uitmp;
_uitmp++;
_hash += (*_uitmp)<<4;
_uitmp++;
_hash += (*_uitmp)<<8;
return _hash;
}
SIMD_FORCE_INLINE void interpolate_normals( btVector3 * normals,GUINT normal_count)
{
btVector3 vec_sum(m_normal);
for(GUINT i=0;i<normal_count;i++)
{
vec_sum += normals[i];
}
GREAL vec_sum_len = vec_sum.length2();
if(vec_sum_len <CONTACT_DIFF_EPSILON) return;
GIM_INV_SQRT(vec_sum_len,vec_sum_len); // 1/sqrt(vec_sum_len)
m_normal = vec_sum*vec_sum_len;
}
};
class gim_contact_array:public gim_array<GIM_CONTACT>
{
public:
gim_contact_array():gim_array<GIM_CONTACT>(64)
{
}
SIMD_FORCE_INLINE void push_contact(const btVector3 &point,const btVector3 & normal,
GREAL depth, GUINT feature1, GUINT feature2)
{
push_back_mem();
GIM_CONTACT & newele = back();
newele.m_point = point;
newele.m_normal = normal;
newele.m_depth = depth;
newele.m_feature1 = feature1;
newele.m_feature2 = feature2;
}
SIMD_FORCE_INLINE void push_triangle_contacts(
const GIM_TRIANGLE_CONTACT_DATA & tricontact,
GUINT feature1,GUINT feature2)
{
for(GUINT i = 0;i<tricontact.m_point_count ;i++ )
{
push_back_mem();
GIM_CONTACT & newele = back();
newele.m_point = tricontact.m_points[i];
newele.m_normal = tricontact.m_separating_normal;
newele.m_depth = tricontact.m_penetration_depth;
newele.m_feature1 = feature1;
newele.m_feature2 = feature2;
}
}
void merge_contacts(const gim_contact_array & contacts, bool normal_contact_average = true);
void merge_contacts_unique(const gim_contact_array & contacts);
};
#endif // GIM_CONTACT_H_INCLUDED

View File

@@ -1,97 +0,0 @@
#ifndef GIM_GEOM_TYPES_H_INCLUDED
#define GIM_GEOM_TYPES_H_INCLUDED
/*! \file gim_geom_types.h
\author Francisco Leon Najera
*/
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This library is free software; you can redistribute it and/or
modify it under the terms of EITHER:
(1) The GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at
your option) any later version. The text of the GNU Lesser
General Public License is included with this library in the
file GIMPACT-LICENSE-LGPL.TXT.
(2) The BSD-style license that is included with this library in
the file GIMPACT-LICENSE-BSD.TXT.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.TXT.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "gim_math.h"
//! Short Integer vector 2D
typedef GSHORT vec2s[2];
//! Integer vector 3D
typedef GSHORT vec3s[3];
//! Integer vector 4D
typedef GSHORT vec4s[4];
//! Short Integer vector 2D
typedef GUSHORT vec2us[2];
//! Integer vector 3D
typedef GUSHORT vec3us[3];
//! Integer vector 4D
typedef GUSHORT vec4us[4];
//! Integer vector 2D
typedef GINT vec2i[2];
//! Integer vector 3D
typedef GINT vec3i[3];
//! Integer vector 4D
typedef GINT vec4i[4];
//! Unsigned Integer vector 2D
typedef GUINT vec2ui[2];
//! Unsigned Integer vector 3D
typedef GUINT vec3ui[3];
//! Unsigned Integer vector 4D
typedef GUINT vec4ui[4];
//! Float vector 2D
typedef GREAL vec2f[2];
//! Float vector 3D
typedef GREAL vec3f[3];
//! Float vector 4D
typedef GREAL vec4f[4];
//! Double vector 2D
typedef GREAL2 vec2d[2];
//! Float vector 3D
typedef GREAL2 vec3d[3];
//! Float vector 4D
typedef GREAL2 vec4d[4];
//! Matrix 2D, row ordered
typedef GREAL mat2f[2][2];
//! Matrix 3D, row ordered
typedef GREAL mat3f[3][3];
//! Matrix 4D, row ordered
typedef GREAL mat4f[4][4];
//! Quaternion
typedef GREAL quatf[4];
//typedef struct _aabb3f aabb3f;
#endif // GIM_GEOM_TYPES_H_INCLUDED

View File

@@ -1,42 +0,0 @@
#ifndef GIM_GEOMETRY_H_INCLUDED
#define GIM_GEOMETRY_H_INCLUDED
/*! \file gim_geometry.h
\author Francisco Leon Najera
*/
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This library is free software; you can redistribute it and/or
modify it under the terms of EITHER:
(1) The GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at
your option) any later version. The text of the GNU Lesser
General Public License is included with this library in the
file GIMPACT-LICENSE-LGPL.TXT.
(2) The BSD-style license that is included with this library in
the file GIMPACT-LICENSE-BSD.TXT.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.TXT.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
///Additional Headers for Collision
#include "gim_basic_geometry_operations.h"
#include "gim_clip_polygon.h"
#include "gim_box_collision.h"
#include "gim_tri_collision.h"
#endif // GIM_VECTOR_H_INCLUDED

View File

@@ -1,902 +0,0 @@
#ifndef GIM_HASH_TABLE_H_INCLUDED
#define GIM_HASH_TABLE_H_INCLUDED
/*! \file gim_trimesh_data.h
\author Francisco Leon Najera
*/
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This library is free software; you can redistribute it and/or
modify it under the terms of EITHER:
(1) The GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at
your option) any later version. The text of the GNU Lesser
General Public License is included with this library in the
file GIMPACT-LICENSE-LGPL.TXT.
(2) The BSD-style license that is included with this library in
the file GIMPACT-LICENSE-BSD.TXT.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.TXT.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "gim_radixsort.h"
#define GIM_INVALID_HASH 0xffffffff //!< A very very high value
#define GIM_DEFAULT_HASH_TABLE_SIZE 380
#define GIM_DEFAULT_HASH_TABLE_NODE_SIZE 4
#define GIM_HASH_TABLE_GROW_FACTOR 2
#define GIM_MIN_RADIX_SORT_SIZE 860 //!< calibrated on a PIII
template<typename T>
struct GIM_HASH_TABLE_NODE
{
GUINT m_key;
T m_data;
GIM_HASH_TABLE_NODE()
{
}
GIM_HASH_TABLE_NODE(const GIM_HASH_TABLE_NODE & value)
{
m_key = value.m_key;
m_data = value.m_data;
}
GIM_HASH_TABLE_NODE(GUINT key, const T & data)
{
m_key = key;
m_data = data;
}
bool operator <(const GIM_HASH_TABLE_NODE<T> & other) const
{
///inverse order, further objects are first
if(m_key < other.m_key) return true;
return false;
}
bool operator >(const GIM_HASH_TABLE_NODE<T> & other) const
{
///inverse order, further objects are first
if(m_key > other.m_key) return true;
return false;
}
bool operator ==(const GIM_HASH_TABLE_NODE<T> & other) const
{
///inverse order, further objects are first
if(m_key == other.m_key) return true;
return false;
}
};
///Macro for getting the key
class GIM_HASH_NODE_GET_KEY
{
public:
template<class T>
inline GUINT operator()( const T& a)
{
return a.m_key;
}
};
///Macro for comparing the key and the element
class GIM_HASH_NODE_CMP_KEY_MACRO
{
public:
template<class T>
inline int operator() ( const T& a, GUINT key)
{
return ((int)(a.m_key - key));
}
};
///Macro for comparing Hash nodes
class GIM_HASH_NODE_CMP_MACRO
{
public:
template<class T>
inline int operator() ( const T& a, const T& b )
{
return ((int)(a.m_key - b.m_key));
}
};
//! Sorting for hash table
/*!
switch automatically between quicksort and radixsort
*/
template<typename T>
void gim_sort_hash_node_array(T * array, GUINT array_count)
{
if(array_count<GIM_MIN_RADIX_SORT_SIZE)
{
gim_heap_sort(array,array_count,GIM_HASH_NODE_CMP_MACRO());
}
else
{
memcopy_elements_func cmpfunc;
gim_radix_sort(array,array_count,GIM_HASH_NODE_GET_KEY(),cmpfunc);
}
}
// Note: assumes long is at least 32 bits.
#define GIM_NUM_PRIME 28
static const GUINT gim_prime_list[GIM_NUM_PRIME] =
{
53ul, 97ul, 193ul, 389ul, 769ul,
1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
1610612741ul, 3221225473ul, 4294967291ul
};
inline GUINT gim_next_prime(GUINT number)
{
//Find nearest upper prime
GUINT result_ind = 0;
gim_binary_search(gim_prime_list,0,(GIM_NUM_PRIME-2),number,result_ind);
// inv: result_ind < 28
return gim_prime_list[result_ind];
}
//! A compact hash table implementation
/*!
A memory aligned compact hash table that coud be treated as an array.
It could be a simple sorted array without the overhead of the hash key bucked, or could
be a formely hash table with an array of keys.
You can use switch_to_hashtable() and switch_to_sorted_array for saving space or increase speed.
</br>
<ul>
<li> if node_size = 0, then this container becomes a simple sorted array allocator. reserve_size is used for reserve memory in m_nodes.
When the array size reaches the size equivalent to 'min_hash_table_size', then it becomes a hash table by calling check_for_switching_to_hashtable.
<li> If node_size != 0, then this container becomes a hash table for ever
</ul>
*/
template<class T>
class gim_hash_table
{
protected:
typedef GIM_HASH_TABLE_NODE<T> _node_type;
//!The nodes
//array< _node_type, SuperAllocator<_node_type> > m_nodes;
gim_array< _node_type > m_nodes;
//SuperBufferedArray< _node_type > m_nodes;
bool m_sorted;
///Hash table data management. The hash table has the indices to the corresponding m_nodes array
GUINT * m_hash_table;//!<
GUINT m_table_size;//!<
GUINT m_node_size;//!<
GUINT m_min_hash_table_size;
//! Returns the cell index
inline GUINT _find_cell(GUINT hashkey)
{
_node_type * nodesptr = m_nodes.pointer();
GUINT start_index = (hashkey%m_table_size)*m_node_size;
GUINT end_index = start_index + m_node_size;
while(start_index<end_index)
{
GUINT value = m_hash_table[start_index];
if(value != GIM_INVALID_HASH)
{
if(nodesptr[value].m_key == hashkey) return start_index;
}
start_index++;
}
return GIM_INVALID_HASH;
}
//! Find the avaliable cell for the hashkey, and return an existing cell if it has the same hash key
inline GUINT _find_avaliable_cell(GUINT hashkey)
{
_node_type * nodesptr = m_nodes.pointer();
GUINT avaliable_index = GIM_INVALID_HASH;
GUINT start_index = (hashkey%m_table_size)*m_node_size;
GUINT end_index = start_index + m_node_size;
while(start_index<end_index)
{
GUINT value = m_hash_table[start_index];
if(value == GIM_INVALID_HASH)
{
if(avaliable_index==GIM_INVALID_HASH)
{
avaliable_index = start_index;
}
}
else if(nodesptr[value].m_key == hashkey)
{
return start_index;
}
start_index++;
}
return avaliable_index;
}
//! reserves the memory for the hash table.
/*!
\pre hash table must be empty
\post reserves the memory for the hash table, an initializes all elements to GIM_INVALID_HASH.
*/
inline void _reserve_table_memory(GUINT newtablesize)
{
if(newtablesize==0) return;
if(m_node_size==0) return;
//Get a Prime size
m_table_size = gim_next_prime(newtablesize);
GUINT datasize = m_table_size*m_node_size;
//Alloc the data buffer
m_hash_table = (GUINT *)gim_alloc(datasize*sizeof(GUINT));
}
inline void _invalidate_keys()
{
GUINT datasize = m_table_size*m_node_size;
for(GUINT i=0;i<datasize;i++)
{
m_hash_table[i] = GIM_INVALID_HASH;// invalidate keys
}
}
//! Clear all memory for the hash table
inline void _clear_table_memory()
{
if(m_hash_table==NULL) return;
gim_free(m_hash_table);
m_hash_table = NULL;
m_table_size = 0;
}
//! Invalidates the keys (Assigning GIM_INVALID_HASH to all) Reorders the hash keys
inline void _rehash()
{
_invalidate_keys();
_node_type * nodesptr = m_nodes.pointer();
for(GUINT i=0;i<(GUINT)m_nodes.size();i++)
{
GUINT nodekey = nodesptr[i].m_key;
if(nodekey != GIM_INVALID_HASH)
{
//Search for the avaliable cell in buffer
GUINT index = _find_avaliable_cell(nodekey);
if(m_hash_table[index]!=GIM_INVALID_HASH)
{//The new index is alreade used... discard this new incomming object, repeated key
btAssert(m_hash_table[index]==nodekey);
nodesptr[i].m_key = GIM_INVALID_HASH;
}
else
{
//;
//Assign the value for alloc
m_hash_table[index] = i;
}
}
}
}
//! Resize hash table indices
inline void _resize_table(GUINT newsize)
{
//Clear memory
_clear_table_memory();
//Alloc the data
_reserve_table_memory(newsize);
//Invalidate keys and rehash
_rehash();
}
//! Destroy hash table memory
inline void _destroy()
{
if(m_hash_table==NULL) return;
_clear_table_memory();
}
//! Finds an avaliable hash table cell, and resizes the table if there isn't space
inline GUINT _assign_hash_table_cell(GUINT hashkey)
{
GUINT cell_index = _find_avaliable_cell(hashkey);
if(cell_index==GIM_INVALID_HASH)
{
//rehashing
_resize_table(m_table_size+1);
GUINT cell_index = _find_avaliable_cell(hashkey);
btAssert(cell_index!=GIM_INVALID_HASH);
}
return cell_index;
}
//! erase by index in hash table
inline bool _erase_by_index_hash_table(GUINT index)
{
if(index >= m_nodes.size()) return false;
if(m_nodes[index].m_key != GIM_INVALID_HASH)
{
//Search for the avaliable cell in buffer
GUINT cell_index = _find_cell(m_nodes[index].m_key);
btAssert(cell_index!=GIM_INVALID_HASH);
btAssert(m_hash_table[cell_index]==index);
m_hash_table[cell_index] = GIM_INVALID_HASH;
}
return this->_erase_unsorted(index);
}
//! erase by key in hash table
inline bool _erase_hash_table(GUINT hashkey)
{
if(hashkey == GIM_INVALID_HASH) return false;
//Search for the avaliable cell in buffer
GUINT cell_index = _find_cell(hashkey);
if(cell_index ==GIM_INVALID_HASH) return false;
GUINT index = m_hash_table[cell_index];
m_hash_table[cell_index] = GIM_INVALID_HASH;
return this->_erase_unsorted(index);
}
//! insert an element in hash table
/*!
If the element exists, this won't insert the element
\return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
If so, the element has been inserted at the last position of the array.
*/
inline GUINT _insert_hash_table(GUINT hashkey, const T & value)
{
if(hashkey==GIM_INVALID_HASH)
{
//Insert anyway
_insert_unsorted(hashkey,value);
return GIM_INVALID_HASH;
}
GUINT cell_index = _assign_hash_table_cell(hashkey);
GUINT value_key = m_hash_table[cell_index];
if(value_key!= GIM_INVALID_HASH) return value_key;// Not overrited
m_hash_table[cell_index] = m_nodes.size();
_insert_unsorted(hashkey,value);
return GIM_INVALID_HASH;
}
//! insert an element in hash table.
/*!
If the element exists, this replaces the element.
\return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
If so, the element has been inserted at the last position of the array.
*/
inline GUINT _insert_hash_table_replace(GUINT hashkey, const T & value)
{
if(hashkey==GIM_INVALID_HASH)
{
//Insert anyway
_insert_unsorted(hashkey,value);
return GIM_INVALID_HASH;
}
GUINT cell_index = _assign_hash_table_cell(hashkey);
GUINT value_key = m_hash_table[cell_index];
if(value_key!= GIM_INVALID_HASH)
{//replaces the existing
m_nodes[value_key] = _node_type(hashkey,value);
return value_key;// index of the replaced element
}
m_hash_table[cell_index] = m_nodes.size();
_insert_unsorted(hashkey,value);
return GIM_INVALID_HASH;
}
///Sorted array data management. The hash table has the indices to the corresponding m_nodes array
inline bool _erase_sorted(GUINT index)
{
if(index>=(GUINT)m_nodes.size()) return false;
m_nodes.erase_sorted(index);
if(m_nodes.size()<2) m_sorted = false;
return true;
}
//! faster, but unsorted
inline bool _erase_unsorted(GUINT index)
{
if(index>=m_nodes.size()) return false;
GUINT lastindex = m_nodes.size()-1;
if(index<lastindex && m_hash_table!=0)
{
GUINT hashkey = m_nodes[lastindex].m_key;
if(hashkey!=GIM_INVALID_HASH)
{
//update the new position of the last element
GUINT cell_index = _find_cell(hashkey);
btAssert(cell_index!=GIM_INVALID_HASH);
//new position of the last element which will be swaped
m_hash_table[cell_index] = index;
}
}
m_nodes.erase(index);
m_sorted = false;
return true;
}
//! Insert in position ordered
/*!
Also checks if it is needed to transform this container to a hash table, by calling check_for_switching_to_hashtable
*/
inline void _insert_in_pos(GUINT hashkey, const T & value, GUINT pos)
{
m_nodes.insert(_node_type(hashkey,value),pos);
this->check_for_switching_to_hashtable();
}
//! Insert an element in an ordered array
inline GUINT _insert_sorted(GUINT hashkey, const T & value)
{
if(hashkey==GIM_INVALID_HASH || size()==0)
{
m_nodes.push_back(_node_type(hashkey,value));
return GIM_INVALID_HASH;
}
//Insert at last position
//Sort element
GUINT result_ind=0;
GUINT last_index = m_nodes.size()-1;
_node_type * ptr = m_nodes.pointer();
bool found = gim_binary_search_ex(
ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO());
//Insert before found index
if(found)
{
return result_ind;
}
else
{
_insert_in_pos(hashkey, value, result_ind);
}
return GIM_INVALID_HASH;
}
inline GUINT _insert_sorted_replace(GUINT hashkey, const T & value)
{
if(hashkey==GIM_INVALID_HASH || size()==0)
{
m_nodes.push_back(_node_type(hashkey,value));
return GIM_INVALID_HASH;
}
//Insert at last position
//Sort element
GUINT result_ind;
GUINT last_index = m_nodes.size()-1;
_node_type * ptr = m_nodes.pointer();
bool found = gim_binary_search_ex(
ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO());
//Insert before found index
if(found)
{
m_nodes[result_ind] = _node_type(hashkey,value);
}
else
{
_insert_in_pos(hashkey, value, result_ind);
}
return result_ind;
}
//! Fast insertion in m_nodes array
inline GUINT _insert_unsorted(GUINT hashkey, const T & value)
{
m_nodes.push_back(_node_type(hashkey,value));
m_sorted = false;
return GIM_INVALID_HASH;
}
public:
/*!
<li> if node_size = 0, then this container becomes a simple sorted array allocator. reserve_size is used for reserve memory in m_nodes.
When the array size reaches the size equivalent to 'min_hash_table_size', then it becomes a hash table by calling check_for_switching_to_hashtable.
<li> If node_size != 0, then this container becomes a hash table for ever
</ul>
*/
gim_hash_table(GUINT reserve_size = GIM_DEFAULT_HASH_TABLE_SIZE,
GUINT node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE,
GUINT min_hash_table_size = GIM_INVALID_HASH)
{
m_hash_table = NULL;
m_table_size = 0;
m_sorted = false;
m_node_size = node_size;
m_min_hash_table_size = min_hash_table_size;
if(m_node_size!=0)
{
if(reserve_size!=0)
{
m_nodes.reserve(reserve_size);
_reserve_table_memory(reserve_size);
_invalidate_keys();
}
else
{
m_nodes.reserve(GIM_DEFAULT_HASH_TABLE_SIZE);
_reserve_table_memory(GIM_DEFAULT_HASH_TABLE_SIZE);
_invalidate_keys();
}
}
else if(reserve_size!=0)
{
m_nodes.reserve(reserve_size);
}
}
~gim_hash_table()
{
_destroy();
}
inline bool is_hash_table()
{
if(m_hash_table) return true;
return false;
}
inline bool is_sorted()
{
if(size()<2) return true;
return m_sorted;
}
bool sort()
{
if(is_sorted()) return true;
if(m_nodes.size()<2) return false;
_node_type * ptr = m_nodes.pointer();
GUINT siz = m_nodes.size();
gim_sort_hash_node_array(ptr,siz);
m_sorted=true;
if(m_hash_table)
{
_rehash();
}
return true;
}
bool switch_to_hashtable()
{
if(m_hash_table) return false;
if(m_node_size==0) m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE;
if(m_nodes.size()<GIM_DEFAULT_HASH_TABLE_SIZE)
{
_resize_table(GIM_DEFAULT_HASH_TABLE_SIZE);
}
else
{
_resize_table(m_nodes.size()+1);
}
return true;
}
bool switch_to_sorted_array()
{
if(m_hash_table==NULL) return true;
_clear_table_memory();
return sort();
}
//!If the container reaches the
bool check_for_switching_to_hashtable()
{
if(this->m_hash_table) return true;
if(!(m_nodes.size()< m_min_hash_table_size))
{
if(m_node_size == 0)
{
m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE;
}
_resize_table(m_nodes.size()+1);
return true;
}
return false;
}
inline void set_sorted(bool value)
{
m_sorted = value;
}
//! Retrieves the amount of keys.
inline GUINT size() const
{
return m_nodes.size();
}
//! Retrieves the hash key.
inline GUINT get_key(GUINT index) const
{
return m_nodes[index].m_key;
}
//! Retrieves the value by index
/*!
*/
inline T * get_value_by_index(GUINT index)
{
return &m_nodes[index].m_data;
}
inline const T& operator[](GUINT index) const
{
return m_nodes[index].m_data;
}
inline T& operator[](GUINT index)
{
return m_nodes[index].m_data;
}
//! Finds the index of the element with the key
/*!
\return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
If so, the element has been inserted at the last position of the array.
*/
inline GUINT find(GUINT hashkey)
{
if(m_hash_table)
{
GUINT cell_index = _find_cell(hashkey);
if(cell_index==GIM_INVALID_HASH) return GIM_INVALID_HASH;
return m_hash_table[cell_index];
}
GUINT last_index = m_nodes.size();
if(last_index<2)
{
if(last_index==0) return GIM_INVALID_HASH;
if(m_nodes[0].m_key == hashkey) return 0;
return GIM_INVALID_HASH;
}
else if(m_sorted)
{
//Binary search
GUINT result_ind = 0;
last_index--;
_node_type * ptr = m_nodes.pointer();
bool found = gim_binary_search_ex(ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO());
if(found) return result_ind;
}
return GIM_INVALID_HASH;
}
//! Retrieves the value associated with the index
/*!
\return the found element, or null
*/
inline T * get_value(GUINT hashkey)
{
GUINT index = find(hashkey);
if(index == GIM_INVALID_HASH) return NULL;
return &m_nodes[index].m_data;
}
/*!
*/
inline bool erase_by_index(GUINT index)
{
if(index > m_nodes.size()) return false;
if(m_hash_table == NULL)
{
if(is_sorted())
{
return this->_erase_sorted(index);
}
else
{
return this->_erase_unsorted(index);
}
}
else
{
return this->_erase_by_index_hash_table(index);
}
return false;
}
inline bool erase_by_index_unsorted(GUINT index)
{
if(index > m_nodes.size()) return false;
if(m_hash_table == NULL)
{
return this->_erase_unsorted(index);
}
else
{
return this->_erase_by_index_hash_table(index);
}
return false;
}
/*!
*/
inline bool erase_by_key(GUINT hashkey)
{
if(size()==0) return false;
if(m_hash_table)
{
return this->_erase_hash_table(hashkey);
}
//Binary search
if(is_sorted()==false) return false;
GUINT result_ind = find(hashkey);
if(result_ind!= GIM_INVALID_HASH)
{
return this->_erase_sorted(result_ind);
}
return false;
}
void clear()
{
m_nodes.clear();
if(m_hash_table==NULL) return;
GUINT datasize = m_table_size*m_node_size;
//Initialize the hashkeys.
GUINT i;
for(i=0;i<datasize;i++)
{
m_hash_table[i] = GIM_INVALID_HASH;// invalidate keys
}
m_sorted = false;
}
//! Insert an element into the hash
/*!
\return If GIM_INVALID_HASH, the object has been inserted succesfully. Else it returns the position
of the existing element.
*/
inline GUINT insert(GUINT hashkey, const T & element)
{
if(m_hash_table)
{
return this->_insert_hash_table(hashkey,element);
}
if(this->is_sorted())
{
return this->_insert_sorted(hashkey,element);
}
return this->_insert_unsorted(hashkey,element);
}
//! Insert an element into the hash, and could overrite an existing object with the same hash.
/*!
\return If GIM_INVALID_HASH, the object has been inserted succesfully. Else it returns the position
of the replaced element.
*/
inline GUINT insert_override(GUINT hashkey, const T & element)
{
if(m_hash_table)
{
return this->_insert_hash_table_replace(hashkey,element);
}
if(this->is_sorted())
{
return this->_insert_sorted_replace(hashkey,element);
}
this->_insert_unsorted(hashkey,element);
return m_nodes.size();
}
//! Insert an element into the hash,But if this container is a sorted array, this inserts it unsorted
/*!
*/
inline GUINT insert_unsorted(GUINT hashkey,const T & element)
{
if(m_hash_table)
{
return this->_insert_hash_table(hashkey,element);
}
return this->_insert_unsorted(hashkey,element);
}
};
#endif // GIM_CONTAINERS_H_INCLUDED

File diff suppressed because it is too large Load Diff

View File

@@ -1,157 +0,0 @@
#ifndef GIM_MATH_H_INCLUDED
#define GIM_MATH_H_INCLUDED
/*! \file gim_math.h
\author Francisco Leon Najera
*/
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This library is free software; you can redistribute it and/or
modify it under the terms of EITHER:
(1) The GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at
your option) any later version. The text of the GNU Lesser
General Public License is included with this library in the
file GIMPACT-LICENSE-LGPL.TXT.
(2) The BSD-style license that is included with this library in
the file GIMPACT-LICENSE-BSD.TXT.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.TXT.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "LinearMath/btScalar.h"
#define GREAL btScalar
#define GREAL2 double
#define GINT int
#define GUINT unsigned int
#define GSHORT short
#define GUSHORT unsigned short
#define GINT64 long long
#define GUINT64 unsigned long long
#define G_PI 3.14159265358979f
#define G_HALF_PI 1.5707963f
//267948966
#define G_TWO_PI 6.28318530f
//71795864
#define G_ROOT3 1.73205f
#define G_ROOT2 1.41421f
#define G_UINT_INFINITY 0xffffffff //!< A very very high value
#define G_REAL_INFINITY FLT_MAX
#define G_SIGN_BITMASK 0x80000000
#define G_EPSILON SIMD_EPSILON
enum GIM_SCALAR_TYPES
{
G_STYPE_REAL =0,
G_STYPE_REAL2,
G_STYPE_SHORT,
G_STYPE_USHORT,
G_STYPE_INT,
G_STYPE_UINT,
G_STYPE_INT64,
G_STYPE_UINT64
};
#define G_DEGTORAD(X) ((X)*3.1415926f/180.0f)
#define G_RADTODEG(X) ((X)*180.0f/3.1415926f)
//! Integer representation of a floating-point value.
#define GIM_IR(x) ((GUINT&)(x))
//! Signed integer representation of a floating-point value.
#define GIM_SIR(x) ((GINT&)(x))
//! Absolute integer representation of a floating-point value
#define GIM_AIR(x) (GIM_IR(x)&0x7fffffff)
//! Floating-point representation of an integer value.
#define GIM_FR(x) ((GREAL&)(x))
#define GIM_MAX(a,b) (a<b?b:a)
#define GIM_MIN(a,b) (a>b?b:a)
#define GIM_MAX3(a,b,c) GIM_MAX(a,GIM_MAX(b,c))
#define GIM_MIN3(a,b,c) GIM_MIN(a,GIM_MIN(b,c))
#define GIM_IS_ZERO(value) (value < G_EPSILON && value > -G_EPSILON)
#define GIM_IS_NEGATIVE(value) (value <= -G_EPSILON)
#define GIM_IS_POSISITVE(value) (value >= G_EPSILON)
#define GIM_NEAR_EQUAL(v1,v2) GIM_IS_ZERO((v1-v2))
///returns a clamped number
#define GIM_CLAMP(number,minval,maxval) (number<minval?minval:(number>maxval?maxval:number))
#define GIM_GREATER(x, y) btFabs(x) > (y)
///Swap numbers
#define GIM_SWAP_NUMBERS(a,b){ \
a = a+b; \
b = a-b; \
a = a-b; \
}\
#define GIM_INV_SQRT(va,isva)\
{\
if(va<=0.0000001f)\
{\
isva = G_REAL_INFINITY;\
}\
else\
{\
GREAL _x = va * 0.5f;\
GUINT _y = 0x5f3759df - ( GIM_IR(va) >> 1);\
isva = GIM_FR(_y);\
isva = isva * ( 1.5f - ( _x * isva * isva ) );\
}\
}\
#define GIM_SQRT(va,sva)\
{\
GIM_INV_SQRT(va,sva);\
sva = 1.0f/sva;\
}\
//! Computes 1.0f / sqrtf(x). Comes from Quake3. See http://www.magic-software.com/3DGEDInvSqrt.html
inline GREAL gim_inv_sqrt(GREAL f)
{
GREAL r;
GIM_INV_SQRT(f,r);
return r;
}
inline GREAL gim_sqrt(GREAL f)
{
GREAL r;
GIM_SQRT(f,r);
return r;
}
#endif // GIM_MATH_H_INCLUDED

View File

@@ -1,135 +0,0 @@
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This library is free software; you can redistribute it and/or
modify it under the terms of EITHER:
(1) The GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at
your option) any later version. The text of the GNU Lesser
General Public License is included with this library in the
file GIMPACT-LICENSE-LGPL.TXT.
(2) The BSD-style license that is included with this library in
the file GIMPACT-LICENSE-BSD.TXT.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.TXT.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "gim_memory.h"
#include "stdlib.h"
#ifdef GIM_SIMD_MEMORY
#include "LinearMath/btAlignedAllocator.h"
#endif
static gim_alloc_function *g_allocfn = 0;
static gim_alloca_function *g_allocafn = 0;
static gim_realloc_function *g_reallocfn = 0;
static gim_free_function *g_freefn = 0;
void gim_set_alloc_handler (gim_alloc_function *fn)
{
g_allocfn = fn;
}
void gim_set_alloca_handler (gim_alloca_function *fn)
{
g_allocafn = fn;
}
void gim_set_realloc_handler (gim_realloc_function *fn)
{
g_reallocfn = fn;
}
void gim_set_free_handler (gim_free_function *fn)
{
g_freefn = fn;
}
gim_alloc_function *gim_get_alloc_handler()
{
return g_allocfn;
}
gim_alloca_function *gim_get_alloca_handler()
{
return g_allocafn;
}
gim_realloc_function *gim_get_realloc_handler ()
{
return g_reallocfn;
}
gim_free_function *gim_get_free_handler ()
{
return g_freefn;
}
void * gim_alloc(size_t size)
{
void * ptr;
if (g_allocfn)
{
ptr = g_allocfn(size);
}
else
{
#ifdef GIM_SIMD_MEMORY
ptr = btAlignedAlloc(size,16);
#else
ptr = malloc(size);
#endif
}
return ptr;
}
void * gim_alloca(size_t size)
{
if (g_allocafn) return g_allocafn(size); else return gim_alloc(size);
}
void * gim_realloc(void *ptr, size_t oldsize, size_t newsize)
{
void * newptr = gim_alloc(newsize);
size_t copysize = oldsize<newsize?oldsize:newsize;
gim_simd_memcpy(newptr,ptr,copysize);
gim_free(ptr);
return newptr;
}
void gim_free(void *ptr)
{
if (!ptr) return;
if (g_freefn)
{
g_freefn(ptr);
}
else
{
#ifdef GIM_SIMD_MEMORY
btAlignedFree(ptr);
#else
free(ptr);
#endif
}
}

View File

@@ -1,190 +0,0 @@
#ifndef GIM_MEMORY_H_INCLUDED
#define GIM_MEMORY_H_INCLUDED
/*! \file gim_memory.h
\author Francisco Leon Najera
*/
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This library is free software; you can redistribute it and/or
modify it under the terms of EITHER:
(1) The GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at
your option) any later version. The text of the GNU Lesser
General Public License is included with this library in the
file GIMPACT-LICENSE-LGPL.TXT.
(2) The BSD-style license that is included with this library in
the file GIMPACT-LICENSE-BSD.TXT.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.TXT.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "gim_math.h"
#include <string.h>
#ifdef PREFETCH
#include <xmmintrin.h> // for prefetch
#define pfval 64
#define pfval2 128
//! Prefetch 64
#define pf(_x,_i) _mm_prefetch((void *)(_x + _i + pfval), 0)
//! Prefetch 128
#define pf2(_x,_i) _mm_prefetch((void *)(_x + _i + pfval2), 0)
#else
//! Prefetch 64
#define pf(_x,_i)
//! Prefetch 128
#define pf2(_x,_i)
#endif
///Functions for manip packed arrays of numbers
#define GIM_COPY_ARRAYS(dest_array,source_array,element_count)\
{\
for (GUINT _i_=0;_i_<element_count ;++_i_)\
{\
dest_array[_i_] = source_array[_i_];\
}\
}\
#define GIM_COPY_ARRAYS_1(dest_array,source_array,element_count,copy_macro)\
{\
for (GUINT _i_=0;_i_<element_count ;++_i_)\
{\
copy_macro(dest_array[_i_],source_array[_i_]);\
}\
}\
#define GIM_ZERO_ARRAY(array,element_count)\
{\
for (GUINT _i_=0;_i_<element_count ;++_i_)\
{\
array[_i_] = 0;\
}\
}\
#define GIM_CONSTANT_ARRAY(array,element_count,constant)\
{\
for (GUINT _i_=0;_i_<element_count ;++_i_)\
{\
array[_i_] = constant;\
}\
}\
///Function prototypes to allocate and free memory.
typedef void * gim_alloc_function (size_t size);
typedef void * gim_alloca_function (size_t size);//Allocs on the heap
typedef void * gim_realloc_function (void *ptr, size_t oldsize, size_t newsize);
typedef void gim_free_function (void *ptr);
///Memory Function Handlers
///set new memory management functions. if fn is 0, the default handlers are used.
void gim_set_alloc_handler (gim_alloc_function *fn);
void gim_set_alloca_handler (gim_alloca_function *fn);
void gim_set_realloc_handler (gim_realloc_function *fn);
void gim_set_free_handler (gim_free_function *fn);
///get current memory management functions.
gim_alloc_function *gim_get_alloc_handler (void);
gim_alloca_function *gim_get_alloca_handler(void);
gim_realloc_function *gim_get_realloc_handler (void);
gim_free_function *gim_get_free_handler (void);
///Standar Memory functions
void * gim_alloc(size_t size);
void * gim_alloca(size_t size);
void * gim_realloc(void *ptr, size_t oldsize, size_t newsize);
void gim_free(void *ptr);
#if defined (_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
#define GIM_SIMD_MEMORY 1
#endif
//! SIMD POINTER INTEGER
#define SIMD_T GUINT64
//! SIMD INTEGER SIZE
#define SIMD_T_SIZE sizeof(SIMD_T)
inline void gim_simd_memcpy(void * dst, const void * src, size_t copysize)
{
#ifdef GIM_SIMD_MEMORY
/*
//'long long int' is incompatible with visual studio 6...
//copy words
SIMD_T * ui_src_ptr = (SIMD_T *)src;
SIMD_T * ui_dst_ptr = (SIMD_T *)dst;
while(copysize>=SIMD_T_SIZE)
{
*(ui_dst_ptr++) = *(ui_src_ptr++);
copysize-=SIMD_T_SIZE;
}
if(copysize==0) return;
*/
char * c_src_ptr = (char *)src;
char * c_dst_ptr = (char *)dst;
while(copysize>0)
{
*(c_dst_ptr++) = *(c_src_ptr++);
copysize--;
}
return;
#else
memcpy(dst,src,copysize);
#endif
}
template<class T>
inline void gim_swap_elements(T* _array,size_t _i,size_t _j)
{
T _e_tmp_ = _array[_i];
_array[_i] = _array[_j];
_array[_j] = _e_tmp_;
}
template<class T>
inline void gim_swap_elements_memcpy(T* _array,size_t _i,size_t _j)
{
char _e_tmp_[sizeof(T)];
gim_simd_memcpy(_e_tmp_,&_array[_i],sizeof(T));
gim_simd_memcpy(&_array[_i],&_array[_j],sizeof(T));
gim_simd_memcpy(&_array[_j],_e_tmp_,sizeof(T));
}
template <int SIZE>
inline void gim_swap_elements_ptr(char * _array,size_t _i,size_t _j)
{
char _e_tmp_[SIZE];
_i*=SIZE;
_j*=SIZE;
gim_simd_memcpy(_e_tmp_,_array+_i,SIZE);
gim_simd_memcpy(_array+_i,_array+_j,SIZE);
gim_simd_memcpy(_array+_j,_e_tmp_,SIZE);
}
#endif // GIM_MEMORY_H_INCLUDED

View File

@@ -1,406 +0,0 @@
#ifndef GIM_RADIXSORT_H_INCLUDED
#define GIM_RADIXSORT_H_INCLUDED
/*! \file gim_radixsort.h
\author Francisco Leon Najera.
Based on the work of Michael Herf : "fast floating-point radix sort"
Avaliable on http://www.stereopsis.com/radix.html
*/
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This library is free software; you can redistribute it and/or
modify it under the terms of EITHER:
(1) The GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at
your option) any later version. The text of the GNU Lesser
General Public License is included with this library in the
file GIMPACT-LICENSE-LGPL.TXT.
(2) The BSD-style license that is included with this library in
the file GIMPACT-LICENSE-BSD.TXT.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.TXT.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "gim_memory.h"
///Macros for sorting.
//! Prototype for comparators
class less_comparator
{
public:
template<class T,class Z>
inline int operator() ( const T& a, const Z& b )
{
return ( a<b?-1:(a>b?1:0));
}
};
//! Prototype for comparators
class integer_comparator
{
public:
template<class T>
inline int operator() ( const T& a, const T& b )
{
return (int)(a-b);
}
};
//!Prototype for getting the integer representation of an object
class uint_key_func
{
public:
template<class T>
inline GUINT operator()( const T& a)
{
return (GUINT)a;
}
};
//!Prototype for copying elements
class copy_elements_func
{
public:
template<class T>
inline void operator()(T& a,T& b)
{
a = b;
}
};
//!Prototype for copying elements
class memcopy_elements_func
{
public:
template<class T>
inline void operator()(T& a,T& b)
{
gim_simd_memcpy(&a,&b,sizeof(T));
}
};
//! @{
struct GIM_RSORT_TOKEN
{
GUINT m_key;
GUINT m_value;
GIM_RSORT_TOKEN()
{
}
GIM_RSORT_TOKEN(const GIM_RSORT_TOKEN& rtoken)
{
m_key = rtoken.m_key;
m_value = rtoken.m_value;
}
inline bool operator <(const GIM_RSORT_TOKEN& other) const
{
return (m_key < other.m_key);
}
inline bool operator >(const GIM_RSORT_TOKEN& other) const
{
return (m_key > other.m_key);
}
};
//! Prototype for comparators
class GIM_RSORT_TOKEN_COMPARATOR
{
public:
inline int operator()( const GIM_RSORT_TOKEN& a, const GIM_RSORT_TOKEN& b )
{
return (int)((a.m_key) - (b.m_key));
}
};
#define kHist 2048
// ---- utils for accessing 11-bit quantities
#define D11_0(x) (x & 0x7FF)
#define D11_1(x) (x >> 11 & 0x7FF)
#define D11_2(x) (x >> 22 )
///Radix sort for unsigned integer keys
inline void gim_radix_sort_rtokens(
GIM_RSORT_TOKEN * array,
GIM_RSORT_TOKEN * sorted, GUINT element_count)
{
GUINT i;
GUINT b0[kHist * 3];
GUINT *b1 = b0 + kHist;
GUINT *b2 = b1 + kHist;
for (i = 0; i < kHist * 3; ++i)
{
b0[i] = 0;
}
GUINT fi;
GUINT pos;
for (i = 0; i < element_count; ++i)
{
fi = array[i].m_key;
b0[D11_0(fi)] ++;
b1[D11_1(fi)] ++;
b2[D11_2(fi)] ++;
}
{
GUINT sum0 = 0, sum1 = 0, sum2 = 0;
GUINT tsum;
for (i = 0; i < kHist; ++i)
{
tsum = b0[i] + sum0;
b0[i] = sum0 - 1;
sum0 = tsum;
tsum = b1[i] + sum1;
b1[i] = sum1 - 1;
sum1 = tsum;
tsum = b2[i] + sum2;
b2[i] = sum2 - 1;
sum2 = tsum;
}
}
for (i = 0; i < element_count; ++i)
{
fi = array[i].m_key;
pos = D11_0(fi);
pos = ++b0[pos];
sorted[pos].m_key = array[i].m_key;
sorted[pos].m_value = array[i].m_value;
}
for (i = 0; i < element_count; ++i)
{
fi = sorted[i].m_key;
pos = D11_1(fi);
pos = ++b1[pos];
array[pos].m_key = sorted[i].m_key;
array[pos].m_value = sorted[i].m_value;
}
for (i = 0; i < element_count; ++i)
{
fi = array[i].m_key;
pos = D11_2(fi);
pos = ++b2[pos];
sorted[pos].m_key = array[i].m_key;
sorted[pos].m_value = array[i].m_value;
}
}
/// Get the sorted tokens from an array. For generic use. Tokens are IRR_RSORT_TOKEN
/*!
*\param array Array of elements to sort
*\param sorted_tokens Tokens of sorted elements
*\param element_count element count
*\param uintkey_macro Functor which retrieves the integer representation of an array element
*/
template<typename T, class GETKEY_CLASS>
void gim_radix_sort_array_tokens(
T* array ,
GIM_RSORT_TOKEN * sorted_tokens,
GUINT element_count,GETKEY_CLASS uintkey_macro)
{
GIM_RSORT_TOKEN * _unsorted = (GIM_RSORT_TOKEN *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*element_count);
for (GUINT _i=0;_i<element_count;++_i)
{
_unsorted[_i].m_key = uintkey_macro(array[_i]);
_unsorted[_i].m_value = _i;
}
gim_radix_sort_rtokens(_unsorted,sorted_tokens,element_count);
gim_free(_unsorted);
gim_free(_unsorted);
}
/// Sorts array in place. For generic use
/*!
\param type Type of the array
\param array
\param element_count
\param get_uintkey_macro Macro for extract the Integer value of the element. Similar to SIMPLE_GET_UINTKEY
\param copy_elements_macro Macro for copy elements, similar to SIMPLE_COPY_ELEMENTS
*/
template<typename T, class GETKEY_CLASS, class COPY_CLASS>
void gim_radix_sort(
T * array, GUINT element_count,
GETKEY_CLASS get_uintkey_macro, COPY_CLASS copy_elements_macro)
{
GIM_RSORT_TOKEN * _sorted = (GIM_RSORT_TOKEN *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*element_count);
gim_radix_sort_array_tokens(array,_sorted,element_count,get_uintkey_macro);
T * _original_array = (T *) gim_alloc(sizeof(T)*element_count);
gim_simd_memcpy(_original_array,array,sizeof(T)*element_count);
for (GUINT _i=0;_i<element_count;++_i)
{
copy_elements_macro(array[_i],_original_array[_sorted[_i].m_value]);
}
gim_free(_original_array);
gim_free(_sorted);
}
//! Failsafe Iterative binary search,
/*!
If the element is not found, it returns the nearest upper element position, may be the further position after the last element.
\param _array
\param _start_i the beginning of the array
\param _end_i the ending index of the array
\param _search_key Value to find
\param _comp_macro macro for comparing elements
\param _found If true the value has found. Boolean
\param _result_index the index of the found element, or if not found then it will get the index of the closest bigger value
*/
template<class T, typename KEYCLASS, typename COMP_CLASS>
bool gim_binary_search_ex(
const T* _array, GUINT _start_i,
GUINT _end_i,GUINT & _result_index,
const KEYCLASS & _search_key,
COMP_CLASS _comp_macro)
{
GUINT _k;
int _comp_result;
GUINT _i = _start_i;
GUINT _j = _end_i+1;
while (_i < _j)
{
_k = (_j+_i-1)/2;
_comp_result = _comp_macro(_array[_k], _search_key);
if (_comp_result == 0)
{
_result_index = _k;
return true;
}
else if (_comp_result < 0)
{
_i = _k+1;
}
else
{
_j = _k;
}
}
_result_index = _i;
return false;
}
//! Failsafe Iterative binary search,Template version
/*!
If the element is not found, it returns the nearest upper element position, may be the further position after the last element.
\param _array
\param _start_i the beginning of the array
\param _end_i the ending index of the array
\param _search_key Value to find
\param _result_index the index of the found element, or if not found then it will get the index of the closest bigger value
\return true if found, else false
*/
template<class T>
bool gim_binary_search(
const T*_array,GUINT _start_i,
GUINT _end_i,const T & _search_key,
GUINT & _result_index)
{
GUINT _i = _start_i;
GUINT _j = _end_i+1;
GUINT _k;
while(_i < _j)
{
_k = (_j+_i-1)/2;
if(_array[_k]==_search_key)
{
_result_index = _k;
return true;
}
else if (_array[_k]<_search_key)
{
_i = _k+1;
}
else
{
_j = _k;
}
}
_result_index = _i;
return false;
}
///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
template <typename T, typename COMP_CLASS>
void gim_down_heap(T *pArr, GUINT k, GUINT n,COMP_CLASS CompareFunc)
{
/* PRE: a[k+1..N] is a heap */
/* POST: a[k..N] is a heap */
T temp = pArr[k - 1];
/* k has child(s) */
while (k <= n/2)
{
int child = 2*k;
if ((child < (int)n) && CompareFunc(pArr[child - 1] , pArr[child])<0)
{
child++;
}
/* pick larger child */
if (CompareFunc(temp , pArr[child - 1])<0)
{
/* move child up */
pArr[k - 1] = pArr[child - 1];
k = child;
}
else
{
break;
}
}
pArr[k - 1] = temp;
} /*downHeap*/
template <typename T, typename COMP_CLASS>
void gim_heap_sort(T *pArr, GUINT element_count, COMP_CLASS CompareFunc)
{
/* sort a[0..N-1], N.B. 0 to N-1 */
GUINT k;
GUINT n = element_count;
for (k = n/2; k > 0; k--)
{
gim_down_heap(pArr, k, n, CompareFunc);
}
/* a[1..N] is now a heap */
while ( n>=2 )
{
gim_swap_elements(pArr,0,n-1); /* largest of a[0..n-1] */
--n;
/* restore a[1..i-1] heap */
gim_down_heap(pArr, 1, n, CompareFunc);
}
}
#endif // GIM_RADIXSORT_H_INCLUDED

View File

@@ -1,640 +0,0 @@
/*! \file gim_tri_collision.h
\author Francisco Leon Najera
*/
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This library is free software; you can redistribute it and/or
modify it under the terms of EITHER:
(1) The GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at
your option) any later version. The text of the GNU Lesser
General Public License is included with this library in the
file GIMPACT-LICENSE-LGPL.TXT.
(2) The BSD-style license that is included with this library in
the file GIMPACT-LICENSE-BSD.TXT.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.TXT.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "gim_tri_collision.h"
#define TRI_LOCAL_EPSILON 0.000001f
#define MIN_EDGE_EDGE_DIS 0.00001f
class GIM_TRIANGLE_CALCULATION_CACHE
{
public:
GREAL margin;
btVector3 tu_vertices[3];
btVector3 tv_vertices[3];
btVector4 tu_plane;
btVector4 tv_plane;
btVector3 closest_point_u;
btVector3 closest_point_v;
btVector3 edge_edge_dir;
btVector3 distances;
GREAL du[4];
GREAL du0du1;
GREAL du0du2;
GREAL dv[4];
GREAL dv0dv1;
GREAL dv0dv2;
btVector3 temp_points[MAX_TRI_CLIPPING];
btVector3 temp_points1[MAX_TRI_CLIPPING];
btVector3 contact_points[MAX_TRI_CLIPPING];
//! if returns false, the faces are paralele
SIMD_FORCE_INLINE bool compute_intervals(
const GREAL &D0,
const GREAL &D1,
const GREAL &D2,
const GREAL &D0D1,
const GREAL &D0D2,
GREAL & scale_edge0,
GREAL & scale_edge1,
GUINT &edge_index0,
GUINT &edge_index1)
{
if(D0D1>0.0f)
{
/* here we know that D0D2<=0.0 */
/* that is D0, D1 are on the same side, D2 on the other or on the plane */
scale_edge0 = -D2/(D0-D2);
scale_edge1 = -D1/(D2-D1);
edge_index0 = 2;edge_index1 = 1;
}
else if(D0D2>0.0f)
{
/* here we know that d0d1<=0.0 */
scale_edge0 = -D0/(D1-D0);
scale_edge1 = -D1/(D2-D1);
edge_index0 = 0;edge_index1 = 1;
}
else if(D1*D2>0.0f || D0!=0.0f)
{
/* here we know that d0d1<=0.0 or that D0!=0.0 */
scale_edge0 = -D0/(D1-D0);
scale_edge1 = -D2/(D0-D2);
edge_index0 = 0 ;edge_index1 = 2;
}
else
{
return false;
}
return true;
}
//! clip triangle
/*!
*/
SIMD_FORCE_INLINE GUINT clip_triangle(
const btVector4 & tri_plane,
const btVector3 * tripoints,
const btVector3 * srcpoints,
btVector3 * clip_points)
{
// edge 0
btVector4 edgeplane;
EDGE_PLANE(tripoints[0],tripoints[1],tri_plane,edgeplane);
GUINT clipped_count = PLANE_CLIP_TRIANGLE3D(
edgeplane,srcpoints[0],srcpoints[1],srcpoints[2],temp_points);
if(clipped_count == 0) return 0;
// edge 1
EDGE_PLANE(tripoints[1],tripoints[2],tri_plane,edgeplane);
clipped_count = PLANE_CLIP_POLYGON3D(
edgeplane,temp_points,clipped_count,temp_points1);
if(clipped_count == 0) return 0;
// edge 2
EDGE_PLANE(tripoints[2],tripoints[0],tri_plane,edgeplane);
clipped_count = PLANE_CLIP_POLYGON3D(
edgeplane,temp_points1,clipped_count,clip_points);
return clipped_count;
/*GUINT i0 = (tri_plane.closestAxis()+1)%3;
GUINT i1 = (i0+1)%3;
// edge 0
btVector3 temp_points[MAX_TRI_CLIPPING];
btVector3 temp_points1[MAX_TRI_CLIPPING];
GUINT clipped_count= PLANE_CLIP_TRIANGLE_GENERIC(
0,srcpoints[0],srcpoints[1],srcpoints[2],temp_points,
DISTANCE_EDGE(tripoints[0],tripoints[1],i0,i1));
if(clipped_count == 0) return 0;
// edge 1
clipped_count = PLANE_CLIP_POLYGON_GENERIC(
0,temp_points,clipped_count,temp_points1,
DISTANCE_EDGE(tripoints[1],tripoints[2],i0,i1));
if(clipped_count == 0) return 0;
// edge 2
clipped_count = PLANE_CLIP_POLYGON_GENERIC(
0,temp_points1,clipped_count,clipped_points,
DISTANCE_EDGE(tripoints[2],tripoints[0],i0,i1));
return clipped_count;*/
}
SIMD_FORCE_INLINE void sort_isect(
GREAL & isect0,GREAL & isect1,GUINT &e0,GUINT &e1,btVector3 & vec0,btVector3 & vec1)
{
if(isect1<isect0)
{
//swap
GIM_SWAP_NUMBERS(isect0,isect1);
GIM_SWAP_NUMBERS(e0,e1);
btVector3 tmp = vec0;
vec0 = vec1;
vec1 = tmp;
}
}
//! Test verifying interval intersection with the direction between planes
/*!
\pre tv_plane and tu_plane must be set
\post
distances[2] is set with the distance
closest_point_u, closest_point_v, edge_edge_dir are set too
\return
- 0: faces are paralele
- 1: face U casts face V
- 2: face V casts face U
- 3: nearest edges
*/
SIMD_FORCE_INLINE GUINT cross_line_intersection_test()
{
// Compute direction of intersection line
edge_edge_dir = tu_plane.cross(tv_plane);
GREAL Dlen;
VEC_LENGTH(edge_edge_dir,Dlen);
if(Dlen<0.0001)
{
return 0; //faces near paralele
}
edge_edge_dir*= 1/Dlen;//normalize
// Compute interval for triangle 1
GUINT tu_e0,tu_e1;//edge indices
GREAL tu_scale_e0,tu_scale_e1;//edge scale
if(!compute_intervals(du[0],du[1],du[2],
du0du1,du0du2,tu_scale_e0,tu_scale_e1,tu_e0,tu_e1)) return 0;
// Compute interval for triangle 2
GUINT tv_e0,tv_e1;//edge indices
GREAL tv_scale_e0,tv_scale_e1;//edge scale
if(!compute_intervals(dv[0],dv[1],dv[2],
dv0dv1,dv0dv2,tv_scale_e0,tv_scale_e1,tv_e0,tv_e1)) return 0;
//proyected vertices
btVector3 up_e0 = tu_vertices[tu_e0].lerp(tu_vertices[(tu_e0+1)%3],tu_scale_e0);
btVector3 up_e1 = tu_vertices[tu_e1].lerp(tu_vertices[(tu_e1+1)%3],tu_scale_e1);
btVector3 vp_e0 = tv_vertices[tv_e0].lerp(tv_vertices[(tv_e0+1)%3],tv_scale_e0);
btVector3 vp_e1 = tv_vertices[tv_e1].lerp(tv_vertices[(tv_e1+1)%3],tv_scale_e1);
//proyected intervals
GREAL isect_u[] = {up_e0.dot(edge_edge_dir),up_e1.dot(edge_edge_dir)};
GREAL isect_v[] = {vp_e0.dot(edge_edge_dir),vp_e1.dot(edge_edge_dir)};
sort_isect(isect_u[0],isect_u[1],tu_e0,tu_e1,up_e0,up_e1);
sort_isect(isect_v[0],isect_v[1],tv_e0,tv_e1,vp_e0,vp_e1);
const GREAL midpoint_u = 0.5f*(isect_u[0]+isect_u[1]); // midpoint
const GREAL midpoint_v = 0.5f*(isect_v[0]+isect_v[1]); // midpoint
if(midpoint_u<midpoint_v)
{
if(isect_u[1]>=isect_v[1]) // face U casts face V
{
return 1;
}
else if(isect_v[0]<=isect_u[0]) // face V casts face U
{
return 2;
}
// closest points
closest_point_u = up_e1;
closest_point_v = vp_e0;
// calc edges and separation
if(isect_u[1]+ MIN_EDGE_EDGE_DIS<isect_v[0]) //calc distance between two lines instead
{
SEGMENT_COLLISION(
tu_vertices[tu_e1],tu_vertices[(tu_e1+1)%3],
tv_vertices[tv_e0],tv_vertices[(tv_e0+1)%3],
closest_point_u,
closest_point_v);
edge_edge_dir = closest_point_u-closest_point_v;
VEC_LENGTH(edge_edge_dir,distances[2]);
edge_edge_dir *= 1.0f/distances[2];// normalize
}
else
{
distances[2] = isect_v[0]-isect_u[1];//distance negative
//edge_edge_dir *= -1.0f; //normal pointing from V to U
}
}
else
{
if(isect_v[1]>=isect_u[1]) // face V casts face U
{
return 2;
}
else if(isect_u[0]<=isect_v[0]) // face U casts face V
{
return 1;
}
// closest points
closest_point_u = up_e0;
closest_point_v = vp_e1;
// calc edges and separation
if(isect_v[1]+MIN_EDGE_EDGE_DIS<isect_u[0]) //calc distance between two lines instead
{
SEGMENT_COLLISION(
tu_vertices[tu_e0],tu_vertices[(tu_e0+1)%3],
tv_vertices[tv_e1],tv_vertices[(tv_e1+1)%3],
closest_point_u,
closest_point_v);
edge_edge_dir = closest_point_u-closest_point_v;
VEC_LENGTH(edge_edge_dir,distances[2]);
edge_edge_dir *= 1.0f/distances[2];// normalize
}
else
{
distances[2] = isect_u[0]-isect_v[1];//distance negative
//edge_edge_dir *= -1.0f; //normal pointing from V to U
}
}
return 3;
}
//! collides by two sides
SIMD_FORCE_INLINE bool triangle_collision(
const btVector3 & u0,
const btVector3 & u1,
const btVector3 & u2,
GREAL margin_u,
const btVector3 & v0,
const btVector3 & v1,
const btVector3 & v2,
GREAL margin_v,
GIM_TRIANGLE_CONTACT_DATA & contacts)
{
margin = margin_u + margin_v;
tu_vertices[0] = u0;
tu_vertices[1] = u1;
tu_vertices[2] = u2;
tv_vertices[0] = v0;
tv_vertices[1] = v1;
tv_vertices[2] = v2;
//create planes
// plane v vs U points
TRIANGLE_PLANE(tv_vertices[0],tv_vertices[1],tv_vertices[2],tv_plane);
du[0] = DISTANCE_PLANE_POINT(tv_plane,tu_vertices[0]);
du[1] = DISTANCE_PLANE_POINT(tv_plane,tu_vertices[1]);
du[2] = DISTANCE_PLANE_POINT(tv_plane,tu_vertices[2]);
du0du1 = du[0] * du[1];
du0du2 = du[0] * du[2];
if(du0du1>0.0f && du0du2>0.0f) // same sign on all of them + not equal 0 ?
{
if(du[0]<0) //we need test behind the triangle plane
{
distances[0] = GIM_MAX3(du[0],du[1],du[2]);
distances[0] = -distances[0];
if(distances[0]>margin) return false; //never intersect
//reorder triangle v
VEC_SWAP(tv_vertices[0],tv_vertices[1]);
VEC_SCALE_4(tv_plane,-1.0f,tv_plane);
}
else
{
distances[0] = GIM_MIN3(du[0],du[1],du[2]);
if(distances[0]>margin) return false; //never intersect
}
}
else
{
//Look if we need to invert the triangle
distances[0] = (du[0]+du[1]+du[2])/3.0f; //centroid
if(distances[0]<0.0f)
{
//reorder triangle v
VEC_SWAP(tv_vertices[0],tv_vertices[1]);
VEC_SCALE_4(tv_plane,-1.0f,tv_plane);
distances[0] = GIM_MAX3(du[0],du[1],du[2]);
distances[0] = -distances[0];
}
else
{
distances[0] = GIM_MIN3(du[0],du[1],du[2]);
}
}
// plane U vs V points
TRIANGLE_PLANE(tu_vertices[0],tu_vertices[1],tu_vertices[2],tu_plane);
dv[0] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[0]);
dv[1] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[1]);
dv[2] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[2]);
dv0dv1 = dv[0] * dv[1];
dv0dv2 = dv[0] * dv[2];
if(dv0dv1>0.0f && dv0dv2>0.0f) // same sign on all of them + not equal 0 ?
{
if(dv[0]<0) //we need test behind the triangle plane
{
distances[1] = GIM_MAX3(dv[0],dv[1],dv[2]);
distances[1] = -distances[1];
if(distances[1]>margin) return false; //never intersect
//reorder triangle u
VEC_SWAP(tu_vertices[0],tu_vertices[1]);
VEC_SCALE_4(tu_plane,-1.0f,tu_plane);
}
else
{
distances[1] = GIM_MIN3(dv[0],dv[1],dv[2]);
if(distances[1]>margin) return false; //never intersect
}
}
else
{
//Look if we need to invert the triangle
distances[1] = (dv[0]+dv[1]+dv[2])/3.0f; //centroid
if(distances[1]<0.0f)
{
//reorder triangle v
VEC_SWAP(tu_vertices[0],tu_vertices[1]);
VEC_SCALE_4(tu_plane,-1.0f,tu_plane);
distances[1] = GIM_MAX3(dv[0],dv[1],dv[2]);
distances[1] = -distances[1];
}
else
{
distances[1] = GIM_MIN3(dv[0],dv[1],dv[2]);
}
}
GUINT bl;
/* bl = cross_line_intersection_test();
if(bl==3)
{
//take edge direction too
bl = distances.maxAxis();
}
else
{*/
bl = 0;
if(distances[0]<distances[1]) bl = 1;
//}
if(bl==2) //edge edge separation
{
if(distances[2]>margin) return false;
contacts.m_penetration_depth = -distances[2] + margin;
contacts.m_points[0] = closest_point_v;
contacts.m_point_count = 1;
VEC_COPY(contacts.m_separating_normal,edge_edge_dir);
return true;
}
//clip face against other
GUINT point_count;
//TODO
if(bl == 0) //clip U points against V
{
point_count = clip_triangle(tv_plane,tv_vertices,tu_vertices,contact_points);
if(point_count == 0) return false;
contacts.merge_points(tv_plane,margin,contact_points,point_count);
}
else //clip V points against U
{
point_count = clip_triangle(tu_plane,tu_vertices,tv_vertices,contact_points);
if(point_count == 0) return false;
contacts.merge_points(tu_plane,margin,contact_points,point_count);
contacts.m_separating_normal *= -1.f;
}
if(contacts.m_point_count == 0) return false;
return true;
}
};
/*class GIM_TRIANGLE_CALCULATION_CACHE
{
public:
GREAL margin;
GUINT clipped_count;
btVector3 tu_vertices[3];
btVector3 tv_vertices[3];
btVector3 temp_points[MAX_TRI_CLIPPING];
btVector3 temp_points1[MAX_TRI_CLIPPING];
btVector3 clipped_points[MAX_TRI_CLIPPING];
GIM_TRIANGLE_CONTACT_DATA contacts1;
GIM_TRIANGLE_CONTACT_DATA contacts2;
//! clip triangle
GUINT clip_triangle(
const btVector4 & tri_plane,
const btVector3 * tripoints,
const btVector3 * srcpoints,
btVector3 * clipped_points)
{
// edge 0
btVector4 edgeplane;
EDGE_PLANE(tripoints[0],tripoints[1],tri_plane,edgeplane);
GUINT clipped_count = PLANE_CLIP_TRIANGLE3D(
edgeplane,srcpoints[0],srcpoints[1],srcpoints[2],temp_points);
if(clipped_count == 0) return 0;
// edge 1
EDGE_PLANE(tripoints[1],tripoints[2],tri_plane,edgeplane);
clipped_count = PLANE_CLIP_POLYGON3D(
edgeplane,temp_points,clipped_count,temp_points1);
if(clipped_count == 0) return 0;
// edge 2
EDGE_PLANE(tripoints[2],tripoints[0],tri_plane,edgeplane);
clipped_count = PLANE_CLIP_POLYGON3D(
edgeplane,temp_points1,clipped_count,clipped_points);
return clipped_count;
}
//! collides only on one side
bool triangle_collision(
const btVector3 & u0,
const btVector3 & u1,
const btVector3 & u2,
GREAL margin_u,
const btVector3 & v0,
const btVector3 & v1,
const btVector3 & v2,
GREAL margin_v,
GIM_TRIANGLE_CONTACT_DATA & contacts)
{
margin = margin_u + margin_v;
tu_vertices[0] = u0;
tu_vertices[1] = u1;
tu_vertices[2] = u2;
tv_vertices[0] = v0;
tv_vertices[1] = v1;
tv_vertices[2] = v2;
//create planes
// plane v vs U points
TRIANGLE_PLANE(tv_vertices[0],tv_vertices[1],tv_vertices[2],contacts1.m_separating_normal);
clipped_count = clip_triangle(
contacts1.m_separating_normal,tv_vertices,tu_vertices,clipped_points);
if(clipped_count == 0 )
{
return false;//Reject
}
//find most deep interval face1
contacts1.merge_points(contacts1.m_separating_normal,margin,clipped_points,clipped_count);
if(contacts1.m_point_count == 0) return false; // too far
//Normal pointing to triangle1
//contacts1.m_separating_normal *= -1.f;
//Clip tri1 by tri2 edges
TRIANGLE_PLANE(tu_vertices[0],tu_vertices[1],tu_vertices[2],contacts2.m_separating_normal);
clipped_count = clip_triangle(
contacts2.m_separating_normal,tu_vertices,tv_vertices,clipped_points);
if(clipped_count == 0 )
{
return false;//Reject
}
//find most deep interval face1
contacts2.merge_points(contacts2.m_separating_normal,margin,clipped_points,clipped_count);
if(contacts2.m_point_count == 0) return false; // too far
contacts2.m_separating_normal *= -1.f;
////check most dir for contacts
if(contacts2.m_penetration_depth<contacts1.m_penetration_depth)
{
contacts.copy_from(contacts2);
}
else
{
contacts.copy_from(contacts1);
}
return true;
}
};*/
bool GIM_TRIANGLE::collide_triangle_hard_test(
const GIM_TRIANGLE & other,
GIM_TRIANGLE_CONTACT_DATA & contact_data) const
{
GIM_TRIANGLE_CALCULATION_CACHE calc_cache;
return calc_cache.triangle_collision(
m_vertices[0],m_vertices[1],m_vertices[2],m_margin,
other.m_vertices[0],other.m_vertices[1],other.m_vertices[2],other.m_margin,
contact_data);
}

View File

@@ -1,379 +0,0 @@
#ifndef GIM_TRI_COLLISION_H_INCLUDED
#define GIM_TRI_COLLISION_H_INCLUDED
/*! \file gim_tri_collision.h
\author Francisco Leon Najera
*/
/*
-----------------------------------------------------------------------------
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.com
This library is free software; you can redistribute it and/or
modify it under the terms of EITHER:
(1) The GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at
your option) any later version. The text of the GNU Lesser
General Public License is included with this library in the
file GIMPACT-LICENSE-LGPL.TXT.
(2) The BSD-style license that is included with this library in
the file GIMPACT-LICENSE-BSD.TXT.
(3) The zlib/libpng license that is included with this library in
the file GIMPACT-LICENSE-ZLIB.TXT.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-----------------------------------------------------------------------------
*/
#include "gim_box_collision.h"
#include "gim_clip_polygon.h"
#define MAX_TRI_CLIPPING 16
//! Structure for collision
struct GIM_TRIANGLE_CONTACT_DATA
{
GREAL m_penetration_depth;
GUINT m_point_count;
btVector4 m_separating_normal;
btVector3 m_points[MAX_TRI_CLIPPING];
SIMD_FORCE_INLINE void copy_from(const GIM_TRIANGLE_CONTACT_DATA& other)
{
m_penetration_depth = other.m_penetration_depth;
m_separating_normal = other.m_separating_normal;
m_point_count = other.m_point_count;
GUINT i = m_point_count;
while(i--)
{
m_points[i] = other.m_points[i];
}
}
GIM_TRIANGLE_CONTACT_DATA()
{
}
GIM_TRIANGLE_CONTACT_DATA(const GIM_TRIANGLE_CONTACT_DATA& other)
{
copy_from(other);
}
//! classify points that are closer
template<typename DISTANCE_FUNC,typename CLASS_PLANE>
SIMD_FORCE_INLINE void mergepoints_generic(const CLASS_PLANE & plane,
GREAL margin, const btVector3 * points, GUINT point_count, DISTANCE_FUNC distance_func)
{
m_point_count = 0;
m_penetration_depth= -1000.0f;
GUINT point_indices[MAX_TRI_CLIPPING];
GUINT _k;
for(_k=0;_k<point_count;_k++)
{
GREAL _dist = -distance_func(plane,points[_k]) + margin;
if(_dist>=0.0f)
{
if(_dist>m_penetration_depth)
{
m_penetration_depth = _dist;
point_indices[0] = _k;
m_point_count=1;
}
else if((_dist+G_EPSILON)>=m_penetration_depth)
{
point_indices[m_point_count] = _k;
m_point_count++;
}
}
}
for( _k=0;_k<m_point_count;_k++)
{
m_points[_k] = points[point_indices[_k]];
}
}
//! classify points that are closer
SIMD_FORCE_INLINE void merge_points(const btVector4 & plane, GREAL margin,
const btVector3 * points, GUINT point_count)
{
m_separating_normal = plane;
mergepoints_generic(plane, margin, points, point_count, DISTANCE_PLANE_3D_FUNC());
}
};
//! Class for colliding triangles
class GIM_TRIANGLE
{
public:
btScalar m_margin;
btVector3 m_vertices[3];
GIM_TRIANGLE():m_margin(0.1f)
{
}
SIMD_FORCE_INLINE GIM_AABB get_box() const
{
return GIM_AABB(m_vertices[0],m_vertices[1],m_vertices[2],m_margin);
}
SIMD_FORCE_INLINE void get_normal(btVector3 &normal) const
{
TRIANGLE_NORMAL(m_vertices[0],m_vertices[1],m_vertices[2],normal);
}
SIMD_FORCE_INLINE void get_plane(btVector4 &plane) const
{
TRIANGLE_PLANE(m_vertices[0],m_vertices[1],m_vertices[2],plane);;
}
SIMD_FORCE_INLINE void apply_transform(const btTransform & trans)
{
m_vertices[0] = trans(m_vertices[0]);
m_vertices[1] = trans(m_vertices[1]);
m_vertices[2] = trans(m_vertices[2]);
}
SIMD_FORCE_INLINE void get_edge_plane(GUINT edge_index,const btVector3 &triangle_normal,btVector4 &plane) const
{
const btVector3 & e0 = m_vertices[edge_index];
const btVector3 & e1 = m_vertices[(edge_index+1)%3];
EDGE_PLANE(e0,e1,triangle_normal,plane);
}
//! Gets the relative transformation of this triangle
/*!
The transformation is oriented to the triangle normal , and aligned to the 1st edge of this triangle. The position corresponds to vertice 0:
- triangle normal corresponds to Z axis.
- 1st normalized edge corresponds to X axis,
*/
SIMD_FORCE_INLINE void get_triangle_transform(btTransform & triangle_transform) const
{
btMatrix3x3 & matrix = triangle_transform.getBasis();
btVector3 zaxis;
get_normal(zaxis);
MAT_SET_Z(matrix,zaxis);
btVector3 xaxis = m_vertices[1] - m_vertices[0];
VEC_NORMALIZE(xaxis);
MAT_SET_X(matrix,xaxis);
//y axis
xaxis = zaxis.cross(xaxis);
MAT_SET_Y(matrix,xaxis);
triangle_transform.setOrigin(m_vertices[0]);
}
//! Test triangles by finding separating axis
/*!
\param other Triangle for collide
\param contact_data Structure for holding contact points, normal and penetration depth; The normal is pointing toward this triangle from the other triangle
*/
bool collide_triangle_hard_test(
const GIM_TRIANGLE & other,
GIM_TRIANGLE_CONTACT_DATA & contact_data) const;
//! Test boxes before doing hard test
/*!
\param other Triangle for collide
\param contact_data Structure for holding contact points, normal and penetration depth; The normal is pointing toward this triangle from the other triangle
\
*/
SIMD_FORCE_INLINE bool collide_triangle(
const GIM_TRIANGLE & other,
GIM_TRIANGLE_CONTACT_DATA & contact_data) const
{
//test box collisioin
GIM_AABB boxu(m_vertices[0],m_vertices[1],m_vertices[2],m_margin);
GIM_AABB boxv(other.m_vertices[0],other.m_vertices[1],other.m_vertices[2],other.m_margin);
if(!boxu.has_collision(boxv)) return false;
//do hard test
return collide_triangle_hard_test(other,contact_data);
}
/*!
Solve the System for u,v parameters:
u*axe1[i1] + v*axe2[i1] = vecproj[i1]
u*axe1[i2] + v*axe2[i2] = vecproj[i2]
sustitute:
v = (vecproj[i2] - u*axe1[i2])/axe2[i2]
then the first equation in terms of 'u':
--> u*axe1[i1] + ((vecproj[i2] - u*axe1[i2])/axe2[i2])*axe2[i1] = vecproj[i1]
--> u*axe1[i1] + vecproj[i2]*axe2[i1]/axe2[i2] - u*axe1[i2]*axe2[i1]/axe2[i2] = vecproj[i1]
--> u*(axe1[i1] - axe1[i2]*axe2[i1]/axe2[i2]) = vecproj[i1] - vecproj[i2]*axe2[i1]/axe2[i2]
--> u*((axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1])/axe2[i2]) = (vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1])/axe2[i2]
--> u*(axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1]) = vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1]
--> u = (vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1]) /(axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1])
if 0.0<= u+v <=1.0 then they are inside of triangle
\return false if the point is outside of triangle.This function doesn't take the margin
*/
SIMD_FORCE_INLINE bool get_uv_parameters(
const btVector3 & point,
const btVector3 & tri_plane,
GREAL & u, GREAL & v) const
{
btVector3 _axe1 = m_vertices[1]-m_vertices[0];
btVector3 _axe2 = m_vertices[2]-m_vertices[0];
btVector3 _vecproj = point - m_vertices[0];
GUINT _i1 = (tri_plane.closestAxis()+1)%3;
GUINT _i2 = (_i1+1)%3;
if(btFabs(_axe2[_i2])<G_EPSILON)
{
u = (_vecproj[_i2]*_axe2[_i1] - _vecproj[_i1]*_axe2[_i2]) /(_axe1[_i2]*_axe2[_i1] - _axe1[_i1]*_axe2[_i2]);
v = (_vecproj[_i1] - u*_axe1[_i1])/_axe2[_i1];
}
else
{
u = (_vecproj[_i1]*_axe2[_i2] - _vecproj[_i2]*_axe2[_i1]) /(_axe1[_i1]*_axe2[_i2] - _axe1[_i2]*_axe2[_i1]);
v = (_vecproj[_i2] - u*_axe1[_i2])/_axe2[_i2];
}
if(u<-G_EPSILON)
{
return false;
}
else if(v<-G_EPSILON)
{
return false;
}
else
{
btScalar sumuv;
sumuv = u+v;
if(sumuv<-G_EPSILON)
{
return false;
}
else if(sumuv-1.0f>G_EPSILON)
{
return false;
}
}
return true;
}
//! is point in triangle beam?
/*!
Test if point is in triangle, with m_margin tolerance
*/
SIMD_FORCE_INLINE bool is_point_inside(const btVector3 & point, const btVector3 & tri_normal) const
{
//Test with edge 0
btVector4 edge_plane;
this->get_edge_plane(0,tri_normal,edge_plane);
GREAL dist = DISTANCE_PLANE_POINT(edge_plane,point);
if(dist-m_margin>0.0f) return false; // outside plane
this->get_edge_plane(1,tri_normal,edge_plane);
dist = DISTANCE_PLANE_POINT(edge_plane,point);
if(dist-m_margin>0.0f) return false; // outside plane
this->get_edge_plane(2,tri_normal,edge_plane);
dist = DISTANCE_PLANE_POINT(edge_plane,point);
if(dist-m_margin>0.0f) return false; // outside plane
return true;
}
//! Bidireccional ray collision
SIMD_FORCE_INLINE bool ray_collision(
const btVector3 & vPoint,
const btVector3 & vDir, btVector3 & pout, btVector3 & triangle_normal,
GREAL & tparam, GREAL tmax = G_REAL_INFINITY)
{
btVector4 faceplane;
{
btVector3 dif1 = m_vertices[1] - m_vertices[0];
btVector3 dif2 = m_vertices[2] - m_vertices[0];
VEC_CROSS(faceplane,dif1,dif2);
faceplane[3] = m_vertices[0].dot(faceplane);
}
GUINT res = LINE_PLANE_COLLISION(faceplane,vDir,vPoint,pout,tparam, btScalar(0), tmax);
if(res == 0) return false;
if(! is_point_inside(pout,faceplane)) return false;
if(res==2) //invert normal
{
triangle_normal.setValue(-faceplane[0],-faceplane[1],-faceplane[2]);
}
else
{
triangle_normal.setValue(faceplane[0],faceplane[1],faceplane[2]);
}
VEC_NORMALIZE(triangle_normal);
return true;
}
//! one direccion ray collision
SIMD_FORCE_INLINE bool ray_collision_front_side(
const btVector3 & vPoint,
const btVector3 & vDir, btVector3 & pout, btVector3 & triangle_normal,
GREAL & tparam, GREAL tmax = G_REAL_INFINITY)
{
btVector4 faceplane;
{
btVector3 dif1 = m_vertices[1] - m_vertices[0];
btVector3 dif2 = m_vertices[2] - m_vertices[0];
VEC_CROSS(faceplane,dif1,dif2);
faceplane[3] = m_vertices[0].dot(faceplane);
}
GUINT res = LINE_PLANE_COLLISION(faceplane,vDir,vPoint,pout,tparam, btScalar(0), tmax);
if(res != 1) return false;
if(!is_point_inside(pout,faceplane)) return false;
triangle_normal.setValue(faceplane[0],faceplane[1],faceplane[2]);
VEC_NORMALIZE(triangle_normal);
return true;
}
};
#endif // GIM_TRI_COLLISION_H_INCLUDED

View File

@@ -1,155 +0,0 @@
INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src )
SET(BulletDynamics_SRCS
Character/btKinematicCharacterController.cpp
ConstraintSolver/btConeTwistConstraint.cpp
ConstraintSolver/btContactConstraint.cpp
ConstraintSolver/btFixedConstraint.cpp
ConstraintSolver/btGearConstraint.cpp
ConstraintSolver/btGeneric6DofConstraint.cpp
ConstraintSolver/btGeneric6DofSpringConstraint.cpp
ConstraintSolver/btHinge2Constraint.cpp
ConstraintSolver/btHingeConstraint.cpp
ConstraintSolver/btPoint2PointConstraint.cpp
ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
ConstraintSolver/btNNCGConstraintSolver.cpp
ConstraintSolver/btSliderConstraint.cpp
ConstraintSolver/btSolve2LinearConstraint.cpp
ConstraintSolver/btTypedConstraint.cpp
ConstraintSolver/btUniversalConstraint.cpp
Dynamics/btDiscreteDynamicsWorld.cpp
Dynamics/btRigidBody.cpp
Dynamics/btSimpleDynamicsWorld.cpp
Dynamics/Bullet-C-API.cpp
Vehicle/btRaycastVehicle.cpp
Vehicle/btWheelInfo.cpp
Featherstone/btMultiBody.cpp
Featherstone/btMultiBodyConstraintSolver.cpp
Featherstone/btMultiBodyDynamicsWorld.cpp
Featherstone/btMultiBodyJointLimitConstraint.cpp
Featherstone/btMultiBodyConstraint.cpp
Featherstone/btMultiBodyPoint2Point.cpp
Featherstone/btMultiBodyJointMotor.cpp
MLCPSolvers/btDantzigLCP.cpp
MLCPSolvers/btMLCPSolver.cpp
)
SET(Root_HDRS
../btBulletDynamicsCommon.h
../btBulletCollisionCommon.h
)
SET(ConstraintSolver_HDRS
ConstraintSolver/btConeTwistConstraint.h
ConstraintSolver/btConstraintSolver.h
ConstraintSolver/btContactConstraint.h
ConstraintSolver/btContactSolverInfo.h
ConstraintSolver/btFixedConstraint.h
ConstraintSolver/btGearConstraint.h
ConstraintSolver/btGeneric6DofConstraint.h
ConstraintSolver/btGeneric6DofSpringConstraint.h
ConstraintSolver/btHinge2Constraint.h
ConstraintSolver/btHingeConstraint.h
ConstraintSolver/btJacobianEntry.h
ConstraintSolver/btPoint2PointConstraint.h
ConstraintSolver/btSequentialImpulseConstraintSolver.h
ConstraintSolver/btNNCGConstraintSolver.h
ConstraintSolver/btSliderConstraint.h
ConstraintSolver/btSolve2LinearConstraint.h
ConstraintSolver/btSolverBody.h
ConstraintSolver/btSolverConstraint.h
ConstraintSolver/btTypedConstraint.h
ConstraintSolver/btUniversalConstraint.h
)
SET(Dynamics_HDRS
Dynamics/btActionInterface.h
Dynamics/btDiscreteDynamicsWorld.h
Dynamics/btDynamicsWorld.h
Dynamics/btSimpleDynamicsWorld.h
Dynamics/btRigidBody.h
)
SET(Vehicle_HDRS
Vehicle/btRaycastVehicle.h
Vehicle/btVehicleRaycaster.h
Vehicle/btWheelInfo.h
)
SET(Featherstone_HDRS
Featherstone/btMultiBody.h
Featherstone/btMultiBodyConstraintSolver.h
Featherstone/btMultiBodyDynamicsWorld.h
Featherstone/btMultiBodyLink.h
Featherstone/btMultiBodyLinkCollider.h
Featherstone/btMultiBodySolverConstraint.h
Featherstone/btMultiBodyConstraint.h
Featherstone/btMultiBodyJointLimitConstraint.h
Featherstone/btMultiBodyConstraint.h
Featherstone/btMultiBodyPoint2Point.h
Featherstone/btMultiBodyJointMotor.h
)
SET(MLCPSolvers_HDRS
MLCPSolvers/btDantzigLCP.h
MLCPSolvers/btDantzigSolver.h
MLCPSolvers/btMLCPSolver.h
MLCPSolvers/btMLCPSolverInterface.h
MLCPSolvers/btPATHSolver.h
MLCPSolvers/btSolveProjectedGaussSeidel.h
)
SET(Character_HDRS
Character/btCharacterControllerInterface.h
Character/btKinematicCharacterController.h
)
SET(BulletDynamics_HDRS
${Root_HDRS}
${ConstraintSolver_HDRS}
${Dynamics_HDRS}
${Vehicle_HDRS}
${Character_HDRS}
${Featherstone_HDRS}
${MLCPSolvers_HDRS}
)
ADD_LIBRARY(BulletDynamics ${BulletDynamics_SRCS} ${BulletDynamics_HDRS})
SET_TARGET_PROPERTIES(BulletDynamics PROPERTIES VERSION ${BULLET_VERSION})
SET_TARGET_PROPERTIES(BulletDynamics PROPERTIES SOVERSION ${BULLET_VERSION})
IF (BUILD_SHARED_LIBS)
TARGET_LINK_LIBRARIES(BulletDynamics BulletCollision LinearMath)
ENDIF (BUILD_SHARED_LIBS)
IF (INSTALL_LIBS)
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS BulletDynamics DESTINATION .)
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS BulletDynamics RUNTIME DESTINATION bin
LIBRARY DESTINATION lib${LIB_SUFFIX}
ARCHIVE DESTINATION lib${LIB_SUFFIX})
INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN
".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
INSTALL(FILES ../btBulletDynamicsCommon.h
DESTINATION ${INCLUDE_INSTALL_DIR}/BulletDynamics)
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
SET_TARGET_PROPERTIES(BulletDynamics PROPERTIES FRAMEWORK true)
SET_TARGET_PROPERTIES(BulletDynamics PROPERTIES PUBLIC_HEADER "${Root_HDRS}")
# Have to list out sub-directories manually:
SET_PROPERTY(SOURCE ${ConstraintSolver_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/ConstraintSolver)
SET_PROPERTY(SOURCE ${Dynamics_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Dynamics)
SET_PROPERTY(SOURCE ${Vehicle_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Vehicle)
SET_PROPERTY(SOURCE ${Character_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Character)
SET_PROPERTY(SOURCE ${Featherstone_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Featherstone)
SET_PROPERTY(SOURCE ${MLCPSolvers_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/MLCPSolvers)
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
ENDIF (INSTALL_LIBS)

View File

@@ -1,126 +0,0 @@
INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/src
${VECTOR_MATH_INCLUDE}
)
SET(BulletMultiThreaded_SRCS
SpuFakeDma.cpp
SpuLibspe2Support.cpp
btThreadSupportInterface.cpp
Win32ThreadSupport.cpp
PosixThreadSupport.cpp
SequentialThreadSupport.cpp
SpuSampleTaskProcess.cpp
SpuCollisionObjectWrapper.cpp
SpuCollisionTaskProcess.cpp
SpuGatheringCollisionDispatcher.cpp
SpuContactManifoldCollisionAlgorithm.cpp
btParallelConstraintSolver.cpp
#SPURS_PEGatherScatterTask/SpuPEGatherScatterTask.cpp
#SpuPEGatherScatterTaskProcess.cpp
SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp
SpuNarrowPhaseCollisionTask/SpuContactResult.cpp
SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp
SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp
SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp
#Some GPU related stuff, mainly CUDA and perhaps OpenCL
btGpu3DGridBroadphase.cpp
)
SET(Root_HDRS
PlatformDefinitions.h
PpuAddressSpace.h
SpuFakeDma.h
SpuDoubleBuffer.h
SpuLibspe2Support.h
btThreadSupportInterface.h
Win32ThreadSupport.h
PosixThreadSupport.h
SequentialThreadSupport.h
SpuSampleTaskProcess.h
SpuCollisionObjectWrapper.cpp
SpuCollisionObjectWrapper.h
SpuCollisionTaskProcess.h
SpuGatheringCollisionDispatcher.h
SpuContactManifoldCollisionAlgorithm.h
btParallelConstraintSolver.h
#SPURS_PEGatherScatterTask/SpuPEGatherScatterTask.h
#SpuPEGatherScatterTaskProcess.h
#Some GPU related stuff, mainly CUDA and perhaps OpenCL
btGpu3DGridBroadphase.h
btGpu3DGridBroadphaseSharedCode.h
btGpu3DGridBroadphaseSharedDefs.h
btGpu3DGridBroadphaseSharedTypes.h
btGpuDefines.h
btGpuUtilsSharedCode.h
btGpuUtilsSharedDefs.h
)
SET(SpuNarrowPhaseCollisionTask_HDRS
SpuNarrowPhaseCollisionTask/Box.h
SpuNarrowPhaseCollisionTask/boxBoxDistance.h
SpuNarrowPhaseCollisionTask/SpuContactResult.h
SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h
SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h
SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h
SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h
SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h
)
SET(BulletMultiThreaded_HDRS
${Root_HDRS}
${SpuNarrowPhaseCollisionTask_HDRS}
)
ADD_LIBRARY(BulletMultiThreaded ${BulletMultiThreaded_SRCS} ${BulletMultiThreaded_HDRS})
SET_TARGET_PROPERTIES(BulletMultiThreaded PROPERTIES VERSION ${BULLET_VERSION})
SET_TARGET_PROPERTIES(BulletMultiThreaded PROPERTIES SOVERSION ${BULLET_VERSION})
SUBDIRS(GpuSoftBodySolvers)
IF (BUILD_SHARED_LIBS)
IF (UNIX)
TARGET_LINK_LIBRARIES(BulletMultiThreaded BulletDynamics BulletCollision pthread)
ELSE()
TARGET_LINK_LIBRARIES(BulletMultiThreaded BulletDynamics BulletCollision)
ENDIF()
ENDIF (BUILD_SHARED_LIBS)
IF (INSTALL_LIBS)
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
#INSTALL of other files requires CMake 2.6
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
# IF(INSTALL_EXTRA_LIBS)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS BulletMultiThreaded DESTINATION .)
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS BulletMultiThreaded
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib${LIB_SUFFIX}
ARCHIVE DESTINATION lib${LIB_SUFFIX})
INSTALL(DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR} DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING
PATTERN "*.h" PATTERN ".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
# ENDIF (INSTALL_EXTRA_LIBS)
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
SET_TARGET_PROPERTIES(BulletMultiThreaded PROPERTIES FRAMEWORK true)
SET_TARGET_PROPERTIES(BulletMultiThreaded PROPERTIES PUBLIC_HEADER "${Root_HDRS}")
# Have to list out sub-directories manually:
SET_PROPERTY(SOURCE ${SpuNarrowPhaseCollisionTask_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/SpuNarrowPhaseCollisionTask)
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
ENDIF (INSTALL_LIBS)

View File

@@ -1,13 +0,0 @@
INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/src
)
SUBDIRS (
OpenCL
)
IF( USE_DX11 )
SUBDIRS( DX11 )
ENDIF( USE_DX11 )

View File

@@ -1,86 +0,0 @@
INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/src
)
SET(DXSDK_DIR $ENV{DXSDK_DIR})
SET(DX11_INCLUDE_PATH "${DIRECTX_SDK_BASE_DIR}/Include" CACHE DOCSTRING "Microsoft directX SDK include path")
INCLUDE_DIRECTORIES(
${DX11_INCLUDE_PATH} "../Shared/"
${VECTOR_MATH_INCLUDE}
)
SET(BulletSoftBodyDX11Solvers_SRCS
btSoftBodySolver_DX11.cpp
btSoftBodySolver_DX11SIMDAware.cpp
)
SET(BulletSoftBodyDX11Solvers_HDRS
btSoftBodySolver_DX11.h
btSoftBodySolver_DX11SIMDAware.h
../Shared/btSoftBodySolverData.h
btSoftBodySolverVertexData_DX11.h
btSoftBodySolverTriangleData_DX11.h
btSoftBodySolverLinkData_DX11.h
btSoftBodySolverLinkData_DX11SIMDAware.h
btSoftBodySolverBuffer_DX11.h
btSoftBodySolverVertexBuffer_DX11.h
)
# OpenCL and HLSL Shaders.
# Build rules generated to stringify these into headers
# which are needed by some of the sources
SET(BulletSoftBodyDX11Solvers_Shaders
OutputToVertexArray
UpdateNormals
Integrate
UpdatePositions
UpdateNodes
ComputeBounds
SolvePositions
SolvePositionsSIMDBatched
SolveCollisionsAndUpdateVelocities
SolveCollisionsAndUpdateVelocitiesSIMDBatched
UpdatePositionsFromVelocities
ApplyForces
PrepareLinks
VSolveLinks
)
foreach(f ${BulletSoftBodyDX11Solvers_Shaders})
LIST(APPEND BulletSoftBodyDX11Solvers_HLSL "HLSL/${f}.hlsl")
endforeach(f)
ADD_LIBRARY(BulletSoftBodySolvers_DX11 ${BulletSoftBodyDX11Solvers_SRCS} ${BulletSoftBodyDX11Solvers_HDRS} ${BulletSoftBodyDX11Solvers_HLSL})
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_DX11 PROPERTIES VERSION ${BULLET_VERSION})
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_DX11 PROPERTIES SOVERSION ${BULLET_VERSION})
IF (BUILD_SHARED_LIBS)
TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_DX11 BulletSoftBody BulletDynamics)
ENDIF (BUILD_SHARED_LIBS)
IF (INSTALL_LIBS)
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS BulletSoftBodySolvers_DX11 DESTINATION .)
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS BulletSoftBodySolvers_DX11
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib${LIB_SUFFIX}
ARCHIVE DESTINATION lib${LIB_SUFFIX})
#headers are already installed by BulletMultiThreaded library
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_DX11 PROPERTIES FRAMEWORK true)
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_DX11 PROPERTIES PUBLIC_HEADER "${BulletSoftBodyDX11Solvers_HDRS}")
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
ENDIF (INSTALL_LIBS)

View File

@@ -1,95 +0,0 @@
MSTRINGIFY(
cbuffer ApplyForcesCB : register( b0 )
{
unsigned int numNodes;
float solverdt;
float epsilon;
int padding3;
};
StructuredBuffer<int> g_vertexClothIdentifier : register( t0 );
StructuredBuffer<float4> g_vertexNormal : register( t1 );
StructuredBuffer<float> g_vertexArea : register( t2 );
StructuredBuffer<float> g_vertexInverseMass : register( t3 );
// TODO: These could be combined into a lift/drag factor array along with medium density
StructuredBuffer<float> g_clothLiftFactor : register( t4 );
StructuredBuffer<float> g_clothDragFactor : register( t5 );
StructuredBuffer<float4> g_clothWindVelocity : register( t6 );
StructuredBuffer<float4> g_clothAcceleration : register( t7 );
StructuredBuffer<float> g_clothMediumDensity : register( t8 );
RWStructuredBuffer<float4> g_vertexForceAccumulator : register( u0 );
RWStructuredBuffer<float4> g_vertexVelocity : register( u1 );
float3 projectOnAxis( float3 v, float3 a )
{
return (a*dot(v, a));
}
[numthreads(128, 1, 1)]
void
ApplyForcesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
{
unsigned int nodeID = DTid.x;
if( nodeID < numNodes )
{
int clothId = g_vertexClothIdentifier[nodeID];
float nodeIM = g_vertexInverseMass[nodeID];
if( nodeIM > 0.0f )
{
float3 nodeV = g_vertexVelocity[nodeID].xyz;
float3 normal = g_vertexNormal[nodeID].xyz;
float area = g_vertexArea[nodeID];
float3 nodeF = g_vertexForceAccumulator[nodeID].xyz;
// Read per-cloth values
float3 clothAcceleration = g_clothAcceleration[clothId].xyz;
float3 clothWindVelocity = g_clothWindVelocity[clothId].xyz;
float liftFactor = g_clothLiftFactor[clothId];
float dragFactor = g_clothDragFactor[clothId];
float mediumDensity = g_clothMediumDensity[clothId];
// Apply the acceleration to the cloth rather than do this via a force
nodeV += (clothAcceleration*solverdt);
g_vertexVelocity[nodeID] = float4(nodeV, 0.f);
float3 relativeWindVelocity = nodeV - clothWindVelocity;
float relativeSpeedSquared = dot(relativeWindVelocity, relativeWindVelocity);
if( relativeSpeedSquared > epsilon )
{
// Correct direction of normal relative to wind direction and get dot product
normal = normal * (dot(normal, relativeWindVelocity) < 0 ? -1.f : 1.f);
float dvNormal = dot(normal, relativeWindVelocity);
if( dvNormal > 0 )
{
float3 force = float3(0.f, 0.f, 0.f);
float c0 = area * dvNormal * relativeSpeedSquared / 2.f;
float c1 = c0 * mediumDensity;
force += normal * (-c1 * liftFactor);
force += normalize(relativeWindVelocity)*(-c1 * dragFactor);
float dtim = solverdt * nodeIM;
float3 forceDTIM = force * dtim;
float3 nodeFPlusForce = nodeF + force;
// m_nodesf[i] -= ProjectOnAxis(m_nodesv[i], force.normalized())/dtim;
float3 nodeFMinus = nodeF - (projectOnAxis(nodeV, normalize(force))/dtim);
nodeF = nodeFPlusForce;
if( dot(forceDTIM, forceDTIM) > dot(nodeV, nodeV) )
nodeF = nodeFMinus;
g_vertexForceAccumulator[nodeID] = float4(nodeF, 0.0f);
}
}
}
}
}
);

View File

@@ -1,83 +0,0 @@
MSTRINGIFY(
cbuffer ComputeBoundsCB : register( b0 )
{
int numNodes;
int numSoftBodies;
int padding1;
int padding2;
};
// Node indices for each link
StructuredBuffer<int> g_vertexClothIdentifier : register( t0 );
StructuredBuffer<float4> g_vertexPositions : register( t1 );
RWStructuredBuffer<uint4> g_clothMinBounds : register( u0 );
RWStructuredBuffer<uint4> g_clothMaxBounds : register( u1 );
groupshared uint4 clothMinBounds[256];
groupshared uint4 clothMaxBounds[256];
[numthreads(128, 1, 1)]
void
ComputeBoundsKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
{
const unsigned int UINT_MAX = 0xffffffff;
// Init min and max bounds arrays
if( GTid.x < numSoftBodies )
{
clothMinBounds[GTid.x] = uint4(UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX);
clothMaxBounds[GTid.x] = uint4(0,0,0,0);
}
AllMemoryBarrierWithGroupSync();
int nodeID = DTid.x;
if( nodeID < numNodes )
{
int clothIdentifier = g_vertexClothIdentifier[nodeID];
if( clothIdentifier >= 0 )
{
float3 position = g_vertexPositions[nodeID].xyz;
// Reinterpret position as uint
uint3 positionUInt = uint3(asuint(position.x), asuint(position.y), asuint(position.z));
// Invert sign bit of positives and whole of negatives to allow comparison as unsigned ints
//positionUInt.x ^= uint((-int(positionUInt.x >> 31) | 0x80000000));
//positionUInt.y ^= uint((-int(positionUInt.y >> 31) | 0x80000000));
//positionUInt.z ^= uint((-int(positionUInt.z >> 31) | 0x80000000));
positionUInt.x ^= (1+~(positionUInt.x >> 31) | 0x80000000);
positionUInt.y ^= (1+~(positionUInt.y >> 31) | 0x80000000);
positionUInt.z ^= (1+~(positionUInt.z >> 31) | 0x80000000);
// Min/max with the LDS values
InterlockedMin(clothMinBounds[clothIdentifier].x, positionUInt.x);
InterlockedMin(clothMinBounds[clothIdentifier].y, positionUInt.y);
InterlockedMin(clothMinBounds[clothIdentifier].z, positionUInt.z);
InterlockedMax(clothMaxBounds[clothIdentifier].x, positionUInt.x);
InterlockedMax(clothMaxBounds[clothIdentifier].y, positionUInt.y);
InterlockedMax(clothMaxBounds[clothIdentifier].z, positionUInt.z);
}
}
AllMemoryBarrierWithGroupSync();
// Use global atomics to update the global versions of the data
if( GTid.x < numSoftBodies )
{
InterlockedMin(g_clothMinBounds[GTid.x].x, clothMinBounds[GTid.x].x);
InterlockedMin(g_clothMinBounds[GTid.x].y, clothMinBounds[GTid.x].y);
InterlockedMin(g_clothMinBounds[GTid.x].z, clothMinBounds[GTid.x].z);
InterlockedMax(g_clothMaxBounds[GTid.x].x, clothMaxBounds[GTid.x].x);
InterlockedMax(g_clothMaxBounds[GTid.x].y, clothMaxBounds[GTid.x].y);
InterlockedMax(g_clothMaxBounds[GTid.x].z, clothMaxBounds[GTid.x].z);
}
}
);

View File

@@ -1,41 +0,0 @@
MSTRINGIFY(
cbuffer IntegrateCB : register( b0 )
{
int numNodes;
float solverdt;
int padding1;
int padding2;
};
// Node indices for each link
StructuredBuffer<float> g_vertexInverseMasses : register( t0 );
RWStructuredBuffer<float4> g_vertexPositions : register( u0 );
RWStructuredBuffer<float4> g_vertexVelocity : register( u1 );
RWStructuredBuffer<float4> g_vertexPreviousPositions : register( u2 );
RWStructuredBuffer<float4> g_vertexForceAccumulator : register( u3 );
[numthreads(128, 1, 1)]
void
IntegrateKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
{
int nodeID = DTid.x;
if( nodeID < numNodes )
{
float3 position = g_vertexPositions[nodeID].xyz;
float3 velocity = g_vertexVelocity[nodeID].xyz;
float3 force = g_vertexForceAccumulator[nodeID].xyz;
float inverseMass = g_vertexInverseMasses[nodeID];
g_vertexPreviousPositions[nodeID] = float4(position, 0.f);
velocity += force * inverseMass * solverdt;
position += velocity * solverdt;
g_vertexForceAccumulator[nodeID] = float4(0.f, 0.f, 0.f, 0.0f);
g_vertexPositions[nodeID] = float4(position, 0.f);
g_vertexVelocity[nodeID] = float4(velocity, 0.f);
}
}
);

View File

@@ -1,63 +0,0 @@
MSTRINGIFY(
cbuffer OutputToVertexArrayCB : register( b0 )
{
int startNode;
int numNodes;
int positionOffset;
int positionStride;
int normalOffset;
int normalStride;
int padding1;
int padding2;
};
StructuredBuffer<float4> g_vertexPositions : register( t0 );
StructuredBuffer<float4> g_vertexNormals : register( t1 );
RWBuffer<float> g_vertexBuffer : register( u0 );
[numthreads(128, 1, 1)]
void
OutputToVertexArrayWithNormalsKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
{
int nodeID = DTid.x;
if( nodeID < numNodes )
{
float4 position = g_vertexPositions[nodeID + startNode];
float4 normal = g_vertexNormals[nodeID + startNode];
// Stride should account for the float->float4 conversion
int positionDestination = nodeID * positionStride + positionOffset;
g_vertexBuffer[positionDestination] = position.x;
g_vertexBuffer[positionDestination+1] = position.y;
g_vertexBuffer[positionDestination+2] = position.z;
int normalDestination = nodeID * normalStride + normalOffset;
g_vertexBuffer[normalDestination] = normal.x;
g_vertexBuffer[normalDestination+1] = normal.y;
g_vertexBuffer[normalDestination+2] = normal.z;
}
}
[numthreads(128, 1, 1)]
void
OutputToVertexArrayWithoutNormalsKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
{
int nodeID = DTid.x;
if( nodeID < numNodes )
{
float4 position = g_vertexPositions[nodeID + startNode];
float4 normal = g_vertexNormals[nodeID + startNode];
// Stride should account for the float->float4 conversion
int positionDestination = nodeID * positionStride + positionOffset;
g_vertexBuffer[positionDestination] = position.x;
g_vertexBuffer[positionDestination+1] = position.y;
g_vertexBuffer[positionDestination+2] = position.z;
}
}
);

View File

@@ -1,44 +0,0 @@
MSTRINGIFY(
cbuffer PrepareLinksCB : register( b0 )
{
int numLinks;
int padding0;
int padding1;
int padding2;
};
// Node indices for each link
StructuredBuffer<int2> g_linksVertexIndices : register( t0 );
StructuredBuffer<float> g_linksMassLSC : register( t1 );
StructuredBuffer<float4> g_nodesPreviousPosition : register( t2 );
RWStructuredBuffer<float> g_linksLengthRatio : register( u0 );
RWStructuredBuffer<float4> g_linksCurrentLength : register( u1 );
[numthreads(128, 1, 1)]
void
PrepareLinksKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
{
int linkID = DTid.x;
if( linkID < numLinks )
{
int2 nodeIndices = g_linksVertexIndices[linkID];
int node0 = nodeIndices.x;
int node1 = nodeIndices.y;
float4 nodePreviousPosition0 = g_nodesPreviousPosition[node0];
float4 nodePreviousPosition1 = g_nodesPreviousPosition[node1];
float massLSC = g_linksMassLSC[linkID];
float4 linkCurrentLength = nodePreviousPosition1 - nodePreviousPosition0;
float linkLengthRatio = dot(linkCurrentLength, linkCurrentLength)*massLSC;
linkLengthRatio = 1./linkLengthRatio;
g_linksCurrentLength[linkID] = linkCurrentLength;
g_linksLengthRatio[linkID] = linkLengthRatio;
}
}
);

View File

@@ -1,55 +0,0 @@
MSTRINGIFY(
cbuffer SolvePositionsFromLinksKernelCB : register( b0 )
{
int startLink;
int numLinks;
float kst;
float ti;
};
// Node indices for each link
StructuredBuffer<int2> g_linksVertexIndices : register( t0 );
StructuredBuffer<float> g_linksMassLSC : register( t1 );
StructuredBuffer<float> g_linksRestLengthSquared : register( t2 );
StructuredBuffer<float> g_verticesInverseMass : register( t3 );
RWStructuredBuffer<float4> g_vertexPositions : register( u0 );
[numthreads(128, 1, 1)]
void
SolvePositionsFromLinksKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
{
int linkID = DTid.x + startLink;
if( DTid.x < numLinks )
{
float massLSC = g_linksMassLSC[linkID];
float restLengthSquared = g_linksRestLengthSquared[linkID];
if( massLSC > 0.0f )
{
int2 nodeIndices = g_linksVertexIndices[linkID];
int node0 = nodeIndices.x;
int node1 = nodeIndices.y;
float3 position0 = g_vertexPositions[node0].xyz;
float3 position1 = g_vertexPositions[node1].xyz;
float inverseMass0 = g_verticesInverseMass[node0];
float inverseMass1 = g_verticesInverseMass[node1];
float3 del = position1 - position0;
float len = dot(del, del);
float k = ((restLengthSquared - len)/(massLSC*(restLengthSquared+len)))*kst;
position0 = position0 - del*(k*inverseMass0);
position1 = position1 + del*(k*inverseMass1);
g_vertexPositions[node0] = float4(position0, 0.f);
g_vertexPositions[node1] = float4(position1, 0.f);
}
}
}
);

View File

@@ -1,147 +0,0 @@
MSTRINGIFY(
cbuffer SolvePositionsFromLinksKernelCB : register( b0 )
{
int startWaveInBatch;
int numWaves;
float kst;
float ti;
};
// Number of batches per wavefront stored one element per logical wavefront
StructuredBuffer<int2> g_wavefrontBatchCountsVertexCounts : register( t0 );
// Set of up to maxNumVertices vertex addresses per wavefront
StructuredBuffer<int> g_vertexAddressesPerWavefront : register( t1 );
StructuredBuffer<float> g_verticesInverseMass : register( t2 );
// Per-link data layed out structured in terms of sub batches within wavefronts
StructuredBuffer<int2> g_linksVertexIndices : register( t3 );
StructuredBuffer<float> g_linksMassLSC : register( t4 );
StructuredBuffer<float> g_linksRestLengthSquared : register( t5 );
RWStructuredBuffer<float4> g_vertexPositions : register( u0 );
// Data loaded on a per-wave basis
groupshared int2 wavefrontBatchCountsVertexCounts[WAVEFRONT_BLOCK_MULTIPLIER];
groupshared float4 vertexPositionSharedData[MAX_NUM_VERTICES_PER_WAVE*WAVEFRONT_BLOCK_MULTIPLIER];
groupshared float vertexInverseMassSharedData[MAX_NUM_VERTICES_PER_WAVE*WAVEFRONT_BLOCK_MULTIPLIER];
// Storing the vertex addresses actually slowed things down a little
//groupshared int vertexAddressSharedData[MAX_NUM_VERTICES_PER_WAVE*WAVEFRONT_BLOCK_MULTIPLIER];
[numthreads(BLOCK_SIZE, 1, 1)]
void
SolvePositionsFromLinksKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
{
const int laneInWavefront = (DTid.x & (WAVEFRONT_SIZE-1));
const int wavefront = startWaveInBatch + (DTid.x / WAVEFRONT_SIZE);
const int firstWavefrontInBlock = startWaveInBatch + Gid.x * WAVEFRONT_BLOCK_MULTIPLIER;
const int localWavefront = wavefront - firstWavefrontInBlock;
int batchesWithinWavefront = 0;
int verticesUsedByWave = 0;
int cond = wavefront < (startWaveInBatch + numWaves);
// Mask out in case there's a stray "wavefront" at the end that's been forced in through the multiplier
if( cond)
{
// Load the batch counts for the wavefronts
int2 batchesAndVerticesWithinWavefront = g_wavefrontBatchCountsVertexCounts[wavefront];
batchesWithinWavefront = batchesAndVerticesWithinWavefront.x;
verticesUsedByWave = batchesAndVerticesWithinWavefront.y;
// Load the vertices for the wavefronts
for( int vertex = laneInWavefront; vertex < verticesUsedByWave; vertex+=WAVEFRONT_SIZE )
{
int vertexAddress = g_vertexAddressesPerWavefront[wavefront*MAX_NUM_VERTICES_PER_WAVE + vertex];
//vertexAddressSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex] = vertexAddress;
vertexPositionSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex] = g_vertexPositions[vertexAddress];
vertexInverseMassSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex] = g_verticesInverseMass[vertexAddress];
}
}
// Ensure compiler does not re-order memory operations
//AllMemoryBarrier();
AllMemoryBarrierWithGroupSync ();
if( cond)
{
// Loop through the batches performing the solve on each in LDS
int baseDataLocationForWave = WAVEFRONT_SIZE * wavefront * MAX_BATCHES_PER_WAVE;
//for( int batch = 0; batch < batchesWithinWavefront; ++batch )
int batch = 0;
do
{
int baseDataLocation = baseDataLocationForWave + WAVEFRONT_SIZE * batch;
int locationOfValue = baseDataLocation + laneInWavefront;
// These loads should all be perfectly linear across the WF
int2 localVertexIndices = g_linksVertexIndices[locationOfValue];
float massLSC = g_linksMassLSC[locationOfValue];
float restLengthSquared = g_linksRestLengthSquared[locationOfValue];
// LDS vertex addresses based on logical wavefront number in block and loaded index
int vertexAddress0 = MAX_NUM_VERTICES_PER_WAVE * localWavefront + localVertexIndices.x;
int vertexAddress1 = MAX_NUM_VERTICES_PER_WAVE * localWavefront + localVertexIndices.y;
float3 position0 = vertexPositionSharedData[vertexAddress0].xyz;
float3 position1 = vertexPositionSharedData[vertexAddress1].xyz;
float inverseMass0 = vertexInverseMassSharedData[vertexAddress0];
float inverseMass1 = vertexInverseMassSharedData[vertexAddress1];
float3 del = position1 - position0;
float len = dot(del, del);
float k = 0;
if( massLSC > 0.0f )
{
k = ((restLengthSquared - len)/(massLSC*(restLengthSquared+len)))*kst;
}
position0 = position0 - del*(k*inverseMass0);
position1 = position1 + del*(k*inverseMass1);
// Ensure compiler does not re-order memory operations
AllMemoryBarrier();
vertexPositionSharedData[vertexAddress0] = float4(position0, 0.f);
vertexPositionSharedData[vertexAddress1] = float4(position1, 0.f);
// Ensure compiler does not re-order memory operations
AllMemoryBarrier();
++batch;
} while( batch < batchesWithinWavefront );
// Update the global memory vertices for the wavefronts
for( int vertex = laneInWavefront; vertex < verticesUsedByWave; vertex+=WAVEFRONT_SIZE )
{
int vertexAddress = g_vertexAddressesPerWavefront[wavefront*MAX_NUM_VERTICES_PER_WAVE + vertex];
g_vertexPositions[vertexAddress] = vertexPositionSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex];
}
}
}
);

View File

@@ -1,48 +0,0 @@
MSTRINGIFY(
cbuffer UpdateConstantsCB : register( b0 )
{
int numLinks;
int padding0;
int padding1;
int padding2;
};
// Node indices for each link
StructuredBuffer<int2> g_linksVertexIndices : register( t0 );
StructuredBuffer<float4> g_vertexPositions : register( t1 );
StructuredBuffer<float> g_vertexInverseMasses : register( t2 );
StructuredBuffer<float> g_linksMaterialLSC : register( t3 );
RWStructuredBuffer<float> g_linksMassLSC : register( u0 );
RWStructuredBuffer<float> g_linksRestLengthSquared : register( u1 );
RWStructuredBuffer<float> g_linksRestLengths : register( u2 );
[numthreads(128, 1, 1)]
void
UpdateConstantsKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
{
int linkID = DTid.x;
if( linkID < numLinks )
{
int2 nodeIndices = g_linksVertexIndices[linkID];
int node0 = nodeIndices.x;
int node1 = nodeIndices.y;
float linearStiffnessCoefficient = g_linksMaterialLSC[ linkID ];
float3 position0 = g_vertexPositions[node0].xyz;
float3 position1 = g_vertexPositions[node1].xyz;
float inverseMass0 = g_vertexInverseMasses[node0];
float inverseMass1 = g_vertexInverseMasses[node1];
float3 difference = position0 - position1;
float length2 = dot(difference, difference);
float length = sqrt(length2);
g_linksRestLengths[linkID] = length;
g_linksMassLSC[linkID] = (inverseMass0 + inverseMass1)/linearStiffnessCoefficient;
g_linksRestLengthSquared[linkID] = length*length;
}
}
);

View File

@@ -1,49 +0,0 @@
MSTRINGIFY(
cbuffer UpdateVelocitiesFromPositionsWithVelocitiesCB : register( b0 )
{
int numNodes;
float isolverdt;
int padding1;
int padding2;
};
StructuredBuffer<float4> g_vertexPositions : register( t0 );
StructuredBuffer<float4> g_vertexPreviousPositions : register( t1 );
StructuredBuffer<int> g_vertexClothIndices : register( t2 );
StructuredBuffer<float> g_clothVelocityCorrectionCoefficients : register( t3 );
StructuredBuffer<float> g_clothDampingFactor : register( t4 );
RWStructuredBuffer<float4> g_vertexVelocities : register( u0 );
RWStructuredBuffer<float4> g_vertexForces : register( u1 );
[numthreads(128, 1, 1)]
void
updateVelocitiesFromPositionsWithVelocitiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
{
int nodeID = DTid.x;
if( nodeID < numNodes )
{
float3 position = g_vertexPositions[nodeID].xyz;
float3 previousPosition = g_vertexPreviousPositions[nodeID].xyz;
float3 velocity = g_vertexVelocities[nodeID].xyz;
int clothIndex = g_vertexClothIndices[nodeID];
float velocityCorrectionCoefficient = g_clothVelocityCorrectionCoefficients[clothIndex];
float dampingFactor = g_clothDampingFactor[clothIndex];
float velocityCoefficient = (1.f - dampingFactor);
float3 difference = position - previousPosition;
velocity += difference*velocityCorrectionCoefficient*isolverdt;
// Damp the velocity
velocity *= velocityCoefficient;
g_vertexVelocities[nodeID] = float4(velocity, 0.f);
g_vertexForces[nodeID] = float4(0.f, 0.f, 0.f, 0.f);
}
}
);

View File

@@ -1,98 +0,0 @@
MSTRINGIFY(
cbuffer UpdateSoftBodiesCB : register( b0 )
{
unsigned int numNodes;
unsigned int startFace;
unsigned int numFaces;
float epsilon;
};
// Node indices for each link
StructuredBuffer<int4> g_triangleVertexIndexSet : register( t0 );
StructuredBuffer<float4> g_vertexPositions : register( t1 );
StructuredBuffer<int> g_vertexTriangleCount : register( t2 );
RWStructuredBuffer<float4> g_vertexNormals : register( u0 );
RWStructuredBuffer<float> g_vertexArea : register( u1 );
RWStructuredBuffer<float4> g_triangleNormals : register( u2 );
RWStructuredBuffer<float> g_triangleArea : register( u3 );
[numthreads(128, 1, 1)]
void
ResetNormalsAndAreasKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
{
if( DTid.x < numNodes )
{
g_vertexNormals[DTid.x] = float4(0.0f, 0.0f, 0.0f, 0.0f);
g_vertexArea[DTid.x] = 0.0f;
}
}
[numthreads(128, 1, 1)]
void
UpdateSoftBodiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
{
int faceID = DTid.x + startFace;
if( DTid.x < numFaces )
{
int4 triangleIndexSet = g_triangleVertexIndexSet[ faceID ];
int nodeIndex0 = triangleIndexSet.x;
int nodeIndex1 = triangleIndexSet.y;
int nodeIndex2 = triangleIndexSet.z;
float3 node0 = g_vertexPositions[nodeIndex0].xyz;
float3 node1 = g_vertexPositions[nodeIndex1].xyz;
float3 node2 = g_vertexPositions[nodeIndex2].xyz;
float3 nodeNormal0 = g_vertexNormals[nodeIndex0].xyz;
float3 nodeNormal1 = g_vertexNormals[nodeIndex1].xyz;
float3 nodeNormal2 = g_vertexNormals[nodeIndex2].xyz;
float vertexArea0 = g_vertexArea[nodeIndex0];
float vertexArea1 = g_vertexArea[nodeIndex1];
float vertexArea2 = g_vertexArea[nodeIndex2];
float3 vector0 = node1 - node0;
float3 vector1 = node2 - node0;
float3 faceNormal = cross(vector0.xyz, vector1.xyz);
float triangleArea = length(faceNormal);
nodeNormal0 = nodeNormal0 + faceNormal;
nodeNormal1 = nodeNormal1 + faceNormal;
nodeNormal2 = nodeNormal2 + faceNormal;
vertexArea0 = vertexArea0 + triangleArea;
vertexArea1 = vertexArea1 + triangleArea;
vertexArea2 = vertexArea2 + triangleArea;
g_triangleNormals[faceID] = float4(normalize(faceNormal), 0.f);
g_vertexNormals[nodeIndex0] = float4(nodeNormal0, 0.f);
g_vertexNormals[nodeIndex1] = float4(nodeNormal1, 0.f);
g_vertexNormals[nodeIndex2] = float4(nodeNormal2, 0.f);
g_triangleArea[faceID] = triangleArea;
g_vertexArea[nodeIndex0] = vertexArea0;
g_vertexArea[nodeIndex1] = vertexArea1;
g_vertexArea[nodeIndex2] = vertexArea2;
}
}
[numthreads(128, 1, 1)]
void
NormalizeNormalsAndAreasKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
{
if( DTid.x < numNodes )
{
float4 normal = g_vertexNormals[DTid.x];
float area = g_vertexArea[DTid.x];
int numTriangles = g_vertexTriangleCount[DTid.x];
float vectorLength = length(normal);
g_vertexNormals[DTid.x] = normalize(normal);
g_vertexArea[DTid.x] = area/float(numTriangles);
}
}
);

View File

@@ -1,44 +0,0 @@
MSTRINGIFY(
cbuffer UpdateVelocitiesFromPositionsWithoutVelocitiesCB : register( b0 )
{
int numNodes;
float isolverdt;
int padding1;
int padding2;
};
StructuredBuffer<float4> g_vertexPositions : register( t0 );
StructuredBuffer<float4> g_vertexPreviousPositions : register( t1 );
StructuredBuffer<int> g_vertexClothIndices : register( t2 );
StructuredBuffer<float> g_clothDampingFactor : register( t3 );
RWStructuredBuffer<float4> g_vertexVelocities : register( u0 );
RWStructuredBuffer<float4> g_vertexForces : register( u1 );
[numthreads(128, 1, 1)]
void
updateVelocitiesFromPositionsWithoutVelocitiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
{
int nodeID = DTid.x;
if( nodeID < numNodes )
{
float3 position = g_vertexPositions[nodeID].xyz;
float3 previousPosition = g_vertexPreviousPositions[nodeID].xyz;
float3 velocity = g_vertexVelocities[nodeID].xyz;
int clothIndex = g_vertexClothIndices[nodeID];
float dampingFactor = g_clothDampingFactor[clothIndex];
float velocityCoefficient = (1.f - dampingFactor);
float3 difference = position - previousPosition;
velocity = difference*velocityCoefficient*isolverdt;
g_vertexVelocities[nodeID] = float4(velocity, 0.f);
g_vertexForces[nodeID] = float4(0.f, 0.f, 0.f, 0.f);
}
}
);

View File

@@ -1,35 +0,0 @@
MSTRINGIFY(
cbuffer UpdatePositionsFromVelocitiesCB : register( b0 )
{
int numNodes;
float solverSDT;
int padding1;
int padding2;
};
StructuredBuffer<float4> g_vertexVelocities : register( t0 );
RWStructuredBuffer<float4> g_vertexPreviousPositions : register( u0 );
RWStructuredBuffer<float4> g_vertexCurrentPosition : register( u1 );
[numthreads(128, 1, 1)]
void
UpdatePositionsFromVelocitiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
{
int vertexID = DTid.x;
if( vertexID < numNodes )
{
float3 previousPosition = g_vertexPreviousPositions[vertexID].xyz;
float3 velocity = g_vertexVelocities[vertexID].xyz;
float3 newPosition = previousPosition + velocity*solverSDT;
g_vertexCurrentPosition[vertexID] = float4(newPosition, 0.f);
g_vertexPreviousPositions[vertexID] = float4(newPosition, 0.f);
}
}
);

View File

@@ -1,55 +0,0 @@
MSTRINGIFY(
cbuffer VSolveLinksCB : register( b0 )
{
int startLink;
int numLinks;
float kst;
int padding;
};
// Node indices for each link
StructuredBuffer<int2> g_linksVertexIndices : register( t0 );
StructuredBuffer<float> g_linksLengthRatio : register( t1 );
StructuredBuffer<float4> g_linksCurrentLength : register( t2 );
StructuredBuffer<float> g_vertexInverseMass : register( t3 );
RWStructuredBuffer<float4> g_vertexVelocity : register( u0 );
[numthreads(128, 1, 1)]
void
VSolveLinksKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
{
int linkID = DTid.x + startLink;
if( DTid.x < numLinks )
{
int2 nodeIndices = g_linksVertexIndices[linkID];
int node0 = nodeIndices.x;
int node1 = nodeIndices.y;
float linkLengthRatio = g_linksLengthRatio[linkID];
float3 linkCurrentLength = g_linksCurrentLength[linkID].xyz;
float3 vertexVelocity0 = g_vertexVelocity[node0].xyz;
float3 vertexVelocity1 = g_vertexVelocity[node1].xyz;
float vertexInverseMass0 = g_vertexInverseMass[node0];
float vertexInverseMass1 = g_vertexInverseMass[node1];
float3 nodeDifference = vertexVelocity0 - vertexVelocity1;
float dotResult = dot(linkCurrentLength, nodeDifference);
float j = -dotResult*linkLengthRatio*kst;
float3 velocityChange0 = linkCurrentLength*(j*vertexInverseMass0);
float3 velocityChange1 = linkCurrentLength*(j*vertexInverseMass1);
vertexVelocity0 += velocityChange0;
vertexVelocity1 -= velocityChange1;
g_vertexVelocity[node0] = float4(vertexVelocity0, 0.f);
g_vertexVelocity[node1] = float4(vertexVelocity1, 0.f);
}
}
);

View File

@@ -1,170 +0,0 @@
MSTRINGIFY(
cbuffer SolvePositionsFromLinksKernelCB : register( b0 )
{
unsigned int numNodes;
float isolverdt;
int padding0;
int padding1;
};
struct CollisionObjectIndices
{
int firstObject;
int endObject;
};
struct CollisionShapeDescription
{
float4x4 shapeTransform;
float4 linearVelocity;
float4 angularVelocity;
int softBodyIdentifier;
int collisionShapeType;
// Shape information
// Compressed from the union
float radius;
float halfHeight;
float margin;
float friction;
int padding0;
int padding1;
};
// From btBroadphaseProxy.h
static const int CAPSULE_SHAPE_PROXYTYPE = 10;
// Node indices for each link
StructuredBuffer<int> g_vertexClothIdentifier : register( t0 );
StructuredBuffer<float4> g_vertexPreviousPositions : register( t1 );
StructuredBuffer<float> g_perClothFriction : register( t2 );
StructuredBuffer<float> g_clothDampingFactor : register( t3 );
StructuredBuffer<CollisionObjectIndices> g_perClothCollisionObjectIndices : register( t4 );
StructuredBuffer<CollisionShapeDescription> g_collisionObjectDetails : register( t5 );
RWStructuredBuffer<float4> g_vertexForces : register( u0 );
RWStructuredBuffer<float4> g_vertexVelocities : register( u1 );
RWStructuredBuffer<float4> g_vertexPositions : register( u2 );
[numthreads(128, 1, 1)]
void
SolveCollisionsAndUpdateVelocitiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
{
int nodeID = DTid.x;
float3 forceOnVertex = float3(0.f, 0.f, 0.f);
if( DTid.x < numNodes )
{
int clothIdentifier = g_vertexClothIdentifier[nodeID];
float4 position = float4(g_vertexPositions[nodeID].xyz, 1.f);
float4 previousPosition = float4(g_vertexPreviousPositions[nodeID].xyz, 1.f);
float3 velocity;
float clothFriction = g_perClothFriction[clothIdentifier];
float dampingFactor = g_clothDampingFactor[clothIdentifier];
float velocityCoefficient = (1.f - dampingFactor);
CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier];
if( collisionObjectIndices.firstObject != collisionObjectIndices.endObject )
{
velocity = float3(15, 0, 0);
// We have some possible collisions to deal with
for( int collision = collisionObjectIndices.firstObject; collision < collisionObjectIndices.endObject; ++collision )
{
CollisionShapeDescription shapeDescription = g_collisionObjectDetails[collision];
float colliderFriction = shapeDescription.friction;
if( shapeDescription.collisionShapeType == CAPSULE_SHAPE_PROXYTYPE )
{
// Colliding with a capsule
float capsuleHalfHeight = shapeDescription.halfHeight;
float capsuleRadius = shapeDescription.radius;
float capsuleMargin = shapeDescription.margin;
float4x4 worldTransform = shapeDescription.shapeTransform;
float4 c1 = float4(0.f, -capsuleHalfHeight, 0.f, 1.f);
float4 c2 = float4(0.f, +capsuleHalfHeight, 0.f, 1.f);
float4 worldC1 = mul(worldTransform, c1);
float4 worldC2 = mul(worldTransform, c2);
float3 segment = (worldC2 - worldC1).xyz;
// compute distance of tangent to vertex along line segment in capsule
float distanceAlongSegment = -( dot( (worldC1 - position).xyz, segment ) / dot(segment, segment) );
float4 closestPoint = (worldC1 + float4(segment * distanceAlongSegment, 0.f));
float distanceFromLine = length(position - closestPoint);
float distanceFromC1 = length(worldC1 - position);
float distanceFromC2 = length(worldC2 - position);
// Final distance from collision, point to push from, direction to push in
// for impulse force
float dist;
float3 normalVector;
if( distanceAlongSegment < 0 )
{
dist = distanceFromC1;
normalVector = normalize(position - worldC1).xyz;
} else if( distanceAlongSegment > 1.f ) {
dist = distanceFromC2;
normalVector = normalize(position - worldC2).xyz;
} else {
dist = distanceFromLine;
normalVector = normalize(position - closestPoint).xyz;
}
float3 colliderLinearVelocity = shapeDescription.linearVelocity.xyz;
float3 colliderAngularVelocity = shapeDescription.angularVelocity.xyz;
float3 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, position.xyz - worldTransform._m03_m13_m23);
float minDistance = capsuleRadius + capsuleMargin;
// In case of no collision, this is the value of velocity
velocity = (position - previousPosition).xyz * velocityCoefficient * isolverdt;
// Check for a collision
if( dist < minDistance )
{
// Project back to surface along normal
position = position + float4((minDistance - dist)*normalVector*0.9, 0.f);
velocity = (position - previousPosition).xyz * velocityCoefficient * isolverdt;
float3 relativeVelocity = velocity - velocityOfSurfacePoint;
float3 p1 = normalize(cross(normalVector, segment));
float3 p2 = normalize(cross(p1, normalVector));
// Full friction is sum of velocities in each direction of plane
float3 frictionVector = p1*dot(relativeVelocity, p1) + p2*dot(relativeVelocity, p2);
// Real friction is peak friction corrected by friction coefficients
frictionVector = frictionVector * (colliderFriction*clothFriction);
float approachSpeed = dot(relativeVelocity, normalVector);
if( approachSpeed <= 0.0 )
forceOnVertex -= frictionVector;
}
}
}
} else {
// Update velocity
float3 difference = position.xyz - previousPosition.xyz;
velocity = difference*velocityCoefficient*isolverdt;
}
g_vertexVelocities[nodeID] = float4(velocity, 0.f);
// Update external force
g_vertexForces[nodeID] = float4(forceOnVertex, 0.f);
g_vertexPositions[nodeID] = float4(position.xyz, 0.f);
}
}
);

View File

@@ -1,191 +0,0 @@
MSTRINGIFY(
cbuffer SolvePositionsFromLinksKernelCB : register( b0 )
{
unsigned int numNodes;
float isolverdt;
int padding0;
int padding1;
};
struct CollisionObjectIndices
{
int firstObject;
int endObject;
};
struct CollisionShapeDescription
{
float4x4 shapeTransform;
float4 linearVelocity;
float4 angularVelocity;
int softBodyIdentifier;
int collisionShapeType;
// Shape information
// Compressed from the union
float radius;
float halfHeight;
float margin;
float friction;
int padding0;
int padding1;
};
// From btBroadphaseProxy.h
static const int CAPSULE_SHAPE_PROXYTYPE = 10;
// Node indices for each link
StructuredBuffer<int> g_vertexClothIdentifier : register( t0 );
StructuredBuffer<float4> g_vertexPreviousPositions : register( t1 );
StructuredBuffer<float> g_perClothFriction : register( t2 );
StructuredBuffer<float> g_clothDampingFactor : register( t3 );
StructuredBuffer<CollisionObjectIndices> g_perClothCollisionObjectIndices : register( t4 );
StructuredBuffer<CollisionShapeDescription> g_collisionObjectDetails : register( t5 );
RWStructuredBuffer<float4> g_vertexForces : register( u0 );
RWStructuredBuffer<float4> g_vertexVelocities : register( u1 );
RWStructuredBuffer<float4> g_vertexPositions : register( u2 );
// A buffer of local collision shapes
// TODO: Iterate to support more than 16
groupshared CollisionShapeDescription localCollisionShapes[16];
[numthreads(128, 1, 1)]
void
SolveCollisionsAndUpdateVelocitiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
{
int nodeID = DTid.x;
float3 forceOnVertex = float3(0.f, 0.f, 0.f);
int clothIdentifier = g_vertexClothIdentifier[nodeID];
float4 position = float4(g_vertexPositions[nodeID].xyz, 1.f);
float4 previousPosition = float4(g_vertexPreviousPositions[nodeID].xyz, 1.f);
float3 velocity;
float clothFriction = g_perClothFriction[clothIdentifier];
float dampingFactor = g_clothDampingFactor[clothIdentifier];
float velocityCoefficient = (1.f - dampingFactor);
CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier];
int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject;
if( numObjects > 0 )
{
// We have some possible collisions to deal with
// First load all of the collision objects into LDS
int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject;
if( GTid.x < numObjects )
{
localCollisionShapes[GTid.x] = g_collisionObjectDetails[ collisionObjectIndices.firstObject + GTid.x ];
}
}
// Safe as the vertices are padded so that not more than one soft body is in a group
AllMemoryBarrierWithGroupSync();
// Annoyingly, even though I know the flow control is not varying, the compiler will not let me skip this
if( numObjects > 0 )
{
velocity = float3(0, 0, 0);
// We have some possible collisions to deal with
for( int collision = 0; collision < numObjects; ++collision )
{
CollisionShapeDescription shapeDescription = localCollisionShapes[collision];
float colliderFriction = shapeDescription.friction;
if( shapeDescription.collisionShapeType == CAPSULE_SHAPE_PROXYTYPE )
{
// Colliding with a capsule
float capsuleHalfHeight = localCollisionShapes[collision].halfHeight;
float capsuleRadius = localCollisionShapes[collision].radius;
float capsuleMargin = localCollisionShapes[collision].margin;
float4x4 worldTransform = localCollisionShapes[collision].shapeTransform;
float4 c1 = float4(0.f, -capsuleHalfHeight, 0.f, 1.f);
float4 c2 = float4(0.f, +capsuleHalfHeight, 0.f, 1.f);
float4 worldC1 = mul(worldTransform, c1);
float4 worldC2 = mul(worldTransform, c2);
float3 segment = (worldC2 - worldC1).xyz;
// compute distance of tangent to vertex along line segment in capsule
float distanceAlongSegment = -( dot( (worldC1 - position).xyz, segment ) / dot(segment, segment) );
float4 closestPoint = (worldC1 + float4(segment * distanceAlongSegment, 0.f));
float distanceFromLine = length(position - closestPoint);
float distanceFromC1 = length(worldC1 - position);
float distanceFromC2 = length(worldC2 - position);
// Final distance from collision, point to push from, direction to push in
// for impulse force
float dist;
float3 normalVector;
if( distanceAlongSegment < 0 )
{
dist = distanceFromC1;
normalVector = normalize(position - worldC1).xyz;
} else if( distanceAlongSegment > 1.f ) {
dist = distanceFromC2;
normalVector = normalize(position - worldC2).xyz;
} else {
dist = distanceFromLine;
normalVector = normalize(position - closestPoint).xyz;
}
float3 colliderLinearVelocity = localCollisionShapes[collision].linearVelocity.xyz;
float3 colliderAngularVelocity = localCollisionShapes[collision].angularVelocity.xyz;
float3 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, position.xyz - worldTransform._m03_m13_m23);
float minDistance = capsuleRadius + capsuleMargin;
// In case of no collision, this is the value of velocity
velocity = (position - previousPosition).xyz * velocityCoefficient * isolverdt;
// Check for a collision
if( dist < minDistance )
{
// Project back to surface along normal
position = position + float4((minDistance - dist)*normalVector*0.9, 0.f);
velocity = (position - previousPosition).xyz * velocityCoefficient * isolverdt;
float3 relativeVelocity = velocity - velocityOfSurfacePoint;
float3 p1 = normalize(cross(normalVector, segment));
float3 p2 = normalize(cross(p1, normalVector));
// Full friction is sum of velocities in each direction of plane
float3 frictionVector = p1*dot(relativeVelocity, p1) + p2*dot(relativeVelocity, p2);
// Real friction is peak friction corrected by friction coefficients
frictionVector = frictionVector * (colliderFriction*clothFriction);
float approachSpeed = dot(relativeVelocity, normalVector);
if( approachSpeed <= 0.0 )
forceOnVertex -= frictionVector;
}
}
}
} else {
// Update velocity
float3 difference = position.xyz - previousPosition.xyz;
velocity = difference*velocityCoefficient*isolverdt;
}
g_vertexVelocities[nodeID] = float4(velocity, 0.f);
// Update external force
g_vertexForces[nodeID] = float4(forceOnVertex, 0.f);
g_vertexPositions[nodeID] = float4(position.xyz, 0.f);
}
);

View File

@@ -1,323 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_SOFT_BODY_SOLVER_BUFFER_DX11_H
#define BT_SOFT_BODY_SOLVER_BUFFER_DX11_H
// DX11 support
#include <windows.h>
#include <crtdbg.h>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dcompiler.h>
#ifndef SAFE_RELEASE
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
#endif
/**
* DX11 Buffer that tracks a host buffer on use to ensure size-correctness.
*/
template <typename ElementType> class btDX11Buffer
{
protected:
ID3D11Device* m_d3dDevice;
ID3D11DeviceContext* m_d3dDeviceContext;
ID3D11Buffer* m_Buffer;
ID3D11ShaderResourceView* m_SRV;
ID3D11UnorderedAccessView* m_UAV;
btAlignedObjectArray< ElementType >* m_CPUBuffer;
// TODO: Separate this from the main class
// as read back buffers can be shared between buffers
ID3D11Buffer* m_readBackBuffer;
int m_gpuSize;
bool m_onGPU;
bool m_readOnlyOnGPU;
bool createBuffer( ID3D11Buffer *preexistingBuffer = 0)
{
HRESULT hr = S_OK;
// Create all CS buffers
if( preexistingBuffer )
{
m_Buffer = preexistingBuffer;
} else {
D3D11_BUFFER_DESC buffer_desc;
ZeroMemory(&buffer_desc, sizeof(buffer_desc));
buffer_desc.Usage = D3D11_USAGE_DEFAULT;
if( m_readOnlyOnGPU )
buffer_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
else
buffer_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS;
buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
buffer_desc.ByteWidth = m_CPUBuffer->size() * sizeof(ElementType);
// At a minimum the buffer must exist
if( buffer_desc.ByteWidth == 0 )
buffer_desc.ByteWidth = sizeof(ElementType);
buffer_desc.StructureByteStride = sizeof(ElementType);
hr = m_d3dDevice->CreateBuffer(&buffer_desc, NULL, &m_Buffer);
if( FAILED( hr ) )
return (hr==S_OK);
}
if( m_readOnlyOnGPU )
{
D3D11_SHADER_RESOURCE_VIEW_DESC srvbuffer_desc;
ZeroMemory(&srvbuffer_desc, sizeof(srvbuffer_desc));
srvbuffer_desc.Format = DXGI_FORMAT_UNKNOWN;
srvbuffer_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
srvbuffer_desc.Buffer.ElementWidth = m_CPUBuffer->size();
if( srvbuffer_desc.Buffer.ElementWidth == 0 )
srvbuffer_desc.Buffer.ElementWidth = 1;
hr = m_d3dDevice->CreateShaderResourceView(m_Buffer, &srvbuffer_desc, &m_SRV);
if( FAILED( hr ) )
return (hr==S_OK);
} else {
// Create SRV
D3D11_SHADER_RESOURCE_VIEW_DESC srvbuffer_desc;
ZeroMemory(&srvbuffer_desc, sizeof(srvbuffer_desc));
srvbuffer_desc.Format = DXGI_FORMAT_UNKNOWN;
srvbuffer_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
srvbuffer_desc.Buffer.ElementWidth = m_CPUBuffer->size();
if( srvbuffer_desc.Buffer.ElementWidth == 0 )
srvbuffer_desc.Buffer.ElementWidth = 1;
hr = m_d3dDevice->CreateShaderResourceView(m_Buffer, &srvbuffer_desc, &m_SRV);
if( FAILED( hr ) )
return (hr==S_OK);
// Create UAV
D3D11_UNORDERED_ACCESS_VIEW_DESC uavbuffer_desc;
ZeroMemory(&uavbuffer_desc, sizeof(uavbuffer_desc));
uavbuffer_desc.Format = DXGI_FORMAT_UNKNOWN;
uavbuffer_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
uavbuffer_desc.Buffer.NumElements = m_CPUBuffer->size();
if( uavbuffer_desc.Buffer.NumElements == 0 )
uavbuffer_desc.Buffer.NumElements = 1;
hr = m_d3dDevice->CreateUnorderedAccessView(m_Buffer, &uavbuffer_desc, &m_UAV);
if( FAILED( hr ) )
return (hr==S_OK);
// Create read back buffer
D3D11_BUFFER_DESC readback_buffer_desc;
ZeroMemory(&readback_buffer_desc, sizeof(readback_buffer_desc));
readback_buffer_desc.ByteWidth = m_CPUBuffer->size() * sizeof(ElementType);
readback_buffer_desc.Usage = D3D11_USAGE_STAGING;
readback_buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
readback_buffer_desc.StructureByteStride = sizeof(ElementType);
hr = m_d3dDevice->CreateBuffer(&readback_buffer_desc, NULL, &m_readBackBuffer);
if( FAILED( hr ) )
return (hr==S_OK);
}
m_gpuSize = m_CPUBuffer->size();
return true;
}
public:
btDX11Buffer( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext, btAlignedObjectArray< ElementType > *CPUBuffer, bool readOnly )
{
m_d3dDevice = d3dDevice;
m_d3dDeviceContext = d3dDeviceContext;
m_Buffer = 0;
m_SRV = 0;
m_UAV = 0;
m_readBackBuffer = 0;
m_CPUBuffer = CPUBuffer;
m_gpuSize = 0;
m_onGPU = false;
m_readOnlyOnGPU = readOnly;
}
virtual ~btDX11Buffer()
{
SAFE_RELEASE(m_Buffer);
SAFE_RELEASE(m_SRV);
SAFE_RELEASE(m_UAV);
SAFE_RELEASE(m_readBackBuffer);
}
ID3D11ShaderResourceView* &getSRV()
{
return m_SRV;
}
ID3D11UnorderedAccessView* &getUAV()
{
return m_UAV;
}
ID3D11Buffer* &getBuffer()
{
return m_Buffer;
}
/**
* Move the data to the GPU if it is not there already.
*/
bool moveToGPU()
{
// Reallocate if GPU size is too small
if( (m_CPUBuffer->size() > m_gpuSize ) )
m_onGPU = false;
if( !m_onGPU && m_CPUBuffer->size() > 0 )
{
// If the buffer doesn't exist or the CPU-side buffer has changed size, create
// We should really delete the old one, too, but let's leave that for later
if( !m_Buffer || (m_CPUBuffer->size() != m_gpuSize) )
{
SAFE_RELEASE(m_Buffer);
SAFE_RELEASE(m_SRV);
SAFE_RELEASE(m_UAV);
SAFE_RELEASE(m_readBackBuffer);
if( !createBuffer() )
{
btAssert("Buffer creation failed.");
return false;
}
}
if( m_gpuSize > 0 )
{
D3D11_BOX destRegion;
destRegion.left = 0;
destRegion.front = 0;
destRegion.top = 0;
destRegion.bottom = 1;
destRegion.back = 1;
destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType);
m_d3dDeviceContext->UpdateSubresource(m_Buffer, 0, &destRegion, &((*m_CPUBuffer)[0]), 0, 0);
m_onGPU = true;
}
}
return true;
}
/**
* Move the data back from the GPU if it is on there and isn't read only.
*/
bool moveFromGPU()
{
if( m_CPUBuffer->size() > 0 )
{
if( m_onGPU && !m_readOnlyOnGPU )
{
// Copy back
D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
//m_pd3dImmediateContext->CopyResource(m_phAngVelReadBackBuffer, m_phAngVel);
D3D11_BOX destRegion;
destRegion.left = 0;
destRegion.front = 0;
destRegion.top = 0;
destRegion.bottom = 1;
destRegion.back = 1;
destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType);
m_d3dDeviceContext->CopySubresourceRegion(
m_readBackBuffer,
0,
0,
0,
0 ,
m_Buffer,
0,
&destRegion
);
m_d3dDeviceContext->Map(m_readBackBuffer, 0, D3D11_MAP_READ, 0, &MappedResource);
//memcpy(m_hAngVel, MappedResource.pData, (m_maxObjs * sizeof(float) ));
memcpy(&((*m_CPUBuffer)[0]), MappedResource.pData, ((m_CPUBuffer->size()) * sizeof(ElementType) ));
m_d3dDeviceContext->Unmap(m_readBackBuffer, 0);
m_onGPU = false;
}
}
return true;
}
/**
* Copy the data back from the GPU without changing its state to be CPU-side.
* Useful if we just want to view it on the host for visualization.
*/
bool copyFromGPU()
{
if( m_CPUBuffer->size() > 0 )
{
if( m_onGPU && !m_readOnlyOnGPU )
{
// Copy back
D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
D3D11_BOX destRegion;
destRegion.left = 0;
destRegion.front = 0;
destRegion.top = 0;
destRegion.bottom = 1;
destRegion.back = 1;
destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType);
m_d3dDeviceContext->CopySubresourceRegion(
m_readBackBuffer,
0,
0,
0,
0 ,
m_Buffer,
0,
&destRegion
);
m_d3dDeviceContext->Map(m_readBackBuffer, 0, D3D11_MAP_READ, 0, &MappedResource);
//memcpy(m_hAngVel, MappedResource.pData, (m_maxObjs * sizeof(float) ));
memcpy(&((*m_CPUBuffer)[0]), MappedResource.pData, ((m_CPUBuffer->size()) * sizeof(ElementType) ));
m_d3dDeviceContext->Unmap(m_readBackBuffer, 0);
}
}
return true;
}
/**
* Call if data has changed on the CPU.
* Can then trigger a move to the GPU as necessary.
*/
virtual void changedOnCPU()
{
m_onGPU = false;
}
}; // class btDX11Buffer
#endif // #ifndef BT_SOFT_BODY_SOLVER_BUFFER_DX11_H

View File

@@ -1,103 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h"
#include "btSoftBodySolverBuffer_DX11.h"
#ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_DX11_H
#define BT_SOFT_BODY_SOLVER_LINK_DATA_DX11_H
struct ID3D11Device;
struct ID3D11DeviceContext;
class btSoftBodyLinkDataDX11 : public btSoftBodyLinkData
{
public:
bool m_onGPU;
ID3D11Device *m_d3dDevice;
ID3D11DeviceContext *m_d3dDeviceContext;
btDX11Buffer<LinkNodePair> m_dx11Links;
btDX11Buffer<float> m_dx11LinkStrength;
btDX11Buffer<float> m_dx11LinksMassLSC;
btDX11Buffer<float> m_dx11LinksRestLengthSquared;
btDX11Buffer<Vectormath::Aos::Vector3> m_dx11LinksCLength;
btDX11Buffer<float> m_dx11LinksLengthRatio;
btDX11Buffer<float> m_dx11LinksRestLength;
btDX11Buffer<float> m_dx11LinksMaterialLinearStiffnessCoefficient;
struct BatchPair
{
int start;
int length;
BatchPair() :
start(0),
length(0)
{
}
BatchPair( int s, int l ) :
start( s ),
length( l )
{
}
};
/**
* Link addressing information for each cloth.
* Allows link locations to be computed independently of data batching.
*/
btAlignedObjectArray< int > m_linkAddresses;
/**
* Start and length values for computation batches over link data.
*/
btAlignedObjectArray< BatchPair > m_batchStartLengths;
//ID3D11Buffer* readBackBuffer;
btSoftBodyLinkDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext );
virtual ~btSoftBodyLinkDataDX11();
/** Allocate enough space in all link-related arrays to fit numLinks links */
virtual void createLinks( int numLinks );
/** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */
virtual void setLinkAt( const LinkDescription &link, int linkIndex );
virtual bool onAccelerator();
virtual bool moveToAccelerator();
virtual bool moveFromAccelerator();
/**
* Generate (and later update) the batching for the entire link set.
* This redoes a lot of work because it batches the entire set when each cloth is inserted.
* In theory we could delay it until just before we need the cloth.
* It's a one-off overhead, though, so that is a later optimisation.
*/
void generateBatches();
};
#endif // #ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_DX11_H

View File

@@ -1,173 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h"
#include "btSoftBodySolverBuffer_DX11.h"
#ifndef BT_ACCELERATED_SOFT_BODY_LINK_DATA_DX11_SIMDAWARE_H
#define BT_ACCELERATED_SOFT_BODY_LINK_DATA_DX11_SIMDAWARE_H
struct ID3D11Device;
struct ID3D11DeviceContext;
class btSoftBodyLinkDataDX11SIMDAware : public btSoftBodyLinkData
{
public:
bool m_onGPU;
ID3D11Device *m_d3dDevice;
ID3D11DeviceContext *m_d3dDeviceContext;
const int m_wavefrontSize;
const int m_linksPerWorkItem;
const int m_maxLinksPerWavefront;
int m_maxBatchesWithinWave;
int m_maxVerticesWithinWave;
int m_numWavefronts;
int m_maxVertex;
struct NumBatchesVerticesPair
{
int numBatches;
int numVertices;
};
// Array storing number of links in each wavefront
btAlignedObjectArray<int> m_linksPerWavefront;
btAlignedObjectArray<NumBatchesVerticesPair> m_numBatchesAndVerticesWithinWaves;
btDX11Buffer< NumBatchesVerticesPair > m_dx11NumBatchesAndVerticesWithinWaves;
// All arrays here will contain batches of m_maxLinksPerWavefront links
// ordered by wavefront.
// with either global vertex pairs or local vertex pairs
btAlignedObjectArray< int > m_wavefrontVerticesGlobalAddresses; // List of global vertices per wavefront
btDX11Buffer<int> m_dx11WavefrontVerticesGlobalAddresses;
btAlignedObjectArray< LinkNodePair > m_linkVerticesLocalAddresses; // Vertex pair for the link
btDX11Buffer<LinkNodePair> m_dx11LinkVerticesLocalAddresses;
btDX11Buffer<float> m_dx11LinkStrength;
btDX11Buffer<float> m_dx11LinksMassLSC;
btDX11Buffer<float> m_dx11LinksRestLengthSquared;
btDX11Buffer<float> m_dx11LinksRestLength;
btDX11Buffer<float> m_dx11LinksMaterialLinearStiffnessCoefficient;
struct BatchPair
{
int start;
int length;
BatchPair() :
start(0),
length(0)
{
}
BatchPair( int s, int l ) :
start( s ),
length( l )
{
}
};
/**
* Link addressing information for each cloth.
* Allows link locations to be computed independently of data batching.
*/
btAlignedObjectArray< int > m_linkAddresses;
/**
* Start and length values for computation batches over link data.
*/
btAlignedObjectArray< BatchPair > m_wavefrontBatchStartLengths;
//ID3D11Buffer* readBackBuffer;
btSoftBodyLinkDataDX11SIMDAware( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext );
virtual ~btSoftBodyLinkDataDX11SIMDAware();
/** Allocate enough space in all link-related arrays to fit numLinks links */
virtual void createLinks( int numLinks );
/** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */
virtual void setLinkAt( const LinkDescription &link, int linkIndex );
virtual bool onAccelerator();
virtual bool moveToAccelerator();
virtual bool moveFromAccelerator();
/**
* Generate (and later update) the batching for the entire link set.
* This redoes a lot of work because it batches the entire set when each cloth is inserted.
* In theory we could delay it until just before we need the cloth.
* It's a one-off overhead, though, so that is a later optimisation.
*/
void generateBatches();
int getMaxVerticesPerWavefront()
{
return m_maxVerticesWithinWave;
}
int getWavefrontSize()
{
return m_wavefrontSize;
}
int getLinksPerWorkItem()
{
return m_linksPerWorkItem;
}
int getMaxLinksPerWavefront()
{
return m_maxLinksPerWavefront;
}
int getMaxBatchesPerWavefront()
{
return m_maxBatchesWithinWave;
}
int getNumWavefronts()
{
return m_numWavefronts;
}
NumBatchesVerticesPair getNumBatchesAndVerticesWithinWavefront( int wavefront )
{
return m_numBatchesAndVerticesWithinWaves[wavefront];
}
int getVertexGlobalAddresses( int vertexIndex )
{
return m_wavefrontVerticesGlobalAddresses[vertexIndex];
}
/**
* Get post-batching local addresses of the vertex pair for a link assuming all vertices used by a wavefront are loaded locally.
*/
LinkNodePair getVertexPairLocalAddresses( int linkIndex )
{
return m_linkVerticesLocalAddresses[linkIndex];
}
};
#endif // #ifndef BT_ACCELERATED_SOFT_BODY_LINK_DATA_DX11_SIMDAWARE_H

View File

@@ -1,96 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h"
#include "btSoftBodySolverBuffer_DX11.h"
#ifndef BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_DX11_H
#define BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_DX11_H
struct ID3D11Device;
struct ID3D11DeviceContext;
class btSoftBodyTriangleDataDX11 : public btSoftBodyTriangleData
{
public:
bool m_onGPU;
ID3D11Device *m_d3dDevice;
ID3D11DeviceContext *m_d3dDeviceContext;
btDX11Buffer<btSoftBodyTriangleData::TriangleNodeSet> m_dx11VertexIndices;
btDX11Buffer<float> m_dx11Area;
btDX11Buffer<Vectormath::Aos::Vector3> m_dx11Normal;
struct BatchPair
{
int start;
int length;
BatchPair() :
start(0),
length(0)
{
}
BatchPair( int s, int l ) :
start( s ),
length( l )
{
}
};
/**
* Link addressing information for each cloth.
* Allows link locations to be computed independently of data batching.
*/
btAlignedObjectArray< int > m_triangleAddresses;
/**
* Start and length values for computation batches over link data.
*/
btAlignedObjectArray< BatchPair > m_batchStartLengths;
//ID3D11Buffer* readBackBuffer;
public:
btSoftBodyTriangleDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext );
virtual ~btSoftBodyTriangleDataDX11();
/** Allocate enough space in all link-related arrays to fit numLinks links */
virtual void createTriangles( int numTriangles );
/** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */
virtual void setTriangleAt( const btSoftBodyTriangleData::TriangleDescription &triangle, int triangleIndex );
virtual bool onAccelerator();
virtual bool moveToAccelerator();
virtual bool moveFromAccelerator();
/**
* Generate (and later update) the batching for the entire triangle set.
* This redoes a lot of work because it batches the entire set when each cloth is inserted.
* In theory we could delay it until just before we need the cloth.
* It's a one-off overhead, though, so that is a later optimisation.
*/
void generateBatches();
};
#endif // #ifndef BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_DX11_H

View File

@@ -1,107 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_DX11_H
#define BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_DX11_H
#include "BulletSoftBody/btSoftBodySolverVertexBuffer.h"
#include <windows.h>
#include <crtdbg.h>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dcompiler.h>
class btDX11VertexBufferDescriptor : public btVertexBufferDescriptor
{
protected:
/** Context of the DX11 device on which the vertex buffer is stored. */
ID3D11DeviceContext* m_context;
/** DX11 vertex buffer */
ID3D11Buffer* m_vertexBuffer;
/** UAV for DX11 buffer */
ID3D11UnorderedAccessView* m_vertexBufferUAV;
public:
/**
* buffer is a pointer to the DX11 buffer to place the vertex data in.
* UAV is a pointer to the UAV representation of the buffer laid out in floats.
* vertexOffset is the offset in floats to the first vertex.
* vertexStride is the stride in floats between vertices.
*/
btDX11VertexBufferDescriptor( ID3D11DeviceContext* context, ID3D11Buffer* buffer, ID3D11UnorderedAccessView *UAV, int vertexOffset, int vertexStride )
{
m_context = context;
m_vertexBuffer = buffer;
m_vertexBufferUAV = UAV;
m_vertexOffset = vertexOffset;
m_vertexStride = vertexStride;
m_hasVertexPositions = true;
}
/**
* buffer is a pointer to the DX11 buffer to place the vertex data in.
* UAV is a pointer to the UAV representation of the buffer laid out in floats.
* vertexOffset is the offset in floats to the first vertex.
* vertexStride is the stride in floats between vertices.
* normalOffset is the offset in floats to the first normal.
* normalStride is the stride in floats between normals.
*/
btDX11VertexBufferDescriptor( ID3D11DeviceContext* context, ID3D11Buffer* buffer, ID3D11UnorderedAccessView *UAV, int vertexOffset, int vertexStride, int normalOffset, int normalStride )
{
m_context = context;
m_vertexBuffer = buffer;
m_vertexBufferUAV = UAV;
m_vertexOffset = vertexOffset;
m_vertexStride = vertexStride;
m_hasVertexPositions = true;
m_normalOffset = normalOffset;
m_normalStride = normalStride;
m_hasNormals = true;
}
virtual ~btDX11VertexBufferDescriptor()
{
}
/**
* Return the type of the vertex buffer descriptor.
*/
virtual BufferTypes getBufferType() const
{
return DX11_BUFFER;
}
virtual ID3D11DeviceContext* getContext() const
{
return m_context;
}
virtual ID3D11Buffer* getbtDX11Buffer() const
{
return m_vertexBuffer;
}
virtual ID3D11UnorderedAccessView* getDX11UAV() const
{
return m_vertexBufferUAV;
}
};
#endif // #ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_DX11_H

View File

@@ -1,63 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h"
#include "btSoftBodySolverBuffer_DX11.h"
#ifndef BT_SOFT_BHODY_SOLVER_VERTEX_DATA_DX11_H
#define BT_SOFT_BHODY_SOLVER_VERTEX_DATA_DX11_H
class btSoftBodyLinkData;
class btSoftBodyLinkData::LinkDescription;
struct ID3D11Device;
struct ID3D11DeviceContext;
class btSoftBodyVertexDataDX11 : public btSoftBodyVertexData
{
protected:
bool m_onGPU;
ID3D11Device *m_d3dDevice;
ID3D11DeviceContext *m_d3dDeviceContext;
public:
btDX11Buffer<int> m_dx11ClothIdentifier;
btDX11Buffer<Vectormath::Aos::Point3> m_dx11VertexPosition;
btDX11Buffer<Vectormath::Aos::Point3> m_dx11VertexPreviousPosition;
btDX11Buffer<Vectormath::Aos::Vector3> m_dx11VertexVelocity;
btDX11Buffer<Vectormath::Aos::Vector3> m_dx11VertexForceAccumulator;
btDX11Buffer<Vectormath::Aos::Vector3> m_dx11VertexNormal;
btDX11Buffer<float> m_dx11VertexInverseMass;
btDX11Buffer<float> m_dx11VertexArea;
btDX11Buffer<int> m_dx11VertexTriangleCount;
//ID3D11Buffer* readBackBuffer;
public:
btSoftBodyVertexDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext );
virtual ~btSoftBodyVertexDataDX11();
virtual bool onAccelerator();
virtual bool moveToAccelerator();
virtual bool moveFromAccelerator(bool bCopy = false, bool bCopyMinimum = true);
};
#endif // #ifndef BT_SOFT_BHODY_SOLVER_VERTEX_DATA_DX11_H

View File

@@ -1,691 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_ACCELERATED_SOFT_BODY_DX11_SOLVER_H
#define BT_ACCELERATED_SOFT_BODY_DX11_SOLVER_H
#include "vectormath/vmInclude.h"
#include "BulletSoftBody/btSoftBodySolvers.h"
#include "btSoftBodySolverVertexBuffer_DX11.h"
#include "btSoftBodySolverLinkData_DX11.h"
#include "btSoftBodySolverVertexData_DX11.h"
#include "btSoftBodySolverTriangleData_DX11.h"
class DXFunctions
{
public:
typedef HRESULT (WINAPI * CompileFromMemoryFunc)(LPCSTR,SIZE_T,LPCSTR,const D3D10_SHADER_MACRO*,LPD3D10INCLUDE,LPCSTR,LPCSTR,UINT,UINT,ID3DX11ThreadPump*,ID3D10Blob**,ID3D10Blob**,HRESULT*);
ID3D11Device * m_dx11Device;
ID3D11DeviceContext* m_dx11Context;
CompileFromMemoryFunc m_dx11CompileFromMemory;
DXFunctions(ID3D11Device *dx11Device, ID3D11DeviceContext* dx11Context, CompileFromMemoryFunc dx11CompileFromMemory) :
m_dx11Device( dx11Device ),
m_dx11Context( dx11Context ),
m_dx11CompileFromMemory( dx11CompileFromMemory )
{
}
class KernelDesc
{
protected:
public:
ID3D11ComputeShader* kernel;
ID3D11Buffer* constBuffer;
KernelDesc()
{
kernel = 0;
constBuffer = 0;
}
virtual ~KernelDesc()
{
// TODO: this should probably destroy its kernel but we need to be careful
// in case KernelDescs are copied
}
};
/**
* Compile a compute shader kernel from a string and return the appropriate KernelDesc object.
*/
KernelDesc compileComputeShaderFromString( const char* shaderString, const char* shaderName, int constBufferSize, D3D10_SHADER_MACRO *compileMacros = 0 );
};
class btDX11SoftBodySolver : public btSoftBodySolver
{
protected:
/**
* Entry in the collision shape array.
* Specifies the shape type, the transform matrix and the necessary details of the collisionShape.
*/
struct CollisionShapeDescription
{
Vectormath::Aos::Transform3 shapeTransform;
Vectormath::Aos::Vector3 linearVelocity;
Vectormath::Aos::Vector3 angularVelocity;
int softBodyIdentifier;
int collisionShapeType;
// Both needed for capsule
float radius;
float halfHeight;
float margin;
float friction;
CollisionShapeDescription()
{
collisionShapeType = 0;
margin = 0;
friction = 0;
}
};
struct UIntVector3
{
UIntVector3()
{
x = 0;
y = 0;
z = 0;
_padding = 0;
}
UIntVector3( unsigned int x_, unsigned int y_, unsigned int z_ )
{
x = x_;
y = y_;
z = z_;
_padding = 0;
}
unsigned int x;
unsigned int y;
unsigned int z;
unsigned int _padding;
};
public:
/**
* SoftBody class to maintain information about a soft body instance
* within a solver.
* This data addresses the main solver arrays.
*/
class btAcceleratedSoftBodyInterface
{
protected:
/** Current number of vertices that are part of this cloth */
int m_numVertices;
/** Maximum number of vertices allocated to be part of this cloth */
int m_maxVertices;
/** Current number of triangles that are part of this cloth */
int m_numTriangles;
/** Maximum number of triangles allocated to be part of this cloth */
int m_maxTriangles;
/** Index of first vertex in the world allocated to this cloth */
int m_firstVertex;
/** Index of first triangle in the world allocated to this cloth */
int m_firstTriangle;
/** Index of first link in the world allocated to this cloth */
int m_firstLink;
/** Maximum number of links allocated to this cloth */
int m_maxLinks;
/** Current number of links allocated to this cloth */
int m_numLinks;
/** The actual soft body this data represents */
btSoftBody *m_softBody;
public:
btAcceleratedSoftBodyInterface( btSoftBody *softBody ) :
m_softBody( softBody )
{
m_numVertices = 0;
m_maxVertices = 0;
m_numTriangles = 0;
m_maxTriangles = 0;
m_firstVertex = 0;
m_firstTriangle = 0;
m_firstLink = 0;
m_maxLinks = 0;
m_numLinks = 0;
}
int getNumVertices() const
{
return m_numVertices;
}
int getNumTriangles() const
{
return m_numTriangles;
}
int getMaxVertices() const
{
return m_maxVertices;
}
int getMaxTriangles() const
{
return m_maxTriangles;
}
int getFirstVertex() const
{
return m_firstVertex;
}
int getFirstTriangle() const
{
return m_firstTriangle;
}
/**
* Update the bounds in the btSoftBody object
*/
void updateBounds( const btVector3 &lowerBound, const btVector3 &upperBound );
// TODO: All of these set functions will have to do checks and
// update the world because restructuring of the arrays will be necessary
// Reasonable use of "friend"?
void setNumVertices( int numVertices )
{
m_numVertices = numVertices;
}
void setNumTriangles( int numTriangles )
{
m_numTriangles = numTriangles;
}
void setMaxVertices( int maxVertices )
{
m_maxVertices = maxVertices;
}
void setMaxTriangles( int maxTriangles )
{
m_maxTriangles = maxTriangles;
}
void setFirstVertex( int firstVertex )
{
m_firstVertex = firstVertex;
}
void setFirstTriangle( int firstTriangle )
{
m_firstTriangle = firstTriangle;
}
void setMaxLinks( int maxLinks )
{
m_maxLinks = maxLinks;
}
void setNumLinks( int numLinks )
{
m_numLinks = numLinks;
}
void setFirstLink( int firstLink )
{
m_firstLink = firstLink;
}
int getMaxLinks()
{
return m_maxLinks;
}
int getNumLinks()
{
return m_numLinks;
}
int getFirstLink()
{
return m_firstLink;
}
btSoftBody* getSoftBody()
{
return m_softBody;
}
};
struct CollisionObjectIndices
{
CollisionObjectIndices( int f, int e )
{
firstObject = f;
endObject = e;
}
int firstObject;
int endObject;
};
struct PrepareLinksCB
{
int numLinks;
int padding0;
int padding1;
int padding2;
};
struct SolvePositionsFromLinksKernelCB
{
int startLink;
int numLinks;
float kst;
float ti;
};
struct IntegrateCB
{
int numNodes;
float solverdt;
int padding1;
int padding2;
};
struct UpdatePositionsFromVelocitiesCB
{
int numNodes;
float solverSDT;
int padding1;
int padding2;
};
struct UpdateVelocitiesFromPositionsWithoutVelocitiesCB
{
int numNodes;
float isolverdt;
int padding1;
int padding2;
};
struct UpdateVelocitiesFromPositionsWithVelocitiesCB
{
int numNodes;
float isolverdt;
int padding1;
int padding2;
};
struct UpdateSoftBodiesCB
{
int numNodes;
int startFace;
int numFaces;
float epsilon;
};
struct ApplyForcesCB
{
unsigned int numNodes;
float solverdt;
float epsilon;
int padding3;
};
struct AddVelocityCB
{
int startNode;
int lastNode;
float velocityX;
float velocityY;
float velocityZ;
int padding1;
int padding2;
int padding3;
};
struct VSolveLinksCB
{
int startLink;
int numLinks;
float kst;
int padding;
};
struct ComputeBoundsCB
{
int numNodes;
int numSoftBodies;
int padding1;
int padding2;
};
struct SolveCollisionsAndUpdateVelocitiesCB
{
unsigned int numNodes;
float isolverdt;
int padding0;
int padding1;
};
protected:
ID3D11Device * m_dx11Device;
ID3D11DeviceContext* m_dx11Context;
DXFunctions dxFunctions;
public:
/** Link data for all cloths. Note that this will be sorted batch-wise for efficient computation and m_linkAddresses will maintain the addressing. */
btSoftBodyLinkDataDX11 m_linkData;
btSoftBodyVertexDataDX11 m_vertexData;
btSoftBodyTriangleDataDX11 m_triangleData;
protected:
/** Variable to define whether we need to update solver constants on the next iteration */
bool m_updateSolverConstants;
bool m_shadersInitialized;
/**
* Cloths owned by this solver.
* Only our cloths are in this array.
*/
btAlignedObjectArray< btAcceleratedSoftBodyInterface * > m_softBodySet;
/** Acceleration value to be applied to all non-static vertices in the solver.
* Index n is cloth n, array sized by number of cloths in the world not the solver.
*/
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothAcceleration;
btDX11Buffer<Vectormath::Aos::Vector3> m_dx11PerClothAcceleration;
/** Wind velocity to be applied normal to all non-static vertices in the solver.
* Index n is cloth n, array sized by number of cloths in the world not the solver.
*/
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothWindVelocity;
btDX11Buffer<Vectormath::Aos::Vector3> m_dx11PerClothWindVelocity;
/** Velocity damping factor */
btAlignedObjectArray< float > m_perClothDampingFactor;
btDX11Buffer<float> m_dx11PerClothDampingFactor;
/** Velocity correction coefficient */
btAlignedObjectArray< float > m_perClothVelocityCorrectionCoefficient;
btDX11Buffer<float> m_dx11PerClothVelocityCorrectionCoefficient;
/** Lift parameter for wind effect on cloth. */
btAlignedObjectArray< float > m_perClothLiftFactor;
btDX11Buffer<float> m_dx11PerClothLiftFactor;
/** Drag parameter for wind effect on cloth. */
btAlignedObjectArray< float > m_perClothDragFactor;
btDX11Buffer<float> m_dx11PerClothDragFactor;
/** Density of the medium in which each cloth sits */
btAlignedObjectArray< float > m_perClothMediumDensity;
btDX11Buffer<float> m_dx11PerClothMediumDensity;
/**
* Collision shape details: pair of index of first collision shape for the cloth and number of collision objects.
*/
btAlignedObjectArray< CollisionObjectIndices > m_perClothCollisionObjects;
btDX11Buffer<CollisionObjectIndices> m_dx11PerClothCollisionObjects;
/**
* Collision shapes being passed across to the cloths in this solver.
*/
btAlignedObjectArray< CollisionShapeDescription > m_collisionObjectDetails;
btDX11Buffer< CollisionShapeDescription > m_dx11CollisionObjectDetails;
/**
* Minimum bounds for each cloth.
* Updated by GPU and returned for use by broad phase.
* These are int vectors as a reminder that they store the int representation of a float, not a float.
* Bit 31 is inverted - is floats are stored with int-sortable values.
*/
btAlignedObjectArray< UIntVector3 > m_perClothMinBounds;
btDX11Buffer< UIntVector3 > m_dx11PerClothMinBounds;
/**
* Maximum bounds for each cloth.
* Updated by GPU and returned for use by broad phase.
* These are int vectors as a reminder that they store the int representation of a float, not a float.
* Bit 31 is inverted - is floats are stored with int-sortable values.
*/
btAlignedObjectArray< UIntVector3 > m_perClothMaxBounds;
btDX11Buffer< UIntVector3 > m_dx11PerClothMaxBounds;
/**
* Friction coefficient for each cloth
*/
btAlignedObjectArray< float > m_perClothFriction;
btDX11Buffer< float > m_dx11PerClothFriction;
DXFunctions::KernelDesc prepareLinksKernel;
DXFunctions::KernelDesc solvePositionsFromLinksKernel;
DXFunctions::KernelDesc vSolveLinksKernel;
DXFunctions::KernelDesc integrateKernel;
DXFunctions::KernelDesc addVelocityKernel;
DXFunctions::KernelDesc updatePositionsFromVelocitiesKernel;
DXFunctions::KernelDesc updateVelocitiesFromPositionsWithoutVelocitiesKernel;
DXFunctions::KernelDesc updateVelocitiesFromPositionsWithVelocitiesKernel;
DXFunctions::KernelDesc solveCollisionsAndUpdateVelocitiesKernel;
DXFunctions::KernelDesc resetNormalsAndAreasKernel;
DXFunctions::KernelDesc normalizeNormalsAndAreasKernel;
DXFunctions::KernelDesc computeBoundsKernel;
DXFunctions::KernelDesc updateSoftBodiesKernel;
DXFunctions::KernelDesc applyForcesKernel;
bool m_enableUpdateBounds;
/**
* Integrate motion on the solver.
*/
virtual void integrate( float solverdt );
float computeTriangleArea(
const Vectormath::Aos::Point3 &vertex0,
const Vectormath::Aos::Point3 &vertex1,
const Vectormath::Aos::Point3 &vertex2 );
virtual bool buildShaders();
void resetNormalsAndAreas( int numVertices );
void normalizeNormalsAndAreas( int numVertices );
void executeUpdateSoftBodies( int firstTriangle, int numTriangles );
void prepareCollisionConstraints();
Vectormath::Aos::Vector3 ProjectOnAxis( const Vectormath::Aos::Vector3 &v, const Vectormath::Aos::Vector3 &a );
void ApplyClampedForce( float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce );
virtual void applyForces( float solverdt );
virtual void updateConstants( float timeStep );
int findSoftBodyIndex( const btSoftBody* const softBody );
//////////////////////////////////////
// Kernel dispatches
virtual void prepareLinks();
void updatePositionsFromVelocities( float solverdt );
void solveLinksForPosition( int startLink, int numLinks, float kst, float ti );
void solveLinksForVelocity( int startLink, int numLinks, float kst );
void updateVelocitiesFromPositionsWithVelocities( float isolverdt );
void updateVelocitiesFromPositionsWithoutVelocities( float isolverdt );
void computeBounds( );
void solveCollisionsAndUpdateVelocities( float isolverdt );
// End kernel dispatches
/////////////////////////////////////
void updateBounds();
void releaseKernels();
public:
btDX11SoftBodySolver(ID3D11Device * dx11Device, ID3D11DeviceContext* dx11Context, DXFunctions::CompileFromMemoryFunc dx11CompileFromMemory = &D3DX11CompileFromMemory);
virtual ~btDX11SoftBodySolver();
virtual SolverTypes getSolverType() const
{
return DX_SOLVER;
}
void setEnableUpdateBounds(bool enableBounds)
{
m_enableUpdateBounds = enableBounds;
}
bool getEnableUpdateBounds() const
{
return m_enableUpdateBounds;
}
virtual btSoftBodyLinkData &getLinkData();
virtual btSoftBodyVertexData &getVertexData();
virtual btSoftBodyTriangleData &getTriangleData();
btAcceleratedSoftBodyInterface *findSoftBodyInterface( const btSoftBody* const softBody );
const btAcceleratedSoftBodyInterface * const findSoftBodyInterface( const btSoftBody* const softBody ) const;
virtual bool checkInitialized();
virtual void updateSoftBodies( );
virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate=false);
virtual void copyBackToSoftBodies(bool bMove = true);
virtual void solveConstraints( float solverdt );
virtual void predictMotion( float solverdt );
virtual void processCollision( btSoftBody *, const btCollisionObjectWrapper* );
virtual void processCollision( btSoftBody*, btSoftBody* );
};
/**
* Class to manage movement of data from a solver to a given target.
* This version is the DX to CPU version.
*/
class btSoftBodySolverOutputDXtoCPU : public btSoftBodySolverOutput
{
protected:
public:
btSoftBodySolverOutputDXtoCPU()
{
}
/** Output current computed vertex data to the vertex buffers for all cloths in the solver. */
virtual void copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer );
};
/**
* Class to manage movement of data from a solver to a given target.
* This version is the DX to DX version and subclasses DX to CPU so that it works for that too.
*/
class btSoftBodySolverOutputDXtoDX : public btSoftBodySolverOutputDXtoCPU
{
protected:
struct OutputToVertexArrayCB
{
int startNode;
int numNodes;
int positionOffset;
int positionStride;
int normalOffset;
int normalStride;
int padding1;
int padding2;
};
DXFunctions dxFunctions;
DXFunctions::KernelDesc outputToVertexArrayWithNormalsKernel;
DXFunctions::KernelDesc outputToVertexArrayWithoutNormalsKernel;
bool m_shadersInitialized;
bool checkInitialized();
bool buildShaders();
void releaseKernels();
public:
btSoftBodySolverOutputDXtoDX(ID3D11Device *dx11Device, ID3D11DeviceContext* dx11Context, DXFunctions::CompileFromMemoryFunc dx11CompileFromMemory = &D3DX11CompileFromMemory) :
dxFunctions( dx11Device, dx11Context, dx11CompileFromMemory )
{
m_shadersInitialized = false;
}
~btSoftBodySolverOutputDXtoDX()
{
releaseKernels();
}
/** Output current computed vertex data to the vertex buffers for all cloths in the solver. */
virtual void copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer );
};
#endif // #ifndef BT_ACCELERATED_SOFT_BODY_DX11_SOLVER_H

View File

@@ -1,81 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "vectormath/vmInclude.h"
#include "btSoftBodySolver_DX11.h"
#include "btSoftBodySolverVertexBuffer_DX11.h"
#include "btSoftBodySolverLinkData_DX11SIMDAware.h"
#include "btSoftBodySolverVertexData_DX11.h"
#include "btSoftBodySolverTriangleData_DX11.h"
#ifndef BT_SOFT_BODY_DX11_SOLVER_SIMDAWARE_H
#define BT_SOFT_BODY_DX11_SOLVER_SIMDAWARE_H
class btDX11SIMDAwareSoftBodySolver : public btDX11SoftBodySolver
{
protected:
struct SolvePositionsFromLinksKernelCB
{
int startWave;
int numWaves;
float kst;
float ti;
};
/** Link data for all cloths. Note that this will be sorted batch-wise for efficient computation and m_linkAddresses will maintain the addressing. */
btSoftBodyLinkDataDX11SIMDAware m_linkData;
/** Variable to define whether we need to update solver constants on the next iteration */
bool m_updateSolverConstants;
virtual bool buildShaders();
void updateConstants( float timeStep );
//////////////////////////////////////
// Kernel dispatches
void solveLinksForPosition( int startLink, int numLinks, float kst, float ti );
// End kernel dispatches
/////////////////////////////////////
public:
btDX11SIMDAwareSoftBodySolver(ID3D11Device * dx11Device, ID3D11DeviceContext* dx11Context, DXFunctions::CompileFromMemoryFunc dx11CompileFromMemory = &D3DX11CompileFromMemory);
virtual ~btDX11SIMDAwareSoftBodySolver();
virtual btSoftBodyLinkData &getLinkData();
virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate=false);
virtual void solveConstraints( float solverdt );
virtual SolverTypes getSolverType() const
{
return DX_SIMD_SOLVER;
}
};
#endif // #ifndef BT_SOFT_BODY_DX11_SOLVER_SIMDAWARE_H

View File

@@ -1,23 +0,0 @@
hasDX11 = findDirectX11()
if (hasDX11) then
project "BulletSoftBodyDX11Solvers"
initDirectX11()
kind "StaticLib"
targetdir "../../../../lib"
includedirs {
".",
"../../.."
}
files {
"**.cpp",
"**.h"
}
end

View File

@@ -1,65 +0,0 @@
INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/src
${AMD_OPENCL_INCLUDES}
)
ADD_DEFINITIONS(-DUSE_AMD_OPENCL)
ADD_DEFINITIONS(-DCL_PLATFORM_AMD)
SET(BulletSoftBodyOpenCLSolvers_SRCS
../btSoftBodySolver_OpenCL.cpp
../btSoftBodySolver_OpenCLSIMDAware.cpp
../btSoftBodySolverOutputCLtoGL.cpp
)
SET(BulletSoftBodyOpenCLSolvers_HDRS
../btSoftBodySolver_OpenCL.h
../btSoftBodySolver_OpenCLSIMDAware.h
../../Shared/btSoftBodySolverData.h
../btSoftBodySolverVertexData_OpenCL.h
../btSoftBodySolverTriangleData_OpenCL.h
../btSoftBodySolverLinkData_OpenCL.h
../btSoftBodySolverLinkData_OpenCLSIMDAware.h
../btSoftBodySolverBuffer_OpenCL.h
../btSoftBodySolverVertexBuffer_OpenGL.h
../btSoftBodySolverOutputCLtoGL.h
)
ADD_LIBRARY(BulletSoftBodySolvers_OpenCL_AMD
${BulletSoftBodyOpenCLSolvers_SRCS}
${BulletSoftBodyOpenCLSolvers_HDRS}
)
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_AMD PROPERTIES VERSION ${BULLET_VERSION})
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_AMD PROPERTIES SOVERSION ${BULLET_VERSION})
IF (BUILD_SHARED_LIBS)
TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_OpenCL_AMD BulletSoftBody)
ENDIF (BUILD_SHARED_LIBS)
IF (INSTALL_LIBS)
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_AMD DESTINATION .)
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_AMD
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib${LIB_SUFFIX}
ARCHIVE DESTINATION lib${LIB_SUFFIX})
#headers are already installed by BulletMultiThreaded library
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_AMD PROPERTIES FRAMEWORK true)
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_AMD PROPERTIES PUBLIC_HEADER "${BulletSoftBodyOpenCLSolvers_HDRS}")
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
ENDIF (INSTALL_LIBS)

View File

@@ -1,27 +0,0 @@
hasCL = findOpenCL_AMD()
if (hasCL) then
project "BulletSoftBodySolvers_OpenCL_AMD"
defines { "USE_AMD_OPENCL","CL_PLATFORM_AMD"}
initOpenCL_AMD()
kind "StaticLib"
targetdir "../../../../../lib"
includedirs {
".",
"../../../..",
"../../../../../Glut"
}
files {
"../btSoftBodySolver_OpenCL.cpp",
"../btSoftBodySolver_OpenCLSIMDAware.cpp",
"../btSoftBodySolverOutputCLtoGL.cpp"
}
end

View File

@@ -1,80 +0,0 @@
INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/src
)
SET(BulletSoftBodyOpenCLSolvers_SRCS
../btSoftBodySolver_OpenCL.cpp
../btSoftBodySolver_OpenCLSIMDAware.cpp
)
SET(BulletSoftBodyOpenCLSolvers_HDRS
../btSoftBodySolver_OpenCL.h
../../Shared/btSoftBodySolverData.h
../btSoftBodySolverVertexData_OpenCL.h
../btSoftBodySolverTriangleData_OpenCL.h
../btSoftBodySolverLinkData_OpenCL.h
../btSoftBodySolverBuffer_OpenCL.h
)
# OpenCL and HLSL Shaders.
# Build rules generated to stringify these into headers
# which are needed by some of the sources
SET(BulletSoftBodyOpenCLSolvers_Shaders
# OutputToVertexArray
UpdateNormals
Integrate
UpdatePositions
UpdateNodes
SolvePositions
UpdatePositionsFromVelocities
ApplyForces
PrepareLinks
VSolveLinks
)
foreach(f ${BulletSoftBodyOpenCLSolvers_Shaders})
LIST(APPEND BulletSoftBodyOpenCLSolvers_OpenCLC "../OpenCLC10/${f}.cl")
endforeach(f)
ADD_LIBRARY(BulletSoftBodySolvers_OpenCL_Apple
${BulletSoftBodyOpenCLSolvers_SRCS}
${BulletSoftBodyOpenCLSolvers_HDRS}
${BulletSoftBodyOpenCLSolvers_OpenCLC}
)
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Apple PROPERTIES VERSION ${BULLET_VERSION})
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Apple PROPERTIES SOVERSION ${BULLET_VERSION})
IF (BUILD_SHARED_LIBS)
IF (APPLE AND (BUILD_SHARED_LIBS OR FRAMEWORK) )
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Apple PROPERTIES LINK_FLAGS "-framework OpenCL")
ENDIF (APPLE AND (BUILD_SHARED_LIBS OR FRAMEWORK) )
TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_OpenCL_Apple BulletSoftBody)
ENDIF (BUILD_SHARED_LIBS)
IF (INSTALL_LIBS)
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Apple DESTINATION .)
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Apple
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib${LIB_SUFFIX}
ARCHIVE DESTINATION lib${LIB_SUFFIX})
#headers are already installed by BulletMultiThreaded library
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Apple PROPERTIES FRAMEWORK true)
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Apple PROPERTIES PUBLIC_HEADER "${BulletSoftBodyOpenCLSolvers_HDRS}")
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
ENDIF (INSTALL_LIBS)

View File

@@ -1,17 +0,0 @@
SUBDIRS( MiniCL )
IF(BUILD_INTEL_OPENCL_DEMOS)
SUBDIRS(Intel)
ENDIF()
IF(BUILD_AMD_OPENCL_DEMOS)
SUBDIRS(AMD)
ENDIF()
IF(BUILD_NVIDIA_OPENCL_DEMOS)
SUBDIRS(NVidia)
ENDIF()
IF(APPLE AND OPENCL_LIBRARY)
SUBDIRS(Apple)
ENDIF()

View File

@@ -1,85 +0,0 @@
INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/src
${INTEL_OPENCL_INCLUDES}
)
ADD_DEFINITIONS(-DUSE_INTEL_OPENCL)
ADD_DEFINITIONS(-DCL_PLATFORM_INTEL)
SET(BulletSoftBodyOpenCLSolvers_SRCS
../btSoftBodySolver_OpenCL.cpp
../btSoftBodySolver_OpenCLSIMDAware.cpp
../btSoftBodySolverOutputCLtoGL.cpp
)
SET(BulletSoftBodyOpenCLSolvers_HDRS
../btSoftBodySolver_OpenCL.h
../btSoftBodySolver_OpenCLSIMDAware.h
../../Shared/btSoftBodySolverData.h
../btSoftBodySolverVertexData_OpenCL.h
../btSoftBodySolverTriangleData_OpenCL.h
../btSoftBodySolverLinkData_OpenCL.h
../btSoftBodySolverLinkData_OpenCLSIMDAware.h
../btSoftBodySolverBuffer_OpenCL.h
../btSoftBodySolverVertexBuffer_OpenGL.h
../btSoftBodySolverOutputCLtoGL.h
)
# OpenCL and HLSL Shaders.
# Build rules generated to stringify these into headers
# which are needed by some of the sources
SET(BulletSoftBodyOpenCLSolvers_Shaders
# OutputToVertexArray
UpdateNormals
Integrate
UpdatePositions
UpdateNodes
SolvePositions
UpdatePositionsFromVelocities
ApplyForces
PrepareLinks
VSolveLinks
)
foreach(f ${BulletSoftBodyOpenCLSolvers_Shaders})
LIST(APPEND BulletSoftBodyOpenCLSolvers_OpenCLC "../OpenCLC10/${f}.cl")
endforeach(f)
ADD_LIBRARY(BulletSoftBodySolvers_OpenCL_Intel
${BulletSoftBodyOpenCLSolvers_SRCS}
${BulletSoftBodyOpenCLSolvers_HDRS}
${BulletSoftBodyOpenCLSolvers_OpenCLC}
)
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Intel PROPERTIES VERSION ${BULLET_VERSION})
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Intel PROPERTIES SOVERSION ${BULLET_VERSION})
IF (BUILD_SHARED_LIBS)
TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_OpenCL_Intel BulletSoftBody)
ENDIF (BUILD_SHARED_LIBS)
IF (INSTALL_LIBS)
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Intel DESTINATION .)
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Intel
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib${LIB_SUFFIX}
ARCHIVE DESTINATION lib${LIB_SUFFIX})
#headers are already installed by BulletMultiThreaded library
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Intel PROPERTIES FRAMEWORK true)
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Intel PROPERTIES PUBLIC_HEADER "${BulletSoftBodyOpenCLSolvers_HDRS}")
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
ENDIF (INSTALL_LIBS)

View File

@@ -1,27 +0,0 @@
hasCL = findOpenCL_Intel()
if (hasCL) then
project "BulletSoftBodySolvers_OpenCL_Intel"
defines { "USE_INTEL_OPENCL","CL_PLATFORM_INTEL"}
initOpenCL_Intel()
kind "StaticLib"
targetdir "../../../../../lib"
includedirs {
".",
"../../../..",
"../../../../../Glut"
}
files {
"../btSoftBodySolver_OpenCL.cpp",
"../btSoftBodySolver_OpenCLSIMDAware.cpp",
"../btSoftBodySolverOutputCLtoGL.cpp"
}
end

View File

@@ -1,78 +0,0 @@
INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/src
)
ADD_DEFINITIONS(-DUSE_MINICL)
SET(BulletSoftBodyOpenCLSolvers_SRCS
../btSoftBodySolver_OpenCL.cpp
)
SET(BulletSoftBodyOpenCLSolvers_HDRS
../btSoftBodySolver_OpenCL.h
../../Shared/btSoftBodySolverData.h
../btSoftBodySolverVertexData_OpenCL.h
../btSoftBodySolverTriangleData_OpenCL.h
../btSoftBodySolverLinkData_OpenCL.h
../btSoftBodySolverBuffer_OpenCL.h
)
# OpenCL and HLSL Shaders.
# Build rules generated to stringify these into headers
# which are needed by some of the sources
SET(BulletSoftBodyOpenCLSolvers_Shaders
# OutputToVertexArray
UpdateNormals
Integrate
UpdatePositions
UpdateNodes
SolvePositions
UpdatePositionsFromVelocities
ApplyForces
PrepareLinks
VSolveLinks
)
foreach(f ${BulletSoftBodyOpenCLSolvers_Shaders})
LIST(APPEND BulletSoftBodyOpenCLSolvers_OpenCLC "../OpenCLC10/${f}.cl")
endforeach(f)
ADD_LIBRARY(BulletSoftBodySolvers_OpenCL_Mini
${BulletSoftBodyOpenCLSolvers_SRCS}
${BulletSoftBodyOpenCLSolvers_HDRS}
${BulletSoftBodyOpenCLSolvers_OpenCLC}
)
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Mini PROPERTIES VERSION ${BULLET_VERSION})
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Mini PROPERTIES SOVERSION ${BULLET_VERSION})
IF (BUILD_SHARED_LIBS)
TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_OpenCL_Mini MiniCL BulletMultiThreaded BulletSoftBody)
ENDIF (BUILD_SHARED_LIBS)
IF (INSTALL_LIBS)
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Mini DESTINATION .)
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Mini
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib${LIB_SUFFIX}
ARCHIVE DESTINATION lib${LIB_SUFFIX})
#headers are already installed by BulletMultiThreaded library
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Mini PROPERTIES FRAMEWORK true)
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Mini PROPERTIES PUBLIC_HEADER "${BulletSoftBodyOpenCLSolvers_HDRS}")
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
ENDIF (INSTALL_LIBS)

View File

@@ -1,249 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include <MiniCL/cl_MiniCL_Defs.h>
#define MSTRINGIFY(A) A
#include "../OpenCLC10/ApplyForces.cl"
#include "../OpenCLC10/Integrate.cl"
#include "../OpenCLC10/PrepareLinks.cl"
#include "../OpenCLC10/SolvePositions.cl"
#include "../OpenCLC10/UpdateNodes.cl"
#include "../OpenCLC10/UpdateNormals.cl"
#include "../OpenCLC10/UpdatePositions.cl"
#include "../OpenCLC10/UpdatePositionsFromVelocities.cl"
#include "../OpenCLC10/VSolveLinks.cl"
#include "../OpenCLC10/UpdateFixedVertexPositions.cl"
//#include "../OpenCLC10/SolveCollisionsAndUpdateVelocities.cl"
MINICL_REGISTER(PrepareLinksKernel)
MINICL_REGISTER(VSolveLinksKernel)
MINICL_REGISTER(UpdatePositionsFromVelocitiesKernel)
MINICL_REGISTER(SolvePositionsFromLinksKernel)
MINICL_REGISTER(updateVelocitiesFromPositionsWithVelocitiesKernel)
MINICL_REGISTER(updateVelocitiesFromPositionsWithoutVelocitiesKernel)
MINICL_REGISTER(IntegrateKernel)
MINICL_REGISTER(ApplyForcesKernel)
MINICL_REGISTER(ResetNormalsAndAreasKernel)
MINICL_REGISTER(NormalizeNormalsAndAreasKernel)
MINICL_REGISTER(UpdateSoftBodiesKernel)
MINICL_REGISTER(UpdateFixedVertexPositions)
float mydot3a(float4 a, float4 b)
{
return a.x*b.x + a.y*b.y + a.z*b.z;
}
typedef struct
{
int firstObject;
int endObject;
} CollisionObjectIndices;
typedef struct
{
float4 shapeTransform[4]; // column major 4x4 matrix
float4 linearVelocity;
float4 angularVelocity;
int softBodyIdentifier;
int collisionShapeType;
// Shape information
// Compressed from the union
float radius;
float halfHeight;
int upAxis;
float margin;
float friction;
int padding0;
} CollisionShapeDescription;
// From btBroadphaseProxy.h
__constant int CAPSULE_SHAPE_PROXYTYPE = 10;
// Multiply column-major matrix against vector
float4 matrixVectorMul( float4 matrix[4], float4 vector )
{
float4 returnVector;
float4 row0 = float4(matrix[0].x, matrix[1].x, matrix[2].x, matrix[3].x);
float4 row1 = float4(matrix[0].y, matrix[1].y, matrix[2].y, matrix[3].y);
float4 row2 = float4(matrix[0].z, matrix[1].z, matrix[2].z, matrix[3].z);
float4 row3 = float4(matrix[0].w, matrix[1].w, matrix[2].w, matrix[3].w);
returnVector.x = dot(row0, vector);
returnVector.y = dot(row1, vector);
returnVector.z = dot(row2, vector);
returnVector.w = dot(row3, vector);
return returnVector;
}
__kernel void
SolveCollisionsAndUpdateVelocitiesKernel(
const int numNodes,
const float isolverdt,
__global int *g_vertexClothIdentifier,
__global float4 *g_vertexPreviousPositions,
__global float * g_perClothFriction,
__global float * g_clothDampingFactor,
__global CollisionObjectIndices * g_perClothCollisionObjectIndices,
__global CollisionShapeDescription * g_collisionObjectDetails,
__global float4 * g_vertexForces,
__global float4 *g_vertexVelocities,
__global float4 *g_vertexPositions GUID_ARG)
{
int nodeID = get_global_id(0);
float4 forceOnVertex = (float4)(0.f, 0.f, 0.f, 0.f);
if( get_global_id(0) < numNodes )
{
int clothIdentifier = g_vertexClothIdentifier[nodeID];
// Abort if this is not a valid cloth
if( clothIdentifier < 0 )
return;
float4 position (g_vertexPositions[nodeID].xyz, 1.f);
float4 previousPosition (g_vertexPreviousPositions[nodeID].xyz, 1.f);
float clothFriction = g_perClothFriction[clothIdentifier];
float dampingFactor = g_clothDampingFactor[clothIdentifier];
float velocityCoefficient = (1.f - dampingFactor);
float4 difference = position - previousPosition;
float4 velocity = difference*velocityCoefficient*isolverdt;
CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier];
int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject;
if( numObjects > 0 )
{
// We have some possible collisions to deal with
for( int collision = collisionObjectIndices.firstObject; collision < collisionObjectIndices.endObject; ++collision )
{
CollisionShapeDescription shapeDescription = g_collisionObjectDetails[collision];
float colliderFriction = shapeDescription.friction;
if( shapeDescription.collisionShapeType == CAPSULE_SHAPE_PROXYTYPE )
{
// Colliding with a capsule
float capsuleHalfHeight = shapeDescription.halfHeight;
float capsuleRadius = shapeDescription.radius;
float capsuleMargin = shapeDescription.margin;
int capsuleupAxis = shapeDescription.upAxis;
// Four columns of worldTransform matrix
float4 worldTransform[4];
worldTransform[0] = shapeDescription.shapeTransform[0];
worldTransform[1] = shapeDescription.shapeTransform[1];
worldTransform[2] = shapeDescription.shapeTransform[2];
worldTransform[3] = shapeDescription.shapeTransform[3];
// Correctly define capsule centerline vector
float4 c1 (0.f, 0.f, 0.f, 1.f);
float4 c2 (0.f, 0.f, 0.f, 1.f);
c1.x = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 0 );
c1.y = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 1 );
c1.z = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 2 );
c2.x = -c1.x;
c2.y = -c1.y;
c2.z = -c1.z;
float4 worldC1 = matrixVectorMul(worldTransform, c1);
float4 worldC2 = matrixVectorMul(worldTransform, c2);
float4 segment = (worldC2 - worldC1);
// compute distance of tangent to vertex along line segment in capsule
float distanceAlongSegment = -( mydot3a( (worldC1 - position), segment ) / mydot3a(segment, segment) );
float4 closestPoint = (worldC1 + (segment * distanceAlongSegment));
float distanceFromLine = length(position - closestPoint);
float distanceFromC1 = length(worldC1 - position);
float distanceFromC2 = length(worldC2 - position);
// Final distance from collision, point to push from, direction to push in
// for impulse force
float dist;
float4 normalVector;
if( distanceAlongSegment < 0 )
{
dist = distanceFromC1;
normalVector = float4(normalize(position - worldC1).xyz, 0.f);
} else if( distanceAlongSegment > 1.f ) {
dist = distanceFromC2;
normalVector = float4(normalize(position - worldC2).xyz, 0.f);
} else {
dist = distanceFromLine;
normalVector = float4(normalize(position - closestPoint).xyz, 0.f);
}
float4 colliderLinearVelocity = shapeDescription.linearVelocity;
float4 colliderAngularVelocity = shapeDescription.angularVelocity;
float4 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, position - float4(worldTransform[0].w, worldTransform[1].w, worldTransform[2].w, 0.f));
float minDistance = capsuleRadius + capsuleMargin;
// In case of no collision, this is the value of velocity
velocity = (position - previousPosition) * velocityCoefficient * isolverdt;
// Check for a collision
if( dist < minDistance )
{
// Project back to surface along normal
position = position + float4(normalVector*(minDistance - dist)*0.9f);
velocity = (position - previousPosition) * velocityCoefficient * isolverdt;
float4 relativeVelocity = velocity - velocityOfSurfacePoint;
float4 p1 = normalize(cross(normalVector, segment));
float4 p2 = normalize(cross(p1, normalVector));
// Full friction is sum of velocities in each direction of plane
float4 frictionVector = p1*mydot3a(relativeVelocity, p1) + p2*mydot3a(relativeVelocity, p2);
// Real friction is peak friction corrected by friction coefficients
frictionVector = frictionVector * (colliderFriction*clothFriction);
float approachSpeed = dot(relativeVelocity, normalVector);
if( approachSpeed <= 0.0f )
forceOnVertex -= frictionVector;
}
}
}
}
g_vertexVelocities[nodeID] = float4(velocity.xyz, 0.f);
// Update external force
g_vertexForces[nodeID] = float4(forceOnVertex.xyz, 0.f);
g_vertexPositions[nodeID] = float4(position.xyz, 0.f);
}
}
MINICL_REGISTER(SolveCollisionsAndUpdateVelocitiesKernel);

View File

@@ -1,84 +0,0 @@
ADD_DEFINITIONS(-DUSE_NVIDIA_OPENCL)
ADD_DEFINITIONS(-DCL_PLATFORM_NVIDIA)
INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/src
${NVIDIA_OPENCL_INCLUDES}
)
SET(BulletSoftBodyOpenCLSolvers_SRCS
../btSoftBodySolver_OpenCL.cpp
../btSoftBodySolver_OpenCLSIMDAware.cpp
../btSoftBodySolverOutputCLtoGL.cpp
)
SET(BulletSoftBodyOpenCLSolvers_HDRS
../btSoftBodySolver_OpenCL.h
../../Shared/btSoftBodySolverData.h
../btSoftBodySolverVertexData_OpenCL.h
../btSoftBodySolverTriangleData_OpenCL.h
../btSoftBodySolverLinkData_OpenCL.h
../btSoftBodySolverLinkData_OpenCLSIMDAware.h
../btSoftBodySolverBuffer_OpenCL.h
../btSoftBodySolverVertexBuffer_OpenGL.h
../btSoftBodySolverOutputCLtoGL.h
)
# OpenCL and HLSL Shaders.
# Build rules generated to stringify these into headers
# which are needed by some of the sources
SET(BulletSoftBodyOpenCLSolvers_Shaders
# OutputToVertexArray
UpdateNormals
Integrate
UpdatePositions
UpdateNodes
SolvePositions
UpdatePositionsFromVelocities
ApplyForces
PrepareLinks
VSolveLinks
)
foreach(f ${BulletSoftBodyOpenCLSolvers_Shaders})
LIST(APPEND BulletSoftBodyOpenCLSolvers_OpenCLC "../OpenCLC10/${f}.cl")
endforeach(f)
ADD_LIBRARY(BulletSoftBodySolvers_OpenCL_NVidia
${BulletSoftBodyOpenCLSolvers_SRCS}
${BulletSoftBodyOpenCLSolvers_HDRS}
${BulletSoftBodyOpenCLSolvers_OpenCLC}
)
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_NVidia PROPERTIES VERSION ${BULLET_VERSION})
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_NVidia PROPERTIES SOVERSION ${BULLET_VERSION})
IF (BUILD_SHARED_LIBS)
TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_OpenCL_NVidia BulletSoftBody BulletDynamics)
ENDIF (BUILD_SHARED_LIBS)
IF (INSTALL_LIBS)
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_NVidia DESTINATION .)
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_NVidia
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib${LIB_SUFFIX}
ARCHIVE DESTINATION lib${LIB_SUFFIX})
#headers are already installed by BulletMultiThreaded library
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_NVidia PROPERTIES FRAMEWORK true)
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_NVidia PROPERTIES PUBLIC_HEADER "${BulletSoftBodyOpenCLSolvers_HDRS}")
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
ENDIF (INSTALL_LIBS)

View File

@@ -1,27 +0,0 @@
hasCL = findOpenCL_NVIDIA()
if (hasCL) then
project "BulletSoftBodySolvers_OpenCL_NVIDIA"
defines { "USE_NVIDIA_OPENCL","CL_PLATFORM_NVIDIA"}
initOpenCL_NVIDIA()
kind "StaticLib"
targetdir "../../../../../lib"
includedirs {
".",
"../../../..",
"../../../../../Glut"
}
files {
"../btSoftBodySolver_OpenCL.cpp",
"../btSoftBodySolver_OpenCLSIMDAware.cpp",
"../btSoftBodySolverOutputCLtoGL.cpp"
}
end

View File

@@ -1,102 +0,0 @@
MSTRINGIFY(
float adot3(float4 a, float4 b)
{
return a.x*b.x + a.y*b.y + a.z*b.z;
}
float alength3(float4 a)
{
a.w = 0;
return length(a);
}
float4 anormalize3(float4 a)
{
a.w = 0;
return normalize(a);
}
float4 projectOnAxis( float4 v, float4 a )
{
return (a*adot3(v, a));
}
__kernel void
ApplyForcesKernel(
const uint numNodes,
const float solverdt,
const float epsilon,
__global int * g_vertexClothIdentifier,
__global float4 * g_vertexNormal,
__global float * g_vertexArea,
__global float * g_vertexInverseMass,
__global float * g_clothLiftFactor,
__global float * g_clothDragFactor,
__global float4 * g_clothWindVelocity,
__global float4 * g_clothAcceleration,
__global float * g_clothMediumDensity,
__global float4 * g_vertexForceAccumulator,
__global float4 * g_vertexVelocity GUID_ARG)
{
unsigned int nodeID = get_global_id(0);
if( nodeID < numNodes )
{
int clothId = g_vertexClothIdentifier[nodeID];
float nodeIM = g_vertexInverseMass[nodeID];
if( nodeIM > 0.0f )
{
float4 nodeV = g_vertexVelocity[nodeID];
float4 normal = g_vertexNormal[nodeID];
float area = g_vertexArea[nodeID];
float4 nodeF = g_vertexForceAccumulator[nodeID];
// Read per-cloth values
float4 clothAcceleration = g_clothAcceleration[clothId];
float4 clothWindVelocity = g_clothWindVelocity[clothId];
float liftFactor = g_clothLiftFactor[clothId];
float dragFactor = g_clothDragFactor[clothId];
float mediumDensity = g_clothMediumDensity[clothId];
// Apply the acceleration to the cloth rather than do this via a force
nodeV += (clothAcceleration*solverdt);
g_vertexVelocity[nodeID] = nodeV;
// Aerodynamics
float4 rel_v = nodeV - clothWindVelocity;
float rel_v_len = alength3(rel_v);
float rel_v2 = dot(rel_v, rel_v);
if( rel_v2 > epsilon )
{
float4 rel_v_nrm = anormalize3(rel_v);
float4 nrm = normal;
nrm = nrm * (dot(nrm, rel_v) < 0 ? -1.f : 1.f);
float4 fDrag = (float4)(0.f, 0.f, 0.f, 0.f);
float4 fLift = (float4)(0.f, 0.f, 0.f, 0.f);
float n_dot_v = dot(nrm, rel_v_nrm);
// drag force
if ( dragFactor > 0.f )
fDrag = 0.5f * dragFactor * mediumDensity * rel_v2 * area * n_dot_v * (-1.0f) * rel_v_nrm;
// lift force
// Check angle of attack
// cos(10<EFBFBD>) = 0.98480
if ( 0 < n_dot_v && n_dot_v < 0.98480f)
fLift = 0.5f * liftFactor * mediumDensity * rel_v_len * area * sqrt(1.0f-n_dot_v*n_dot_v) * (cross(cross(nrm, rel_v_nrm), rel_v_nrm));
nodeF += fDrag + fLift;
g_vertexForceAccumulator[nodeID] = nodeF;
}
}
}
}
);

View File

@@ -1,82 +0,0 @@
MSTRINGIFY(
#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n
#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n
__kernel void
ComputeBoundsKernel(
const int numNodes,
const int numSoftBodies,
__global int * g_vertexClothIdentifier,
__global float4 * g_vertexPositions,
/* Unfortunately, to get the atomics below to work these arrays cannot be */
/* uint4, though that is the layout of the data */
/* Therefore this is little-endian-only code */
volatile __global uint * g_clothMinBounds,
volatile __global uint * g_clothMaxBounds,
volatile __local uint * clothMinBounds,
volatile __local uint * clothMaxBounds)
{
// Init min and max bounds arrays
if( get_local_id(0) < numSoftBodies )
{
clothMinBounds[get_local_id(0)*4] = UINT_MAX;
clothMinBounds[get_local_id(0)*4+1] = UINT_MAX;
clothMinBounds[get_local_id(0)*4+2] = UINT_MAX;
clothMinBounds[get_local_id(0)*4+3] = UINT_MAX;
clothMaxBounds[get_local_id(0)*4] = 0;
clothMaxBounds[get_local_id(0)*4+1] = 0;
clothMaxBounds[get_local_id(0)*4+2] = 0;
clothMaxBounds[get_local_id(0)*4+3] = 0;
}
barrier(CLK_LOCAL_MEM_FENCE);
int nodeID = get_global_id(0);
if( nodeID < numNodes )
{
int clothIdentifier = g_vertexClothIdentifier[nodeID];
if( clothIdentifier >= 0 )
{
float4 position = (float4)(g_vertexPositions[nodeID].xyz, 0.f);
/* Reinterpret position as uint */
uint4 positionUInt = (uint4)(as_uint(position.x), as_uint(position.y), as_uint(position.z), 0);
/* Invert sign bit of positives and whole of negatives to allow comparison as unsigned ints */
positionUInt.x ^= (1+~(positionUInt.x >> 31) | 0x80000000);
positionUInt.y ^= (1+~(positionUInt.y >> 31) | 0x80000000);
positionUInt.z ^= (1+~(positionUInt.z >> 31) | 0x80000000);
// Min/max with the LDS values
atom_min(&(clothMinBounds[clothIdentifier*4]), positionUInt.x);
atom_min(&(clothMinBounds[clothIdentifier*4+1]), positionUInt.y);
atom_min(&(clothMinBounds[clothIdentifier*4+2]), positionUInt.z);
atom_max(&(clothMaxBounds[clothIdentifier*4]), positionUInt.x);
atom_max(&(clothMaxBounds[clothIdentifier*4+1]), positionUInt.y);
atom_max(&(clothMaxBounds[clothIdentifier*4+2]), positionUInt.z);
}
}
barrier(CLK_LOCAL_MEM_FENCE);
/* Use global atomics to update the global versions of the data */
if( get_local_id(0) < numSoftBodies )
{
/*atom_min(&(g_clothMinBounds[get_local_id(0)].x), clothMinBounds[get_local_id(0)].x);*/
atom_min(&(g_clothMinBounds[get_local_id(0)*4]), clothMinBounds[get_local_id(0)*4]);
atom_min(&(g_clothMinBounds[get_local_id(0)*4+1]), clothMinBounds[get_local_id(0)*4+1]);
atom_min(&(g_clothMinBounds[get_local_id(0)*4+2]), clothMinBounds[get_local_id(0)*4+2]);
atom_max(&(g_clothMaxBounds[get_local_id(0)*4]), clothMaxBounds[get_local_id(0)*4]);
atom_max(&(g_clothMaxBounds[get_local_id(0)*4+1]), clothMaxBounds[get_local_id(0)*4+1]);
atom_max(&(g_clothMaxBounds[get_local_id(0)*4+2]), clothMaxBounds[get_local_id(0)*4+2]);
}
}
);

View File

@@ -1,35 +0,0 @@
MSTRINGIFY(
// Node indices for each link
__kernel void
IntegrateKernel(
const int numNodes,
const float solverdt,
__global float * g_vertexInverseMasses,
__global float4 * g_vertexPositions,
__global float4 * g_vertexVelocity,
__global float4 * g_vertexPreviousPositions,
__global float4 * g_vertexForceAccumulator GUID_ARG)
{
int nodeID = get_global_id(0);
if( nodeID < numNodes )
{
float4 position = g_vertexPositions[nodeID];
float4 velocity = g_vertexVelocity[nodeID];
float4 force = g_vertexForceAccumulator[nodeID];
float inverseMass = g_vertexInverseMasses[nodeID];
g_vertexPreviousPositions[nodeID] = position;
velocity += force * inverseMass * solverdt;
position += velocity * solverdt;
g_vertexForceAccumulator[nodeID] = (float4)(0.f, 0.f, 0.f, 0.0f);
g_vertexPositions[nodeID] = position;
g_vertexVelocity[nodeID] = velocity;
}
}
);

View File

@@ -1,46 +0,0 @@
MSTRINGIFY(
__kernel void
OutputToVertexArrayWithNormalsKernel(
const int startNode, const int numNodes, __global float *g_vertexBuffer,
const int positionOffset, const int positionStride, const __global float4* g_vertexPositions,
const int normalOffset, const int normalStride, const __global float4* g_vertexNormals )
{
int nodeID = get_global_id(0);
if( nodeID < numNodes )
{
float4 position = g_vertexPositions[nodeID + startNode];
float4 normal = g_vertexNormals[nodeID + startNode];
// Stride should account for the float->float4 conversion
int positionDestination = nodeID * positionStride + positionOffset;
g_vertexBuffer[positionDestination] = position.x;
g_vertexBuffer[positionDestination+1] = position.y;
g_vertexBuffer[positionDestination+2] = position.z;
int normalDestination = nodeID * normalStride + normalOffset;
g_vertexBuffer[normalDestination] = normal.x;
g_vertexBuffer[normalDestination+1] = normal.y;
g_vertexBuffer[normalDestination+2] = normal.z;
}
}
__kernel void
OutputToVertexArrayWithoutNormalsKernel(
const int startNode, const int numNodes, __global float *g_vertexBuffer,
const int positionOffset, const int positionStride, const __global float4* g_vertexPositions )
{
int nodeID = get_global_id(0);
if( nodeID < numNodes )
{
float4 position = g_vertexPositions[nodeID + startNode];
// Stride should account for the float->float4 conversion
int positionDestination = nodeID * positionStride + positionOffset;
g_vertexBuffer[positionDestination] = position.x;
g_vertexBuffer[positionDestination+1] = position.y;
g_vertexBuffer[positionDestination+2] = position.z;
}
}
);

View File

@@ -1,38 +0,0 @@
MSTRINGIFY(
__kernel void
PrepareLinksKernel(
const int numLinks,
__global int2 * g_linksVertexIndices,
__global float * g_linksMassLSC,
__global float4 * g_nodesPreviousPosition,
__global float * g_linksLengthRatio,
__global float4 * g_linksCurrentLength GUID_ARG)
{
int linkID = get_global_id(0);
if( linkID < numLinks )
{
int2 nodeIndices = g_linksVertexIndices[linkID];
int node0 = nodeIndices.x;
int node1 = nodeIndices.y;
float4 nodePreviousPosition0 = g_nodesPreviousPosition[node0];
float4 nodePreviousPosition1 = g_nodesPreviousPosition[node1];
float massLSC = g_linksMassLSC[linkID];
float4 linkCurrentLength = nodePreviousPosition1 - nodePreviousPosition0;
linkCurrentLength.w = 0.f;
float linkLengthRatio = dot(linkCurrentLength, linkCurrentLength)*massLSC;
linkLengthRatio = 1.0f/linkLengthRatio;
g_linksCurrentLength[linkID] = linkCurrentLength;
g_linksLengthRatio[linkID] = linkLengthRatio;
}
}
);

View File

@@ -1,204 +0,0 @@
MSTRINGIFY(
float mydot3a(float4 a, float4 b)
{
return a.x*b.x + a.y*b.y + a.z*b.z;
}
typedef struct
{
int firstObject;
int endObject;
} CollisionObjectIndices;
typedef struct
{
float4 shapeTransform[4]; // column major 4x4 matrix
float4 linearVelocity;
float4 angularVelocity;
int softBodyIdentifier;
int collisionShapeType;
// Shape information
// Compressed from the union
float radius;
float halfHeight;
int upAxis;
float margin;
float friction;
int padding0;
} CollisionShapeDescription;
// From btBroadphaseProxy.h
__constant int CAPSULE_SHAPE_PROXYTYPE = 10;
// Multiply column-major matrix against vector
float4 matrixVectorMul( float4 matrix[4], float4 vector )
{
float4 returnVector;
float4 row0 = (float4)(matrix[0].x, matrix[1].x, matrix[2].x, matrix[3].x);
float4 row1 = (float4)(matrix[0].y, matrix[1].y, matrix[2].y, matrix[3].y);
float4 row2 = (float4)(matrix[0].z, matrix[1].z, matrix[2].z, matrix[3].z);
float4 row3 = (float4)(matrix[0].w, matrix[1].w, matrix[2].w, matrix[3].w);
returnVector.x = dot(row0, vector);
returnVector.y = dot(row1, vector);
returnVector.z = dot(row2, vector);
returnVector.w = dot(row3, vector);
return returnVector;
}
__kernel void
SolveCollisionsAndUpdateVelocitiesKernel(
const int numNodes,
const float isolverdt,
__global int *g_vertexClothIdentifier,
__global float4 *g_vertexPreviousPositions,
__global float * g_perClothFriction,
__global float * g_clothDampingFactor,
__global CollisionObjectIndices * g_perClothCollisionObjectIndices,
__global CollisionShapeDescription * g_collisionObjectDetails,
__global float4 * g_vertexForces,
__global float4 *g_vertexVelocities,
__global float4 *g_vertexPositions GUID_ARG)
{
int nodeID = get_global_id(0);
float4 forceOnVertex = (float4)(0.f, 0.f, 0.f, 0.f);
if( get_global_id(0) < numNodes )
{
int clothIdentifier = g_vertexClothIdentifier[nodeID];
// Abort if this is not a valid cloth
if( clothIdentifier < 0 )
return;
float4 position = (float4)(g_vertexPositions[nodeID].xyz, 1.f);
float4 previousPosition = (float4)(g_vertexPreviousPositions[nodeID].xyz, 1.f);
float clothFriction = g_perClothFriction[clothIdentifier];
float dampingFactor = g_clothDampingFactor[clothIdentifier];
float velocityCoefficient = (1.f - dampingFactor);
float4 difference = position - previousPosition;
float4 velocity = difference*velocityCoefficient*isolverdt;
CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier];
int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject;
if( numObjects > 0 )
{
// We have some possible collisions to deal with
for( int collision = collisionObjectIndices.firstObject; collision < collisionObjectIndices.endObject; ++collision )
{
CollisionShapeDescription shapeDescription = g_collisionObjectDetails[collision];
float colliderFriction = shapeDescription.friction;
if( shapeDescription.collisionShapeType == CAPSULE_SHAPE_PROXYTYPE )
{
// Colliding with a capsule
float capsuleHalfHeight = shapeDescription.halfHeight;
float capsuleRadius = shapeDescription.radius;
float capsuleMargin = shapeDescription.margin;
int capsuleupAxis = shapeDescription.upAxis;
// Four columns of worldTransform matrix
float4 worldTransform[4];
worldTransform[0] = shapeDescription.shapeTransform[0];
worldTransform[1] = shapeDescription.shapeTransform[1];
worldTransform[2] = shapeDescription.shapeTransform[2];
worldTransform[3] = shapeDescription.shapeTransform[3];
// Correctly define capsule centerline vector
float4 c1 = (float4)(0.f, 0.f, 0.f, 1.f);
float4 c2 = (float4)(0.f, 0.f, 0.f, 1.f);
c1.x = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 0 );
c1.y = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 1 );
c1.z = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 2 );
c2.x = -c1.x;
c2.y = -c1.y;
c2.z = -c1.z;
float4 worldC1 = matrixVectorMul(worldTransform, c1);
float4 worldC2 = matrixVectorMul(worldTransform, c2);
float4 segment = (worldC2 - worldC1);
// compute distance of tangent to vertex along line segment in capsule
float distanceAlongSegment = -( mydot3a( (worldC1 - position), segment ) / mydot3a(segment, segment) );
float4 closestPoint = (worldC1 + (float4)(segment * distanceAlongSegment));
float distanceFromLine = length(position - closestPoint);
float distanceFromC1 = length(worldC1 - position);
float distanceFromC2 = length(worldC2 - position);
// Final distance from collision, point to push from, direction to push in
// for impulse force
float dist;
float4 normalVector;
if( distanceAlongSegment < 0 )
{
dist = distanceFromC1;
normalVector = (float4)(normalize(position - worldC1).xyz, 0.f);
} else if( distanceAlongSegment > 1.f ) {
dist = distanceFromC2;
normalVector = (float4)(normalize(position - worldC2).xyz, 0.f);
} else {
dist = distanceFromLine;
normalVector = (float4)(normalize(position - closestPoint).xyz, 0.f);
}
float4 colliderLinearVelocity = shapeDescription.linearVelocity;
float4 colliderAngularVelocity = shapeDescription.angularVelocity;
float4 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, position - (float4)(worldTransform[0].w, worldTransform[1].w, worldTransform[2].w, 0.f));
float minDistance = capsuleRadius + capsuleMargin;
// In case of no collision, this is the value of velocity
velocity = (position - previousPosition) * velocityCoefficient * isolverdt;
// Check for a collision
if( dist < minDistance )
{
// Project back to surface along normal
position = position + (float4)((minDistance - dist)*normalVector*0.9f);
velocity = (position - previousPosition) * velocityCoefficient * isolverdt;
float4 relativeVelocity = velocity - velocityOfSurfacePoint;
float4 p1 = normalize(cross(normalVector, segment));
float4 p2 = normalize(cross(p1, normalVector));
// Full friction is sum of velocities in each direction of plane
float4 frictionVector = p1*mydot3a(relativeVelocity, p1) + p2*mydot3a(relativeVelocity, p2);
// Real friction is peak friction corrected by friction coefficients
frictionVector = frictionVector * (colliderFriction*clothFriction);
float approachSpeed = dot(relativeVelocity, normalVector);
if( approachSpeed <= 0.0f )
forceOnVertex -= frictionVector;
}
}
}
}
g_vertexVelocities[nodeID] = (float4)(velocity.xyz, 0.f);
// Update external force
g_vertexForces[nodeID] = (float4)(forceOnVertex.xyz, 0.f);
g_vertexPositions[nodeID] = (float4)(position.xyz, 0.f);
}
}
);

View File

@@ -1,242 +0,0 @@
MSTRINGIFY(
//#pragma OPENCL EXTENSION cl_amd_printf:enable\n
float mydot3a(float4 a, float4 b)
{
return a.x*b.x + a.y*b.y + a.z*b.z;
}
float mylength3(float4 a)
{
a.w = 0;
return length(a);
}
float4 mynormalize3(float4 a)
{
a.w = 0;
return normalize(a);
}
typedef struct
{
int firstObject;
int endObject;
} CollisionObjectIndices;
typedef struct
{
float4 shapeTransform[4]; // column major 4x4 matrix
float4 linearVelocity;
float4 angularVelocity;
int softBodyIdentifier;
int collisionShapeType;
// Shape information
// Compressed from the union
float radius;
float halfHeight;
int upAxis;
float margin;
float friction;
int padding0;
} CollisionShapeDescription;
// From btBroadphaseProxy.h
__constant int CAPSULE_SHAPE_PROXYTYPE = 10;
// Multiply column-major matrix against vector
float4 matrixVectorMul( float4 matrix[4], float4 vector )
{
float4 returnVector;
float4 row0 = (float4)(matrix[0].x, matrix[1].x, matrix[2].x, matrix[3].x);
float4 row1 = (float4)(matrix[0].y, matrix[1].y, matrix[2].y, matrix[3].y);
float4 row2 = (float4)(matrix[0].z, matrix[1].z, matrix[2].z, matrix[3].z);
float4 row3 = (float4)(matrix[0].w, matrix[1].w, matrix[2].w, matrix[3].w);
returnVector.x = dot(row0, vector);
returnVector.y = dot(row1, vector);
returnVector.z = dot(row2, vector);
returnVector.w = dot(row3, vector);
return returnVector;
}
__kernel void
SolveCollisionsAndUpdateVelocitiesKernel(
const int numNodes,
const float isolverdt,
__global int *g_vertexClothIdentifier,
__global float4 *g_vertexPreviousPositions,
__global float * g_perClothFriction,
__global float * g_clothDampingFactor,
__global CollisionObjectIndices * g_perClothCollisionObjectIndices,
__global CollisionShapeDescription * g_collisionObjectDetails,
__global float4 * g_vertexForces,
__global float4 *g_vertexVelocities,
__global float4 *g_vertexPositions,
__local CollisionShapeDescription *localCollisionShapes,
__global float * g_vertexInverseMasses)
{
int nodeID = get_global_id(0);
float4 forceOnVertex = (float4)(0.f, 0.f, 0.f, 0.f);
int clothIdentifier = g_vertexClothIdentifier[nodeID];
// Abort if this is not a valid cloth
if( clothIdentifier < 0 )
return;
float4 position = (float4)(g_vertexPositions[nodeID].xyz, 0.f);
float4 previousPosition = (float4)(g_vertexPreviousPositions[nodeID].xyz, 0.f);
float clothFriction = g_perClothFriction[clothIdentifier];
float dampingFactor = g_clothDampingFactor[clothIdentifier];
float velocityCoefficient = (1.f - dampingFactor);
float4 difference = position - previousPosition;
float4 velocity = difference*velocityCoefficient*isolverdt;
float inverseMass = g_vertexInverseMasses[nodeID];
CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier];
int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject;
if( numObjects > 0 )
{
// We have some possible collisions to deal with
// First load all of the collision objects into LDS
int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject;
if( get_local_id(0) < numObjects )
{
localCollisionShapes[get_local_id(0)] = g_collisionObjectDetails[ collisionObjectIndices.firstObject + get_local_id(0) ];
}
}
// Safe as the vertices are padded so that not more than one soft body is in a group
barrier(CLK_LOCAL_MEM_FENCE);
// Annoyingly, even though I know the flow control is not varying, the compiler will not let me skip this
if( numObjects > 0 )
{
// We have some possible collisions to deal with
for( int collision = 0; collision < numObjects; ++collision )
{
CollisionShapeDescription shapeDescription = localCollisionShapes[collision];
float colliderFriction = localCollisionShapes[collision].friction;
if( localCollisionShapes[collision].collisionShapeType == CAPSULE_SHAPE_PROXYTYPE )
{
// Colliding with a capsule
float capsuleHalfHeight = localCollisionShapes[collision].halfHeight;
float capsuleRadius = localCollisionShapes[collision].radius;
float capsuleMargin = localCollisionShapes[collision].margin;
int capsuleupAxis = localCollisionShapes[collision].upAxis;
if ( capsuleHalfHeight <= 0 )
capsuleHalfHeight = 0.0001f;
float4 worldTransform[4];
worldTransform[0] = localCollisionShapes[collision].shapeTransform[0];
worldTransform[1] = localCollisionShapes[collision].shapeTransform[1];
worldTransform[2] = localCollisionShapes[collision].shapeTransform[2];
worldTransform[3] = localCollisionShapes[collision].shapeTransform[3];
// Correctly define capsule centerline vector
float4 c1 = (float4)(0.f, 0.f, 0.f, 1.f);
float4 c2 = (float4)(0.f, 0.f, 0.f, 1.f);
c1.x = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 0 );
c1.y = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 1 );
c1.z = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 2 );
c2.x = -c1.x;
c2.y = -c1.y;
c2.z = -c1.z;
float4 worldC1 = matrixVectorMul(worldTransform, c1);
float4 worldC2 = matrixVectorMul(worldTransform, c2);
float4 segment = (float4)((worldC2 - worldC1).xyz, 0.f);
float4 segmentNormalized = mynormalize3(segment);
float distanceAlongSegment =mydot3a( (position - worldC1), segmentNormalized );
float4 closestPointOnSegment = (worldC1 + (float4)(segmentNormalized * distanceAlongSegment));
float distanceFromLine = mylength3(position - closestPointOnSegment);
float distanceFromC1 = mylength3(worldC1 - position);
float distanceFromC2 = mylength3(worldC2 - position);
// Final distance from collision, point to push from, direction to push in
// for impulse force
float dist;
float4 normalVector;
if( distanceAlongSegment < 0 )
{
dist = distanceFromC1;
normalVector = (float4)(normalize(position - worldC1).xyz, 0.f);
} else if( distanceAlongSegment > length(segment) ) {
dist = distanceFromC2;
normalVector = (float4)(normalize(position - worldC2).xyz, 0.f);
} else {
dist = distanceFromLine;
normalVector = (float4)(normalize(position - closestPointOnSegment).xyz, 0.f);
}
float minDistance = capsuleRadius + capsuleMargin;
float4 closestPointOnSurface = (float4)((position + (minDistance - dist) * normalVector).xyz, 0.f);
float4 colliderLinearVelocity = shapeDescription.linearVelocity;
float4 colliderAngularVelocity = shapeDescription.angularVelocity;
float4 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, closestPointOnSurface - (float4)(worldTransform[0].w, worldTransform[1].w, worldTransform[2].w, 0.f));
// Check for a collision
if( dist < minDistance )
{
// Project back to surface along normal
position = closestPointOnSurface;
velocity = (position - previousPosition) * velocityCoefficient * isolverdt;
float4 relativeVelocity = velocity - velocityOfSurfacePoint;
float4 p1 = mynormalize3(cross(normalVector, segment));
float4 p2 = mynormalize3(cross(p1, normalVector));
float4 tangentialVel = p1*mydot3a(relativeVelocity, p1) + p2*mydot3a(relativeVelocity, p2);
float frictionCoef = (colliderFriction * clothFriction);
if (frictionCoef>1.f)
frictionCoef = 1.f;
//only apply friction if objects are not moving apart
float projVel = mydot3a(relativeVelocity,normalVector);
if ( projVel >= -0.001f)
{
if ( inverseMass > 0 )
{
//float4 myforceOnVertex = -tangentialVel * frictionCoef * isolverdt * (1.0f / inverseMass);
position += (-tangentialVel * frictionCoef) / (isolverdt);
}
}
// In case of no collision, this is the value of velocity
velocity = (position - previousPosition) * velocityCoefficient * isolverdt;
}
}
}
}
g_vertexVelocities[nodeID] = (float4)(velocity.xyz, 0.f);
// Update external force
g_vertexForces[nodeID] = (float4)(forceOnVertex.xyz, 0.f);
g_vertexPositions[nodeID] = (float4)(position.xyz, 0.f);
}
);

View File

@@ -1,57 +0,0 @@
MSTRINGIFY(
float mydot3(float4 a, float4 b)
{
return a.x*b.x + a.y*b.y + a.z*b.z;
}
__kernel void
SolvePositionsFromLinksKernel(
const int startLink,
const int numLinks,
const float kst,
const float ti,
__global int2 * g_linksVertexIndices,
__global float * g_linksMassLSC,
__global float * g_linksRestLengthSquared,
__global float * g_verticesInverseMass,
__global float4 * g_vertexPositions GUID_ARG)
{
int linkID = get_global_id(0) + startLink;
if( get_global_id(0) < numLinks )
{
float massLSC = g_linksMassLSC[linkID];
float restLengthSquared = g_linksRestLengthSquared[linkID];
if( massLSC > 0.0f )
{
int2 nodeIndices = g_linksVertexIndices[linkID];
int node0 = nodeIndices.x;
int node1 = nodeIndices.y;
float4 position0 = g_vertexPositions[node0];
float4 position1 = g_vertexPositions[node1];
float inverseMass0 = g_verticesInverseMass[node0];
float inverseMass1 = g_verticesInverseMass[node1];
float4 del = position1 - position0;
float len = mydot3(del, del);
float k = ((restLengthSquared - len)/(massLSC*(restLengthSquared+len)))*kst;
position0 = position0 - del*(k*inverseMass0);
position1 = position1 + del*(k*inverseMass1);
g_vertexPositions[node0] = position0;
g_vertexPositions[node1] = position1;
}
}
}
);

View File

@@ -1,130 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
MSTRINGIFY(
float mydot3(float4 a, float4 b)
{
return a.x*b.x + a.y*b.y + a.z*b.z;
}
__kernel __attribute__((reqd_work_group_size(WAVEFRONT_BLOCK_MULTIPLIER*WAVEFRONT_SIZE, 1, 1)))
void
SolvePositionsFromLinksKernel(
const int startWaveInBatch,
const int numWaves,
const float kst,
const float ti,
__global int2 *g_wavefrontBatchCountsVertexCounts,
__global int *g_vertexAddressesPerWavefront,
__global int2 * g_linksVertexIndices,
__global float * g_linksMassLSC,
__global float * g_linksRestLengthSquared,
__global float * g_verticesInverseMass,
__global float4 * g_vertexPositions,
__local int2 *wavefrontBatchCountsVertexCounts,
__local float4 *vertexPositionSharedData,
__local float *vertexInverseMassSharedData)
{
const int laneInWavefront = (get_global_id(0) & (WAVEFRONT_SIZE-1));
const int wavefront = startWaveInBatch + (get_global_id(0) / WAVEFRONT_SIZE);
const int firstWavefrontInBlock = startWaveInBatch + get_group_id(0) * WAVEFRONT_BLOCK_MULTIPLIER;
const int localWavefront = wavefront - firstWavefrontInBlock;
// Mask out in case there's a stray "wavefront" at the end that's been forced in through the multiplier
if( wavefront < (startWaveInBatch + numWaves) )
{
// Load the batch counts for the wavefronts
int2 batchesAndVerticesWithinWavefront = g_wavefrontBatchCountsVertexCounts[wavefront];
int batchesWithinWavefront = batchesAndVerticesWithinWavefront.x;
int verticesUsedByWave = batchesAndVerticesWithinWavefront.y;
// Load the vertices for the wavefronts
for( int vertex = laneInWavefront; vertex < verticesUsedByWave; vertex+=WAVEFRONT_SIZE )
{
int vertexAddress = g_vertexAddressesPerWavefront[wavefront*MAX_NUM_VERTICES_PER_WAVE + vertex];
vertexPositionSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex] = g_vertexPositions[vertexAddress];
vertexInverseMassSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex] = g_verticesInverseMass[vertexAddress];
}
barrier(CLK_LOCAL_MEM_FENCE);
// Loop through the batches performing the solve on each in LDS
int baseDataLocationForWave = WAVEFRONT_SIZE * wavefront * MAX_BATCHES_PER_WAVE;
//for( int batch = 0; batch < batchesWithinWavefront; ++batch )
int batch = 0;
do
{
int baseDataLocation = baseDataLocationForWave + WAVEFRONT_SIZE * batch;
int locationOfValue = baseDataLocation + laneInWavefront;
// These loads should all be perfectly linear across the WF
int2 localVertexIndices = g_linksVertexIndices[locationOfValue];
float massLSC = g_linksMassLSC[locationOfValue];
float restLengthSquared = g_linksRestLengthSquared[locationOfValue];
// LDS vertex addresses based on logical wavefront number in block and loaded index
int vertexAddress0 = MAX_NUM_VERTICES_PER_WAVE * localWavefront + localVertexIndices.x;
int vertexAddress1 = MAX_NUM_VERTICES_PER_WAVE * localWavefront + localVertexIndices.y;
float4 position0 = vertexPositionSharedData[vertexAddress0];
float4 position1 = vertexPositionSharedData[vertexAddress1];
float inverseMass0 = vertexInverseMassSharedData[vertexAddress0];
float inverseMass1 = vertexInverseMassSharedData[vertexAddress1];
float4 del = position1 - position0;
float len = mydot3(del, del);
float k = 0;
if( massLSC > 0.0f )
{
k = ((restLengthSquared - len)/(massLSC*(restLengthSquared+len)))*kst;
}
position0 = position0 - del*(k*inverseMass0);
position1 = position1 + del*(k*inverseMass1);
// Ensure compiler does not re-order memory operations
barrier(CLK_LOCAL_MEM_FENCE);
vertexPositionSharedData[vertexAddress0] = position0;
vertexPositionSharedData[vertexAddress1] = position1;
// Ensure compiler does not re-order memory operations
barrier(CLK_LOCAL_MEM_FENCE);
++batch;
} while( batch < batchesWithinWavefront );
// Update the global memory vertices for the wavefronts
for( int vertex = laneInWavefront; vertex < verticesUsedByWave; vertex+=WAVEFRONT_SIZE )
{
int vertexAddress = g_vertexAddressesPerWavefront[wavefront*MAX_NUM_VERTICES_PER_WAVE + vertex];
g_vertexPositions[vertexAddress] = (float4)(vertexPositionSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex].xyz, 0.f);
}
}
}
);

View File

@@ -1,44 +0,0 @@
MSTRINGIFY(
/*#define float3 float4
float dot3(float3 a, float3 b)
{
return a.x*b.x + a.y*b.y + a.z*b.z;
}*/
__kernel void
UpdateConstantsKernel(
const int numLinks,
__global int2 * g_linksVertexIndices,
__global float4 * g_vertexPositions,
__global float * g_vertexInverseMasses,
__global float * g_linksMaterialLSC,
__global float * g_linksMassLSC,
__global float * g_linksRestLengthSquared,
__global float * g_linksRestLengths)
{
int linkID = get_global_id(0);
if( linkID < numLinks )
{
int2 nodeIndices = g_linksVertexIndices[linkID];
int node0 = nodeIndices.x;
int node1 = nodeIndices.y;
float linearStiffnessCoefficient = g_linksMaterialLSC[ linkID ];
float3 position0 = g_vertexPositions[node0].xyz;
float3 position1 = g_vertexPositions[node1].xyz;
float inverseMass0 = g_vertexInverseMasses[node0];
float inverseMass1 = g_vertexInverseMasses[node1];
float3 difference = position0 - position1;
float length2 = dot(difference, difference);
float length = sqrt(length2);
g_linksRestLengths[linkID] = length;
g_linksMassLSC[linkID] = (inverseMass0 + inverseMass1)/linearStiffnessCoefficient;
g_linksRestLengthSquared[linkID] = length*length;
}
}
);

View File

@@ -1,25 +0,0 @@
MSTRINGIFY(
__kernel void
UpdateFixedVertexPositions(
const uint numNodes,
__global int * g_anchorIndex,
__global float4 * g_vertexPositions,
__global float4 * g_anchorPositions GUID_ARG)
{
unsigned int nodeID = get_global_id(0);
if( nodeID < numNodes )
{
int anchorIndex = g_anchorIndex[nodeID];
float4 position = g_vertexPositions[nodeID];
if ( anchorIndex >= 0 )
{
float4 anchorPosition = g_anchorPositions[anchorIndex];
g_vertexPositions[nodeID] = anchorPosition;
}
}
}
);

View File

@@ -1,39 +0,0 @@
MSTRINGIFY(
__kernel void
updateVelocitiesFromPositionsWithVelocitiesKernel(
int numNodes,
float isolverdt,
__global float4 * g_vertexPositions,
__global float4 * g_vertexPreviousPositions,
__global int * g_vertexClothIndices,
__global float *g_clothVelocityCorrectionCoefficients,
__global float * g_clothDampingFactor,
__global float4 * g_vertexVelocities,
__global float4 * g_vertexForces GUID_ARG)
{
int nodeID = get_global_id(0);
if( nodeID < numNodes )
{
float4 position = g_vertexPositions[nodeID];
float4 previousPosition = g_vertexPreviousPositions[nodeID];
float4 velocity = g_vertexVelocities[nodeID];
int clothIndex = g_vertexClothIndices[nodeID];
float velocityCorrectionCoefficient = g_clothVelocityCorrectionCoefficients[clothIndex];
float dampingFactor = g_clothDampingFactor[clothIndex];
float velocityCoefficient = (1.f - dampingFactor);
float4 difference = position - previousPosition;
velocity += difference*velocityCorrectionCoefficient*isolverdt;
// Damp the velocity
velocity *= velocityCoefficient;
g_vertexVelocities[nodeID] = velocity;
g_vertexForces[nodeID] = (float4)(0.f, 0.f, 0.f, 0.f);
}
}
);

View File

@@ -1,102 +0,0 @@
MSTRINGIFY(
float length3(float4 a)
{
a.w = 0;
return length(a);
}
float4 normalize3(float4 a)
{
a.w = 0;
return normalize(a);
}
__kernel void
ResetNormalsAndAreasKernel(
const unsigned int numNodes,
__global float4 * g_vertexNormals,
__global float * g_vertexArea GUID_ARG)
{
if( get_global_id(0) < numNodes )
{
g_vertexNormals[get_global_id(0)] = (float4)(0.0f, 0.0f, 0.0f, 0.0f);
g_vertexArea[get_global_id(0)] = 0.0f;
}
}
__kernel void
UpdateSoftBodiesKernel(
const unsigned int startFace,
const unsigned int numFaces,
__global int4 * g_triangleVertexIndexSet,
__global float4 * g_vertexPositions,
__global float4 * g_vertexNormals,
__global float * g_vertexArea,
__global float4 * g_triangleNormals,
__global float * g_triangleArea GUID_ARG)
{
int faceID = get_global_id(0) + startFace;
if( get_global_id(0) < numFaces )
{
int4 triangleIndexSet = g_triangleVertexIndexSet[ faceID ];
int nodeIndex0 = triangleIndexSet.x;
int nodeIndex1 = triangleIndexSet.y;
int nodeIndex2 = triangleIndexSet.z;
float4 node0 = g_vertexPositions[nodeIndex0];
float4 node1 = g_vertexPositions[nodeIndex1];
float4 node2 = g_vertexPositions[nodeIndex2];
float4 nodeNormal0 = g_vertexNormals[nodeIndex0];
float4 nodeNormal1 = g_vertexNormals[nodeIndex1];
float4 nodeNormal2 = g_vertexNormals[nodeIndex2];
float vertexArea0 = g_vertexArea[nodeIndex0];
float vertexArea1 = g_vertexArea[nodeIndex1];
float vertexArea2 = g_vertexArea[nodeIndex2];
float4 vector0 = node1 - node0;
float4 vector1 = node2 - node0;
float4 faceNormal = cross(vector0, vector1);
float triangleArea = length(faceNormal);
nodeNormal0 = nodeNormal0 + faceNormal;
nodeNormal1 = nodeNormal1 + faceNormal;
nodeNormal2 = nodeNormal2 + faceNormal;
vertexArea0 = vertexArea0 + triangleArea;
vertexArea1 = vertexArea1 + triangleArea;
vertexArea2 = vertexArea2 + triangleArea;
g_triangleNormals[faceID] = normalize3(faceNormal);
g_vertexNormals[nodeIndex0] = nodeNormal0;
g_vertexNormals[nodeIndex1] = nodeNormal1;
g_vertexNormals[nodeIndex2] = nodeNormal2;
g_triangleArea[faceID] = triangleArea;
g_vertexArea[nodeIndex0] = vertexArea0;
g_vertexArea[nodeIndex1] = vertexArea1;
g_vertexArea[nodeIndex2] = vertexArea2;
}
}
__kernel void
NormalizeNormalsAndAreasKernel(
const unsigned int numNodes,
__global int * g_vertexTriangleCount,
__global float4 * g_vertexNormals,
__global float * g_vertexArea GUID_ARG)
{
if( get_global_id(0) < numNodes )
{
float4 normal = g_vertexNormals[get_global_id(0)];
float area = g_vertexArea[get_global_id(0)];
int numTriangles = g_vertexTriangleCount[get_global_id(0)];
float vectorLength = length3(normal);
g_vertexNormals[get_global_id(0)] = normalize3(normal);
g_vertexArea[get_global_id(0)] = area/(float)(numTriangles);
}
}
);

View File

@@ -1,34 +0,0 @@
MSTRINGIFY(
__kernel void
updateVelocitiesFromPositionsWithoutVelocitiesKernel(
const int numNodes,
const float isolverdt,
__global float4 * g_vertexPositions,
__global float4 * g_vertexPreviousPositions,
__global int * g_vertexClothIndices,
__global float * g_clothDampingFactor,
__global float4 * g_vertexVelocities,
__global float4 * g_vertexForces GUID_ARG)
{
int nodeID = get_global_id(0);
if( nodeID < numNodes )
{
float4 position = g_vertexPositions[nodeID];
float4 previousPosition = g_vertexPreviousPositions[nodeID];
float4 velocity = g_vertexVelocities[nodeID];
int clothIndex = g_vertexClothIndices[nodeID];
float dampingFactor = g_clothDampingFactor[clothIndex];
float velocityCoefficient = (1.f - dampingFactor);
float4 difference = position - previousPosition;
velocity = difference*velocityCoefficient*isolverdt;
g_vertexVelocities[nodeID] = velocity;
g_vertexForces[nodeID] = (float4)(0.f, 0.f, 0.f, 0.f);
}
}
);

View File

@@ -1,28 +0,0 @@
MSTRINGIFY(
__kernel void
UpdatePositionsFromVelocitiesKernel(
const int numNodes,
const float solverSDT,
__global float4 * g_vertexVelocities,
__global float4 * g_vertexPreviousPositions,
__global float4 * g_vertexCurrentPosition GUID_ARG)
{
int vertexID = get_global_id(0);
if( vertexID < numNodes )
{
float4 previousPosition = g_vertexPreviousPositions[vertexID];
float4 velocity = g_vertexVelocities[vertexID];
float4 newPosition = previousPosition + velocity*solverSDT;
g_vertexCurrentPosition[vertexID] = newPosition;
g_vertexPreviousPositions[vertexID] = newPosition;
}
}
);

View File

@@ -1,45 +0,0 @@
MSTRINGIFY(
__kernel void
VSolveLinksKernel(
int startLink,
int numLinks,
float kst,
__global int2 * g_linksVertexIndices,
__global float * g_linksLengthRatio,
__global float4 * g_linksCurrentLength,
__global float * g_vertexInverseMass,
__global float4 * g_vertexVelocity GUID_ARG)
{
int linkID = get_global_id(0) + startLink;
if( get_global_id(0) < numLinks )
{
int2 nodeIndices = g_linksVertexIndices[linkID];
int node0 = nodeIndices.x;
int node1 = nodeIndices.y;
float linkLengthRatio = g_linksLengthRatio[linkID];
float3 linkCurrentLength = g_linksCurrentLength[linkID].xyz;
float3 vertexVelocity0 = g_vertexVelocity[node0].xyz;
float3 vertexVelocity1 = g_vertexVelocity[node1].xyz;
float vertexInverseMass0 = g_vertexInverseMass[node0];
float vertexInverseMass1 = g_vertexInverseMass[node1];
float3 nodeDifference = vertexVelocity0 - vertexVelocity1;
float dotResult = dot(linkCurrentLength, nodeDifference);
float j = -dotResult*linkLengthRatio*kst;
float3 velocityChange0 = linkCurrentLength*(j*vertexInverseMass0);
float3 velocityChange1 = linkCurrentLength*(j*vertexInverseMass1);
vertexVelocity0 += velocityChange0;
vertexVelocity1 -= velocityChange1;
g_vertexVelocity[node0] = (float4)(vertexVelocity0, 0.f);
g_vertexVelocity[node1] = (float4)(vertexVelocity1, 0.f);
}
}
);

View File

@@ -1,209 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_SOFT_BODY_SOLVER_BUFFER_OPENCL_H
#define BT_SOFT_BODY_SOLVER_BUFFER_OPENCL_H
// OpenCL support
#ifdef USE_MINICL
#include "MiniCL/cl.h"
#else //USE_MINICL
#ifdef __APPLE__
#include <OpenCL/OpenCL.h>
#else
#include <CL/cl.h>
#endif //__APPLE__
#endif//USE_MINICL
#ifndef SAFE_RELEASE
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
#endif
template <typename ElementType> class btOpenCLBuffer
{
public:
cl_command_queue m_cqCommandQue;
cl_context m_clContext;
cl_mem m_buffer;
btAlignedObjectArray< ElementType > * m_CPUBuffer;
int m_gpuSize;
bool m_onGPU;
bool m_readOnlyOnGPU;
bool m_allocated;
bool createBuffer( cl_mem* preexistingBuffer = 0)
{
cl_int err;
if( preexistingBuffer )
{
m_buffer = *preexistingBuffer;
}
else {
cl_mem_flags flags= m_readOnlyOnGPU ? CL_MEM_READ_ONLY : CL_MEM_READ_WRITE;
size_t size = m_CPUBuffer->size() * sizeof(ElementType);
// At a minimum the buffer must exist
if( size == 0 )
size = sizeof(ElementType);
m_buffer = clCreateBuffer(m_clContext, flags, size, 0, &err);
if( err != CL_SUCCESS )
{
btAssert( "Buffer::Buffer(m_buffer)");
}
}
m_gpuSize = m_CPUBuffer->size();
return true;
}
public:
btOpenCLBuffer( cl_command_queue commandQue,cl_context ctx, btAlignedObjectArray< ElementType >* CPUBuffer, bool readOnly)
:m_cqCommandQue(commandQue),
m_clContext(ctx),
m_buffer(0),
m_CPUBuffer(CPUBuffer),
m_gpuSize(0),
m_onGPU(false),
m_readOnlyOnGPU(readOnly),
m_allocated(false)
{
}
~btOpenCLBuffer()
{
clReleaseMemObject(m_buffer);
}
bool moveToGPU()
{
cl_int err;
if( (m_CPUBuffer->size() != m_gpuSize) )
{
m_onGPU = false;
}
if( !m_allocated && m_CPUBuffer->size() == 0 )
{
// If it isn't on the GPU and yet there is no data on the CPU side this may cause a problem with some kernels.
// We should create *something* on the device side
if (!createBuffer()) {
return false;
}
m_allocated = true;
}
if( !m_onGPU && m_CPUBuffer->size() > 0 )
{
if (!m_allocated || (m_CPUBuffer->size() != m_gpuSize)) {
if (!createBuffer()) {
return false;
}
m_allocated = true;
}
size_t size = m_CPUBuffer->size() * sizeof(ElementType);
err = clEnqueueWriteBuffer(m_cqCommandQue,m_buffer,
CL_FALSE,
0,
size,
&((*m_CPUBuffer)[0]),0,0,0);
if( err != CL_SUCCESS )
{
btAssert( "CommandQueue::enqueueWriteBuffer(m_buffer)" );
}
m_onGPU = true;
}
return true;
}
bool moveFromGPU()
{
cl_int err;
if (m_CPUBuffer->size() > 0) {
if (m_onGPU && !m_readOnlyOnGPU) {
size_t size = m_CPUBuffer->size() * sizeof(ElementType);
err = clEnqueueReadBuffer(m_cqCommandQue,
m_buffer,
CL_TRUE,
0,
size,
&((*m_CPUBuffer)[0]),0,0,0);
if( err != CL_SUCCESS )
{
btAssert( "CommandQueue::enqueueReadBuffer(m_buffer)" );
}
m_onGPU = false;
}
}
return true;
}
bool copyFromGPU()
{
cl_int err;
size_t size = m_CPUBuffer->size() * sizeof(ElementType);
if (m_CPUBuffer->size() > 0) {
if (m_onGPU && !m_readOnlyOnGPU) {
err = clEnqueueReadBuffer(m_cqCommandQue,
m_buffer,
CL_TRUE,
0,size,
&((*m_CPUBuffer)[0]),0,0,0);
if( err != CL_SUCCESS )
{
btAssert( "CommandQueue::enqueueReadBuffer(m_buffer)");
}
}
}
return true;
}
virtual void changedOnCPU()
{
m_onGPU = false;
}
}; // class btOpenCLBuffer
#endif // #ifndef BT_SOFT_BODY_SOLVER_BUFFER_OPENCL_H

View File

@@ -1,99 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h"
#include "btSoftBodySolverBuffer_OpenCL.h"
#ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_OPENCL_H
#define BT_SOFT_BODY_SOLVER_LINK_DATA_OPENCL_H
class btSoftBodyLinkDataOpenCL : public btSoftBodyLinkData
{
public:
bool m_onGPU;
cl_command_queue m_cqCommandQue;
btOpenCLBuffer<LinkNodePair> m_clLinks;
btOpenCLBuffer<float> m_clLinkStrength;
btOpenCLBuffer<float> m_clLinksMassLSC;
btOpenCLBuffer<float> m_clLinksRestLengthSquared;
btOpenCLBuffer<Vectormath::Aos::Vector3> m_clLinksCLength;
btOpenCLBuffer<float> m_clLinksLengthRatio;
btOpenCLBuffer<float> m_clLinksRestLength;
btOpenCLBuffer<float> m_clLinksMaterialLinearStiffnessCoefficient;
struct BatchPair
{
int start;
int length;
BatchPair() :
start(0),
length(0)
{
}
BatchPair( int s, int l ) :
start( s ),
length( l )
{
}
};
/**
* Link addressing information for each cloth.
* Allows link locations to be computed independently of data batching.
*/
btAlignedObjectArray< int > m_linkAddresses;
/**
* Start and length values for computation batches over link data.
*/
btAlignedObjectArray< BatchPair > m_batchStartLengths;
btSoftBodyLinkDataOpenCL(cl_command_queue queue, cl_context ctx);
virtual ~btSoftBodyLinkDataOpenCL();
/** Allocate enough space in all link-related arrays to fit numLinks links */
virtual void createLinks( int numLinks );
/** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */
virtual void setLinkAt(
const LinkDescription &link,
int linkIndex );
virtual bool onAccelerator();
virtual bool moveToAccelerator();
virtual bool moveFromAccelerator();
/**
* Generate (and later update) the batching for the entire link set.
* This redoes a lot of work because it batches the entire set when each cloth is inserted.
* In theory we could delay it until just before we need the cloth.
* It's a one-off overhead, though, so that is a later optimisation.
*/
void generateBatches();
};
#endif // #ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_OPENCL_H

Some files were not shown because too many files have changed in this diff Show More