Remove btSoftBodySolver_CPU.*

Move btSoftBodySolverData.h to src/BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h
Attempt to re-enable MiniCL version of OpenCLClothDemo (cloth-capsule collision still broken)
Add optional OpenCL acceleration to SerializeDemo (just for cloth)
This commit is contained in:
erwin.coumans
2011-11-11 19:00:26 +00:00
parent 14352169ab
commit 66c349caa6
40 changed files with 2442 additions and 1649 deletions

View File

@@ -31,7 +31,7 @@ class btDX11SIMDAwareSoftBodySolver;
#include "BulletSoftBody/btSoftBodySolvers.h"
#include "BulletSoftBody/btDefaultSoftBodySolver.h"
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolver_CPU.h"
#include "BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.h"
#include "BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.h"

View File

@@ -21,7 +21,6 @@ IF (USE_GLUT)
LINK_LIBRARIES(
OpenGLSupport
BulletSoftBodySolvers_OpenCL_Mini
BulletSoftBodySolvers_CPU
MiniCL
BulletMultiThreaded
BulletSoftBody

View File

@@ -18,15 +18,18 @@ subject to the following restrictions:
#endif
#ifndef USE_MINICL
#define USE_SIMDAWARE_SOLVER
#ifndef __APPLE__
//#define USE_SIMDAWARE_SOLVER
#endif
#if !defined (__APPLE__)
#define USE_GPU_SOLVER
#if defined (_WIN32)
#if defined (_WIN32) && !defined(USE_MINICL)
#define USE_GPU_COPY //only tested on Windows
#endif //_WIN32
#endif //__APPLE__
#endif //USE_MINICL
#endif //_WIN32 && !USE_MINICL
#endif //!__APPLE__
@@ -43,13 +46,7 @@ const int numFlags = 5;
const int clothWidth = 40;
const int clothHeight = 60;//60;
float _windAngle = 1.0;//0.4;
float _windStrength = 10.;
float _windStrength = 0.;
@@ -57,7 +54,6 @@ float _windStrength = 10.;
#include "LinearMath/btHashMap.h"
#include "BulletSoftBody/btSoftRigidDynamicsWorld.h"
#include "vectormath/vmInclude.h"
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolver_CPU.h"
#include "BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.h"
#include "BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.h"
#include "BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexBuffer_OpenGL.h"
@@ -95,7 +91,6 @@ btCollisionDispatcher* m_dispatcher;
btConstraintSolver* m_solver;
btDefaultCollisionConfiguration* m_collisionConfiguration;
btCPUSoftBodySolver *g_cpuSolver = NULL;
btOpenCLSoftBodySolver *g_openCLSolver = NULL;
btOpenCLSoftBodySolverSIMDAware *g_openCLSIMDSolver = NULL;
@@ -368,9 +363,8 @@ void initBullet(void)
#endif // #ifdef USE_GPU_COPY
#endif
#else
g_cpuSolver = new btCPUSoftBodySolver;
g_solver = g_cpuSolver;
g_softBodyOutput = new btSoftBodySolverOutputCPUtoCPU;
g_openCLSolver = new btOpenCLSoftBodySolver( g_cqCommandQue, g_cxMainContext );
g_solver = g_openCLSolver;
#endif
//m_collisionConfiguration = new btDefaultCollisionConfiguration();
@@ -471,11 +465,11 @@ void initBullet(void)
#endif
#ifdef USE_GPU_SOLVER
//#ifdef USE_GPU_SOLVER
createFlag( *g_openCLSolver, clothWidth, clothHeight, m_flags );
#else
createFlag( *g_cpuSolver, clothWidth, clothHeight, m_flags );
#endif
//#else
//#endif
// Create output buffer descriptions for ecah flag
// These describe where the simulation should send output data to
@@ -544,7 +538,7 @@ void doFlags()
//debugDraw.setDebugMode(btIDebugDraw::DBG_DrawWireframe);
//g_solver->copyBackToSoftBodies();
//m_dynamicsWorld->debugDrawWorld();
m_dynamicsWorld->debugDrawWorld();
}
@@ -607,8 +601,6 @@ int main(int argc, char *argv[])
goGL();
if( g_cpuSolver )
delete g_cpuSolver;
if( g_openCLSolver )
delete g_openCLSolver;
if( g_openCLSIMDSolver )

View File

@@ -0,0 +1,131 @@
INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/src
${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL
${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletFileLoader
${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletWorldImporter
${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL
${AMD_OPENCL_INCLUDES}
)
ADD_DEFINITIONS(-DDESERIALIZE_SOFT_BODIES)
ADD_DEFINITIONS(-DUSE_AMD_OPENCL)
ADD_DEFINITIONS(-DCL_PLATFORM_AMD)
IF (CMAKE_CL_64)
SET(CMAK_GLEW_LIBRARY
${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew64.lib )
ELSE(CMAKE_CL_64)
SET(CMAK_GLEW_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew32.lib )
ENDIF(CMAKE_CL_64)
IF (USE_GLUT)
LINK_LIBRARIES(
OpenGLSupport
BulletWorldImporter
BulletSoftBody
BulletDynamics
BulletCollision
BulletFileLoader
LinearMath
BulletSoftBodySolvers_OpenCL_AMD
BulletMultiThreaded
${GLUT_glut_LIBRARY}
${OPENGL_gl_LIBRARY}
${OPENGL_glu_LIBRARY}
${CMAK_GLEW_LIBRARY}
${CMAKE_ATISTREAMSDK_LIBPATH}/OpenCL.lib
)
IF (WIN32)
ADD_EXECUTABLE(AppSerializeDemo_AMD
../main.cpp
../SerializeDemo.cpp
../SerializeDemo.h
${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc
${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOclUtils.h
${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOclCommon.h
${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOclUtils.cpp
${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOclCommon.cpp
${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/clew.c
${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/clew.h
)
ELSE()
ADD_EXECUTABLE(AppSerializeDemo_AMD
../main.cpp
../SerializeDemo.cpp
../SerializeDemo.h
${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOclUtils.h
${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOclCommon.h
${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOclUtils.cpp
${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOclCommon.cpp
${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/clew.c
${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/clew.h
)
ENDIF()
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
IF (WIN32)
IF (CMAKE_CL_64)
ADD_CUSTOM_COMMAND(
TARGET AppSerializeDemo_AMD
POST_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/glut64.dll ${CMAKE_CURRENT_BINARY_DIR}
)
ELSE(CMAKE_CL_64)
ADD_CUSTOM_COMMAND(
TARGET AppSerializeDemo_AMD
POST_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/GLUT32.DLL ${CMAKE_CURRENT_BINARY_DIR}
)
ENDIF(CMAKE_CL_64)
ENDIF(WIN32)
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
ELSE (USE_GLUT)
LINK_LIBRARIES(
OpenGLSupport
BulletWorldImporter
BulletSoftBody
BulletDynamics
BulletCollision
BulletFileLoader
LinearMath
BulletSoftBodySolvers_OpenCL_AMD
BulletMultiThreaded
${OPENGL_gl_LIBRARY}
${OPENGL_glu_LIBRARY}
${CMAK_GLEW_LIBRARY}
${CMAKE_ATISTREAMSDK_LIBPATH}/OpenCL.lib
)
ADD_EXECUTABLE(AppSerializeDemo_AMD
WIN32
../../OpenGL/Win32AppMain.cpp
../Win32SerializeDemo.cpp
../SerializeDemo.cpp
../SerializeDemo.h
${BULLET_PHYSICS_SOURCE_DIR}/msvc/bullet.rc
${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOclUtils.h
${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOclCommon.h
${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOclUtils.cpp
${BULLET_PHYSICS_SOURCE_DIR}/Demos/SharedOpenCL/btOclCommon.cpp
)
ENDIF (USE_GLUT)
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES AND NOT INTERNAL_UPDATE_SERIALIZATION_STRUCTURES)
ADD_CUSTOM_COMMAND(
TARGET AppSerializeDemo_AMD
POST_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/Demos/SerializeDemo/testFile.bullet ${CMAKE_CURRENT_BINARY_DIR}/testFile.bullet
)
ENDIF ()
IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES)
SET_TARGET_PROPERTIES(AppSerializeDemo_AMD PROPERTIES DEBUG_POSTFIX "_Debug")
SET_TARGET_PROPERTIES(AppSerializeDemo_AMD PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel")
SET_TARGET_PROPERTIES(AppSerializeDemo_AMD PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo")
ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES)

View File

@@ -0,0 +1,65 @@
hasCL = findOpenCL_AMD()
if (hasCL) then
project "AppOpenCLClothDemo_AMD"
defines { "USE_AMD_OPENCL","CL_PLATFORM_AMD"}
initOpenCL_AMD()
language "C++"
kind "ConsoleApp"
targetdir "../../.."
libdirs {"../../../Glut"}
links {
"LinearMath",
"BulletCollision",
"BulletDynamics",
"BulletSoftBody",
"BulletSoftBodySolvers_OpenCL_AMD",
"opengl32"
}
configuration "x64"
links {
"glut64",
"glew64"
}
configuration "x32"
links {
"glut32",
"glew32"
}
configuration{}
includedirs {
"../../../src",
"../../../Glut",
"../../SharedOpenCL",
"../../OpenGL"
}
files {
"../cl_cloth_demo.cpp",
"../../SharedOpenCL/btOclUtils.h",
"../../SharedOpenCL/btOclCommon.h",
"../../SharedOpenCL/btOclUtils.cpp",
"../../SharedOpenCL/btOclCommon.cpp",
"../../OpenGL/GLDebugDrawer.cpp",
"../../OpenGL/stb_image.cpp",
"../../OpenGL/stb_image.h",
"../gl_win.cpp",
"../clstuff.cpp",
"../clstuff.h",
"../gl_win.h",
"../cloth.h"
}
end

View File

@@ -11,6 +11,10 @@ SET(GLUT_ROOT ${BULLET_PHYSICS_SOURCE_DIR}/Glut)
# You shouldn't have to modify anything below this line
########################################################
IF(BUILD_AMD_OPENCL_DEMOS)
SUBDIRS(AMD)
ENDIF()
INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/src
${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL
@@ -86,4 +90,6 @@ IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES)
SET_TARGET_PROPERTIES(AppSerializeDemo PROPERTIES DEBUG_POSTFIX "_Debug")
SET_TARGET_PROPERTIES(AppSerializeDemo PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel")
SET_TARGET_PROPERTIES(AppSerializeDemo PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo")
ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES)
ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES)

View File

@@ -51,12 +51,26 @@ subject to the following restrictions:
#ifdef DESERIALIZE_SOFT_BODIES
#include "BulletSoftBody/btSoftBodySolvers.h"
#ifdef USE_AMD_OPENCL
#include <BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.h>
#include <BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.h>
extern cl_context g_cxMainContext;
extern cl_device_id g_cdDevice;
extern cl_command_queue g_cqCommandQue;
#endif
btSoftBodySolver* fSoftBodySolver=0;
#include "BulletSoftBody/btSoftBodyHelpers.h"
#include "BulletSoftBody/btSoftRigidDynamicsWorld.h"
#include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h"
#endif
void SerializeDemo::clientMoveAndDisplay()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -69,8 +83,27 @@ void SerializeDemo::clientMoveAndDisplay()
{
m_dynamicsWorld->stepSimulation(ms / 1000000.f);
//optional but useful: debug drawing
if (fSoftBodySolver)
fSoftBodySolver->copyBackToSoftBodies();
m_dynamicsWorld->debugDrawWorld();
if (m_dynamicsWorld->getWorldType()==BT_SOFT_RIGID_DYNAMICS_WORLD)
{
//optional but useful: debug drawing
btSoftRigidDynamicsWorld* softWorld = (btSoftRigidDynamicsWorld*)m_dynamicsWorld;
for ( int i=0;i<softWorld->getSoftBodyArray().size();i++)
{
btSoftBody* psb=(btSoftBody*)softWorld->getSoftBodyArray()[i];
if (softWorld->getDebugDrawer() && !(softWorld->getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe)))
{
btSoftBodyHelpers::DrawFrame(psb,softWorld->getDebugDrawer());
btSoftBodyHelpers::Draw(psb,softWorld->getDebugDrawer(),softWorld->getDrawFlags());
}
}
}
}
renderme();
@@ -87,6 +120,22 @@ void SerializeDemo::displayCallback(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (m_dynamicsWorld->getWorldType()==BT_SOFT_RIGID_DYNAMICS_WORLD)
{
//optional but useful: debug drawing
btSoftRigidDynamicsWorld* softWorld = (btSoftRigidDynamicsWorld*)m_dynamicsWorld;
for ( int i=0;i<softWorld->getSoftBodyArray().size();i++)
{
btSoftBody* psb=(btSoftBody*)softWorld->getSoftBodyArray()[i];
if (softWorld->getDebugDrawer() && !(softWorld->getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe)))
{
btSoftBodyHelpers::DrawFrame(psb,softWorld->getDebugDrawer());
btSoftBodyHelpers::Draw(psb,softWorld->getDebugDrawer(),softWorld->getDrawFlags());
}
}
}
renderme();
//optional but useful: debug drawing to detect problems
@@ -97,7 +146,12 @@ void SerializeDemo::displayCallback(void) {
swapBuffers();
}
enum SolverType
{
kSolverAccelerationOpenCL_CPU = 1,
kSolverAccelerationOpenCL_GPU = 2,
kSolverAccelerationNone = 3
};
void SerializeDemo::setupEmptyDynamicsWorld()
@@ -123,7 +177,62 @@ void SerializeDemo::setupEmptyDynamicsWorld()
m_solver = sol;
#ifdef DESERIALIZE_SOFT_BODIES
btSoftRigidDynamicsWorld* world = new btSoftRigidDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
#ifdef USE_AMD_OPENCL
int solverAccel = kSolverAccelerationOpenCL_GPU;
if ( 1 ) {
switch (solverAccel)
{
case kSolverAccelerationOpenCL_GPU:
{
fSoftBodySolver
= new btOpenCLSoftBodySolverSIMDAware( g_cqCommandQue,
g_cxMainContext );
// fSoftBodySolver = new btOpenCLSoftBodySolver( g_cqCommandQue, g_cxMainContext);
/*if (!fSoftBodySolver->checkInitialized())
{
btAssert(0);
delete fSoftBodySolver;
fSoftBodySolver = NULL;
}
*/
break;
}
case kSolverAccelerationOpenCL_CPU:
{
//fSoftBodySolver = new btCPUSoftBodySolver();
break;
};
case kSolverAccelerationNone:
default:
{
fSoftBodySolver = NULL;
}
};
}
else
{
if ( solverAccel != kSolverAccelerationNone )
{
}
else
{
}
fSoftBodySolver = NULL;
}
#else
fSoftBodySolver = NULL;
#endif
btSoftRigidDynamicsWorld* world = new btSoftRigidDynamicsWorld(m_dispatcher, m_broadphase, m_solver,
m_collisionConfiguration, fSoftBodySolver);
m_dynamicsWorld = world;
//world->setDrawFlags(world->getDrawFlags()^fDrawFlags::Clusters);
#else
@@ -510,6 +619,7 @@ SerializeDemo::~SerializeDemo()
void SerializeDemo::initPhysics()
{
m_idle = true;
setTexturing(true);
setShadows(true);

View File

@@ -19,69 +19,93 @@ subject to the following restrictions:
#include "btBulletDynamicsCommon.h"
#include "LinearMath/btHashMap.h"
class OurValue
{
int m_uid;
public:
OurValue(const btVector3& initialPos)
:m_position(initialPos)
{
static int gUid=0;
m_uid=gUid;
gUid++;
}
btVector3 m_position;
int getUid() const
{
return m_uid;
}
};
#ifdef USE_AMD_OPENCL
#ifdef _DEBUG
bool bDebug = true;
#else
bool bDebug = false;
#endif
#include "btOclCommon.h"
#include "btOclUtils.h"
#include <LinearMath/btScalar.h>
cl_context g_cxMainContext;
cl_device_id g_cdDevice;
cl_command_queue g_cqCommandQue;
// Returns true if OpenCL is initialized properly, false otherwise.
bool initCL( void* glCtx, void* glDC )
{
int ciErrNum = 0;
#ifdef BT_USE_CLEW
ciErrNum = clewInit( "OpenCL.dll" );
if ( ciErrNum != CLEW_SUCCESS ) {
return false;
}
#endif
#if defined(CL_PLATFORM_MINI_CL)
cl_device_type deviceType = CL_DEVICE_TYPE_CPU;
#elif defined(CL_PLATFORM_AMD)
cl_device_type deviceType = CL_DEVICE_TYPE_GPU;
#elif defined(CL_PLATFORM_NVIDIA)
cl_device_type deviceType = CL_DEVICE_TYPE_GPU;
#else
cl_device_type deviceType = CL_DEVICE_TYPE_CPU;
#endif
//g_cxMainContext = btOclCommon::createContextFromType(CL_DEVICE_TYPE_ALL, &ciErrNum);
//g_cxMainContext = btOclCommon::createContextFromType(CL_DEVICE_TYPE_GPU, &ciErrNum);
//g_cxMainContext = btOclCommon::createContextFromType(CL_DEVICE_TYPE_CPU, &ciErrNum);
//try CL_DEVICE_TYPE_DEBUG for sequential, non-threaded execution, when using MiniCL on CPU, it gives a full callstack at the crash in the kernel
//#ifdef USE_MINICL
// g_cxMainContext = btOclCommon::createContextFromType(CL_DEVICE_TYPE_DEBUG, &ciErrNum);
//#else
g_cxMainContext = btOclCommon::createContextFromType(deviceType, &ciErrNum, glCtx, glDC);
//#endif
oclCHECKERROR(ciErrNum, CL_SUCCESS);
g_cdDevice = btOclGetMaxFlopsDev(g_cxMainContext);
if ( bDebug ) {
btOclPrintDevInfo(g_cdDevice);
}
// create a command-queue
g_cqCommandQue = clCreateCommandQueue(g_cxMainContext, g_cdDevice, 0, &ciErrNum);
oclCHECKERROR(ciErrNum, CL_SUCCESS);
return true;
}
#endif //#ifdef USE_AMD_OPENCL
int main(int argc,char** argv)
{
GLDebugDrawer gDebugDrawer;
#ifdef USE_AMD_OPENCL
bool initialized = initCL(0,0);
btAssert(initialized);
#endif //USE_AMD_OPENCL
///testing the btHashMap
btHashMap<btHashKey<OurValue>,OurValue> map;
OurValue value1(btVector3(2,3,4));
btHashKey<OurValue> key1(value1.getUid());
map.insert(key1,value1);
OurValue value2(btVector3(5,6,7));
btHashKey<OurValue> key2(value2.getUid());
map.insert(key2,value2);
{
OurValue value3(btVector3(7,8,9));
btHashKey<OurValue> key3(value3.getUid());
map.insert(key3,value3);
}
map.remove(key2);
// const OurValue* ourPtr = map.find(key1);
// for (int i=0;i<map.size();i++)
// {
// OurValue* tmp = map.getAtIndex(i);
// //printf("tmp value=%f,%f,%f\n",tmp->m_position.getX(),tmp->m_position.getY(),tmp->m_position.getZ());
// }
SerializeDemo ccdDemo;
ccdDemo.initPhysics();
ccdDemo.getDynamicsWorld()->setDebugDrawer(&gDebugDrawer);
SerializeDemo serializeDemo;
serializeDemo.initPhysics();
serializeDemo.getDynamicsWorld()->setDebugDrawer(&gDebugDrawer);
#ifdef CHECK_MEMORY_LEAKS
ccdDemo.exitPhysics();
serializeDemo.exitPhysics();
#else
return glutmain(argc, argv,640,480,"Bullet Physics Demo. http://bulletphysics.org",&ccdDemo);
return glutmain(argc, argv,640,480,"Bullet Physics Demo. http://bulletphysics.org",&serializeDemo);
#endif
//default glut doesn't return from mainloop

Binary file not shown.

View File

@@ -18,7 +18,7 @@ subject to the following restrictions:
#include "btOclCommon.h"
static const char* spPlatformVendor =
static char* spPlatformVendor =
#if defined(CL_PLATFORM_MINI_CL)
"MiniCL, SCEA";
#elif defined(CL_PLATFORM_INTEL)
@@ -37,6 +37,7 @@ static const char* spPlatformVendor =
#endif //_WIN32
#endif
cl_context btOclCommon::createContextFromType(cl_device_type deviceType, cl_int* pErrNum, void* pGLContext, void* pGLDC )
{
cl_uint numPlatforms;
@@ -91,8 +92,9 @@ cl_context btOclCommon::createContextFromType(cl_device_type deviceType, cl_int*
0,
0
};
#ifndef CL_PLATFORM_MINI_CL
#ifndef CL_PLATFORM_MINI_CL
#ifdef _WIN32
#ifndef BT_USE_CLEW
// If we have a gl context then enable interop
if( pGLContext )
{
@@ -101,7 +103,8 @@ cl_context btOclCommon::createContextFromType(cl_device_type deviceType, cl_int*
cps[4] = CL_WGL_HDC_KHR;
cps[5] = (cl_context_properties)pGLDC;
}
#endif
#endif // DONT_USE_CLEW
#endif //_WIN32
#endif //CL_PLATFORM_MINI_CL
/* Use NULL for backward compatibility */
@@ -115,3 +118,4 @@ cl_context btOclCommon::createContextFromType(cl_device_type deviceType, cl_int*
return retContext;
}

View File

@@ -16,20 +16,7 @@ subject to the following restrictions:
#ifndef BTOCLCOMMON_H
#define BTOCLCOMMON_H
#ifdef __APPLE__
#ifdef USE_MINICL
#include <MiniCL/cl.h>
#else
#include <OpenCL/cl.h>
#endif
#else
#ifdef USE_MINICL
#include <MiniCL/cl.h>
#else
#include <CL/cl.h>
#endif
#endif //__APPLE__
#include "btOclUtils.h"
class btOclCommon
{
@@ -38,8 +25,9 @@ public:
// to have to understand GL types.
// It is a HGLRC in _WIN32 or a GLXContext otherwise.
static cl_context createContextFromType(cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx = 0, void* pGLDC = 0);
};
#endif // BTOCLCOMMON_H
#endif // BTOCLCOMMON_H

View File

@@ -13,11 +13,14 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define myprintf printf
#include "btOclUtils.h"
@@ -56,92 +59,6 @@ cl_device_id btOclGetDev(cl_context cxMainContext, unsigned int nr)
//////////////////////////////////////////////////////////////////////////////
//! Gets the id of device with maximal FLOPS from the context
//!
//! @return the id
//! @param cxMainContext OpenCL context
//////////////////////////////////////////////////////////////////////////////
cl_device_id btOclGetMaxFlopsDev(cl_context cxMainContext)
{
size_t szParmDataBytes;
cl_device_id* cdDevices;
// get the list of GPU devices associated with context
clGetContextInfo(cxMainContext, CL_CONTEXT_DEVICES, 0, NULL, &szParmDataBytes);
cdDevices = (cl_device_id*) malloc(szParmDataBytes);
size_t device_count = szParmDataBytes / sizeof(cl_device_id);
clGetContextInfo(cxMainContext, CL_CONTEXT_DEVICES, szParmDataBytes, cdDevices, NULL);
cl_device_id max_flops_device = cdDevices[0];
int max_flops = 0;
size_t current_device = 0;
// CL_DEVICE_MAX_COMPUTE_UNITS
cl_uint compute_units;
clGetDeviceInfo(cdDevices[current_device], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(compute_units), &compute_units, NULL);
// CL_DEVICE_MAX_CLOCK_FREQUENCY
cl_uint clock_frequency;
clGetDeviceInfo(cdDevices[current_device], CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(clock_frequency), &clock_frequency, NULL);
cl_device_type device_type;
clGetDeviceInfo(cdDevices[current_device], CL_DEVICE_TYPE, sizeof(device_type), &device_type, NULL);
int SIMDmultiplier = 1;
if( device_type == CL_DEVICE_TYPE_CPU )
{
// For simplicity assume that the CPU is running single SSE instructions
// This will of course depend on the kernel
SIMDmultiplier = 4;
} else if( device_type == CL_DEVICE_TYPE_GPU ) {
// Approximation to GPU compute power
// As long as this beats the CPU number that's the important thing, really
#if defined(CL_PLATFORM_INTEL)
// SSE - 4, AVX1,2 - 8 : TODO: detect AVX?
SIMDmultiplier = 4;
#elif defined(CL_PLATFORM_AMD)
// 16 processing elements, 5 ALUs each
SIMDmultiplier = 80;
#elif defined(CL_PLATFORM_NVIDIA)
// 8 processing elements, dual issue - pre-Fermi at least
SIMDmultiplier = 16;
#else
SIMDmultiplier = 1;
#endif
}
max_flops = compute_units * clock_frequency * SIMDmultiplier;
++current_device;
while( current_device < device_count )
{
// CL_DEVICE_MAX_COMPUTE_UNITS
cl_uint compute_units;
clGetDeviceInfo(cdDevices[current_device], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(compute_units), &compute_units, NULL);
// CL_DEVICE_MAX_CLOCK_FREQUENCY
cl_uint clock_frequency;
clGetDeviceInfo(cdDevices[current_device], CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(clock_frequency), &clock_frequency, NULL);
int flops = compute_units * clock_frequency;
if( flops > max_flops )
{
max_flops = flops;
max_flops_device = cdDevices[current_device];
}
++current_device;
}
free(cdDevices);
return max_flops_device;
}
//////////////////////////////////////////////////////////////////////////////
//! Loads a Program file and prepends the cPreamble to the code.
@@ -221,140 +138,139 @@ cl_device_id btOclGetFirstDev(cl_context cxMainContext)
void btOclPrintDevInfo(cl_device_id device)
{
char device_string[1024];
bool nv_device_attibute_query = false;
// CL_DEVICE_NAME
clGetDeviceInfo(device, CL_DEVICE_NAME, sizeof(device_string), &device_string, NULL);
printf(" CL_DEVICE_NAME: \t\t\t%s\n", device_string);
myprintf(" CL_DEVICE_NAME: \t\t\t%s\n", device_string);
// CL_DEVICE_VENDOR
clGetDeviceInfo(device, CL_DEVICE_VENDOR, sizeof(device_string), &device_string, NULL);
printf(" CL_DEVICE_VENDOR: \t\t\t%s\n", device_string);
myprintf(" CL_DEVICE_VENDOR: \t\t\t%s\n", device_string);
// CL_DRIVER_VERSION
clGetDeviceInfo(device, CL_DRIVER_VERSION, sizeof(device_string), &device_string, NULL);
printf(" CL_DRIVER_VERSION: \t\t\t%s\n", device_string);
myprintf(" CL_DRIVER_VERSION: \t\t\t%s\n", device_string);
// CL_DEVICE_INFO
cl_device_type type;
clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(type), &type, NULL);
if( type & CL_DEVICE_TYPE_CPU )
printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_CPU");
myprintf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_CPU");
if( type & CL_DEVICE_TYPE_GPU )
printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_GPU");
myprintf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_GPU");
if( type & CL_DEVICE_TYPE_ACCELERATOR )
printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_ACCELERATOR");
myprintf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_ACCELERATOR");
if( type & CL_DEVICE_TYPE_DEFAULT )
printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_DEFAULT");
myprintf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_DEFAULT");
// CL_DEVICE_MAX_COMPUTE_UNITS
cl_uint compute_units;
clGetDeviceInfo(device, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(compute_units), &compute_units, NULL);
printf(" CL_DEVICE_MAX_COMPUTE_UNITS:\t\t%u\n", compute_units);
myprintf(" CL_DEVICE_MAX_COMPUTE_UNITS:\t\t%u\n", compute_units);
// CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS
size_t workitem_dims;
clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(workitem_dims), &workitem_dims, NULL);
printf(" CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS:\t%d\n", workitem_dims);
myprintf(" CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS:\t%u\n", workitem_dims);
// CL_DEVICE_MAX_WORK_ITEM_SIZES
size_t workitem_size[3];
clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(workitem_size), &workitem_size, NULL);
printf(" CL_DEVICE_MAX_WORK_ITEM_SIZES:\t%d / %d / %d \n", workitem_size[0], workitem_size[1], workitem_size[2]);
myprintf(" CL_DEVICE_MAX_WORK_ITEM_SIZES:\t%u / %u / %u \n", workitem_size[0], workitem_size[1], workitem_size[2]);
// CL_DEVICE_MAX_WORK_GROUP_SIZE
size_t workgroup_size;
clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(workgroup_size), &workgroup_size, NULL);
printf(" CL_DEVICE_MAX_WORK_GROUP_SIZE:\t%d\n", workgroup_size);
myprintf(" CL_DEVICE_MAX_WORK_GROUP_SIZE:\t%u\n", workgroup_size);
// CL_DEVICE_MAX_CLOCK_FREQUENCY
cl_uint clock_frequency;
clGetDeviceInfo(device, CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(clock_frequency), &clock_frequency, NULL);
printf(" CL_DEVICE_MAX_CLOCK_FREQUENCY:\t%u MHz\n", clock_frequency);
myprintf(" CL_DEVICE_MAX_CLOCK_FREQUENCY:\t%u MHz\n", clock_frequency);
// CL_DEVICE_ADDRESS_BITS
cl_uint addr_bits;
clGetDeviceInfo(device, CL_DEVICE_ADDRESS_BITS, sizeof(addr_bits), &addr_bits, NULL);
printf(" CL_DEVICE_ADDRESS_BITS:\t\t%u\n", addr_bits);
myprintf(" CL_DEVICE_ADDRESS_BITS:\t\t%u\n", addr_bits);
// CL_DEVICE_MAX_MEM_ALLOC_SIZE
cl_ulong max_mem_alloc_size;
clGetDeviceInfo(device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(max_mem_alloc_size), &max_mem_alloc_size, NULL);
printf(" CL_DEVICE_MAX_MEM_ALLOC_SIZE:\t\t%u MByte\n", (unsigned int)(max_mem_alloc_size / (1024 * 1024)));
myprintf(" CL_DEVICE_MAX_MEM_ALLOC_SIZE:\t\t%u MByte\n", (unsigned int)(max_mem_alloc_size / (1024 * 1024)));
// CL_DEVICE_GLOBAL_MEM_SIZE
cl_ulong mem_size;
clGetDeviceInfo(device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(mem_size), &mem_size, NULL);
printf(" CL_DEVICE_GLOBAL_MEM_SIZE:\t\t%u MByte\n", (unsigned int)(mem_size / (1024 * 1024)));
myprintf(" CL_DEVICE_GLOBAL_MEM_SIZE:\t\t%u MByte\n", (unsigned int)(mem_size / (1024 * 1024)));
// CL_DEVICE_ERROR_CORRECTION_SUPPORT
cl_bool error_correction_support;
clGetDeviceInfo(device, CL_DEVICE_ERROR_CORRECTION_SUPPORT, sizeof(error_correction_support), &error_correction_support, NULL);
printf(" CL_DEVICE_ERROR_CORRECTION_SUPPORT:\t%s\n", error_correction_support == CL_TRUE ? "yes" : "no");
myprintf(" CL_DEVICE_ERROR_CORRECTION_SUPPORT:\t%s\n", error_correction_support == CL_TRUE ? "yes" : "no");
// CL_DEVICE_LOCAL_MEM_TYPE
cl_device_local_mem_type local_mem_type;
clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_TYPE, sizeof(local_mem_type), &local_mem_type, NULL);
printf(" CL_DEVICE_LOCAL_MEM_TYPE:\t\t%s\n", local_mem_type == 1 ? "local" : "global");
myprintf(" CL_DEVICE_LOCAL_MEM_TYPE:\t\t%s\n", local_mem_type == 1 ? "local" : "global");
// CL_DEVICE_LOCAL_MEM_SIZE
clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(mem_size), &mem_size, NULL);
printf(" CL_DEVICE_LOCAL_MEM_SIZE:\t\t%u KByte\n", (unsigned int)(mem_size / 1024));
myprintf(" CL_DEVICE_LOCAL_MEM_SIZE:\t\t%u KByte\n", (unsigned int)(mem_size / 1024));
// CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE
clGetDeviceInfo(device, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof(mem_size), &mem_size, NULL);
printf(" CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE:\t%u KByte\n", (unsigned int)(mem_size / 1024));
myprintf(" CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE:\t%u KByte\n", (unsigned int)(mem_size / 1024));
// CL_DEVICE_QUEUE_PROPERTIES
cl_command_queue_properties queue_properties;
clGetDeviceInfo(device, CL_DEVICE_QUEUE_PROPERTIES, sizeof(queue_properties), &queue_properties, NULL);
if( queue_properties & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE )
printf(" CL_DEVICE_QUEUE_PROPERTIES:\t\t%s\n", "CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE");
myprintf(" CL_DEVICE_QUEUE_PROPERTIES:\t\t%s\n", "CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE");
if( queue_properties & CL_QUEUE_PROFILING_ENABLE )
printf(" CL_DEVICE_QUEUE_PROPERTIES:\t\t%s\n", "CL_QUEUE_PROFILING_ENABLE");
myprintf(" CL_DEVICE_QUEUE_PROPERTIES:\t\t%s\n", "CL_QUEUE_PROFILING_ENABLE");
// CL_DEVICE_IMAGE_SUPPORT
cl_bool image_support;
clGetDeviceInfo(device, CL_DEVICE_IMAGE_SUPPORT, sizeof(image_support), &image_support, NULL);
printf(" CL_DEVICE_IMAGE_SUPPORT:\t\t%u\n", image_support);
myprintf(" CL_DEVICE_IMAGE_SUPPORT:\t\t%u\n", image_support);
// CL_DEVICE_MAX_READ_IMAGE_ARGS
cl_uint max_read_image_args;
clGetDeviceInfo(device, CL_DEVICE_MAX_READ_IMAGE_ARGS, sizeof(max_read_image_args), &max_read_image_args, NULL);
printf(" CL_DEVICE_MAX_READ_IMAGE_ARGS:\t%u\n", max_read_image_args);
myprintf(" CL_DEVICE_MAX_READ_IMAGE_ARGS:\t%u\n", max_read_image_args);
// CL_DEVICE_MAX_WRITE_IMAGE_ARGS
cl_uint max_write_image_args;
clGetDeviceInfo(device, CL_DEVICE_MAX_WRITE_IMAGE_ARGS, sizeof(max_write_image_args), &max_write_image_args, NULL);
printf(" CL_DEVICE_MAX_WRITE_IMAGE_ARGS:\t%u\n", max_write_image_args);
myprintf(" CL_DEVICE_MAX_WRITE_IMAGE_ARGS:\t%u\n", max_write_image_args);
// CL_DEVICE_IMAGE2D_MAX_WIDTH, CL_DEVICE_IMAGE2D_MAX_HEIGHT, CL_DEVICE_IMAGE3D_MAX_WIDTH, CL_DEVICE_IMAGE3D_MAX_HEIGHT, CL_DEVICE_IMAGE3D_MAX_DEPTH
size_t szMaxDims[5];
printf("\n CL_DEVICE_IMAGE <dim>");
myprintf("\n CL_DEVICE_IMAGE <dim>\n");
clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof(size_t), &szMaxDims[0], NULL);
printf("\t\t\t2D_MAX_WIDTH\t %d\n", szMaxDims[0]);
myprintf("\t\t\t2D_MAX_WIDTH\t %u\n", szMaxDims[0]);
clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof(size_t), &szMaxDims[1], NULL);
printf("\t\t\t\t\t2D_MAX_HEIGHT\t %d\n", szMaxDims[1]);
myprintf("\t\t\t\t\t2D_MAX_HEIGHT\t %u\n", szMaxDims[1]);
clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof(size_t), &szMaxDims[2], NULL);
printf("\t\t\t\t\t3D_MAX_WIDTH\t %d\n", szMaxDims[2]);
myprintf("\t\t\t\t\t3D_MAX_WIDTH\t %u\n", szMaxDims[2]);
clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof(size_t), &szMaxDims[3], NULL);
printf("\t\t\t\t\t3D_MAX_HEIGHT\t %d\n", szMaxDims[3]);
myprintf("\t\t\t\t\t3D_MAX_HEIGHT\t %u\n", szMaxDims[3]);
clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof(size_t), &szMaxDims[4], NULL);
printf("\t\t\t\t\t3D_MAX_DEPTH\t %d\n", szMaxDims[4]);
myprintf("\t\t\t\t\t3D_MAX_DEPTH\t %u\n", szMaxDims[4]);
// CL_DEVICE_EXTENSIONS: get device extensions, and if any then parse & log the string onto separate lines
clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, sizeof(device_string), &device_string, NULL);
if (device_string != 0)
{
printf("\n CL_DEVICE_EXTENSIONS:%s\n",device_string);
myprintf("\n CL_DEVICE_EXTENSIONS:%s\n",device_string);
}
else
{
printf(" CL_DEVICE_EXTENSIONS: None\n");
myprintf(" CL_DEVICE_EXTENSIONS: None\n");
}
// CL_DEVICE_PREFERRED_VECTOR_WIDTH_<type>
printf(" CL_DEVICE_PREFERRED_VECTOR_WIDTH_<t>\t");
myprintf(" CL_DEVICE_PREFERRED_VECTOR_WIDTH_<t>\t\n");
cl_uint vec_width [6];
clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, sizeof(cl_uint), &vec_width[0], NULL);
clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT, sizeof(cl_uint), &vec_width[1], NULL);
@@ -362,6 +278,7 @@ void btOclPrintDevInfo(cl_device_id device)
clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG, sizeof(cl_uint), &vec_width[3], NULL);
clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, sizeof(cl_uint), &vec_width[4], NULL);
clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE, sizeof(cl_uint), &vec_width[5], NULL);
printf("CHAR %u, SHORT %u, INT %u, FLOAT %u, DOUBLE %u\n\n\n",
myprintf("CHAR %u, SHORT %u, INT %u, FLOAT %u, DOUBLE %u\n\n",
vec_width[0], vec_width[1], vec_width[2], vec_width[3], vec_width[4]);
}

View File

@@ -18,15 +18,17 @@ subject to the following restrictions:
#ifdef USE_MINICL
#include <MiniCL/cl.h>
#else //USE_MINICL
#ifdef BT_USE_CLEW
#include "clew.h"
#else
#ifdef __APPLE__
#include <OpenCL/cl.h>
#else
#include <CL/cl.h>
#endif __APPLE__
#endif
#include <stdio.h>
#ifdef __APPLE__
#include <OpenCL/cl.h>
#else
#include <CL/cl.h>
#endif //__APPLE__
#endif //BT_USE_CLEW
#endif //USE_MINICL
//#define oclCHECKERROR(a, b) btAssert((a) == (b))
@@ -35,7 +37,6 @@ subject to the following restrictions:
void btOclPrintDevInfo(cl_device_id device);
cl_device_id btOclGetDev(cl_context cxMainContext, unsigned int nr);
cl_device_id btOclGetMaxFlopsDev(cl_context cxMainContext);
char* btOclLoadProgSource(const char* cFilename, const char* cPreamble, size_t* szFinalLength);
cl_device_id btOclGetFirstDev(cl_context cxMainContext);
#endif //BT_OCL_UTILS_H

313
Demos/SharedOpenCL/clew.c Normal file
View File

@@ -0,0 +1,313 @@
//////////////////////////////////////////////////////////////////////////
// Copyright (c) 2009 Organic Vectory B.V.
// Written by George van Venrooij
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file license.txt)
//////////////////////////////////////////////////////////////////////////
#ifndef USE_MINICL
#include "clew.h"
//! \file clew.c
//! \brief OpenCL run-time loader source
#ifndef CLCC_GENERATE_DOCUMENTATION
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN
#define NOMINMAX
#include <windows.h>
typedef HMODULE CLCC_DYNLIB_HANDLE;
#define CLCC_DYNLIB_OPEN LoadLibrary
#define CLCC_DYNLIB_CLOSE FreeLibrary
#define CLCC_DYNLIB_IMPORT GetProcAddress
#else
#include <dlfcn.h>
typedef void* CLCC_DYNLIB_HANDLE;
#define CLCC_DYNLIB_OPEN(path) dlopen(path, RTLD_NOW | RTLD_GLOBAL)
#define CLCC_DYNLIB_CLOSE dlclose
#define CLCC_DYNLIB_IMPORT dlsym
#endif
#else
//typedef implementation_defined CLCC_DYNLIB_HANDLE;
//#define CLCC_DYNLIB_OPEN(path) implementation_defined
//#define CLCC_DYNLIB_CLOSE implementation_defined
//#define CLCC_DYNLIB_IMPORT implementation_defined
#endif
#include <stdlib.h>
//! \brief module handle
static CLCC_DYNLIB_HANDLE module = NULL;
// Variables holding function entry points
#ifndef CLCC_GENERATE_DOCUMENTATION
PFNCLGETPLATFORMIDS __clewGetPlatformIDs = NULL;
PFNCLGETPLATFORMINFO __clewGetPlatformInfo = NULL;
PFNCLGETDEVICEIDS __clewGetDeviceIDs = NULL;
PFNCLGETDEVICEINFO __clewGetDeviceInfo = NULL;
PFNCLCREATECONTEXT __clewCreateContext = NULL;
PFNCLCREATECONTEXTFROMTYPE __clewCreateContextFromType = NULL;
PFNCLRETAINCONTEXT __clewRetainContext = NULL;
PFNCLRELEASECONTEXT __clewReleaseContext = NULL;
PFNCLGETCONTEXTINFO __clewGetContextInfo = NULL;
PFNCLCREATECOMMANDQUEUE __clewCreateCommandQueue = NULL;
PFNCLRETAINCOMMANDQUEUE __clewRetainCommandQueue = NULL;
PFNCLRELEASECOMMANDQUEUE __clewReleaseCommandQueue = NULL;
PFNCLGETCOMMANDQUEUEINFO __clewGetCommandQueueInfo = NULL;
PFNCLSETCOMMANDQUEUEPROPERTY __clewSetCommandQueueProperty = NULL;
PFNCLCREATEBUFFER __clewCreateBuffer = NULL;
PFNCLCREATEIMAGE2D __clewCreateImage2D = NULL;
PFNCLCREATEIMAGE3D __clewCreateImage3D = NULL;
PFNCLRETAINMEMOBJECT __clewRetainMemObject = NULL;
PFNCLRELEASEMEMOBJECT __clewReleaseMemObject = NULL;
PFNCLGETSUPPORTEDIMAGEFORMATS __clewGetSupportedImageFormats = NULL;
PFNCLGETMEMOBJECTINFO __clewGetMemObjectInfo = NULL;
PFNCLGETIMAGEINFO __clewGetImageInfo = NULL;
PFNCLCREATESAMPLER __clewCreateSampler = NULL;
PFNCLRETAINSAMPLER __clewRetainSampler = NULL;
PFNCLRELEASESAMPLER __clewReleaseSampler = NULL;
PFNCLGETSAMPLERINFO __clewGetSamplerInfo = NULL;
PFNCLCREATEPROGRAMWITHSOURCE __clewCreateProgramWithSource = NULL;
PFNCLCREATEPROGRAMWITHBINARY __clewCreateProgramWithBinary = NULL;
PFNCLRETAINPROGRAM __clewRetainProgram = NULL;
PFNCLRELEASEPROGRAM __clewReleaseProgram = NULL;
PFNCLBUILDPROGRAM __clewBuildProgram = NULL;
PFNCLUNLOADCOMPILER __clewUnloadCompiler = NULL;
PFNCLGETPROGRAMINFO __clewGetProgramInfo = NULL;
PFNCLGETPROGRAMBUILDINFO __clewGetProgramBuildInfo = NULL;
PFNCLCREATEKERNEL __clewCreateKernel = NULL;
PFNCLCREATEKERNELSINPROGRAM __clewCreateKernelsInProgram = NULL;
PFNCLRETAINKERNEL __clewRetainKernel = NULL;
PFNCLRELEASEKERNEL __clewReleaseKernel = NULL;
PFNCLSETKERNELARG __clewSetKernelArg = NULL;
PFNCLGETKERNELINFO __clewGetKernelInfo = NULL;
PFNCLGETKERNELWORKGROUPINFO __clewGetKernelWorkGroupInfo = NULL;
PFNCLWAITFOREVENTS __clewWaitForEvents = NULL;
PFNCLGETEVENTINFO __clewGetEventInfo = NULL;
PFNCLRETAINEVENT __clewRetainEvent = NULL;
PFNCLRELEASEEVENT __clewReleaseEvent = NULL;
PFNCLGETEVENTPROFILINGINFO __clewGetEventProfilingInfo = NULL;
PFNCLFLUSH __clewFlush = NULL;
PFNCLFINISH __clewFinish = NULL;
PFNCLENQUEUEREADBUFFER __clewEnqueueReadBuffer = NULL;
PFNCLENQUEUEWRITEBUFFER __clewEnqueueWriteBuffer = NULL;
PFNCLENQUEUECOPYBUFFER __clewEnqueueCopyBuffer = NULL;
PFNCLENQUEUEREADIMAGE __clewEnqueueReadImage = NULL;
PFNCLENQUEUEWRITEIMAGE __clewEnqueueWriteImage = NULL;
PFNCLENQUEUECOPYIMAGE __clewEnqueueCopyImage = NULL;
PFNCLENQUEUECOPYIMAGETOBUFFER __clewEnqueueCopyImageToBuffer = NULL;
PFNCLENQUEUECOPYBUFFERTOIMAGE __clewEnqueueCopyBufferToImage = NULL;
PFNCLENQUEUEMAPBUFFER __clewEnqueueMapBuffer = NULL;
PFNCLENQUEUEMAPIMAGE __clewEnqueueMapImage = NULL;
PFNCLENQUEUEUNMAPMEMOBJECT __clewEnqueueUnmapMemObject = NULL;
PFNCLENQUEUENDRANGEKERNEL __clewEnqueueNDRangeKernel = NULL;
PFNCLENQUEUETASK __clewEnqueueTask = NULL;
PFNCLENQUEUENATIVEKERNEL __clewEnqueueNativeKernel = NULL;
PFNCLENQUEUEMARKER __clewEnqueueMarker = NULL;
PFNCLENQUEUEWAITFOREVENTS __clewEnqueueWaitForEvents = NULL;
PFNCLENQUEUEBARRIER __clewEnqueueBarrier = NULL;
PFNCLGETEXTENSIONFUNCTIONADDRESS __clewGetExtensionFunctionAddress = NULL;
#endif // CLCC_GENERATE_DOCUMENTATION
//! \brief Unloads OpenCL dynamic library, should not be called directly
static void clewExit(void)
{
if (module != NULL)
{
// Ignore errors
CLCC_DYNLIB_CLOSE(module);
module = NULL;
}
}
//! \param path path to dynamic library to load
//! \return CLEW_ERROR_OPEN_FAILED if the library could not be opened
//! CLEW_ERROR_ATEXIT_FAILED if atexit(clewExit) failed
//! CLEW_SUCCESS when the library was succesfully loaded
int clewInit(const char* path)
{
int error = 0;
// Check if already initialized
if (module != NULL)
{
return CLEW_SUCCESS;
}
// Load library
module = CLCC_DYNLIB_OPEN(path);
// Check for errors
if (module == NULL)
{
return CLEW_ERROR_OPEN_FAILED;
}
// Set unloading
error = atexit(clewExit);
if (error)
{
// Failure queing atexit, shutdown with error
CLCC_DYNLIB_CLOSE(module);
module = NULL;
return CLEW_ERROR_ATEXIT_FAILED;
}
// Determine function entry-points
__clewGetPlatformIDs = (PFNCLGETPLATFORMIDS )CLCC_DYNLIB_IMPORT(module, "clGetPlatformIDs");
__clewGetPlatformInfo = (PFNCLGETPLATFORMINFO )CLCC_DYNLIB_IMPORT(module, "clGetPlatformInfo");
__clewGetDeviceIDs = (PFNCLGETDEVICEIDS )CLCC_DYNLIB_IMPORT(module, "clGetDeviceIDs");
__clewGetDeviceInfo = (PFNCLGETDEVICEINFO )CLCC_DYNLIB_IMPORT(module, "clGetDeviceInfo");
__clewCreateContext = (PFNCLCREATECONTEXT )CLCC_DYNLIB_IMPORT(module, "clCreateContext");
__clewCreateContextFromType = (PFNCLCREATECONTEXTFROMTYPE )CLCC_DYNLIB_IMPORT(module, "clCreateContextFromType");
__clewRetainContext = (PFNCLRETAINCONTEXT )CLCC_DYNLIB_IMPORT(module, "clRetainContext");
__clewReleaseContext = (PFNCLRELEASECONTEXT )CLCC_DYNLIB_IMPORT(module, "clReleaseContext");
__clewGetContextInfo = (PFNCLGETCONTEXTINFO )CLCC_DYNLIB_IMPORT(module, "clGetContextInfo");
__clewCreateCommandQueue = (PFNCLCREATECOMMANDQUEUE )CLCC_DYNLIB_IMPORT(module, "clCreateCommandQueue");
__clewRetainCommandQueue = (PFNCLRETAINCOMMANDQUEUE )CLCC_DYNLIB_IMPORT(module, "clRetainCommandQueue");
__clewReleaseCommandQueue = (PFNCLRELEASECOMMANDQUEUE )CLCC_DYNLIB_IMPORT(module, "clReleaseCommandQueue");
__clewGetCommandQueueInfo = (PFNCLGETCOMMANDQUEUEINFO )CLCC_DYNLIB_IMPORT(module, "clGetCommandQueueInfo");
__clewSetCommandQueueProperty = (PFNCLSETCOMMANDQUEUEPROPERTY )CLCC_DYNLIB_IMPORT(module, "clSetCommandQueueProperty");
__clewCreateBuffer = (PFNCLCREATEBUFFER )CLCC_DYNLIB_IMPORT(module, "clCreateBuffer");
__clewCreateImage2D = (PFNCLCREATEIMAGE2D )CLCC_DYNLIB_IMPORT(module, "clCreateImage2D");
__clewCreateImage3D = (PFNCLCREATEIMAGE3D )CLCC_DYNLIB_IMPORT(module, "clCreateImage3D");
__clewRetainMemObject = (PFNCLRETAINMEMOBJECT )CLCC_DYNLIB_IMPORT(module, "clRetainMemObject");
__clewReleaseMemObject = (PFNCLRELEASEMEMOBJECT )CLCC_DYNLIB_IMPORT(module, "clReleaseMemObject");
__clewGetSupportedImageFormats = (PFNCLGETSUPPORTEDIMAGEFORMATS )CLCC_DYNLIB_IMPORT(module, "clGetSupportedImageFormats");
__clewGetMemObjectInfo = (PFNCLGETMEMOBJECTINFO )CLCC_DYNLIB_IMPORT(module, "clGetMemObjectInfo");
__clewGetImageInfo = (PFNCLGETIMAGEINFO )CLCC_DYNLIB_IMPORT(module, "clGetImageInfo");
__clewCreateSampler = (PFNCLCREATESAMPLER )CLCC_DYNLIB_IMPORT(module, "clCreateSampler");
__clewRetainSampler = (PFNCLRETAINSAMPLER )CLCC_DYNLIB_IMPORT(module, "clRetainSampler");
__clewReleaseSampler = (PFNCLRELEASESAMPLER )CLCC_DYNLIB_IMPORT(module, "clReleaseSampler");
__clewGetSamplerInfo = (PFNCLGETSAMPLERINFO )CLCC_DYNLIB_IMPORT(module, "clGetSamplerInfo");
__clewCreateProgramWithSource = (PFNCLCREATEPROGRAMWITHSOURCE )CLCC_DYNLIB_IMPORT(module, "clCreateProgramWithSource");
__clewCreateProgramWithBinary = (PFNCLCREATEPROGRAMWITHBINARY )CLCC_DYNLIB_IMPORT(module, "clCreateProgramWithBinary");
__clewRetainProgram = (PFNCLRETAINPROGRAM )CLCC_DYNLIB_IMPORT(module, "clRetainProgram");
__clewReleaseProgram = (PFNCLRELEASEPROGRAM )CLCC_DYNLIB_IMPORT(module, "clReleaseProgram");
__clewBuildProgram = (PFNCLBUILDPROGRAM )CLCC_DYNLIB_IMPORT(module, "clBuildProgram");
__clewUnloadCompiler = (PFNCLUNLOADCOMPILER )CLCC_DYNLIB_IMPORT(module, "clUnloadCompiler");
__clewGetProgramInfo = (PFNCLGETPROGRAMINFO )CLCC_DYNLIB_IMPORT(module, "clGetProgramInfo");
__clewGetProgramBuildInfo = (PFNCLGETPROGRAMBUILDINFO )CLCC_DYNLIB_IMPORT(module, "clGetProgramBuildInfo");
__clewCreateKernel = (PFNCLCREATEKERNEL )CLCC_DYNLIB_IMPORT(module, "clCreateKernel");
__clewCreateKernelsInProgram = (PFNCLCREATEKERNELSINPROGRAM )CLCC_DYNLIB_IMPORT(module, "clCreateKernelsInProgram");
__clewRetainKernel = (PFNCLRETAINKERNEL )CLCC_DYNLIB_IMPORT(module, "clRetainKernel");
__clewReleaseKernel = (PFNCLRELEASEKERNEL )CLCC_DYNLIB_IMPORT(module, "clReleaseKernel");
__clewSetKernelArg = (PFNCLSETKERNELARG )CLCC_DYNLIB_IMPORT(module, "clSetKernelArg");
__clewGetKernelInfo = (PFNCLGETKERNELINFO )CLCC_DYNLIB_IMPORT(module, "clGetKernelInfo");
__clewGetKernelWorkGroupInfo = (PFNCLGETKERNELWORKGROUPINFO )CLCC_DYNLIB_IMPORT(module, "clGetKernelWorkGroupInfo");
__clewWaitForEvents = (PFNCLWAITFOREVENTS )CLCC_DYNLIB_IMPORT(module, "clWaitForEvents");
__clewGetEventInfo = (PFNCLGETEVENTINFO )CLCC_DYNLIB_IMPORT(module, "clGetEventInfo");
__clewRetainEvent = (PFNCLRETAINEVENT )CLCC_DYNLIB_IMPORT(module, "clRetainEvent");
__clewReleaseEvent = (PFNCLRELEASEEVENT )CLCC_DYNLIB_IMPORT(module, "clReleaseEvent");
__clewGetEventProfilingInfo = (PFNCLGETEVENTPROFILINGINFO )CLCC_DYNLIB_IMPORT(module, "clGetEventProfilingInfo");
__clewFlush = (PFNCLFLUSH )CLCC_DYNLIB_IMPORT(module, "clFlush");
__clewFinish = (PFNCLFINISH )CLCC_DYNLIB_IMPORT(module, "clFinish");
__clewEnqueueReadBuffer = (PFNCLENQUEUEREADBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueReadBuffer");
__clewEnqueueWriteBuffer = (PFNCLENQUEUEWRITEBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueWriteBuffer");
__clewEnqueueCopyBuffer = (PFNCLENQUEUECOPYBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyBuffer");
__clewEnqueueReadImage = (PFNCLENQUEUEREADIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueReadImage");
__clewEnqueueWriteImage = (PFNCLENQUEUEWRITEIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueWriteImage");
__clewEnqueueCopyImage = (PFNCLENQUEUECOPYIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyImage");
__clewEnqueueCopyImageToBuffer = (PFNCLENQUEUECOPYIMAGETOBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyImageToBuffer");
__clewEnqueueCopyBufferToImage = (PFNCLENQUEUECOPYBUFFERTOIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyBufferToImage");
__clewEnqueueMapBuffer = (PFNCLENQUEUEMAPBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueMapBuffer");
__clewEnqueueMapImage = (PFNCLENQUEUEMAPIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueMapImage");
__clewEnqueueUnmapMemObject = (PFNCLENQUEUEUNMAPMEMOBJECT )CLCC_DYNLIB_IMPORT(module, "clEnqueueUnmapMemObject");
__clewEnqueueNDRangeKernel = (PFNCLENQUEUENDRANGEKERNEL )CLCC_DYNLIB_IMPORT(module, "clEnqueueNDRangeKernel");
__clewEnqueueTask = (PFNCLENQUEUETASK )CLCC_DYNLIB_IMPORT(module, "clEnqueueTask");
__clewEnqueueNativeKernel = (PFNCLENQUEUENATIVEKERNEL )CLCC_DYNLIB_IMPORT(module, "clEnqueueNativeKernel");
__clewEnqueueMarker = (PFNCLENQUEUEMARKER )CLCC_DYNLIB_IMPORT(module, "clEnqueueMarker");
__clewEnqueueWaitForEvents = (PFNCLENQUEUEWAITFOREVENTS )CLCC_DYNLIB_IMPORT(module, "clEnqueueWaitForEvents");
__clewEnqueueBarrier = (PFNCLENQUEUEBARRIER )CLCC_DYNLIB_IMPORT(module, "clEnqueueBarrier");
__clewGetExtensionFunctionAddress = (PFNCLGETEXTENSIONFUNCTIONADDRESS )CLCC_DYNLIB_IMPORT(module, "clGetExtensionFunctionAddress");
return CLEW_SUCCESS;
}
//! \param error CL error code
//! \return a string representation of the error code
const char* clewErrorString(cl_int error)
{
static const char* strings[] =
{
// Error Codes
"CL_SUCCESS" // 0
, "CL_DEVICE_NOT_FOUND" // -1
, "CL_DEVICE_NOT_AVAILABLE" // -2
, "CL_COMPILER_NOT_AVAILABLE" // -3
, "CL_MEM_OBJECT_ALLOCATION_FAILURE" // -4
, "CL_OUT_OF_RESOURCES" // -5
, "CL_OUT_OF_HOST_MEMORY" // -6
, "CL_PROFILING_INFO_NOT_AVAILABLE" // -7
, "CL_MEM_COPY_OVERLAP" // -8
, "CL_IMAGE_FORMAT_MISMATCH" // -9
, "CL_IMAGE_FORMAT_NOT_SUPPORTED" // -10
, "CL_BUILD_PROGRAM_FAILURE" // -11
, "CL_MAP_FAILURE" // -12
, "" // -13
, "" // -14
, "" // -15
, "" // -16
, "" // -17
, "" // -18
, "" // -19
, "" // -20
, "" // -21
, "" // -22
, "" // -23
, "" // -24
, "" // -25
, "" // -26
, "" // -27
, "" // -28
, "" // -29
, "CL_INVALID_VALUE" // -30
, "CL_INVALID_DEVICE_TYPE" // -31
, "CL_INVALID_PLATFORM" // -32
, "CL_INVALID_DEVICE" // -33
, "CL_INVALID_CONTEXT" // -34
, "CL_INVALID_QUEUE_PROPERTIES" // -35
, "CL_INVALID_COMMAND_QUEUE" // -36
, "CL_INVALID_HOST_PTR" // -37
, "CL_INVALID_MEM_OBJECT" // -38
, "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR" // -39
, "CL_INVALID_IMAGE_SIZE" // -40
, "CL_INVALID_SAMPLER" // -41
, "CL_INVALID_BINARY" // -42
, "CL_INVALID_BUILD_OPTIONS" // -43
, "CL_INVALID_PROGRAM" // -44
, "CL_INVALID_PROGRAM_EXECUTABLE" // -45
, "CL_INVALID_KERNEL_NAME" // -46
, "CL_INVALID_KERNEL_DEFINITION" // -47
, "CL_INVALID_KERNEL" // -48
, "CL_INVALID_ARG_INDEX" // -49
, "CL_INVALID_ARG_VALUE" // -50
, "CL_INVALID_ARG_SIZE" // -51
, "CL_INVALID_KERNEL_ARGS" // -52
, "CL_INVALID_WORK_DIMENSION" // -53
, "CL_INVALID_WORK_GROUP_SIZE" // -54
, "CL_INVALID_WORK_ITEM_SIZE" // -55
, "CL_INVALID_GLOBAL_OFFSET" // -56
, "CL_INVALID_EVENT_WAIT_LIST" // -57
, "CL_INVALID_EVENT" // -58
, "CL_INVALID_OPERATION" // -59
, "CL_INVALID_GL_OBJECT" // -60
, "CL_INVALID_BUFFER_SIZE" // -61
, "CL_INVALID_MIP_LEVEL" // -62
, "CL_INVALID_GLOBAL_WORK_SIZE" // -63
};
return strings[-error];
}
#endif

1316
Demos/SharedOpenCL/clew.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,6 @@ ${BULLET_PHYSICS_SOURCE_DIR}/src
SUBDIRS (
OpenCL
CPU
)
IF( USE_DX11 )

View File

@@ -1,42 +0,0 @@
INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/src
${VECTOR_MATH_INCLUDE}
)
SET(BulletSoftBodyCPUSolvers_SRCS
btSoftBodySolver_CPU.cpp
)
SET(BulletSoftBodyCPUSolvers_HDRS
btSoftBodySolver_CPU.h
btSoftBodySolverData.h
)
ADD_LIBRARY(BulletSoftBodySolvers_CPU ${BulletSoftBodyCPUSolvers_SRCS} ${BulletSoftBodyCPUSolvers_HDRS} )
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_CPU PROPERTIES VERSION ${BULLET_VERSION})
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_CPU PROPERTIES SOVERSION ${BULLET_VERSION})
IF (BUILD_SHARED_LIBS)
TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_CPU 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_CPU DESTINATION .)
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS BulletSoftBodySolvers_CPU 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_CPU PROPERTIES FRAMEWORK true)
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_CPU PROPERTIES PUBLIC_HEADER "${BulletSoftBodyCPUSolvers_HDRS}")
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
ENDIF (INSTALL_LIBS)

View File

@@ -1,979 +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 "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "vectormath/vmInclude.h"
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolver_CPU.h"
#include "BulletSoftBody/btSoftBody.h"
#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
btCPUSoftBodySolver::btCPUSoftBodySolver()
{
// Initial we will clearly need to update solver constants
// For now this is global for the cloths linked with this solver - we should probably make this body specific
// for performance in future once we understand more clearly when constants need to be updated
m_updateSolverConstants = true;
}
btCPUSoftBodySolver::~btCPUSoftBodySolver()
{
}
btSoftBodyLinkData &btCPUSoftBodySolver::getLinkData()
{
return m_linkData;
}
btSoftBodyVertexData &btCPUSoftBodySolver::getVertexData()
{
return m_vertexData;
}
btSoftBodyTriangleData &btCPUSoftBodySolver::getTriangleData()
{
return m_triangleData;
}
static Vectormath::Aos::Vector3 toVector3( const btVector3 &vec )
{
Vectormath::Aos::Vector3 outVec( vec.getX(), vec.getY(), vec.getZ() );
return outVec;
}
static Vectormath::Aos::Transform3 toTransform3( const btTransform &transform )
{
Vectormath::Aos::Transform3 outTransform;
outTransform.setCol(0, toVector3(transform.getBasis().getColumn(0)));
outTransform.setCol(1, toVector3(transform.getBasis().getColumn(1)));
outTransform.setCol(2, toVector3(transform.getBasis().getColumn(2)));
outTransform.setCol(3, toVector3(transform.getOrigin()));
return outTransform;
}
void btCPUSoftBodySolver::btAcceleratedSoftBodyInterface::updateBounds( const btVector3 &lowerBound, const btVector3 &upperBound )
{
float scalarMargin = this->getSoftBody()->getCollisionShape()->getMargin();
btVector3 vectorMargin( scalarMargin, scalarMargin, scalarMargin );
m_softBody->m_bounds[0] = lowerBound - vectorMargin;
m_softBody->m_bounds[1] = upperBound + vectorMargin;
}
void btCPUSoftBodySolver::copyBackToSoftBodies()
{
// Loop over soft bodies, copying all the vertex positions back for each body in turn
for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
{
btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[ softBodyIndex ];
btSoftBody *softBody = softBodyInterface->getSoftBody();
int firstVertex = softBodyInterface->getFirstVertex();
int numVertices = softBodyInterface->getNumVertices();
// Copy vertices from solver back into the softbody
for( int vertex = 0; vertex < numVertices; ++vertex )
{
using Vectormath::Aos::Point3;
Point3 vertexPosition( getVertexData().getVertexPositions()[firstVertex + vertex] );
softBody->m_nodes[vertex].m_x.setX( vertexPosition.getX() );
softBody->m_nodes[vertex].m_x.setY( vertexPosition.getY() );
softBody->m_nodes[vertex].m_x.setZ( vertexPosition.getZ() );
softBody->m_nodes[vertex].m_n.setX( vertexPosition.getX() );
softBody->m_nodes[vertex].m_n.setY( vertexPosition.getY() );
softBody->m_nodes[vertex].m_n.setZ( vertexPosition.getZ() );
}
}
} // btCPUSoftBodySolver::copyBackToSoftBodies
void btCPUSoftBodySolver::optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate )
{
if( forceUpdate || m_softBodySet.size() != softBodies.size() )
{
// Have a change in the soft body set so update, reloading all the data
getVertexData().clear();
getTriangleData().clear();
getLinkData().clear();
m_softBodySet.resize(0);
for( int softBodyIndex = 0; softBodyIndex < softBodies.size(); ++softBodyIndex )
{
btSoftBody *softBody = softBodies[ softBodyIndex ];
using Vectormath::Aos::Matrix3;
using Vectormath::Aos::Point3;
// Create SoftBody that will store the information within the solver
btAcceleratedSoftBodyInterface *newSoftBody = new btAcceleratedSoftBodyInterface( softBody );
m_softBodySet.push_back( newSoftBody );
m_perClothAcceleration.push_back( toVector3(softBody->getWorldInfo()->m_gravity) );
m_perClothDampingFactor.push_back(softBody->m_cfg.kDP);
m_perClothVelocityCorrectionCoefficient.push_back( softBody->m_cfg.kVCF );
m_perClothLiftFactor.push_back( softBody->m_cfg.kLF );
m_perClothDragFactor.push_back( softBody->m_cfg.kDG );
m_perClothMediumDensity.push_back(softBody->getWorldInfo()->air_density);
m_perClothCollisionObjects.push_back( CollisionObjectIndices(-1, -1) );
// Add space for new vertices and triangles in the default solver for now
// TODO: Include space here for tearing too later
int firstVertex = getVertexData().getNumVertices();
int numVertices = softBody->m_nodes.size();
int maxVertices = numVertices;
// Allocate space for new vertices in all the vertex arrays
getVertexData().createVertices( maxVertices, softBodyIndex );
int firstTriangle = getTriangleData().getNumTriangles();
int numTriangles = softBody->m_faces.size();
int maxTriangles = numTriangles;
getTriangleData().createTriangles( maxTriangles );
// Copy vertices from softbody into the solver
for( int vertex = 0; vertex < numVertices; ++vertex )
{
Point3 multPoint(softBody->m_nodes[vertex].m_x.getX(), softBody->m_nodes[vertex].m_x.getY(), softBody->m_nodes[vertex].m_x.getZ());
btSoftBodyVertexData::VertexDescription desc;
// TODO: Position in the softbody might be pre-transformed
// or we may need to adapt for the pose.
//desc.setPosition( cloth.getMeshTransform()*multPoint );
desc.setPosition( multPoint );
float vertexInverseMass = softBody->m_nodes[vertex].m_im;
desc.setInverseMass(vertexInverseMass);
getVertexData().setVertexAt( desc, firstVertex + vertex );
}
// Copy triangles similarly
// We're assuming here that vertex indices are based on the firstVertex rather than the entire scene
for( int triangle = 0; triangle < numTriangles; ++triangle )
{
// Note that large array storage is relative to the array not to the cloth
// So we need to add firstVertex to each value
int vertexIndex0 = (softBody->m_faces[triangle].m_n[0] - &(softBody->m_nodes[0]));
int vertexIndex1 = (softBody->m_faces[triangle].m_n[1] - &(softBody->m_nodes[0]));
int vertexIndex2 = (softBody->m_faces[triangle].m_n[2] - &(softBody->m_nodes[0]));
btSoftBodyTriangleData::TriangleDescription newTriangle(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, vertexIndex2 + firstVertex);
getTriangleData().setTriangleAt( newTriangle, firstTriangle + triangle );
// Increase vertex triangle counts for this triangle
getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex0)++;
getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex1)++;
getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex2)++;
}
int firstLink = getLinkData().getNumLinks();
int numLinks = softBody->m_links.size();
int maxLinks = numLinks;
// Allocate space for the links
getLinkData().createLinks( numLinks );
// Add the links
for( int link = 0; link < numLinks; ++link )
{
int vertexIndex0 = softBody->m_links[link].m_n[0] - &(softBody->m_nodes[0]);
int vertexIndex1 = softBody->m_links[link].m_n[1] - &(softBody->m_nodes[0]);
btSoftBodyLinkData::LinkDescription newLink(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, softBody->m_links[link].m_material->m_kLST);
newLink.setLinkStrength(1.f);
getLinkData().setLinkAt(newLink, firstLink + link);
}
newSoftBody->setFirstVertex( firstVertex );
newSoftBody->setFirstTriangle( firstTriangle );
newSoftBody->setNumVertices( numVertices );
newSoftBody->setMaxVertices( maxVertices );
newSoftBody->setNumTriangles( numTriangles );
newSoftBody->setMaxTriangles( maxTriangles );
newSoftBody->setFirstLink( firstLink );
newSoftBody->setNumLinks( numLinks );
}
updateConstants(0.f);
}
}
void btCPUSoftBodySolver::updateSoftBodies()
{
using namespace Vectormath::Aos;
int numVertices = m_vertexData.getNumVertices();
int numTriangles = m_triangleData.getNumTriangles();
// Initialise normal and vertex counts
for( int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex )
{
m_vertexData.getArea(vertexIndex) = 0.f;
m_vertexData.getNormal(vertexIndex) = Vector3(0.f, 0.f, 0.f);
}
// Update the areas for the triangles and vertices.
for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex )
{
float &triangleArea( m_triangleData.getTriangleArea( triangleIndex ) );
const btSoftBodyTriangleData::TriangleNodeSet &vertices( m_triangleData.getVertexSet(triangleIndex) );
Point3 &vertexPosition0( m_vertexData.getPosition( vertices.vertex0 ) );
Point3 &vertexPosition1( m_vertexData.getPosition( vertices.vertex1 ) );
Point3 &vertexPosition2( m_vertexData.getPosition( vertices.vertex2 ) );
triangleArea = computeTriangleArea( vertexPosition0, vertexPosition1, vertexPosition2 );
// Add to areas for vertices and increase the count of the number of triangles affecting the vertex
m_vertexData.getArea(vertices.vertex0) += triangleArea;
m_vertexData.getArea(vertices.vertex1) += triangleArea;
m_vertexData.getArea(vertices.vertex2) += triangleArea;
Point3 &vertex0( m_vertexData.getPosition(vertices.vertex0) );
Point3 &vertex1( m_vertexData.getPosition(vertices.vertex1) );
Point3 &vertex2( m_vertexData.getPosition(vertices.vertex2) );
Vector3 triangleNormal = cross( vertex1-vertex0, vertex2 - vertex0 );
m_triangleData.getNormal(triangleIndex) = normalize(triangleNormal);
m_vertexData.getNormal(vertices.vertex0) += triangleNormal;
m_vertexData.getNormal(vertices.vertex1) += triangleNormal;
m_vertexData.getNormal(vertices.vertex2) += triangleNormal;
}
// Normalise the area and normals
for( int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex )
{
m_vertexData.getArea(vertexIndex) /= m_vertexData.getTriangleCount(vertexIndex);
m_vertexData.getNormal(vertexIndex) = normalize( m_vertexData.getNormal(vertexIndex) );
}
// Clear the collision shape array for the next frame
m_collisionObjectDetails.clear();
} // updateSoftBodies
Vectormath::Aos::Vector3 btCPUSoftBodySolver::ProjectOnAxis( const Vectormath::Aos::Vector3 &v, const Vectormath::Aos::Vector3 &a )
{
return a*Vectormath::Aos::dot(v, a);
}
void btCPUSoftBodySolver::ApplyClampedForce( float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce )
{
float dtInverseMass = solverdt*inverseMass;
if( Vectormath::Aos::lengthSqr(force * dtInverseMass) > Vectormath::Aos::lengthSqr(vertexVelocity) )
{
vertexForce -= ProjectOnAxis( vertexVelocity, normalize( force ) )/dtInverseMass;
} else {
vertexForce += force;
}
}
bool btCPUSoftBodySolver::checkInitialized()
{
return true;
}
void btCPUSoftBodySolver::applyForces( float solverdt )
{
using namespace Vectormath::Aos;
int numVertices = m_vertexData.getNumVertices();
for( int clothIndex = 0; clothIndex < m_softBodySet.size(); ++clothIndex )
{
btAcceleratedSoftBodyInterface *currentCloth = m_softBodySet[clothIndex];
const int startVertex = currentCloth->getFirstVertex();
const int numVertices = currentCloth->getNumVertices();
Vector3 velocityChange = m_perClothAcceleration[clothIndex]*solverdt;
for( int vertexIndex = startVertex; vertexIndex < (startVertex + numVertices); ++vertexIndex )
{
float inverseMass = m_vertexData.getInverseMass( vertexIndex );
Vector3 &vertexVelocity( m_vertexData.getVelocity( vertexIndex ) );
// First apply the global acceleration to all vertices
if( inverseMass > 0 )
vertexVelocity += velocityChange;
// If it's a non-static vertex
if( m_vertexData.getInverseMass(vertexIndex) > 0 )
{
// Wind effects on a wind-per-cloth basis
float liftFactor = m_perClothLiftFactor[clothIndex];
float dragFactor = m_perClothDragFactor[clothIndex];
if( (liftFactor > 0.f) || (dragFactor > 0.f) )
{
Vector3 normal = m_vertexData.getNormal(vertexIndex);
Vector3 relativeWindVelocity = m_vertexData.getVelocity(vertexIndex) - m_perClothWindVelocity[clothIndex];
float relativeSpeedSquared = lengthSqr(relativeWindVelocity);
if( relativeSpeedSquared > FLT_EPSILON )
{
normal = normal * (dot(normal, relativeWindVelocity) < 0 ? -1.f : +1.f);
float dvNormal = dot(normal, relativeWindVelocity);
if( dvNormal > 0 )
{
Vector3 force( 0.f, 0.f, 0.f );
float c0 = m_vertexData.getArea(vertexIndex) * dvNormal * relativeSpeedSquared / 2;
float c1 = c0 * m_perClothMediumDensity[clothIndex];
force += normal * (-c1 * liftFactor);
force += normalize(relativeWindVelocity)*(-c1 * dragFactor);
Vectormath::Aos::Vector3 &vertexForce( m_vertexData.getForceAccumulator(vertexIndex) );
ApplyClampedForce( solverdt, force, vertexVelocity, inverseMass, vertexForce );
}
}
}
}
}
}
} // btCPUSoftBodySolver::applyForces
/**
* Integrate motion on the solver.
*/
void btCPUSoftBodySolver::integrate( float solverdt )
{
using namespace Vectormath::Aos;
int numVertices = m_vertexData.getNumVertices();
for( int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex )
{
Point3 &position( m_vertexData.getPosition(vertexIndex) );
Point3 &previousPosition( m_vertexData.getPreviousPosition(vertexIndex) );
Vector3 &forceAccumulator( m_vertexData.getForceAccumulator(vertexIndex) );
Vector3 &velocity( m_vertexData.getVelocity(vertexIndex) );
float inverseMass = m_vertexData.getInverseMass(vertexIndex);
previousPosition = position;
velocity += forceAccumulator * inverseMass * solverdt;
position += velocity * solverdt;
forceAccumulator = Vector3(0.f, 0.f, 0.f);
}
} // btCPUSoftBodySolver::integrate
float btCPUSoftBodySolver::computeTriangleArea(
const Vectormath::Aos::Point3 &vertex0,
const Vectormath::Aos::Point3 &vertex1,
const Vectormath::Aos::Point3 &vertex2 )
{
Vectormath::Aos::Vector3 a = vertex1 - vertex0;
Vectormath::Aos::Vector3 b = vertex2 - vertex0;
Vectormath::Aos::Vector3 crossProduct = cross(a, b);
float area = length( crossProduct );
return area;
}
void btCPUSoftBodySolver::updateConstants( float timeStep )
{
using namespace Vectormath::Aos;
if( m_updateSolverConstants )
{
m_updateSolverConstants = false;
// Will have to redo this if we change the structure (tear, maybe) or various other possible changes
// Initialise link constants
const int numLinks = m_linkData.getNumLinks();
for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex )
{
btSoftBodyLinkData::LinkNodePair &vertices( m_linkData.getVertexPair(linkIndex) );
m_linkData.getRestLength(linkIndex) = length((m_vertexData.getPosition( vertices.vertex0 ) - m_vertexData.getPosition( vertices.vertex1 )));
float invMass0 = m_vertexData.getInverseMass(vertices.vertex0);
float invMass1 = m_vertexData.getInverseMass(vertices.vertex1);
float linearStiffness = m_linkData.getLinearStiffnessCoefficient(linkIndex);
float massLSC = (invMass0 + invMass1)/linearStiffness;
m_linkData.getMassLSC(linkIndex) = massLSC;
float restLength = m_linkData.getRestLength(linkIndex);
float restLengthSquared = restLength*restLength;
m_linkData.getRestLengthSquared(linkIndex) = restLengthSquared;
}
}
} // btCPUSoftBodySolver::updateConstants
void btCPUSoftBodySolver::updateBounds()
{
using Vectormath::Aos::Point3;
for( int clothIndex = 0; clothIndex < m_softBodySet.size(); ++clothIndex )
{
btAcceleratedSoftBodyInterface *currentCloth = m_softBodySet[clothIndex];
btVector3 startBound(FLT_MAX, FLT_MAX, FLT_MAX);
btVector3 endBound(FLT_MIN, FLT_MIN, FLT_MIN);
const int startVertex = currentCloth->getFirstVertex();
const int numVertices = currentCloth->getNumVertices();
int endVertex = startVertex + numVertices;
for(int vertexIndex = startVertex; vertexIndex < endVertex; ++vertexIndex)
{
btVector3 vertexPosition( m_vertexData.getVertexPositions()[vertexIndex].getX(), m_vertexData.getVertexPositions()[vertexIndex].getY(), m_vertexData.getVertexPositions()[vertexIndex].getZ() );
startBound.setX( btMin( startBound.getX(), vertexPosition.getX() ) );
startBound.setY( btMin( startBound.getY(), vertexPosition.getY() ) );
startBound.setZ( btMin( startBound.getZ(), vertexPosition.getZ() ) );
endBound.setX( btMax( endBound.getX(), vertexPosition.getX() ) );
endBound.setY( btMax( endBound.getY(), vertexPosition.getY() ) );
endBound.setZ( btMax( endBound.getZ(), vertexPosition.getZ() ) );
}
m_softBodySet[clothIndex]->updateBounds( startBound, endBound );
}
}
class btCPUSB_QuickSortCompare
{
public:
bool operator() ( const btCPUCollisionShapeDescription& a, const btCPUCollisionShapeDescription& b )
{
return ( a.softBodyIdentifier < b.softBodyIdentifier );
}
};
/**
* Sort the collision object details array and generate indexing into it for the per-cloth collision object array.
*/
void btCPUSoftBodySolver::prepareCollisionConstraints()
{
// First do a simple sort on the collision objects
btAlignedObjectArray<int> numObjectsPerClothPrefixSum;
btAlignedObjectArray<int> numObjectsPerCloth;
numObjectsPerCloth.resize( m_softBodySet.size(), 0 );
numObjectsPerClothPrefixSum.resize( m_softBodySet.size(), 0 );
if (!m_perClothCollisionObjects.size())
return;
m_collisionObjectDetails.quickSort( btCPUSB_QuickSortCompare() );
// Generating indexing for perClothCollisionObjects
// First clear the previous values with the "no collision object for cloth" constant
for( int clothIndex = 0; clothIndex < m_perClothCollisionObjects.size(); ++clothIndex )
{
m_perClothCollisionObjects[clothIndex].firstObject = -1;
m_perClothCollisionObjects[clothIndex].endObject = -1;
}
int currentCloth = 0;
int startIndex = 0;
for( int collisionObject = 0; collisionObject < m_collisionObjectDetails.size(); ++collisionObject )
{
int nextCloth = m_collisionObjectDetails[collisionObject].softBodyIdentifier;
if( nextCloth != currentCloth )
{
// Changed cloth in the array
// Set the end index and the range is what we need for currentCloth
m_perClothCollisionObjects[currentCloth].firstObject = startIndex;
m_perClothCollisionObjects[currentCloth].endObject = collisionObject;
currentCloth = nextCloth;
startIndex = collisionObject;
}
}
// And update last cloth
m_perClothCollisionObjects[currentCloth].firstObject = startIndex;
m_perClothCollisionObjects[currentCloth].endObject = m_collisionObjectDetails.size();
} // prepareCollisionConstraints
void btCPUSoftBodySolver::solveConstraints( float solverdt )
{
using Vectormath::Aos::Vector3;
using Vectormath::Aos::Point3;
using Vectormath::Aos::lengthSqr;
using Vectormath::Aos::dot;
// Prepare links
int numLinks = m_linkData.getNumLinks();
int numVertices = m_vertexData.getNumVertices();
float kst = 1.f;
for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex )
{
btSoftBodyLinkData::LinkNodePair &nodePair( m_linkData.getVertexPair(linkIndex) );
Vector3 currentLength = m_vertexData.getPreviousPosition( nodePair.vertex1 ) - m_vertexData.getPreviousPosition( nodePair.vertex0 );
m_linkData.getCurrentLength(linkIndex) = currentLength;
// If mass at both ends of links is 0 (both static points) then we don't want this information.
// In reality this would be a fairly pointless link, but it could have been inserted
float linkLengthRatio = 0;
if( m_linkData.getMassLSC(linkIndex) > 0 )
linkLengthRatio = 1.f/(lengthSqr(currentLength) * m_linkData.getMassLSC(linkIndex));
m_linkData.getLinkLengthRatio(linkIndex) = linkLengthRatio;
}
prepareCollisionConstraints();
for( int iteration = 0; iteration < m_numberOfVelocityIterations ; ++iteration )
{
// Solve velocity
for(int linkIndex = 0; linkIndex < numLinks; ++linkIndex)
{
int vertexIndex0 = m_linkData.getVertexPair(linkIndex).vertex0;
int vertexIndex1 = m_linkData.getVertexPair(linkIndex).vertex1;
float j = -dot(m_linkData.getCurrentLength(linkIndex), m_vertexData.getVelocity(vertexIndex0) - m_vertexData.getVelocity(vertexIndex1)) * m_linkData.getLinkLengthRatio(linkIndex)*kst;
// If both ends of the link have no mass then this will be zero. Catch that case.
// TODO: Should really catch the /0 in the link setup, too
//if(psb->m_linksc0[i]>0)
{
m_vertexData.getVelocity(vertexIndex0) = m_vertexData.getVelocity(vertexIndex0) + m_linkData.getCurrentLength(linkIndex)*j*m_vertexData.getInverseMass(vertexIndex0);
m_vertexData.getVelocity(vertexIndex1) = m_vertexData.getVelocity(vertexIndex1) - m_linkData.getCurrentLength(linkIndex)*j*m_vertexData.getInverseMass(vertexIndex1);
}
}
}
// Compute new positions from velocity
// Also update the previous position so that our position computation is now based on the new position from the velocity solution
// rather than based directly on the original positions
if( m_numberOfVelocityIterations > 0 )
{
for(int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex)
{
m_vertexData.getPosition(vertexIndex) = m_vertexData.getPreviousPosition(vertexIndex) + m_vertexData.getVelocity(vertexIndex) * solverdt;
m_vertexData.getPreviousPosition(vertexIndex) = m_vertexData.getPosition(vertexIndex);
}
}
// Solve drift
for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration )
{
for( int clothIndex = 0; clothIndex < m_softBodySet.size(); ++clothIndex )
{
btAcceleratedSoftBodyInterface *currentCloth = m_softBodySet[clothIndex];
const int startLink = currentCloth->getFirstLink();
const int numLinks = currentCloth->getNumLinks();
int endLink = startLink + numLinks;
for(int linkIndex = startLink; linkIndex < endLink; ++linkIndex)
{
int vertexIndex0 = m_linkData.getVertexPair(linkIndex).vertex0;
int vertexIndex1 = m_linkData.getVertexPair(linkIndex).vertex1;
float massLSC = m_linkData.getMassLSC(linkIndex);
if( massLSC > 0.f )
{
Point3 &vertexPosition0( m_vertexData.getPosition( vertexIndex0 ) );
Point3 &vertexPosition1( m_vertexData.getPosition( vertexIndex1 ) );
Vector3 del = vertexPosition1 - vertexPosition0;
float len = lengthSqr(del);
float restLength2 = m_linkData.getRestLengthSquared(linkIndex);
float k = ((restLength2 - len) / (massLSC * (restLength2 + len) ) )*kst;
vertexPosition0 -= del*(k*m_vertexData.getInverseMass(vertexIndex0));
vertexPosition1 += del*(k*m_vertexData.getInverseMass(vertexIndex1));
}
}
}
}
// Clear forces so that friction is applied correctly
for( int clothIndex = 0; clothIndex < m_softBodySet.size(); ++clothIndex )
{
btAcceleratedSoftBodyInterface *currentCloth = m_softBodySet[clothIndex];
const int startLink = currentCloth->getFirstLink();
const int numLinks = currentCloth->getNumLinks();
const int startVertex = currentCloth->getFirstVertex();
const int numVertices = currentCloth->getNumVertices();
const int lastVertex = startVertex + numVertices;
// Update the velocities based on the change in position
// TODO: Damping should only be applied to the action of link constraints so the cloth still falls but then moves stiffly once it hits something
float velocityCoefficient = (1.f - m_perClothDampingFactor[clothIndex]);
float velocityCorrectionCoefficient = m_perClothVelocityCorrectionCoefficient[clothIndex];
float isolverDt = 1.f/solverdt;
for(int vertexIndex = startVertex; vertexIndex < lastVertex; ++vertexIndex)
{
m_vertexData.getForceAccumulator( vertexIndex ) = Vector3(0.f, 0.f, 0.f);
}
}
// Solve collision constraints
// Very simple solver that pushes the vertex out of collision imposters for now
// to test integration with the broad phase code.
// May also want to put this into position solver loop every n iterations depending on
// how it behaves
for( int clothIndex = 0; clothIndex < m_softBodySet.size(); ++clothIndex )
{
btAcceleratedSoftBodyInterface *currentCloth = m_softBodySet[clothIndex];
float clothFriction = currentCloth->getSoftBody()->getFriction();
const int startVertex = currentCloth->getFirstVertex();
const int numVertices = currentCloth->getNumVertices();
int endVertex = startVertex + numVertices;
float velocityCoefficient = (1.f - m_perClothDampingFactor[clothIndex]);
float velocityCorrectionCoefficient = m_perClothVelocityCorrectionCoefficient[clothIndex];
float isolverDt = 1.f/solverdt;
int startObject = m_perClothCollisionObjects[clothIndex].firstObject;
int endObject = m_perClothCollisionObjects[clothIndex].endObject;
if( endObject == startObject )
{
// No collisions so just do the force update
for(int vertexIndex = startVertex; vertexIndex < endVertex; ++vertexIndex)
{
m_vertexData.getForceAccumulator( vertexIndex ) = Vector3(0.f, 0.f, 0.f);
}
// Recompute velocity based on updated position inclusive of drift
for(int vertexIndex = startVertex; vertexIndex < endVertex; ++vertexIndex)
{
m_vertexData.getVelocity(vertexIndex) = (m_vertexData.getPosition(vertexIndex) - m_vertexData.getPreviousPosition(vertexIndex)) * velocityCoefficient * isolverDt;
}
} else {
for( int collisionObject = startObject; collisionObject < endObject; ++collisionObject )
{
btCPUCollisionShapeDescription &shapeDescription( m_collisionObjectDetails[collisionObject] );
float colliderFriction = shapeDescription.friction;
if( shapeDescription.collisionShapeType == CAPSULE_SHAPE_PROXYTYPE )
{
using namespace Vectormath::Aos;
float capsuleHalfHeight = shapeDescription.shapeInformation.capsule.halfHeight;
float capsuleRadius = shapeDescription.shapeInformation.capsule.radius;
int capsuleUpAxis = shapeDescription.shapeInformation.capsule.upAxis;
float capsuleMargin = shapeDescription.margin;
Transform3 worldTransform = shapeDescription.shapeTransform;
// As this is a GPU comparison solver just iterate over the vertices
for( int vertexIndex = startVertex; vertexIndex < endVertex; ++vertexIndex )
{
// Clear force for vertex first
m_vertexData.getForceAccumulator( vertexIndex ) = Vector3(0.f, 0.f, 0.f);
Point3 vertex( m_vertexData.getPosition( vertexIndex ) );
// Correctly define the centerline depending on the upAxis
Point3 c1(0.f, 0.f, 0.f);
Point3 c2(0.f, 0.f, 0.f);
if( capsuleUpAxis == 0 ) {
c1.setX(-capsuleHalfHeight);
c2.setX(capsuleHalfHeight);
} else if( capsuleUpAxis == 1 ) {
c1.setY(-capsuleHalfHeight);
c2.setY(capsuleHalfHeight);
} else {
c1.setZ(-capsuleHalfHeight);
c2.setZ(capsuleHalfHeight);
}
Point3 worldC1 = worldTransform * c1;
Point3 worldC2 = worldTransform * c2;
Vector3 segment = worldC2 - worldC1;
// compute distance of tangent to vertex along line segment in capsule
float distanceAlongSegment = -( dot( worldC1 - vertex, segment ) / lengthSqr(segment) );
Point3 closestPoint = (worldC1 + segment * distanceAlongSegment);
float distanceFromLine = length(vertex - closestPoint);
float distanceFromC1 = length(worldC1 - vertex);
float distanceFromC2 = length(worldC2 - vertex);
// Final distance from collision, point to push from, direction to push in
// for impulse force
float distance;
Point3 sourcePoint;
Vector3 normalVector;
if( distanceAlongSegment < 0 )
{
distance = distanceFromC1;
sourcePoint = worldC1;
normalVector = normalize(vertex - worldC1);
} else if( distanceAlongSegment > 1.f ) {
distance = distanceFromC2;
sourcePoint = worldC2;
normalVector = normalize(vertex - worldC2);
} else {
distance = distanceFromLine;
sourcePoint = closestPoint;
normalVector = normalize(vertex - closestPoint);
}
Vector3 colliderLinearVelocity( shapeDescription.linearVelocity );
Vector3 colliderAngularVelocity( shapeDescription.angularVelocity );
Vector3 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, Vector3(vertex) - worldTransform.getTranslation());
float minDistance = capsuleRadius + capsuleMargin;
bool collided = false;
if( distance < minDistance )
{
// Project back to surface along normal
Vectormath::Aos::Point3 sourcePos = m_vertexData.getPosition( vertexIndex );
Vectormath::Aos::Vector3 posChange = (minDistance - distance)*normalVector*0.9;
//if( length(posChange) > 1 )
// std::cerr << "Poschange: " << length(posChange) << "\n";
Vectormath::Aos::Point3 newPos = sourcePos + posChange;
m_vertexData.getPosition( vertexIndex ) = newPos;
//m_vertexData.getPosition( vertexIndex ) = m_vertexData.getPosition( vertexIndex ) + (minDistance - distance)*normalVector*0.9;
// Experiment with moving back along source vector.
// Removes all ability to slide because it projects back along the vector length so it would undo lateral movement.
// TODO: This isn't quite right because we should take the movement of the collider into account as well
/*Vector3 incomingMoveVector( normalize(m_vertexData.getPreviousPosition(vertexIndex) - m_vertexData.getPosition(vertexIndex)) );
Vector3 normalDirectionMoveOut( (minDistance - distance)*normalVector*0.9 );
float distanceOnIncomingVector = dot(normalDirectionMoveOut, incomingMoveVector);
Vector3 vectorCorrection( distanceOnIncomingVector*incomingMoveVector );
m_vertexData.getPosition( vertexIndex ) = m_vertexData.getPosition( vertexIndex ) + vectorCorrection;*/
collided = true;
}
// Update velocity of vertex based on position
m_vertexData.getVelocity(vertexIndex) = (m_vertexData.getPosition(vertexIndex) - m_vertexData.getPreviousPosition(vertexIndex)) * velocityCoefficient * isolverDt;
// If we collided before we are on the surface so have friction
if( collided )
{
// Compute friction
// TODO: Just vertex velocity not enough, really we need the velocity
// relative to closest point on the surface of the collider
Vector3 vertexVelocity( m_vertexData.getVelocity(vertexIndex) );
Vector3 relativeVelocity( vertexVelocity - velocityOfSurfacePoint );
// First compute vectors for plane perpendicular to normal vector
// Cross any vector with normal vector first then cross the normal with it again
Vector3 p1(normalize(cross(normalVector, segment)));
Vector3 p2(normalize(cross(p1, normalVector)));
// Full friction is sum of velocities in each direction of plane.
Vector3 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 );
// For now just update vertex position by moving to radius distance along the push vector
// Could use this as the basis for simple vector distance constraint for the point later, possibly?
// That way in the main solver loop all shape types could be the same... though when
// we need to apply bi-directionally it becomes more complicated
// Add friction vector to the force accumulator
Vector3 &currentForce( m_vertexData.getForceAccumulator( vertexIndex ) );
// Only apply if the vertex is moving towards the object to reduce jitter error
if( approachSpeed <= 0.0 )
currentForce -= frictionVector;
}
}
}
} // for( int collisionObject = startObject; collisionObject < endObject; ++collisionObject )
} // if( endObject == startObject )
}
} // btCPUSoftBodySolver::solveConstraints
btCPUSoftBodySolver::btAcceleratedSoftBodyInterface *btCPUSoftBodySolver::findSoftBodyInterface( const btSoftBody* const softBody )
{
for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
{
btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[softBodyIndex];
if( softBodyInterface->getSoftBody() == softBody )
return softBodyInterface;
}
return 0;
}
const btCPUSoftBodySolver::btAcceleratedSoftBodyInterface * const btCPUSoftBodySolver::findSoftBodyInterface( const btSoftBody* const softBody ) const
{
for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
{
const btAcceleratedSoftBodyInterface *const softBodyInterface = m_softBodySet[softBodyIndex];
if( softBodyInterface->getSoftBody() == softBody )
return softBodyInterface;
}
return 0;
}
int btCPUSoftBodySolver::findSoftBodyIndex( const btSoftBody* const softBody )
{
for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
{
btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[softBodyIndex];
if( softBodyInterface->getSoftBody() == softBody )
return softBodyIndex;
}
return 1;
}
void btSoftBodySolverOutputCPUtoCPU::copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer )
{
// Currently only support CPU output buffers
const btSoftBodySolver *solver = softBody->getSoftBodySolver();
btAssert( solver->getSolverType() == btSoftBodySolver::CPU_SOLVER );
const btCPUSoftBodySolver *cpuSolver = static_cast< const btCPUSoftBodySolver * >( solver );
const btCPUSoftBodySolver::btAcceleratedSoftBodyInterface * const currentCloth = cpuSolver->findSoftBodyInterface( softBody );
const btSoftBodyVertexData &vertexData( cpuSolver->m_vertexData );
if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER )
{
const int firstVertex = currentCloth->getFirstVertex();
const int lastVertex = firstVertex + currentCloth->getNumVertices();
const btCPUVertexBufferDescriptor *cpuVertexBuffer = static_cast< btCPUVertexBufferDescriptor* >(vertexBuffer);
float *basePointer = cpuVertexBuffer->getBasePointer();
if( vertexBuffer->hasVertexPositions() )
{
const int vertexOffset = cpuVertexBuffer->getVertexOffset();
const int vertexStride = cpuVertexBuffer->getVertexStride();
float *vertexPointer = basePointer + vertexOffset;
for( int vertexIndex = firstVertex; vertexIndex < lastVertex; ++vertexIndex )
{
Vectormath::Aos::Point3 position = vertexData.getPosition(vertexIndex);
*(vertexPointer + 0) = position.getX();
*(vertexPointer + 1) = position.getY();
*(vertexPointer + 2) = position.getZ();
vertexPointer += vertexStride;
}
}
if( vertexBuffer->hasNormals() )
{
const int normalOffset = cpuVertexBuffer->getNormalOffset();
const int normalStride = cpuVertexBuffer->getNormalStride();
float *normalPointer = basePointer + normalOffset;
for( int vertexIndex = firstVertex; vertexIndex < lastVertex; ++vertexIndex )
{
Vectormath::Aos::Vector3 normal = vertexData.getNormal(vertexIndex);
*(normalPointer + 0) = normal.getX();
*(normalPointer + 1) = normal.getY();
*(normalPointer + 2) = normal.getZ();
normalPointer += normalStride;
}
}
} else {
btAssert( 0=="Invalid vertex buffer descriptor used in CPU output." );
}
} // btCPUSoftBodySolver::outputToVertexBuffers
void btCPUSoftBodySolver::processCollision( btSoftBody*, btSoftBody *)
{
}
// Add the collision object to the set to deal with for a particular soft body
void btCPUSoftBodySolver::processCollision( btSoftBody *softBody, btCollisionObject* collisionObject )
{
int softBodyIndex = findSoftBodyIndex( softBody );
if( softBodyIndex >= 0 )
{
btCollisionShape *collisionShape = collisionObject->getCollisionShape();
float friction = collisionObject->getFriction();
int shapeType = collisionShape->getShapeType();
if( shapeType == CAPSULE_SHAPE_PROXYTYPE )
{
// Add to the list of expected collision objects
btCPUCollisionShapeDescription newCollisionShapeDescription;
newCollisionShapeDescription.softBodyIdentifier = softBodyIndex;
newCollisionShapeDescription.collisionShapeType = shapeType;
newCollisionShapeDescription.shapeTransform = toTransform3(collisionObject->getWorldTransform());
btCapsuleShape *capsule = static_cast<btCapsuleShape*>( collisionShape );
newCollisionShapeDescription.shapeInformation.capsule.radius = capsule->getRadius();
newCollisionShapeDescription.shapeInformation.capsule.halfHeight = capsule->getHalfHeight();
newCollisionShapeDescription.shapeInformation.capsule.upAxis = capsule->getUpAxis();
newCollisionShapeDescription.margin = capsule->getMargin();
newCollisionShapeDescription.friction = friction;
btRigidBody* body = static_cast< btRigidBody* >( collisionObject );
newCollisionShapeDescription.linearVelocity = toVector3(body->getLinearVelocity());
newCollisionShapeDescription.angularVelocity = toVector3(body->getAngularVelocity());
m_collisionObjectDetails.push_back( newCollisionShapeDescription );
} else {
btAssert("Unsupported collision shape type\n");
}
} else {
btAssert("Unknown soft body");
}
} // btCPUSoftBodySolver::processCollision
void btCPUSoftBodySolver::predictMotion( float timeStep )
{
// Fill the force arrays with current acceleration data etc
m_perClothWindVelocity.resize( m_softBodySet.size() );
for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
{
btSoftBody *softBody = m_softBodySet[softBodyIndex]->getSoftBody();
m_perClothWindVelocity[softBodyIndex] = toVector3(softBody->getWindVelocity());
}
// Apply forces that we know about to the cloths
applyForces( timeStep * getTimeScale() );
// Itegrate motion for all soft bodies dealt with by the solver
integrate( timeStep * getTimeScale() );
// Update bounds
// Will update the bounds for all softBodies being dealt with by the solver and
// set the values in the btSoftBody object
updateBounds();
// End prediction work for solvers
}

View File

@@ -1,370 +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_CPU_SOLVER_H
#define BT_ACCELERATED_SOFT_BODY_CPU_SOLVER_H
#include "vectormath/vmInclude.h"
#include "BulletSoftBody/btSoftBodySolvers.h"
#include "BulletSoftBody/btSoftBodySolverVertexBuffer.h"
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolverData.h"
struct btCPUCollisionShapeDescription
{
int softBodyIdentifier;
int collisionShapeType;
Vectormath::Aos::Transform3 shapeTransform;
union
{
struct Sphere
{
float radius;
} sphere;
struct Capsule
{
float radius;
float halfHeight;
int upAxis;
} capsule;
} shapeInformation;
float margin;
float friction;
Vectormath::Aos::Vector3 linearVelocity;
Vectormath::Aos::Vector3 angularVelocity;
btCPUCollisionShapeDescription()
{
collisionShapeType = 0;
margin = 0;
friction = 0;
}
};
class btCPUSoftBodySolver : public btSoftBodySolver
{
protected:
/**
* Entry in the collision shape array.
* Specifies the shape type, the transform matrix and the necessary details of the collisionShape.
*/
// Public because output classes need it. This is a better encapsulation to break in the short term
// Than having the solvers themselves need dependencies on DX, CL etc unnecessarily
public:
struct CollisionObjectIndices
{
CollisionObjectIndices( int f, int e )
{
firstObject = f;
endObject = e;
}
int firstObject;
int endObject;
};
/**
* 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() const
{
return m_maxLinks;
}
int getNumLinks() const
{
return m_numLinks;
}
int getFirstLink() const
{
return m_firstLink;
}
btSoftBody* getSoftBody()
{
return m_softBody;
}
const btSoftBody* const getSoftBody() const
{
return m_softBody;
}
};
btSoftBodyLinkData m_linkData;
btSoftBodyVertexData m_vertexData;
btSoftBodyTriangleData m_triangleData;
protected:
/** Variable to define whether we need to update solver constants on the next iteration */
bool m_updateSolverConstants;
/**
* 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;
/** 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;
/** Velocity damping factor */
btAlignedObjectArray< float > m_perClothDampingFactor;
/** Velocity correction coefficient */
btAlignedObjectArray< float > m_perClothVelocityCorrectionCoefficient;
/** Lift parameter for wind effect on cloth. */
btAlignedObjectArray< float > m_perClothLiftFactor;
/** Drag parameter for wind effect on cloth. */
btAlignedObjectArray< float > m_perClothDragFactor;
/** Density of the medium in which each cloth sits */
btAlignedObjectArray< float > m_perClothMediumDensity;
/**
* Collision shape details: pair of index of first collision shape for the cloth and number of collision objects.
*/
btAlignedObjectArray< CollisionObjectIndices > m_perClothCollisionObjects;
/**
* Collision shapes being passed across to the cloths in this solver.
*/
btAlignedObjectArray< btCPUCollisionShapeDescription > m_collisionObjectDetails;
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 );
float computeTriangleArea(
const Vectormath::Aos::Point3 &vertex0,
const Vectormath::Aos::Point3 &vertex1,
const Vectormath::Aos::Point3 &vertex2 );
void applyForces( float solverdt );
void integrate( float solverdt );
void updateConstants( float timeStep );
int findSoftBodyIndex( const btSoftBody* const softBody );
/** Update the bounds of the soft body objects in the solver */
void updateBounds();
public:
btCPUSoftBodySolver();
virtual ~btCPUSoftBodySolver();
virtual SolverTypes getSolverType() const
{
return CPU_SOLVER;
}
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();
virtual void solveConstraints( float solverdt );
virtual void predictMotion( float solverdt );
virtual void processCollision( btSoftBody *, btCollisionObject* );
virtual void processCollision( btSoftBody*, btSoftBody *);
};
/**
* Class to manage movement of data from a solver to a given target.
* This version is the CPU to CPU generic version.
*/
class btSoftBodySolverOutputCPUtoCPU : public btSoftBodySolverOutput
{
protected:
public:
btSoftBodySolverOutputCPUtoCPU()
{
}
/** 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_CPU_SOLVER_H

View File

@@ -8,7 +8,7 @@ SET(DX11_INCLUDE_PATH "${DIRECTX_SDK_BASE_DIR}/Include" CACHE DOCSTRING "Micros
INCLUDE_DIRECTORIES(
${DX11_INCLUDE_PATH} "../cpu/"
${DX11_INCLUDE_PATH} "../Shared/"
${VECTOR_MATH_INCLUDE}
)
@@ -20,7 +20,7 @@ SET(BulletSoftBodyDX11Solvers_SRCS
SET(BulletSoftBodyDX11Solvers_HDRS
btSoftBodySolver_DX11.h
btSoftBodySolver_DX11SIMDAware.h
../cpu/btSoftBodySolverData.h
../Shared/btSoftBodySolverData.h
btSoftBodySolverVertexData_DX11.h
btSoftBodySolverTriangleData_DX11.h
btSoftBodySolverLinkData_DX11.h

View File

@@ -14,7 +14,7 @@ subject to the following restrictions:
*/
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolverData.h"
#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h"
#include "btSoftBodySolverBuffer_DX11.h"

View File

@@ -13,7 +13,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolverData.h"
#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h"
#include "btSoftBodySolverBuffer_DX11.h"
#ifndef BT_ACCELERATED_SOFT_BODY_LINK_DATA_DX11_SIMDAWARE_H

View File

@@ -13,7 +13,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolverData.h"
#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h"
#include "btSoftBodySolverBuffer_DX11.h"

View File

@@ -14,7 +14,7 @@ subject to the following restrictions:
*/
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolverData.h"
#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h"
#include "btSoftBodySolverBuffer_DX11.h"

View File

@@ -18,7 +18,7 @@ SET(BulletSoftBodyOpenCLSolvers_SRCS
SET(BulletSoftBodyOpenCLSolvers_HDRS
../btSoftBodySolver_OpenCL.h
../btSoftBodySolver_OpenCLSIMDAware.h
../../CPU/btSoftBodySolverData.h
../../Shared/btSoftBodySolverData.h
../btSoftBodySolverVertexData_OpenCL.h
../btSoftBodySolverTriangleData_OpenCL.h
../btSoftBodySolverLinkData_OpenCL.h

View File

@@ -13,7 +13,7 @@ SET(BulletSoftBodyOpenCLSolvers_SRCS
SET(BulletSoftBodyOpenCLSolvers_HDRS
../btSoftBodySolver_OpenCL.h
../../CPU/btSoftBodySolverData.h
../../Shared/btSoftBodySolverData.h
../btSoftBodySolverVertexData_OpenCL.h
../btSoftBodySolverTriangleData_OpenCL.h
../btSoftBodySolverLinkData_OpenCL.h

View File

@@ -18,7 +18,7 @@ SET(BulletSoftBodyOpenCLSolvers_SRCS
SET(BulletSoftBodyOpenCLSolvers_HDRS
../btSoftBodySolver_OpenCL.h
../btSoftBodySolver_OpenCLSIMDAware.h
../../CPU/btSoftBodySolverData.h
../../Shared/btSoftBodySolverData.h
../btSoftBodySolverVertexData_OpenCL.h
../btSoftBodySolverTriangleData_OpenCL.h
../btSoftBodySolverLinkData_OpenCL.h

View File

@@ -14,7 +14,7 @@ SET(BulletSoftBodyOpenCLSolvers_SRCS
SET(BulletSoftBodyOpenCLSolvers_HDRS
../btSoftBodySolver_OpenCL.h
../../CPU/btSoftBodySolverData.h
../../Shared/btSoftBodySolverData.h
../btSoftBodySolverVertexData_OpenCL.h
../btSoftBodySolverTriangleData_OpenCL.h
../btSoftBodySolverLinkData_OpenCL.h

View File

@@ -24,9 +24,12 @@ subject to the following restrictions:
#include "../OpenCLC10/UpdateNormals.cl"
#include "../OpenCLC10/UpdatePositions.cl"
#include "../OpenCLC10/UpdatePositionsFromVelocities.cl"
//#include "../OpenCLC10/VSolveLinks.cl"
#include "../OpenCLC10/VSolveLinks.cl"
//#include "../OpenCLC10/SolveCollisionsAndUpdateVelocities.cl"
MINICL_REGISTER(PrepareLinksKernel)
MINICL_REGISTER(VSolveLinksKernel)
MINICL_REGISTER(UpdatePositionsFromVelocitiesKernel)
MINICL_REGISTER(SolvePositionsFromLinksKernel)
MINICL_REGISTER(updateVelocitiesFromPositionsWithVelocitiesKernel)
@@ -38,3 +41,208 @@ MINICL_REGISTER(NormalizeNormalsAndAreasKernel)
MINICL_REGISTER(UpdateSoftBodiesKernel)
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

@@ -17,7 +17,7 @@ SET(BulletSoftBodyOpenCLSolvers_SRCS
SET(BulletSoftBodyOpenCLSolvers_HDRS
../btSoftBodySolver_OpenCL.h
../../CPU/btSoftBodySolverData.h
../../Shared/btSoftBodySolverData.h
../btSoftBodySolverVertexData_OpenCL.h
../btSoftBodySolverTriangleData_OpenCL.h
../btSoftBodySolverLinkData_OpenCL.h

View File

@@ -78,8 +78,8 @@ ApplyForcesKernel(
float4 nodeFMinus = nodeF - (projectOnAxis(nodeV, normalize(force))/dtim);
nodeF = nodeFPlusForce;
if( dot(forceDTIM, forceDTIM) > dot(nodeV, nodeV) )
nodeF = nodeFMinus;
//if( dot(forceDTIM, forceDTIM) > dot(nodeV, nodeV) )
// nodeF = nodeFMinus;
g_vertexForceAccumulator[nodeID] = nodeF;
}

View File

@@ -1,8 +1,8 @@
MSTRINGIFY(
#pragma OPENCL EXTENSION cl_amd_printf : enable\n
float mydot3(float4 a, float4 b)
float mydot3a(float4 a, float4 b)
{
return a.x*b.x + a.y*b.y + a.z*b.z;
}
@@ -67,7 +67,7 @@ SolveCollisionsAndUpdateVelocitiesKernel(
__global CollisionShapeDescription * g_collisionObjectDetails,
__global float4 * g_vertexForces,
__global float4 *g_vertexVelocities,
__global float4 *g_vertexPositions)
__global float4 *g_vertexPositions GUID_ARG)
{
int nodeID = get_global_id(0);
float4 forceOnVertex = (float4)(0.f, 0.f, 0.f, 0.f);
@@ -134,7 +134,7 @@ SolveCollisionsAndUpdateVelocitiesKernel(
float4 segment = (worldC2 - worldC1);
// compute distance of tangent to vertex along line segment in capsule
float distanceAlongSegment = -( mydot3( (worldC1 - position), segment ) / mydot3(segment, segment) );
float distanceAlongSegment = -( mydot3a( (worldC1 - position), segment ) / mydot3a(segment, segment) );
float4 closestPoint = (worldC1 + (float4)(segment * distanceAlongSegment));
float distanceFromLine = length(position - closestPoint);
@@ -178,7 +178,7 @@ SolveCollisionsAndUpdateVelocitiesKernel(
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*mydot3(relativeVelocity, p1) + p2*mydot3(relativeVelocity, p2);
float4 frictionVector = p1*mydot3a(relativeVelocity, p1) + p2*mydot3a(relativeVelocity, p2);
// Real friction is peak friction corrected by friction coefficients
frictionVector = frictionVector * (colliderFriction*clothFriction);

View File

@@ -13,7 +13,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolverData.h"
#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h"
#include "btSoftBodySolverBuffer_OpenCL.h"

View File

@@ -13,7 +13,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolverData.h"
#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h"
#include "btSoftBodySolverBuffer_OpenCL.h"

View File

@@ -14,7 +14,7 @@ subject to the following restrictions:
*/
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolverData.h"
#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h"
#include "btSoftBodySolverBuffer_OpenCL.h"

View File

@@ -13,7 +13,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolverData.h"
#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h"
#include "btSoftBodySolverBuffer_OpenCL.h"
#ifndef BT_SOFT_BODY_SOLVER_VERTEX_DATA_OPENCL_H

View File

@@ -1642,10 +1642,11 @@ void btOpenCLSoftBodySolver::processCollision( btSoftBody *softBody, btCollision
m_collisionObjectDetails.push_back( newCollisionShapeDescription );
} else {
btAssert(0 && "Unsupported collision shape type\n");
printf("Unsupported collision shape type\n");
//btAssert(0 && "Unsupported collision shape type\n");
}
} else {
btAssert("Unknown soft body");
btAssert(0,"Unknown soft body");
}
} // btOpenCLSoftBodySolver::processCollision

View File

@@ -1822,7 +1822,7 @@ btScalar btSoftBody::RayFromToCaster::rayFromToTriangle( const btVector3& rayF
void btSoftBody::pointersToIndices()
{
#define PTR2IDX(_p_,_b_) reinterpret_cast<btSoftBody::Node*>((_p_)-(_b_))
btSoftBody::Node* base=&m_nodes[0];
btSoftBody::Node* base=m_nodes.size() ? &m_nodes[0] : 0;
int i,ni;
for(i=0,ni=m_nodes.size();i<ni;++i)
@@ -1866,7 +1866,7 @@ void btSoftBody::indicesToPointers(const int* map)
{
#define IDX2PTR(_p_,_b_) map?(&(_b_)[map[(((char*)_p_)-(char*)0)]]): \
(&(_b_)[(((char*)_p_)-(char*)0)])
btSoftBody::Node* base=&m_nodes[0];
btSoftBody::Node* base=m_nodes.size() ? &m_nodes[0]:0;
int i,ni;
for(i=0,ni=m_nodes.size();i<ni;++i)

View File

@@ -57,11 +57,118 @@ struct float8
}
};
float select( float arg0, float arg1, bool select)
{
if (select)
return arg0;
return arg1;
}
#define __constant
struct float3
{
float x,y,z;
float3& operator+=(const float3& other)
{
x += other.x;
y += other.y;
z += other.z;
return *this;
}
float3& operator-=(const float3& other)
{
x -= other.x;
y -= other.y;
z -= other.z;
return *this;
}
};
static float dot(const float3&a ,const float3& b)
{
float3 tmp;
tmp.x = a.x*b.x;
tmp.y = a.y*b.y;
tmp.z = a.z*b.z;
return tmp.x+tmp.y+tmp.z;
}
static float3 operator-(const float3& a,const float3& b)
{
float3 tmp;
tmp.x = a.x - b.x;
tmp.y = a.y - b.y;
tmp.z = a.z - b.z;
return tmp;
}
static float3 operator*(const float& scalar,const float3& b)
{
float3 tmp;
tmp.x = scalar * b.x;
tmp.y = scalar * b.y;
tmp.z = scalar * b.z;
return tmp;
}
static float3 operator*(const float3& a,const float& scalar)
{
float3 tmp;
tmp.x = a.x * scalar;
tmp.y = a.y * scalar;
tmp.z = a.z * scalar;
return tmp;
}
static float3 operator*(const float3& a,const float3& b)
{
float3 tmp;
tmp.x = a.x * b.x;
tmp.y = a.y * b.y;
tmp.z = a.z * b.z;
return tmp;
}
//ATTRIBUTE_ALIGNED16(struct) float4
struct float4
{
float x,y,z,w;
union
{
struct {
float x;
float y;
float z;
};
float3 xyz;
};
float w;
float4() {}
float4(float v0, float v1, float v2, float v3)
{
x=v0;
y=v1;
z=v2;
w=v3;
}
float4(float3 xyz, float scalarW)
{
x = xyz.x;
y = xyz.y;
z = xyz.z;
w = scalarW;
}
float4(float v)
{
x = y = z = w = v;
@@ -76,6 +183,8 @@ struct float4
return tmp;
}
float4 operator*(const float& other)
{
float4 tmp;
@@ -203,6 +312,7 @@ static float4 operator/(const float4& b,float a)
static float dot(const float4&a ,const float4& b)
{
float4 tmp;