reorder files, in preparation for Bullet 3 -> Bullet 2 merge
This commit is contained in:
344
src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.cl
Normal file
344
src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.cl
Normal file
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
Copyright (c) 2012 Advanced Micro Devices, Inc.
|
||||
|
||||
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.
|
||||
*/
|
||||
//Originally written by Takahiro Harada
|
||||
|
||||
|
||||
#pragma OPENCL EXTENSION cl_amd_printf : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
|
||||
|
||||
#ifdef cl_ext_atomic_counters_32
|
||||
#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
|
||||
#else
|
||||
#define counter32_t volatile __global int*
|
||||
#endif
|
||||
|
||||
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned char u8;
|
||||
|
||||
#define GET_GROUP_IDX get_group_id(0)
|
||||
#define GET_LOCAL_IDX get_local_id(0)
|
||||
#define GET_GLOBAL_IDX get_global_id(0)
|
||||
#define GET_GROUP_SIZE get_local_size(0)
|
||||
#define GET_NUM_GROUPS get_num_groups(0)
|
||||
#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
|
||||
#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
|
||||
#define AtomInc(x) atom_inc(&(x))
|
||||
#define AtomInc1(x, out) out = atom_inc(&(x))
|
||||
#define AppendInc(x, out) out = atomic_inc(x)
|
||||
#define AtomAdd(x, value) atom_add(&(x), value)
|
||||
#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
|
||||
#define AtomXhg(x, value) atom_xchg ( &(x), value )
|
||||
|
||||
|
||||
#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
|
||||
|
||||
#define make_float4 (float4)
|
||||
#define make_float2 (float2)
|
||||
#define make_uint4 (uint4)
|
||||
#define make_int4 (int4)
|
||||
#define make_uint2 (uint2)
|
||||
#define make_int2 (int2)
|
||||
|
||||
|
||||
#define max2 max
|
||||
#define min2 min
|
||||
|
||||
|
||||
#define WG_SIZE 64
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_worldPos[4];
|
||||
float4 m_worldNormal;
|
||||
u32 m_coeffs;
|
||||
int m_batchIdx;
|
||||
|
||||
int m_bodyA;//sign bit set for fixed objects
|
||||
int m_bodyB;
|
||||
}Contact4;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int m_n;
|
||||
int m_start;
|
||||
int m_staticIdx;
|
||||
int m_paddings[1];
|
||||
} ConstBuffer;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int m_a;
|
||||
int m_b;
|
||||
u32 m_idx;
|
||||
}Elem;
|
||||
|
||||
#define STACK_SIZE (WG_SIZE*10)
|
||||
//#define STACK_SIZE (WG_SIZE)
|
||||
#define RING_SIZE 1024
|
||||
#define RING_SIZE_MASK (RING_SIZE-1)
|
||||
#define CHECK_SIZE (WG_SIZE)
|
||||
|
||||
|
||||
#define GET_RING_CAPACITY (RING_SIZE - ldsRingEnd)
|
||||
#define RING_END ldsTmp
|
||||
|
||||
u32 readBuf(__local u32* buff, int idx)
|
||||
{
|
||||
idx = idx % (32*CHECK_SIZE);
|
||||
int bitIdx = idx%32;
|
||||
int bufIdx = idx/32;
|
||||
return buff[bufIdx] & (1<<bitIdx);
|
||||
}
|
||||
|
||||
void writeBuf(__local u32* buff, int idx)
|
||||
{
|
||||
idx = idx % (32*CHECK_SIZE);
|
||||
int bitIdx = idx%32;
|
||||
int bufIdx = idx/32;
|
||||
// buff[bufIdx] |= (1<<bitIdx);
|
||||
atom_or( &buff[bufIdx], (1<<bitIdx) );
|
||||
}
|
||||
|
||||
u32 tryWrite(__local u32* buff, int idx)
|
||||
{
|
||||
idx = idx % (32*CHECK_SIZE);
|
||||
int bitIdx = idx%32;
|
||||
int bufIdx = idx/32;
|
||||
u32 ans = (u32)atom_or( &buff[bufIdx], (1<<bitIdx) );
|
||||
return ((ans >> bitIdx)&1) == 0;
|
||||
}
|
||||
|
||||
// batching on the GPU
|
||||
__kernel void CreateBatches( __global const Contact4* gConstraints, __global Contact4* gConstraintsOut,
|
||||
__global const u32* gN, __global const u32* gStart,
|
||||
int m_staticIdx )
|
||||
{
|
||||
__local u32 ldsStackIdx[STACK_SIZE];
|
||||
__local u32 ldsStackEnd;
|
||||
__local Elem ldsRingElem[RING_SIZE];
|
||||
__local u32 ldsRingEnd;
|
||||
__local u32 ldsTmp;
|
||||
__local u32 ldsCheckBuffer[CHECK_SIZE];
|
||||
__local u32 ldsFixedBuffer[CHECK_SIZE];
|
||||
__local u32 ldsGEnd;
|
||||
__local u32 ldsDstEnd;
|
||||
|
||||
int wgIdx = GET_GROUP_IDX;
|
||||
int lIdx = GET_LOCAL_IDX;
|
||||
|
||||
const int m_n = gN[wgIdx];
|
||||
const int m_start = gStart[wgIdx];
|
||||
|
||||
if( lIdx == 0 )
|
||||
{
|
||||
ldsRingEnd = 0;
|
||||
ldsGEnd = 0;
|
||||
ldsStackEnd = 0;
|
||||
ldsDstEnd = m_start;
|
||||
}
|
||||
|
||||
// while(1)
|
||||
//was 250
|
||||
for(int ie=0; ie<50; ie++)
|
||||
{
|
||||
ldsFixedBuffer[lIdx] = 0;
|
||||
|
||||
for(int giter=0; giter<4; giter++)
|
||||
{
|
||||
int ringCap = GET_RING_CAPACITY;
|
||||
|
||||
// 1. fill ring
|
||||
if( ldsGEnd < m_n )
|
||||
{
|
||||
while( ringCap > WG_SIZE )
|
||||
{
|
||||
if( ldsGEnd >= m_n ) break;
|
||||
if( lIdx < ringCap - WG_SIZE )
|
||||
{
|
||||
int srcIdx;
|
||||
AtomInc1( ldsGEnd, srcIdx );
|
||||
if( srcIdx < m_n )
|
||||
{
|
||||
int dstIdx;
|
||||
AtomInc1( ldsRingEnd, dstIdx );
|
||||
|
||||
int a = gConstraints[m_start+srcIdx].m_bodyA;
|
||||
int b = gConstraints[m_start+srcIdx].m_bodyB;
|
||||
ldsRingElem[dstIdx].m_a = (a>b)? b:a;
|
||||
ldsRingElem[dstIdx].m_b = (a>b)? a:b;
|
||||
ldsRingElem[dstIdx].m_idx = srcIdx;
|
||||
}
|
||||
}
|
||||
ringCap = GET_RING_CAPACITY;
|
||||
}
|
||||
}
|
||||
|
||||
GROUP_LDS_BARRIER;
|
||||
|
||||
// 2. fill stack
|
||||
__local Elem* dst = ldsRingElem;
|
||||
if( lIdx == 0 ) RING_END = 0;
|
||||
|
||||
int srcIdx=lIdx;
|
||||
int end = ldsRingEnd;
|
||||
|
||||
{
|
||||
for(int ii=0; ii<end; ii+=WG_SIZE, srcIdx+=WG_SIZE)
|
||||
{
|
||||
Elem e;
|
||||
if(srcIdx<end) e = ldsRingElem[srcIdx];
|
||||
bool done = (srcIdx<end)?false:true;
|
||||
|
||||
for(int i=lIdx; i<CHECK_SIZE; i+=WG_SIZE) ldsCheckBuffer[lIdx] = 0;
|
||||
|
||||
if( !done )
|
||||
{
|
||||
int aUsed = readBuf( ldsFixedBuffer, abs(e.m_a));
|
||||
int bUsed = readBuf( ldsFixedBuffer, abs(e.m_b));
|
||||
|
||||
if( aUsed==0 && bUsed==0 )
|
||||
{
|
||||
int aAvailable;
|
||||
int bAvailable;
|
||||
int ea = abs(e.m_a);
|
||||
int eb = abs(e.m_b);
|
||||
|
||||
aAvailable = tryWrite( ldsCheckBuffer, ea );
|
||||
bAvailable = tryWrite( ldsCheckBuffer, eb );
|
||||
|
||||
bool aStatic = (e.m_a<0) ||(ea==m_staticIdx);
|
||||
bool bStatic = (e.m_b<0) ||(eb==m_staticIdx);
|
||||
|
||||
aAvailable = aStatic? 1: aAvailable;
|
||||
bAvailable = bStatic? 1: bAvailable;
|
||||
|
||||
bool success = (aAvailable && bAvailable);
|
||||
if(success)
|
||||
{
|
||||
|
||||
if (!aStatic)
|
||||
writeBuf( ldsFixedBuffer, ea );
|
||||
if (!bStatic)
|
||||
writeBuf( ldsFixedBuffer, eb );
|
||||
}
|
||||
done = success;
|
||||
}
|
||||
}
|
||||
|
||||
// put it aside
|
||||
if(srcIdx<end)
|
||||
{
|
||||
if( done )
|
||||
{
|
||||
int dstIdx; AtomInc1( ldsStackEnd, dstIdx );
|
||||
if( dstIdx < STACK_SIZE )
|
||||
ldsStackIdx[dstIdx] = e.m_idx;
|
||||
else{
|
||||
done = false;
|
||||
AtomAdd( ldsStackEnd, -1 );
|
||||
}
|
||||
}
|
||||
if( !done )
|
||||
{
|
||||
int dstIdx; AtomInc1( RING_END, dstIdx );
|
||||
dst[dstIdx] = e;
|
||||
}
|
||||
}
|
||||
|
||||
// if filled, flush
|
||||
if( ldsStackEnd == STACK_SIZE )
|
||||
{
|
||||
for(int i=lIdx; i<STACK_SIZE; i+=WG_SIZE)
|
||||
{
|
||||
int idx = m_start + ldsStackIdx[i];
|
||||
int dstIdx; AtomInc1( ldsDstEnd, dstIdx );
|
||||
gConstraintsOut[ dstIdx ] = gConstraints[ idx ];
|
||||
gConstraintsOut[ dstIdx ].m_batchIdx = ie;
|
||||
}
|
||||
if( lIdx == 0 ) ldsStackEnd = 0;
|
||||
|
||||
//for(int i=lIdx; i<CHECK_SIZE; i+=WG_SIZE)
|
||||
ldsFixedBuffer[lIdx] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( lIdx == 0 ) ldsRingEnd = RING_END;
|
||||
}
|
||||
|
||||
GROUP_LDS_BARRIER;
|
||||
|
||||
for(int i=lIdx; i<ldsStackEnd; i+=WG_SIZE)
|
||||
{
|
||||
int idx = m_start + ldsStackIdx[i];
|
||||
int dstIdx; AtomInc1( ldsDstEnd, dstIdx );
|
||||
gConstraintsOut[ dstIdx ] = gConstraints[ idx ];
|
||||
gConstraintsOut[ dstIdx ].m_batchIdx = ie;
|
||||
}
|
||||
|
||||
// in case it couldn't consume any pair. Flush them
|
||||
// todo. Serial batch worth while?
|
||||
if( ldsStackEnd == 0 )
|
||||
{
|
||||
for(int i=lIdx; i<ldsRingEnd; i+=WG_SIZE)
|
||||
{
|
||||
int idx = m_start + ldsRingElem[i].m_idx;
|
||||
int dstIdx; AtomInc1( ldsDstEnd, dstIdx );
|
||||
gConstraintsOut[ dstIdx ] = gConstraints[ idx ];
|
||||
gConstraintsOut[ dstIdx ].m_batchIdx = 100+i;
|
||||
}
|
||||
GROUP_LDS_BARRIER;
|
||||
if( lIdx == 0 ) ldsRingEnd = 0;
|
||||
}
|
||||
|
||||
if( lIdx == 0 ) ldsStackEnd = 0;
|
||||
|
||||
GROUP_LDS_BARRIER;
|
||||
|
||||
// termination
|
||||
if( ldsGEnd == m_n && ldsRingEnd == 0 )
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
348
src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.h
Normal file
348
src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.h
Normal file
@@ -0,0 +1,348 @@
|
||||
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
|
||||
static const char* batchingKernelsCL= \
|
||||
"/*\n"
|
||||
"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
|
||||
"\n"
|
||||
"This software is provided 'as-is', without any express or implied warranty.\n"
|
||||
"In no event will the authors be held liable for any damages arising from the use of this software.\n"
|
||||
"Permission is granted to anyone to use this software for any purpose, \n"
|
||||
"including commercial applications, and to alter it and redistribute it freely, \n"
|
||||
"subject to the following restrictions:\n"
|
||||
"\n"
|
||||
"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.\n"
|
||||
"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
|
||||
"3. This notice may not be removed or altered from any source distribution.\n"
|
||||
"*/\n"
|
||||
"//Originally written by Takahiro Harada\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
|
||||
"\n"
|
||||
"#ifdef cl_ext_atomic_counters_32\n"
|
||||
"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
|
||||
"#else\n"
|
||||
"#define counter32_t volatile __global int*\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"typedef unsigned int u32;\n"
|
||||
"typedef unsigned short u16;\n"
|
||||
"typedef unsigned char u8;\n"
|
||||
"\n"
|
||||
"#define GET_GROUP_IDX get_group_id(0)\n"
|
||||
"#define GET_LOCAL_IDX get_local_id(0)\n"
|
||||
"#define GET_GLOBAL_IDX get_global_id(0)\n"
|
||||
"#define GET_GROUP_SIZE get_local_size(0)\n"
|
||||
"#define GET_NUM_GROUPS get_num_groups(0)\n"
|
||||
"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
|
||||
"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
|
||||
"#define AtomInc(x) atom_inc(&(x))\n"
|
||||
"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
|
||||
"#define AppendInc(x, out) out = atomic_inc(x)\n"
|
||||
"#define AtomAdd(x, value) atom_add(&(x), value)\n"
|
||||
"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
|
||||
"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
|
||||
"\n"
|
||||
"#define make_float4 (float4)\n"
|
||||
"#define make_float2 (float2)\n"
|
||||
"#define make_uint4 (uint4)\n"
|
||||
"#define make_int4 (int4)\n"
|
||||
"#define make_uint2 (uint2)\n"
|
||||
"#define make_int2 (int2)\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define max2 max\n"
|
||||
"#define min2 min\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define WG_SIZE 64\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"typedef struct \n"
|
||||
"{\n"
|
||||
" float4 m_worldPos[4];\n"
|
||||
" float4 m_worldNormal;\n"
|
||||
" u32 m_coeffs;\n"
|
||||
" int m_batchIdx;\n"
|
||||
"\n"
|
||||
" int m_bodyA;//sign bit set for fixed objects\n"
|
||||
" int m_bodyB;\n"
|
||||
"}Contact4;\n"
|
||||
"\n"
|
||||
"typedef struct \n"
|
||||
"{\n"
|
||||
" int m_n;\n"
|
||||
" int m_start;\n"
|
||||
" int m_staticIdx;\n"
|
||||
" int m_paddings[1];\n"
|
||||
"} ConstBuffer;\n"
|
||||
"\n"
|
||||
"typedef struct \n"
|
||||
"{\n"
|
||||
" int m_a;\n"
|
||||
" int m_b;\n"
|
||||
" u32 m_idx;\n"
|
||||
"}Elem;\n"
|
||||
"\n"
|
||||
"#define STACK_SIZE (WG_SIZE*10)\n"
|
||||
"//#define STACK_SIZE (WG_SIZE)\n"
|
||||
"#define RING_SIZE 1024\n"
|
||||
"#define RING_SIZE_MASK (RING_SIZE-1)\n"
|
||||
"#define CHECK_SIZE (WG_SIZE)\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define GET_RING_CAPACITY (RING_SIZE - ldsRingEnd)\n"
|
||||
"#define RING_END ldsTmp\n"
|
||||
"\n"
|
||||
"u32 readBuf(__local u32* buff, int idx)\n"
|
||||
"{\n"
|
||||
" idx = idx % (32*CHECK_SIZE);\n"
|
||||
" int bitIdx = idx%32;\n"
|
||||
" int bufIdx = idx/32;\n"
|
||||
" return buff[bufIdx] & (1<<bitIdx);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void writeBuf(__local u32* buff, int idx)\n"
|
||||
"{\n"
|
||||
" idx = idx % (32*CHECK_SIZE);\n"
|
||||
" int bitIdx = idx%32;\n"
|
||||
" int bufIdx = idx/32;\n"
|
||||
"// buff[bufIdx] |= (1<<bitIdx);\n"
|
||||
" atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"u32 tryWrite(__local u32* buff, int idx)\n"
|
||||
"{\n"
|
||||
" idx = idx % (32*CHECK_SIZE);\n"
|
||||
" int bitIdx = idx%32;\n"
|
||||
" int bufIdx = idx/32;\n"
|
||||
" u32 ans = (u32)atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
|
||||
" return ((ans >> bitIdx)&1) == 0;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"// batching on the GPU\n"
|
||||
"__kernel void CreateBatches( __global const Contact4* gConstraints, __global Contact4* gConstraintsOut,\n"
|
||||
" __global const u32* gN, __global const u32* gStart, \n"
|
||||
" int m_staticIdx )\n"
|
||||
"{\n"
|
||||
" __local u32 ldsStackIdx[STACK_SIZE];\n"
|
||||
" __local u32 ldsStackEnd;\n"
|
||||
" __local Elem ldsRingElem[RING_SIZE];\n"
|
||||
" __local u32 ldsRingEnd;\n"
|
||||
" __local u32 ldsTmp;\n"
|
||||
" __local u32 ldsCheckBuffer[CHECK_SIZE];\n"
|
||||
" __local u32 ldsFixedBuffer[CHECK_SIZE];\n"
|
||||
" __local u32 ldsGEnd;\n"
|
||||
" __local u32 ldsDstEnd;\n"
|
||||
"\n"
|
||||
" int wgIdx = GET_GROUP_IDX;\n"
|
||||
" int lIdx = GET_LOCAL_IDX;\n"
|
||||
" \n"
|
||||
" const int m_n = gN[wgIdx];\n"
|
||||
" const int m_start = gStart[wgIdx];\n"
|
||||
" \n"
|
||||
" if( lIdx == 0 )\n"
|
||||
" {\n"
|
||||
" ldsRingEnd = 0;\n"
|
||||
" ldsGEnd = 0;\n"
|
||||
" ldsStackEnd = 0;\n"
|
||||
" ldsDstEnd = m_start;\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
"// while(1)\n"
|
||||
"//was 250\n"
|
||||
" for(int ie=0; ie<50; ie++)\n"
|
||||
" {\n"
|
||||
" ldsFixedBuffer[lIdx] = 0;\n"
|
||||
"\n"
|
||||
" for(int giter=0; giter<4; giter++)\n"
|
||||
" {\n"
|
||||
" int ringCap = GET_RING_CAPACITY;\n"
|
||||
" \n"
|
||||
" // 1. fill ring\n"
|
||||
" if( ldsGEnd < m_n )\n"
|
||||
" {\n"
|
||||
" while( ringCap > WG_SIZE )\n"
|
||||
" {\n"
|
||||
" if( ldsGEnd >= m_n ) break;\n"
|
||||
" if( lIdx < ringCap - WG_SIZE )\n"
|
||||
" {\n"
|
||||
" int srcIdx;\n"
|
||||
" AtomInc1( ldsGEnd, srcIdx );\n"
|
||||
" if( srcIdx < m_n )\n"
|
||||
" {\n"
|
||||
" int dstIdx;\n"
|
||||
" AtomInc1( ldsRingEnd, dstIdx );\n"
|
||||
" \n"
|
||||
" int a = gConstraints[m_start+srcIdx].m_bodyA;\n"
|
||||
" int b = gConstraints[m_start+srcIdx].m_bodyB;\n"
|
||||
" ldsRingElem[dstIdx].m_a = (a>b)? b:a;\n"
|
||||
" ldsRingElem[dstIdx].m_b = (a>b)? a:b;\n"
|
||||
" ldsRingElem[dstIdx].m_idx = srcIdx;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" ringCap = GET_RING_CAPACITY;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" GROUP_LDS_BARRIER;\n"
|
||||
" \n"
|
||||
" // 2. fill stack\n"
|
||||
" __local Elem* dst = ldsRingElem;\n"
|
||||
" if( lIdx == 0 ) RING_END = 0;\n"
|
||||
"\n"
|
||||
" int srcIdx=lIdx;\n"
|
||||
" int end = ldsRingEnd;\n"
|
||||
"\n"
|
||||
" {\n"
|
||||
" for(int ii=0; ii<end; ii+=WG_SIZE, srcIdx+=WG_SIZE)\n"
|
||||
" {\n"
|
||||
" Elem e;\n"
|
||||
" if(srcIdx<end) e = ldsRingElem[srcIdx];\n"
|
||||
" bool done = (srcIdx<end)?false:true;\n"
|
||||
"\n"
|
||||
" for(int i=lIdx; i<CHECK_SIZE; i+=WG_SIZE) ldsCheckBuffer[lIdx] = 0;\n"
|
||||
" \n"
|
||||
" if( !done )\n"
|
||||
" {\n"
|
||||
" int aUsed = readBuf( ldsFixedBuffer, abs(e.m_a));\n"
|
||||
" int bUsed = readBuf( ldsFixedBuffer, abs(e.m_b));\n"
|
||||
"\n"
|
||||
" if( aUsed==0 && bUsed==0 )\n"
|
||||
" {\n"
|
||||
" int aAvailable;\n"
|
||||
" int bAvailable;\n"
|
||||
" int ea = abs(e.m_a);\n"
|
||||
" int eb = abs(e.m_b);\n"
|
||||
"\n"
|
||||
" aAvailable = tryWrite( ldsCheckBuffer, ea );\n"
|
||||
" bAvailable = tryWrite( ldsCheckBuffer, eb );\n"
|
||||
"\n"
|
||||
" bool aStatic = (e.m_a<0) ||(ea==m_staticIdx);\n"
|
||||
" bool bStatic = (e.m_b<0) ||(eb==m_staticIdx);\n"
|
||||
" \n"
|
||||
" aAvailable = aStatic? 1: aAvailable;\n"
|
||||
" bAvailable = bStatic? 1: bAvailable;\n"
|
||||
"\n"
|
||||
" bool success = (aAvailable && bAvailable);\n"
|
||||
" if(success)\n"
|
||||
" {\n"
|
||||
" \n"
|
||||
" if (!aStatic)\n"
|
||||
" writeBuf( ldsFixedBuffer, ea );\n"
|
||||
" if (!bStatic)\n"
|
||||
" writeBuf( ldsFixedBuffer, eb );\n"
|
||||
" }\n"
|
||||
" done = success;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" // put it aside\n"
|
||||
" if(srcIdx<end)\n"
|
||||
" {\n"
|
||||
" if( done )\n"
|
||||
" {\n"
|
||||
" int dstIdx; AtomInc1( ldsStackEnd, dstIdx );\n"
|
||||
" if( dstIdx < STACK_SIZE )\n"
|
||||
" ldsStackIdx[dstIdx] = e.m_idx;\n"
|
||||
" else{\n"
|
||||
" done = false;\n"
|
||||
" AtomAdd( ldsStackEnd, -1 );\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" if( !done )\n"
|
||||
" {\n"
|
||||
" int dstIdx; AtomInc1( RING_END, dstIdx );\n"
|
||||
" dst[dstIdx] = e;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" // if filled, flush\n"
|
||||
" if( ldsStackEnd == STACK_SIZE )\n"
|
||||
" {\n"
|
||||
" for(int i=lIdx; i<STACK_SIZE; i+=WG_SIZE)\n"
|
||||
" {\n"
|
||||
" int idx = m_start + ldsStackIdx[i];\n"
|
||||
" int dstIdx; AtomInc1( ldsDstEnd, dstIdx );\n"
|
||||
" gConstraintsOut[ dstIdx ] = gConstraints[ idx ];\n"
|
||||
" gConstraintsOut[ dstIdx ].m_batchIdx = ie;\n"
|
||||
" }\n"
|
||||
" if( lIdx == 0 ) ldsStackEnd = 0;\n"
|
||||
"\n"
|
||||
" //for(int i=lIdx; i<CHECK_SIZE; i+=WG_SIZE) \n"
|
||||
" ldsFixedBuffer[lIdx] = 0;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" if( lIdx == 0 ) ldsRingEnd = RING_END;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" GROUP_LDS_BARRIER;\n"
|
||||
"\n"
|
||||
" for(int i=lIdx; i<ldsStackEnd; i+=WG_SIZE)\n"
|
||||
" {\n"
|
||||
" int idx = m_start + ldsStackIdx[i];\n"
|
||||
" int dstIdx; AtomInc1( ldsDstEnd, dstIdx );\n"
|
||||
" gConstraintsOut[ dstIdx ] = gConstraints[ idx ];\n"
|
||||
" gConstraintsOut[ dstIdx ].m_batchIdx = ie;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" // in case it couldn't consume any pair. Flush them\n"
|
||||
" // todo. Serial batch worth while?\n"
|
||||
" if( ldsStackEnd == 0 )\n"
|
||||
" {\n"
|
||||
" for(int i=lIdx; i<ldsRingEnd; i+=WG_SIZE)\n"
|
||||
" {\n"
|
||||
" int idx = m_start + ldsRingElem[i].m_idx;\n"
|
||||
" int dstIdx; AtomInc1( ldsDstEnd, dstIdx );\n"
|
||||
" gConstraintsOut[ dstIdx ] = gConstraints[ idx ];\n"
|
||||
" gConstraintsOut[ dstIdx ].m_batchIdx = 100+i;\n"
|
||||
" }\n"
|
||||
" GROUP_LDS_BARRIER;\n"
|
||||
" if( lIdx == 0 ) ldsRingEnd = 0;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" if( lIdx == 0 ) ldsStackEnd = 0;\n"
|
||||
"\n"
|
||||
" GROUP_LDS_BARRIER;\n"
|
||||
"\n"
|
||||
" // termination\n"
|
||||
" if( ldsGEnd == m_n && ldsRingEnd == 0 )\n"
|
||||
" break;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
;
|
||||
236
src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.cl
Normal file
236
src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.cl
Normal file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
Copyright (c) 2012 Advanced Micro Devices, Inc.
|
||||
|
||||
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.
|
||||
*/
|
||||
//Originally written by Erwin Coumans
|
||||
|
||||
|
||||
#pragma OPENCL EXTENSION cl_amd_printf : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
|
||||
|
||||
#ifdef cl_ext_atomic_counters_32
|
||||
#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
|
||||
#else
|
||||
#define counter32_t volatile __global int*
|
||||
#endif
|
||||
|
||||
#define SIMD_WIDTH 64
|
||||
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned char u8;
|
||||
|
||||
#define GET_GROUP_IDX get_group_id(0)
|
||||
#define GET_LOCAL_IDX get_local_id(0)
|
||||
#define GET_GLOBAL_IDX get_global_id(0)
|
||||
#define GET_GROUP_SIZE get_local_size(0)
|
||||
#define GET_NUM_GROUPS get_num_groups(0)
|
||||
#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
|
||||
#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
|
||||
#define AtomInc(x) atom_inc(&(x))
|
||||
#define AtomInc1(x, out) out = atom_inc(&(x))
|
||||
#define AppendInc(x, out) out = atomic_inc(x)
|
||||
#define AtomAdd(x, value) atom_add(&(x), value)
|
||||
#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
|
||||
#define AtomXhg(x, value) atom_xchg ( &(x), value )
|
||||
|
||||
|
||||
#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
|
||||
|
||||
#define make_float4 (float4)
|
||||
#define make_float2 (float2)
|
||||
#define make_uint4 (uint4)
|
||||
#define make_int4 (int4)
|
||||
#define make_uint2 (uint2)
|
||||
#define make_int2 (int2)
|
||||
|
||||
|
||||
#define max2 max
|
||||
#define min2 min
|
||||
|
||||
|
||||
#define WG_SIZE 64
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_worldPos[4];
|
||||
float4 m_worldNormal;
|
||||
u32 m_coeffs;
|
||||
int m_batchIdx;
|
||||
|
||||
int m_bodyAPtrAndSignBit;//sign bit set for fixed objects
|
||||
int m_bodyBPtrAndSignBit;
|
||||
}Contact4;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int m_n;
|
||||
int m_start;
|
||||
int m_staticIdx;
|
||||
int m_paddings[1];
|
||||
} ConstBuffer;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int m_a;
|
||||
int m_b;
|
||||
u32 m_idx;
|
||||
}Elem;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// batching on the GPU
|
||||
__kernel void CreateBatchesBruteForce( __global Contact4* gConstraints, __global const u32* gN, __global const u32* gStart, int m_staticIdx )
|
||||
{
|
||||
int wgIdx = GET_GROUP_IDX;
|
||||
int lIdx = GET_LOCAL_IDX;
|
||||
|
||||
const int m_n = gN[wgIdx];
|
||||
const int m_start = gStart[wgIdx];
|
||||
|
||||
if( lIdx == 0 )
|
||||
{
|
||||
for (int i=0;i<m_n;i++)
|
||||
{
|
||||
int srcIdx = i+m_start;
|
||||
int batchIndex = i;
|
||||
gConstraints[ srcIdx ].m_batchIdx = batchIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define CHECK_SIZE (WG_SIZE)
|
||||
|
||||
|
||||
|
||||
|
||||
u32 readBuf(__local u32* buff, int idx)
|
||||
{
|
||||
idx = idx % (32*CHECK_SIZE);
|
||||
int bitIdx = idx%32;
|
||||
int bufIdx = idx/32;
|
||||
return buff[bufIdx] & (1<<bitIdx);
|
||||
}
|
||||
|
||||
void writeBuf(__local u32* buff, int idx)
|
||||
{
|
||||
idx = idx % (32*CHECK_SIZE);
|
||||
int bitIdx = idx%32;
|
||||
int bufIdx = idx/32;
|
||||
buff[bufIdx] |= (1<<bitIdx);
|
||||
//atom_or( &buff[bufIdx], (1<<bitIdx) );
|
||||
}
|
||||
|
||||
u32 tryWrite(__local u32* buff, int idx)
|
||||
{
|
||||
idx = idx % (32*CHECK_SIZE);
|
||||
int bitIdx = idx%32;
|
||||
int bufIdx = idx/32;
|
||||
u32 ans = (u32)atom_or( &buff[bufIdx], (1<<bitIdx) );
|
||||
return ((ans >> bitIdx)&1) == 0;
|
||||
}
|
||||
|
||||
|
||||
// batching on the GPU
|
||||
__kernel void CreateBatchesNew( __global Contact4* gConstraints, __global const u32* gN, __global const u32* gStart, int staticIdx )
|
||||
{
|
||||
int wgIdx = GET_GROUP_IDX;
|
||||
int lIdx = GET_LOCAL_IDX;
|
||||
const int numConstraints = gN[wgIdx];
|
||||
const int m_start = gStart[wgIdx];
|
||||
|
||||
|
||||
__local u32 ldsFixedBuffer[CHECK_SIZE];
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if( lIdx == 0 )
|
||||
{
|
||||
|
||||
|
||||
__global Contact4* cs = &gConstraints[m_start];
|
||||
|
||||
|
||||
int numValidConstraints = 0;
|
||||
int batchIdx = 0;
|
||||
|
||||
while( numValidConstraints < numConstraints)
|
||||
{
|
||||
int nCurrentBatch = 0;
|
||||
// clear flag
|
||||
|
||||
for(int i=0; i<CHECK_SIZE; i++)
|
||||
ldsFixedBuffer[i] = 0;
|
||||
|
||||
for(int i=numValidConstraints; i<numConstraints; i++)
|
||||
{
|
||||
|
||||
int bodyAS = cs[i].m_bodyAPtrAndSignBit;
|
||||
int bodyBS = cs[i].m_bodyBPtrAndSignBit;
|
||||
int bodyA = abs(bodyAS);
|
||||
int bodyB = abs(bodyBS);
|
||||
bool aIsStatic = (bodyAS<0) || bodyAS==staticIdx;
|
||||
bool bIsStatic = (bodyBS<0) || bodyBS==staticIdx;
|
||||
int aUnavailable = aIsStatic ? 0 : readBuf( ldsFixedBuffer, bodyA);
|
||||
int bUnavailable = bIsStatic ? 0 : readBuf( ldsFixedBuffer, bodyB);
|
||||
|
||||
if( aUnavailable==0 && bUnavailable==0 ) // ok
|
||||
{
|
||||
if (!aIsStatic)
|
||||
{
|
||||
writeBuf( ldsFixedBuffer, bodyA );
|
||||
}
|
||||
if (!bIsStatic)
|
||||
{
|
||||
writeBuf( ldsFixedBuffer, bodyB );
|
||||
}
|
||||
|
||||
cs[i].m_batchIdx = batchIdx;
|
||||
|
||||
if (i!=numValidConstraints)
|
||||
{
|
||||
//btSwap(cs[i],cs[numValidConstraints]);
|
||||
|
||||
Contact4 tmp = cs[i];
|
||||
cs[i] = cs[numValidConstraints];
|
||||
cs[numValidConstraints] = tmp;
|
||||
|
||||
}
|
||||
|
||||
numValidConstraints++;
|
||||
|
||||
nCurrentBatch++;
|
||||
if( nCurrentBatch == SIMD_WIDTH)
|
||||
{
|
||||
nCurrentBatch = 0;
|
||||
for(int i=0; i<CHECK_SIZE; i++)
|
||||
ldsFixedBuffer[i] = 0;
|
||||
|
||||
}
|
||||
}
|
||||
}//for
|
||||
batchIdx ++;
|
||||
}//while
|
||||
}//if( lIdx == 0 )
|
||||
|
||||
//return batchIdx;
|
||||
}
|
||||
240
src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.h
Normal file
240
src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.h
Normal file
@@ -0,0 +1,240 @@
|
||||
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
|
||||
static const char* batchingKernelsNewCL= \
|
||||
"/*\n"
|
||||
"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
|
||||
"\n"
|
||||
"This software is provided 'as-is', without any express or implied warranty.\n"
|
||||
"In no event will the authors be held liable for any damages arising from the use of this software.\n"
|
||||
"Permission is granted to anyone to use this software for any purpose, \n"
|
||||
"including commercial applications, and to alter it and redistribute it freely, \n"
|
||||
"subject to the following restrictions:\n"
|
||||
"\n"
|
||||
"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.\n"
|
||||
"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
|
||||
"3. This notice may not be removed or altered from any source distribution.\n"
|
||||
"*/\n"
|
||||
"//Originally written by Erwin Coumans\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
|
||||
"\n"
|
||||
"#ifdef cl_ext_atomic_counters_32\n"
|
||||
"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
|
||||
"#else\n"
|
||||
"#define counter32_t volatile __global int*\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"#define SIMD_WIDTH 64\n"
|
||||
"\n"
|
||||
"typedef unsigned int u32;\n"
|
||||
"typedef unsigned short u16;\n"
|
||||
"typedef unsigned char u8;\n"
|
||||
"\n"
|
||||
"#define GET_GROUP_IDX get_group_id(0)\n"
|
||||
"#define GET_LOCAL_IDX get_local_id(0)\n"
|
||||
"#define GET_GLOBAL_IDX get_global_id(0)\n"
|
||||
"#define GET_GROUP_SIZE get_local_size(0)\n"
|
||||
"#define GET_NUM_GROUPS get_num_groups(0)\n"
|
||||
"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
|
||||
"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
|
||||
"#define AtomInc(x) atom_inc(&(x))\n"
|
||||
"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
|
||||
"#define AppendInc(x, out) out = atomic_inc(x)\n"
|
||||
"#define AtomAdd(x, value) atom_add(&(x), value)\n"
|
||||
"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
|
||||
"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
|
||||
"\n"
|
||||
"#define make_float4 (float4)\n"
|
||||
"#define make_float2 (float2)\n"
|
||||
"#define make_uint4 (uint4)\n"
|
||||
"#define make_int4 (int4)\n"
|
||||
"#define make_uint2 (uint2)\n"
|
||||
"#define make_int2 (int2)\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define max2 max\n"
|
||||
"#define min2 min\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define WG_SIZE 64\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"typedef struct \n"
|
||||
"{\n"
|
||||
" float4 m_worldPos[4];\n"
|
||||
" float4 m_worldNormal;\n"
|
||||
" u32 m_coeffs;\n"
|
||||
" int m_batchIdx;\n"
|
||||
"\n"
|
||||
" int m_bodyAPtrAndSignBit;//sign bit set for fixed objects\n"
|
||||
" int m_bodyBPtrAndSignBit;\n"
|
||||
"}Contact4;\n"
|
||||
"\n"
|
||||
"typedef struct \n"
|
||||
"{\n"
|
||||
" int m_n;\n"
|
||||
" int m_start;\n"
|
||||
" int m_staticIdx;\n"
|
||||
" int m_paddings[1];\n"
|
||||
"} ConstBuffer;\n"
|
||||
"\n"
|
||||
"typedef struct \n"
|
||||
"{\n"
|
||||
" int m_a;\n"
|
||||
" int m_b;\n"
|
||||
" u32 m_idx;\n"
|
||||
"}Elem;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"// batching on the GPU\n"
|
||||
"__kernel void CreateBatchesBruteForce( __global Contact4* gConstraints, __global const u32* gN, __global const u32* gStart, int m_staticIdx )\n"
|
||||
"{\n"
|
||||
" int wgIdx = GET_GROUP_IDX;\n"
|
||||
" int lIdx = GET_LOCAL_IDX;\n"
|
||||
" \n"
|
||||
" const int m_n = gN[wgIdx];\n"
|
||||
" const int m_start = gStart[wgIdx];\n"
|
||||
" \n"
|
||||
" if( lIdx == 0 )\n"
|
||||
" {\n"
|
||||
" for (int i=0;i<m_n;i++)\n"
|
||||
" {\n"
|
||||
" int srcIdx = i+m_start;\n"
|
||||
" int batchIndex = i;\n"
|
||||
" gConstraints[ srcIdx ].m_batchIdx = batchIndex; \n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define CHECK_SIZE (WG_SIZE)\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"u32 readBuf(__local u32* buff, int idx)\n"
|
||||
"{\n"
|
||||
" idx = idx % (32*CHECK_SIZE);\n"
|
||||
" int bitIdx = idx%32;\n"
|
||||
" int bufIdx = idx/32;\n"
|
||||
" return buff[bufIdx] & (1<<bitIdx);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void writeBuf(__local u32* buff, int idx)\n"
|
||||
"{\n"
|
||||
" idx = idx % (32*CHECK_SIZE);\n"
|
||||
" int bitIdx = idx%32;\n"
|
||||
" int bufIdx = idx/32;\n"
|
||||
" buff[bufIdx] |= (1<<bitIdx);\n"
|
||||
" //atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"u32 tryWrite(__local u32* buff, int idx)\n"
|
||||
"{\n"
|
||||
" idx = idx % (32*CHECK_SIZE);\n"
|
||||
" int bitIdx = idx%32;\n"
|
||||
" int bufIdx = idx/32;\n"
|
||||
" u32 ans = (u32)atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
|
||||
" return ((ans >> bitIdx)&1) == 0;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"// batching on the GPU\n"
|
||||
"__kernel void CreateBatchesNew( __global Contact4* gConstraints, __global const u32* gN, __global const u32* gStart, int staticIdx )\n"
|
||||
"{\n"
|
||||
" int wgIdx = GET_GROUP_IDX;\n"
|
||||
" int lIdx = GET_LOCAL_IDX;\n"
|
||||
" const int numConstraints = gN[wgIdx];\n"
|
||||
" const int m_start = gStart[wgIdx];\n"
|
||||
" \n"
|
||||
" \n"
|
||||
" __local u32 ldsFixedBuffer[CHECK_SIZE];\n"
|
||||
" \n"
|
||||
" \n"
|
||||
" \n"
|
||||
" \n"
|
||||
" \n"
|
||||
" if( lIdx == 0 )\n"
|
||||
" {\n"
|
||||
" \n"
|
||||
" \n"
|
||||
" __global Contact4* cs = &gConstraints[m_start]; \n"
|
||||
" \n"
|
||||
" \n"
|
||||
" int numValidConstraints = 0;\n"
|
||||
" int batchIdx = 0;\n"
|
||||
"\n"
|
||||
" while( numValidConstraints < numConstraints)\n"
|
||||
" {\n"
|
||||
" int nCurrentBatch = 0;\n"
|
||||
" // clear flag\n"
|
||||
" \n"
|
||||
" for(int i=0; i<CHECK_SIZE; i++) \n"
|
||||
" ldsFixedBuffer[i] = 0; \n"
|
||||
"\n"
|
||||
" for(int i=numValidConstraints; i<numConstraints; i++)\n"
|
||||
" {\n"
|
||||
"\n"
|
||||
" int bodyAS = cs[i].m_bodyAPtrAndSignBit;\n"
|
||||
" int bodyBS = cs[i].m_bodyBPtrAndSignBit;\n"
|
||||
" int bodyA = abs(bodyAS);\n"
|
||||
" int bodyB = abs(bodyBS);\n"
|
||||
" bool aIsStatic = (bodyAS<0) || bodyAS==staticIdx;\n"
|
||||
" bool bIsStatic = (bodyBS<0) || bodyBS==staticIdx;\n"
|
||||
" int aUnavailable = aIsStatic ? 0 : readBuf( ldsFixedBuffer, bodyA);\n"
|
||||
" int bUnavailable = bIsStatic ? 0 : readBuf( ldsFixedBuffer, bodyB);\n"
|
||||
" \n"
|
||||
" if( aUnavailable==0 && bUnavailable==0 ) // ok\n"
|
||||
" {\n"
|
||||
" if (!aIsStatic)\n"
|
||||
" {\n"
|
||||
" writeBuf( ldsFixedBuffer, bodyA );\n"
|
||||
" }\n"
|
||||
" if (!bIsStatic)\n"
|
||||
" {\n"
|
||||
" writeBuf( ldsFixedBuffer, bodyB );\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" cs[i].m_batchIdx = batchIdx;\n"
|
||||
"\n"
|
||||
" if (i!=numValidConstraints)\n"
|
||||
" {\n"
|
||||
" //b3Swap(cs[i],cs[numValidConstraints]);\n"
|
||||
" \n"
|
||||
" Contact4 tmp = cs[i];\n"
|
||||
" cs[i] = cs[numValidConstraints];\n"
|
||||
" cs[numValidConstraints] = tmp;\n"
|
||||
" \n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" numValidConstraints++;\n"
|
||||
" \n"
|
||||
" nCurrentBatch++;\n"
|
||||
" if( nCurrentBatch == SIMD_WIDTH)\n"
|
||||
" {\n"
|
||||
" nCurrentBatch = 0;\n"
|
||||
" for(int i=0; i<CHECK_SIZE; i++) \n"
|
||||
" ldsFixedBuffer[i] = 0;\n"
|
||||
" \n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }//for\n"
|
||||
" batchIdx ++;\n"
|
||||
" }//while\n"
|
||||
" }//if( lIdx == 0 )\n"
|
||||
" \n"
|
||||
" //return batchIdx;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
;
|
||||
92
src/Bullet3OpenCL/RigidBody/kernels/integrateKernel.cl
Normal file
92
src/Bullet3OpenCL/RigidBody/kernels/integrateKernel.cl
Normal file
@@ -0,0 +1,92 @@
|
||||
|
||||
float4 quatMult(float4 q1, float4 q2)
|
||||
{
|
||||
float4 q;
|
||||
q.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y;
|
||||
q.y = q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z;
|
||||
q.z = q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x;
|
||||
q.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z;
|
||||
return q;
|
||||
}
|
||||
|
||||
float4 quatNorm(float4 q)
|
||||
{
|
||||
float len = native_sqrt(dot(q, q));
|
||||
if(len > 0.f)
|
||||
{
|
||||
q *= 1.f / len;
|
||||
}
|
||||
else
|
||||
{
|
||||
q.x = q.y = q.z = 0.f;
|
||||
q.w = 1.f;
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_pos;
|
||||
float4 m_quat;
|
||||
float4 m_linVel;
|
||||
float4 m_angVel;
|
||||
|
||||
unsigned int m_collidableIdx;
|
||||
float m_invMass;
|
||||
float m_restituitionCoeff;
|
||||
float m_frictionCoeff;
|
||||
} Body;
|
||||
|
||||
|
||||
|
||||
|
||||
__kernel void
|
||||
integrateTransformsKernel( __global Body* bodies,const int numNodes, float timeStep, float angularDamping, float4 gravityAcceleration)
|
||||
{
|
||||
int nodeID = get_global_id(0);
|
||||
float BT_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254f);
|
||||
if( nodeID < numNodes && (bodies[nodeID].m_invMass != 0.f))
|
||||
{
|
||||
//angular velocity
|
||||
{
|
||||
float4 axis;
|
||||
//add some hardcoded angular damping
|
||||
bodies[nodeID].m_angVel.x *= angularDamping;
|
||||
bodies[nodeID].m_angVel.y *= angularDamping;
|
||||
bodies[nodeID].m_angVel.z *= angularDamping;
|
||||
|
||||
float4 angvel = bodies[nodeID].m_angVel;
|
||||
float fAngle = native_sqrt(dot(angvel, angvel));
|
||||
//limit the angular motion
|
||||
if(fAngle*timeStep > BT_GPU_ANGULAR_MOTION_THRESHOLD)
|
||||
{
|
||||
fAngle = BT_GPU_ANGULAR_MOTION_THRESHOLD / timeStep;
|
||||
}
|
||||
if(fAngle < 0.001f)
|
||||
{
|
||||
// use Taylor's expansions of sync function
|
||||
axis = angvel * (0.5f*timeStep-(timeStep*timeStep*timeStep)*0.020833333333f * fAngle * fAngle);
|
||||
}
|
||||
else
|
||||
{
|
||||
// sync(fAngle) = sin(c*fAngle)/t
|
||||
axis = angvel * ( native_sin(0.5f * fAngle * timeStep) / fAngle);
|
||||
}
|
||||
float4 dorn = axis;
|
||||
dorn.w = native_cos(fAngle * timeStep * 0.5f);
|
||||
float4 orn0 = bodies[nodeID].m_quat;
|
||||
|
||||
float4 predictedOrn = quatMult(dorn, orn0);
|
||||
predictedOrn = quatNorm(predictedOrn);
|
||||
bodies[nodeID].m_quat=predictedOrn;
|
||||
}
|
||||
|
||||
//linear velocity
|
||||
bodies[nodeID].m_pos += bodies[nodeID].m_linVel * timeStep;
|
||||
|
||||
//apply gravity
|
||||
bodies[nodeID].m_linVel += gravityAcceleration * timeStep;
|
||||
|
||||
}
|
||||
}
|
||||
96
src/Bullet3OpenCL/RigidBody/kernels/integrateKernel.h
Normal file
96
src/Bullet3OpenCL/RigidBody/kernels/integrateKernel.h
Normal file
@@ -0,0 +1,96 @@
|
||||
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
|
||||
static const char* integrateKernelCL= \
|
||||
"\n"
|
||||
"float4 quatMult(float4 q1, float4 q2)\n"
|
||||
"{\n"
|
||||
" float4 q;\n"
|
||||
" q.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y;\n"
|
||||
" q.y = q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z;\n"
|
||||
" q.z = q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x;\n"
|
||||
" q.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z; \n"
|
||||
" return q;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"float4 quatNorm(float4 q)\n"
|
||||
"{\n"
|
||||
" float len = native_sqrt(dot(q, q));\n"
|
||||
" if(len > 0.f)\n"
|
||||
" {\n"
|
||||
" q *= 1.f / len;\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" q.x = q.y = q.z = 0.f;\n"
|
||||
" q.w = 1.f;\n"
|
||||
" }\n"
|
||||
" return q;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_pos;\n"
|
||||
" float4 m_quat;\n"
|
||||
" float4 m_linVel;\n"
|
||||
" float4 m_angVel;\n"
|
||||
"\n"
|
||||
" unsigned int m_collidableIdx;\n"
|
||||
" float m_invMass;\n"
|
||||
" float m_restituitionCoeff;\n"
|
||||
" float m_frictionCoeff;\n"
|
||||
"} Body;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__kernel void \n"
|
||||
" integrateTransformsKernel( __global Body* bodies,const int numNodes, float timeStep, float angularDamping, float4 gravityAcceleration)\n"
|
||||
"{\n"
|
||||
" int nodeID = get_global_id(0);\n"
|
||||
" float B3_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254f);\n"
|
||||
" if( nodeID < numNodes && (bodies[nodeID].m_invMass != 0.f))\n"
|
||||
" {\n"
|
||||
" //angular velocity\n"
|
||||
" {\n"
|
||||
" float4 axis;\n"
|
||||
" //add some hardcoded angular damping\n"
|
||||
" bodies[nodeID].m_angVel.x *= angularDamping;\n"
|
||||
" bodies[nodeID].m_angVel.y *= angularDamping;\n"
|
||||
" bodies[nodeID].m_angVel.z *= angularDamping;\n"
|
||||
" \n"
|
||||
" float4 angvel = bodies[nodeID].m_angVel;\n"
|
||||
" float fAngle = native_sqrt(dot(angvel, angvel));\n"
|
||||
" //limit the angular motion\n"
|
||||
" if(fAngle*timeStep > B3_GPU_ANGULAR_MOTION_THRESHOLD)\n"
|
||||
" {\n"
|
||||
" fAngle = B3_GPU_ANGULAR_MOTION_THRESHOLD / timeStep;\n"
|
||||
" }\n"
|
||||
" if(fAngle < 0.001f)\n"
|
||||
" {\n"
|
||||
" // use Taylor's expansions of sync function\n"
|
||||
" axis = angvel * (0.5f*timeStep-(timeStep*timeStep*timeStep)*0.020833333333f * fAngle * fAngle);\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" // sync(fAngle) = sin(c*fAngle)/t\n"
|
||||
" axis = angvel * ( native_sin(0.5f * fAngle * timeStep) / fAngle);\n"
|
||||
" }\n"
|
||||
" float4 dorn = axis;\n"
|
||||
" dorn.w = native_cos(fAngle * timeStep * 0.5f);\n"
|
||||
" float4 orn0 = bodies[nodeID].m_quat;\n"
|
||||
"\n"
|
||||
" float4 predictedOrn = quatMult(dorn, orn0);\n"
|
||||
" predictedOrn = quatNorm(predictedOrn);\n"
|
||||
" bodies[nodeID].m_quat=predictedOrn;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" //linear velocity \n"
|
||||
" bodies[nodeID].m_pos += bodies[nodeID].m_linVel * timeStep;\n"
|
||||
" \n"
|
||||
" //apply gravity\n"
|
||||
" bodies[nodeID].m_linVel += gravityAcceleration * timeStep;\n"
|
||||
" \n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
;
|
||||
476
src/Bullet3OpenCL/RigidBody/kernels/solveContact.cl
Normal file
476
src/Bullet3OpenCL/RigidBody/kernels/solveContact.cl
Normal file
@@ -0,0 +1,476 @@
|
||||
/*
|
||||
Copyright (c) 2012 Advanced Micro Devices, Inc.
|
||||
|
||||
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.
|
||||
*/
|
||||
//Originally written by Takahiro Harada
|
||||
|
||||
|
||||
//#pragma OPENCL EXTENSION cl_amd_printf : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
|
||||
|
||||
|
||||
#ifdef cl_ext_atomic_counters_32
|
||||
#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
|
||||
#else
|
||||
#define counter32_t volatile global int*
|
||||
#endif
|
||||
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned char u8;
|
||||
|
||||
#define GET_GROUP_IDX get_group_id(0)
|
||||
#define GET_LOCAL_IDX get_local_id(0)
|
||||
#define GET_GLOBAL_IDX get_global_id(0)
|
||||
#define GET_GROUP_SIZE get_local_size(0)
|
||||
#define GET_NUM_GROUPS get_num_groups(0)
|
||||
#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
|
||||
#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
|
||||
#define AtomInc(x) atom_inc(&(x))
|
||||
#define AtomInc1(x, out) out = atom_inc(&(x))
|
||||
#define AppendInc(x, out) out = atomic_inc(x)
|
||||
#define AtomAdd(x, value) atom_add(&(x), value)
|
||||
#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
|
||||
#define AtomXhg(x, value) atom_xchg ( &(x), value )
|
||||
|
||||
|
||||
#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
|
||||
|
||||
#define mymake_float4 (float4)
|
||||
//#define make_float2 (float2)
|
||||
//#define make_uint4 (uint4)
|
||||
//#define make_int4 (int4)
|
||||
//#define make_uint2 (uint2)
|
||||
//#define make_int2 (int2)
|
||||
|
||||
|
||||
#define max2 max
|
||||
#define min2 min
|
||||
|
||||
|
||||
///////////////////////////////////////
|
||||
// Vector
|
||||
///////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
float4 fastNormalize4(float4 v)
|
||||
{
|
||||
return fast_normalize(v);
|
||||
}
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
float4 cross3(float4 a, float4 b)
|
||||
{
|
||||
return cross(a,b);
|
||||
}
|
||||
|
||||
__inline
|
||||
float dot3F4(float4 a, float4 b)
|
||||
{
|
||||
float4 a1 = mymake_float4(a.xyz,0.f);
|
||||
float4 b1 = mymake_float4(b.xyz,0.f);
|
||||
return dot(a1, b1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
float4 normalize3(const float4 a)
|
||||
{
|
||||
float4 n = mymake_float4(a.x, a.y, a.z, 0.f);
|
||||
return fastNormalize4( n );
|
||||
// float length = sqrtf(dot3F4(a, a));
|
||||
// return 1.f/length * a;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////
|
||||
// Matrix3x3
|
||||
///////////////////////////////////////
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_row[3];
|
||||
}Matrix3x3;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
float4 mtMul1(Matrix3x3 a, float4 b);
|
||||
|
||||
__inline
|
||||
float4 mtMul3(float4 a, Matrix3x3 b);
|
||||
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
float4 mtMul1(Matrix3x3 a, float4 b)
|
||||
{
|
||||
float4 ans;
|
||||
ans.x = dot3F4( a.m_row[0], b );
|
||||
ans.y = dot3F4( a.m_row[1], b );
|
||||
ans.z = dot3F4( a.m_row[2], b );
|
||||
ans.w = 0.f;
|
||||
return ans;
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 mtMul3(float4 a, Matrix3x3 b)
|
||||
{
|
||||
float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
|
||||
float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
|
||||
float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
|
||||
|
||||
float4 ans;
|
||||
ans.x = dot3F4( a, colx );
|
||||
ans.y = dot3F4( a, coly );
|
||||
ans.z = dot3F4( a, colz );
|
||||
return ans;
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
// Quaternion
|
||||
///////////////////////////////////////
|
||||
|
||||
typedef float4 Quaternion;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define WG_SIZE 64
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_pos;
|
||||
Quaternion m_quat;
|
||||
float4 m_linVel;
|
||||
float4 m_angVel;
|
||||
|
||||
u32 m_shapeIdx;
|
||||
float m_invMass;
|
||||
float m_restituitionCoeff;
|
||||
float m_frictionCoeff;
|
||||
} Body;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Matrix3x3 m_invInertia;
|
||||
Matrix3x3 m_initInvInertia;
|
||||
} Shape;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_linear;
|
||||
float4 m_worldPos[4];
|
||||
float4 m_center;
|
||||
float m_jacCoeffInv[4];
|
||||
float m_b[4];
|
||||
float m_appliedRambdaDt[4];
|
||||
|
||||
float m_fJacCoeffInv[2];
|
||||
float m_fAppliedRambdaDt[2];
|
||||
|
||||
u32 m_bodyA;
|
||||
u32 m_bodyB;
|
||||
|
||||
int m_batchIdx;
|
||||
u32 m_paddings[1];
|
||||
} Constraint4;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_worldPos[4];
|
||||
float4 m_worldNormal;
|
||||
u32 m_coeffs;
|
||||
int m_batchIdx;
|
||||
|
||||
int m_bodyAPtrAndSignBit;
|
||||
int m_bodyBPtrAndSignBit;
|
||||
} Contact4;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int m_nConstraints;
|
||||
int m_start;
|
||||
int m_batchIdx;
|
||||
int m_nSplit;
|
||||
// int m_paddings[1];
|
||||
} ConstBuffer;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int m_solveFriction;
|
||||
int m_maxBatch; // long batch really kills the performance
|
||||
int m_batchIdx;
|
||||
int m_nSplit;
|
||||
// int m_paddings[1];
|
||||
} ConstBufferBatchSolve;
|
||||
|
||||
void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1);
|
||||
|
||||
void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)
|
||||
{
|
||||
*linear = mymake_float4(-n.xyz,0.f);
|
||||
*angular0 = -cross3(r0, n);
|
||||
*angular1 = cross3(r1, n);
|
||||
}
|
||||
|
||||
float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 );
|
||||
|
||||
float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )
|
||||
{
|
||||
return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);
|
||||
}
|
||||
|
||||
|
||||
float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,
|
||||
float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1);
|
||||
|
||||
float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,
|
||||
float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1)
|
||||
{
|
||||
// linear0,1 are normlized
|
||||
float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;
|
||||
float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);
|
||||
float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;
|
||||
float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);
|
||||
return -1.f/(jmj0+jmj1+jmj2+jmj3);
|
||||
}
|
||||
|
||||
|
||||
void solveContact(__global Constraint4* cs,
|
||||
float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,
|
||||
float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB);
|
||||
|
||||
void solveContact(__global Constraint4* cs,
|
||||
float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,
|
||||
float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB)
|
||||
{
|
||||
float minRambdaDt = 0;
|
||||
float maxRambdaDt = FLT_MAX;
|
||||
|
||||
for(int ic=0; ic<4; ic++)
|
||||
{
|
||||
if( cs->m_jacCoeffInv[ic] == 0.f ) continue;
|
||||
|
||||
float4 angular0, angular1, linear;
|
||||
float4 r0 = cs->m_worldPos[ic] - posA;
|
||||
float4 r1 = cs->m_worldPos[ic] - posB;
|
||||
setLinearAndAngular( -cs->m_linear, r0, r1, &linear, &angular0, &angular1 );
|
||||
|
||||
float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1,
|
||||
*linVelA, *angVelA, *linVelB, *angVelB ) + cs->m_b[ic];
|
||||
rambdaDt *= cs->m_jacCoeffInv[ic];
|
||||
|
||||
{
|
||||
float prevSum = cs->m_appliedRambdaDt[ic];
|
||||
float updated = prevSum;
|
||||
updated += rambdaDt;
|
||||
updated = max2( updated, minRambdaDt );
|
||||
updated = min2( updated, maxRambdaDt );
|
||||
rambdaDt = updated - prevSum;
|
||||
cs->m_appliedRambdaDt[ic] = updated;
|
||||
}
|
||||
|
||||
float4 linImp0 = invMassA*linear*rambdaDt;
|
||||
float4 linImp1 = invMassB*(-linear)*rambdaDt;
|
||||
float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;
|
||||
float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;
|
||||
|
||||
*linVelA += linImp0;
|
||||
*angVelA += angImp0;
|
||||
*linVelB += linImp1;
|
||||
*angVelB += angImp1;
|
||||
}
|
||||
}
|
||||
|
||||
void btPlaneSpace1 (const float4* n, float4* p, float4* q);
|
||||
void btPlaneSpace1 (const float4* n, float4* p, float4* q)
|
||||
{
|
||||
if (fabs(n[0].z) > 0.70710678f) {
|
||||
// choose p in y-z plane
|
||||
float a = n[0].y*n[0].y + n[0].z*n[0].z;
|
||||
float k = 1.f/sqrt(a);
|
||||
p[0].x = 0;
|
||||
p[0].y = -n[0].z*k;
|
||||
p[0].z = n[0].y*k;
|
||||
// set q = n x p
|
||||
q[0].x = a*k;
|
||||
q[0].y = -n[0].x*p[0].z;
|
||||
q[0].z = n[0].x*p[0].y;
|
||||
}
|
||||
else {
|
||||
// choose p in x-y plane
|
||||
float a = n[0].x*n[0].x + n[0].y*n[0].y;
|
||||
float k = 1.f/sqrt(a);
|
||||
p[0].x = -n[0].y*k;
|
||||
p[0].y = n[0].x*k;
|
||||
p[0].z = 0;
|
||||
// set q = n x p
|
||||
q[0].x = -n[0].z*p[0].y;
|
||||
q[0].y = n[0].z*p[0].x;
|
||||
q[0].z = a*k;
|
||||
}
|
||||
}
|
||||
|
||||
void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs);
|
||||
void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs)
|
||||
{
|
||||
//float frictionCoeff = ldsCs[0].m_linear.w;
|
||||
int aIdx = ldsCs[0].m_bodyA;
|
||||
int bIdx = ldsCs[0].m_bodyB;
|
||||
|
||||
float4 posA = gBodies[aIdx].m_pos;
|
||||
float4 linVelA = gBodies[aIdx].m_linVel;
|
||||
float4 angVelA = gBodies[aIdx].m_angVel;
|
||||
float invMassA = gBodies[aIdx].m_invMass;
|
||||
Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;
|
||||
|
||||
float4 posB = gBodies[bIdx].m_pos;
|
||||
float4 linVelB = gBodies[bIdx].m_linVel;
|
||||
float4 angVelB = gBodies[bIdx].m_angVel;
|
||||
float invMassB = gBodies[bIdx].m_invMass;
|
||||
Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;
|
||||
|
||||
solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,
|
||||
posB, &linVelB, &angVelB, invMassB, invInertiaB );
|
||||
|
||||
if (gBodies[aIdx].m_invMass)
|
||||
{
|
||||
gBodies[aIdx].m_linVel = linVelA;
|
||||
gBodies[aIdx].m_angVel = angVelA;
|
||||
} else
|
||||
{
|
||||
gBodies[aIdx].m_linVel = mymake_float4(0,0,0,0);
|
||||
gBodies[aIdx].m_angVel = mymake_float4(0,0,0,0);
|
||||
|
||||
}
|
||||
if (gBodies[bIdx].m_invMass)
|
||||
{
|
||||
gBodies[bIdx].m_linVel = linVelB;
|
||||
gBodies[bIdx].m_angVel = angVelB;
|
||||
} else
|
||||
{
|
||||
gBodies[bIdx].m_linVel = mymake_float4(0,0,0,0);
|
||||
gBodies[bIdx].m_angVel = mymake_float4(0,0,0,0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int m_valInt0;
|
||||
int m_valInt1;
|
||||
int m_valInt2;
|
||||
int m_valInt3;
|
||||
|
||||
float m_val0;
|
||||
float m_val1;
|
||||
float m_val2;
|
||||
float m_val3;
|
||||
} SolverDebugInfo;
|
||||
|
||||
|
||||
|
||||
|
||||
__kernel
|
||||
__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
|
||||
void BatchSolveKernelContact(__global Body* gBodies,
|
||||
__global Shape* gShapes,
|
||||
__global Constraint4* gConstraints,
|
||||
__global int* gN,
|
||||
__global int* gOffsets,
|
||||
int maxBatch,
|
||||
int bIdx,
|
||||
int nSplit
|
||||
)
|
||||
{
|
||||
//__local int ldsBatchIdx[WG_SIZE+1];
|
||||
__local int ldsCurBatch;
|
||||
__local int ldsNextBatch;
|
||||
__local int ldsStart;
|
||||
|
||||
int lIdx = GET_LOCAL_IDX;
|
||||
int wgIdx = GET_GROUP_IDX;
|
||||
|
||||
// int gIdx = GET_GLOBAL_IDX;
|
||||
// debugInfo[gIdx].m_valInt0 = gIdx;
|
||||
//debugInfo[gIdx].m_valInt1 = GET_GROUP_SIZE;
|
||||
|
||||
|
||||
int xIdx = (wgIdx/(nSplit/2))*2 + (bIdx&1);
|
||||
int yIdx = (wgIdx%(nSplit/2))*2 + (bIdx>>1);
|
||||
int cellIdx = xIdx+yIdx*nSplit;
|
||||
|
||||
if( gN[cellIdx] == 0 )
|
||||
return;
|
||||
|
||||
const int start = gOffsets[cellIdx];
|
||||
const int end = start + gN[cellIdx];
|
||||
|
||||
|
||||
if( lIdx == 0 )
|
||||
{
|
||||
ldsCurBatch = 0;
|
||||
ldsNextBatch = 0;
|
||||
ldsStart = start;
|
||||
}
|
||||
|
||||
|
||||
GROUP_LDS_BARRIER;
|
||||
|
||||
int idx=ldsStart+lIdx;
|
||||
while (ldsCurBatch < maxBatch)
|
||||
{
|
||||
for(; idx<end; )
|
||||
{
|
||||
if (gConstraints[idx].m_batchIdx == ldsCurBatch)
|
||||
{
|
||||
solveContactConstraint( gBodies, gShapes, &gConstraints[idx] );
|
||||
|
||||
idx+=64;
|
||||
} else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
GROUP_LDS_BARRIER;
|
||||
if( lIdx == 0 )
|
||||
{
|
||||
ldsCurBatch++;
|
||||
}
|
||||
GROUP_LDS_BARRIER;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
480
src/Bullet3OpenCL/RigidBody/kernels/solveContact.h
Normal file
480
src/Bullet3OpenCL/RigidBody/kernels/solveContact.h
Normal file
@@ -0,0 +1,480 @@
|
||||
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
|
||||
static const char* solveContactCL= \
|
||||
"/*\n"
|
||||
"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
|
||||
"\n"
|
||||
"This software is provided 'as-is', without any express or implied warranty.\n"
|
||||
"In no event will the authors be held liable for any damages arising from the use of this software.\n"
|
||||
"Permission is granted to anyone to use this software for any purpose, \n"
|
||||
"including commercial applications, and to alter it and redistribute it freely, \n"
|
||||
"subject to the following restrictions:\n"
|
||||
"\n"
|
||||
"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.\n"
|
||||
"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
|
||||
"3. This notice may not be removed or altered from any source distribution.\n"
|
||||
"*/\n"
|
||||
"//Originally written by Takahiro Harada\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"//#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#ifdef cl_ext_atomic_counters_32\n"
|
||||
"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
|
||||
"#else\n"
|
||||
"#define counter32_t volatile global int*\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"typedef unsigned int u32;\n"
|
||||
"typedef unsigned short u16;\n"
|
||||
"typedef unsigned char u8;\n"
|
||||
"\n"
|
||||
"#define GET_GROUP_IDX get_group_id(0)\n"
|
||||
"#define GET_LOCAL_IDX get_local_id(0)\n"
|
||||
"#define GET_GLOBAL_IDX get_global_id(0)\n"
|
||||
"#define GET_GROUP_SIZE get_local_size(0)\n"
|
||||
"#define GET_NUM_GROUPS get_num_groups(0)\n"
|
||||
"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
|
||||
"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
|
||||
"#define AtomInc(x) atom_inc(&(x))\n"
|
||||
"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
|
||||
"#define AppendInc(x, out) out = atomic_inc(x)\n"
|
||||
"#define AtomAdd(x, value) atom_add(&(x), value)\n"
|
||||
"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
|
||||
"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
|
||||
"\n"
|
||||
"#define mymake_float4 (float4)\n"
|
||||
"//#define make_float2 (float2)\n"
|
||||
"//#define make_uint4 (uint4)\n"
|
||||
"//#define make_int4 (int4)\n"
|
||||
"//#define make_uint2 (uint2)\n"
|
||||
"//#define make_int2 (int2)\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define max2 max\n"
|
||||
"#define min2 min\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"// Vector\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 fastNormalize4(float4 v)\n"
|
||||
"{\n"
|
||||
" return fast_normalize(v);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 cross3(float4 a, float4 b)\n"
|
||||
"{\n"
|
||||
" return cross(a,b);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float dot3F4(float4 a, float4 b)\n"
|
||||
"{\n"
|
||||
" float4 a1 = mymake_float4(a.xyz,0.f);\n"
|
||||
" float4 b1 = mymake_float4(b.xyz,0.f);\n"
|
||||
" return dot(a1, b1);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 normalize3(const float4 a)\n"
|
||||
"{\n"
|
||||
" float4 n = mymake_float4(a.x, a.y, a.z, 0.f);\n"
|
||||
" return fastNormalize4( n );\n"
|
||||
"// float length = sqrtf(dot3F4(a, a));\n"
|
||||
"// return 1.f/length * a;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"// Matrix3x3\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_row[3];\n"
|
||||
"}Matrix3x3;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 mtMul1(Matrix3x3 a, float4 b);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 mtMul3(float4 a, Matrix3x3 b);\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 mtMul1(Matrix3x3 a, float4 b)\n"
|
||||
"{\n"
|
||||
" float4 ans;\n"
|
||||
" ans.x = dot3F4( a.m_row[0], b );\n"
|
||||
" ans.y = dot3F4( a.m_row[1], b );\n"
|
||||
" ans.z = dot3F4( a.m_row[2], b );\n"
|
||||
" ans.w = 0.f;\n"
|
||||
" return ans;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 mtMul3(float4 a, Matrix3x3 b)\n"
|
||||
"{\n"
|
||||
" float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
|
||||
" float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
|
||||
" float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
|
||||
"\n"
|
||||
" float4 ans;\n"
|
||||
" ans.x = dot3F4( a, colx );\n"
|
||||
" ans.y = dot3F4( a, coly );\n"
|
||||
" ans.z = dot3F4( a, colz );\n"
|
||||
" return ans;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"// Quaternion\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"\n"
|
||||
"typedef float4 Quaternion;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define WG_SIZE 64\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_pos;\n"
|
||||
" Quaternion m_quat;\n"
|
||||
" float4 m_linVel;\n"
|
||||
" float4 m_angVel;\n"
|
||||
"\n"
|
||||
" u32 m_shapeIdx;\n"
|
||||
" float m_invMass;\n"
|
||||
" float m_restituitionCoeff;\n"
|
||||
" float m_frictionCoeff;\n"
|
||||
"} Body;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" Matrix3x3 m_invInertia;\n"
|
||||
" Matrix3x3 m_initInvInertia;\n"
|
||||
"} Shape;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_linear;\n"
|
||||
" float4 m_worldPos[4];\n"
|
||||
" float4 m_center; \n"
|
||||
" float m_jacCoeffInv[4];\n"
|
||||
" float m_b[4];\n"
|
||||
" float m_appliedRambdaDt[4];\n"
|
||||
"\n"
|
||||
" float m_fJacCoeffInv[2]; \n"
|
||||
" float m_fAppliedRambdaDt[2]; \n"
|
||||
"\n"
|
||||
" u32 m_bodyA;\n"
|
||||
" u32 m_bodyB;\n"
|
||||
"\n"
|
||||
" int m_batchIdx;\n"
|
||||
" u32 m_paddings[1];\n"
|
||||
"} Constraint4;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_worldPos[4];\n"
|
||||
" float4 m_worldNormal;\n"
|
||||
" u32 m_coeffs;\n"
|
||||
" int m_batchIdx;\n"
|
||||
"\n"
|
||||
" int m_bodyAPtrAndSignBit;\n"
|
||||
" int m_bodyBPtrAndSignBit;\n"
|
||||
"} Contact4;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" int m_nConstraints;\n"
|
||||
" int m_start;\n"
|
||||
" int m_batchIdx;\n"
|
||||
" int m_nSplit;\n"
|
||||
"// int m_paddings[1];\n"
|
||||
"} ConstBuffer;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" int m_solveFriction;\n"
|
||||
" int m_maxBatch; // long batch really kills the performance\n"
|
||||
" int m_batchIdx;\n"
|
||||
" int m_nSplit;\n"
|
||||
"// int m_paddings[1];\n"
|
||||
"} ConstBufferBatchSolve;\n"
|
||||
"\n"
|
||||
"void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1);\n"
|
||||
"\n"
|
||||
"void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)\n"
|
||||
"{\n"
|
||||
" *linear = mymake_float4(-n.xyz,0.f);\n"
|
||||
" *angular0 = -cross3(r0, n);\n"
|
||||
" *angular1 = cross3(r1, n);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 );\n"
|
||||
"\n"
|
||||
"float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )\n"
|
||||
"{\n"
|
||||
" return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
|
||||
" float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1);\n"
|
||||
"\n"
|
||||
"float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
|
||||
" float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1)\n"
|
||||
"{\n"
|
||||
" // linear0,1 are normlized\n"
|
||||
" float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;\n"
|
||||
" float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
|
||||
" float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;\n"
|
||||
" float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
|
||||
" return -1.f/(jmj0+jmj1+jmj2+jmj3);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"void solveContact(__global Constraint4* cs,\n"
|
||||
" float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,\n"
|
||||
" float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB);\n"
|
||||
"\n"
|
||||
"void solveContact(__global Constraint4* cs,\n"
|
||||
" float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,\n"
|
||||
" float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB)\n"
|
||||
"{\n"
|
||||
" float minRambdaDt = 0;\n"
|
||||
" float maxRambdaDt = FLT_MAX;\n"
|
||||
"\n"
|
||||
" for(int ic=0; ic<4; ic++)\n"
|
||||
" {\n"
|
||||
" if( cs->m_jacCoeffInv[ic] == 0.f ) continue;\n"
|
||||
"\n"
|
||||
" float4 angular0, angular1, linear;\n"
|
||||
" float4 r0 = cs->m_worldPos[ic] - posA;\n"
|
||||
" float4 r1 = cs->m_worldPos[ic] - posB;\n"
|
||||
" setLinearAndAngular( -cs->m_linear, r0, r1, &linear, &angular0, &angular1 );\n"
|
||||
"\n"
|
||||
" float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1, \n"
|
||||
" *linVelA, *angVelA, *linVelB, *angVelB ) + cs->m_b[ic];\n"
|
||||
" rambdaDt *= cs->m_jacCoeffInv[ic];\n"
|
||||
"\n"
|
||||
" {\n"
|
||||
" float prevSum = cs->m_appliedRambdaDt[ic];\n"
|
||||
" float updated = prevSum;\n"
|
||||
" updated += rambdaDt;\n"
|
||||
" updated = max2( updated, minRambdaDt );\n"
|
||||
" updated = min2( updated, maxRambdaDt );\n"
|
||||
" rambdaDt = updated - prevSum;\n"
|
||||
" cs->m_appliedRambdaDt[ic] = updated;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" float4 linImp0 = invMassA*linear*rambdaDt;\n"
|
||||
" float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
|
||||
" float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
|
||||
" float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
|
||||
"\n"
|
||||
" *linVelA += linImp0;\n"
|
||||
" *angVelA += angImp0;\n"
|
||||
" *linVelB += linImp1;\n"
|
||||
" *angVelB += angImp1;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void b3PlaneSpace1 (const float4* n, float4* p, float4* q);\n"
|
||||
" void b3PlaneSpace1 (const float4* n, float4* p, float4* q)\n"
|
||||
"{\n"
|
||||
" if (fabs(n[0].z) > 0.70710678f) {\n"
|
||||
" // choose p in y-z plane\n"
|
||||
" float a = n[0].y*n[0].y + n[0].z*n[0].z;\n"
|
||||
" float k = 1.f/sqrt(a);\n"
|
||||
" p[0].x = 0;\n"
|
||||
" p[0].y = -n[0].z*k;\n"
|
||||
" p[0].z = n[0].y*k;\n"
|
||||
" // set q = n x p\n"
|
||||
" q[0].x = a*k;\n"
|
||||
" q[0].y = -n[0].x*p[0].z;\n"
|
||||
" q[0].z = n[0].x*p[0].y;\n"
|
||||
" }\n"
|
||||
" else {\n"
|
||||
" // choose p in x-y plane\n"
|
||||
" float a = n[0].x*n[0].x + n[0].y*n[0].y;\n"
|
||||
" float k = 1.f/sqrt(a);\n"
|
||||
" p[0].x = -n[0].y*k;\n"
|
||||
" p[0].y = n[0].x*k;\n"
|
||||
" p[0].z = 0;\n"
|
||||
" // set q = n x p\n"
|
||||
" q[0].x = -n[0].z*p[0].y;\n"
|
||||
" q[0].y = n[0].z*p[0].x;\n"
|
||||
" q[0].z = a*k;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs);\n"
|
||||
"void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs)\n"
|
||||
"{\n"
|
||||
" //float frictionCoeff = ldsCs[0].m_linear.w;\n"
|
||||
" int aIdx = ldsCs[0].m_bodyA;\n"
|
||||
" int bIdx = ldsCs[0].m_bodyB;\n"
|
||||
"\n"
|
||||
" float4 posA = gBodies[aIdx].m_pos;\n"
|
||||
" float4 linVelA = gBodies[aIdx].m_linVel;\n"
|
||||
" float4 angVelA = gBodies[aIdx].m_angVel;\n"
|
||||
" float invMassA = gBodies[aIdx].m_invMass;\n"
|
||||
" Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
|
||||
"\n"
|
||||
" float4 posB = gBodies[bIdx].m_pos;\n"
|
||||
" float4 linVelB = gBodies[bIdx].m_linVel;\n"
|
||||
" float4 angVelB = gBodies[bIdx].m_angVel;\n"
|
||||
" float invMassB = gBodies[bIdx].m_invMass;\n"
|
||||
" Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
|
||||
"\n"
|
||||
" solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
|
||||
" posB, &linVelB, &angVelB, invMassB, invInertiaB );\n"
|
||||
"\n"
|
||||
" if (gBodies[aIdx].m_invMass)\n"
|
||||
" {\n"
|
||||
" gBodies[aIdx].m_linVel = linVelA;\n"
|
||||
" gBodies[aIdx].m_angVel = angVelA;\n"
|
||||
" } else\n"
|
||||
" {\n"
|
||||
" gBodies[aIdx].m_linVel = mymake_float4(0,0,0,0);\n"
|
||||
" gBodies[aIdx].m_angVel = mymake_float4(0,0,0,0);\n"
|
||||
" \n"
|
||||
" }\n"
|
||||
" if (gBodies[bIdx].m_invMass)\n"
|
||||
" {\n"
|
||||
" gBodies[bIdx].m_linVel = linVelB;\n"
|
||||
" gBodies[bIdx].m_angVel = angVelB;\n"
|
||||
" } else\n"
|
||||
" {\n"
|
||||
" gBodies[bIdx].m_linVel = mymake_float4(0,0,0,0);\n"
|
||||
" gBodies[bIdx].m_angVel = mymake_float4(0,0,0,0);\n"
|
||||
" \n"
|
||||
" }\n"
|
||||
"\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"typedef struct \n"
|
||||
"{\n"
|
||||
" int m_valInt0;\n"
|
||||
" int m_valInt1;\n"
|
||||
" int m_valInt2;\n"
|
||||
" int m_valInt3;\n"
|
||||
"\n"
|
||||
" float m_val0;\n"
|
||||
" float m_val1;\n"
|
||||
" float m_val2;\n"
|
||||
" float m_val3;\n"
|
||||
"} SolverDebugInfo;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__kernel\n"
|
||||
"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
|
||||
"void BatchSolveKernelContact(__global Body* gBodies,\n"
|
||||
" __global Shape* gShapes,\n"
|
||||
" __global Constraint4* gConstraints,\n"
|
||||
" __global int* gN,\n"
|
||||
" __global int* gOffsets,\n"
|
||||
" int maxBatch,\n"
|
||||
" int bIdx,\n"
|
||||
" int nSplit\n"
|
||||
" )\n"
|
||||
"{\n"
|
||||
" //__local int ldsBatchIdx[WG_SIZE+1];\n"
|
||||
" __local int ldsCurBatch;\n"
|
||||
" __local int ldsNextBatch;\n"
|
||||
" __local int ldsStart;\n"
|
||||
"\n"
|
||||
" int lIdx = GET_LOCAL_IDX;\n"
|
||||
" int wgIdx = GET_GROUP_IDX;\n"
|
||||
"\n"
|
||||
"// int gIdx = GET_GLOBAL_IDX;\n"
|
||||
"// debugInfo[gIdx].m_valInt0 = gIdx;\n"
|
||||
" //debugInfo[gIdx].m_valInt1 = GET_GROUP_SIZE;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" int xIdx = (wgIdx/(nSplit/2))*2 + (bIdx&1);\n"
|
||||
" int yIdx = (wgIdx%(nSplit/2))*2 + (bIdx>>1);\n"
|
||||
" int cellIdx = xIdx+yIdx*nSplit;\n"
|
||||
" \n"
|
||||
" if( gN[cellIdx] == 0 ) \n"
|
||||
" return;\n"
|
||||
"\n"
|
||||
" const int start = gOffsets[cellIdx];\n"
|
||||
" const int end = start + gN[cellIdx];\n"
|
||||
"\n"
|
||||
" \n"
|
||||
" if( lIdx == 0 )\n"
|
||||
" {\n"
|
||||
" ldsCurBatch = 0;\n"
|
||||
" ldsNextBatch = 0;\n"
|
||||
" ldsStart = start;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" GROUP_LDS_BARRIER;\n"
|
||||
"\n"
|
||||
" int idx=ldsStart+lIdx;\n"
|
||||
" while (ldsCurBatch < maxBatch)\n"
|
||||
" {\n"
|
||||
" for(; idx<end; )\n"
|
||||
" {\n"
|
||||
" if (gConstraints[idx].m_batchIdx == ldsCurBatch)\n"
|
||||
" {\n"
|
||||
" solveContactConstraint( gBodies, gShapes, &gConstraints[idx] );\n"
|
||||
"\n"
|
||||
" idx+=64;\n"
|
||||
" } else\n"
|
||||
" {\n"
|
||||
" break;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" GROUP_LDS_BARRIER;\n"
|
||||
" if( lIdx == 0 )\n"
|
||||
" {\n"
|
||||
" ldsCurBatch++;\n"
|
||||
" }\n"
|
||||
" GROUP_LDS_BARRIER;\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
" \n"
|
||||
"}\n"
|
||||
"\n"
|
||||
;
|
||||
506
src/Bullet3OpenCL/RigidBody/kernels/solveFriction.cl
Normal file
506
src/Bullet3OpenCL/RigidBody/kernels/solveFriction.cl
Normal file
@@ -0,0 +1,506 @@
|
||||
/*
|
||||
Copyright (c) 2012 Advanced Micro Devices, Inc.
|
||||
|
||||
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.
|
||||
*/
|
||||
//Originally written by Takahiro Harada
|
||||
|
||||
|
||||
//#pragma OPENCL EXTENSION cl_amd_printf : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
|
||||
|
||||
|
||||
#ifdef cl_ext_atomic_counters_32
|
||||
#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
|
||||
#else
|
||||
#define counter32_t volatile global int*
|
||||
#endif
|
||||
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned char u8;
|
||||
|
||||
#define GET_GROUP_IDX get_group_id(0)
|
||||
#define GET_LOCAL_IDX get_local_id(0)
|
||||
#define GET_GLOBAL_IDX get_global_id(0)
|
||||
#define GET_GROUP_SIZE get_local_size(0)
|
||||
#define GET_NUM_GROUPS get_num_groups(0)
|
||||
#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
|
||||
#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
|
||||
#define AtomInc(x) atom_inc(&(x))
|
||||
#define AtomInc1(x, out) out = atom_inc(&(x))
|
||||
#define AppendInc(x, out) out = atomic_inc(x)
|
||||
#define AtomAdd(x, value) atom_add(&(x), value)
|
||||
#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
|
||||
#define AtomXhg(x, value) atom_xchg ( &(x), value )
|
||||
|
||||
|
||||
#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
|
||||
|
||||
#define mymake_float4 (float4)
|
||||
//#define make_float2 (float2)
|
||||
//#define make_uint4 (uint4)
|
||||
//#define make_int4 (int4)
|
||||
//#define make_uint2 (uint2)
|
||||
//#define make_int2 (int2)
|
||||
|
||||
|
||||
#define max2 max
|
||||
#define min2 min
|
||||
|
||||
|
||||
///////////////////////////////////////
|
||||
// Vector
|
||||
///////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
float4 fastNormalize4(float4 v)
|
||||
{
|
||||
return fast_normalize(v);
|
||||
}
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
float4 cross3(float4 a, float4 b)
|
||||
{
|
||||
return cross(a,b);
|
||||
}
|
||||
|
||||
__inline
|
||||
float dot3F4(float4 a, float4 b)
|
||||
{
|
||||
float4 a1 = mymake_float4(a.xyz,0.f);
|
||||
float4 b1 = mymake_float4(b.xyz,0.f);
|
||||
return dot(a1, b1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
float4 normalize3(const float4 a)
|
||||
{
|
||||
float4 n = mymake_float4(a.x, a.y, a.z, 0.f);
|
||||
return fastNormalize4( n );
|
||||
// float length = sqrtf(dot3F4(a, a));
|
||||
// return 1.f/length * a;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////
|
||||
// Matrix3x3
|
||||
///////////////////////////////////////
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_row[3];
|
||||
}Matrix3x3;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
float4 mtMul1(Matrix3x3 a, float4 b);
|
||||
|
||||
__inline
|
||||
float4 mtMul3(float4 a, Matrix3x3 b);
|
||||
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
float4 mtMul1(Matrix3x3 a, float4 b)
|
||||
{
|
||||
float4 ans;
|
||||
ans.x = dot3F4( a.m_row[0], b );
|
||||
ans.y = dot3F4( a.m_row[1], b );
|
||||
ans.z = dot3F4( a.m_row[2], b );
|
||||
ans.w = 0.f;
|
||||
return ans;
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 mtMul3(float4 a, Matrix3x3 b)
|
||||
{
|
||||
float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
|
||||
float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
|
||||
float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
|
||||
|
||||
float4 ans;
|
||||
ans.x = dot3F4( a, colx );
|
||||
ans.y = dot3F4( a, coly );
|
||||
ans.z = dot3F4( a, colz );
|
||||
return ans;
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
// Quaternion
|
||||
///////////////////////////////////////
|
||||
|
||||
typedef float4 Quaternion;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define WG_SIZE 64
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_pos;
|
||||
Quaternion m_quat;
|
||||
float4 m_linVel;
|
||||
float4 m_angVel;
|
||||
|
||||
u32 m_shapeIdx;
|
||||
float m_invMass;
|
||||
float m_restituitionCoeff;
|
||||
float m_frictionCoeff;
|
||||
} Body;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Matrix3x3 m_invInertia;
|
||||
Matrix3x3 m_initInvInertia;
|
||||
} Shape;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_linear;
|
||||
float4 m_worldPos[4];
|
||||
float4 m_center;
|
||||
float m_jacCoeffInv[4];
|
||||
float m_b[4];
|
||||
float m_appliedRambdaDt[4];
|
||||
|
||||
float m_fJacCoeffInv[2];
|
||||
float m_fAppliedRambdaDt[2];
|
||||
|
||||
u32 m_bodyA;
|
||||
u32 m_bodyB;
|
||||
|
||||
int m_batchIdx;
|
||||
u32 m_paddings[1];
|
||||
} Constraint4;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_worldPos[4];
|
||||
float4 m_worldNormal;
|
||||
u32 m_coeffs;
|
||||
int m_batchIdx;
|
||||
|
||||
int m_bodyAPtrAndSignBit;
|
||||
int m_bodyBPtrAndSignBit;
|
||||
} Contact4;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int m_nConstraints;
|
||||
int m_start;
|
||||
int m_batchIdx;
|
||||
int m_nSplit;
|
||||
// int m_paddings[1];
|
||||
} ConstBuffer;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int m_solveFriction;
|
||||
int m_maxBatch; // long batch really kills the performance
|
||||
int m_batchIdx;
|
||||
int m_nSplit;
|
||||
// int m_paddings[1];
|
||||
} ConstBufferBatchSolve;
|
||||
|
||||
void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1);
|
||||
|
||||
void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)
|
||||
{
|
||||
*linear = mymake_float4(-n.xyz,0.f);
|
||||
*angular0 = -cross3(r0, n);
|
||||
*angular1 = cross3(r1, n);
|
||||
}
|
||||
|
||||
float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 );
|
||||
|
||||
float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )
|
||||
{
|
||||
return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);
|
||||
}
|
||||
|
||||
|
||||
float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,
|
||||
float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1);
|
||||
|
||||
float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,
|
||||
float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1)
|
||||
{
|
||||
// linear0,1 are normlized
|
||||
float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;
|
||||
float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);
|
||||
float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;
|
||||
float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);
|
||||
return -1.f/(jmj0+jmj1+jmj2+jmj3);
|
||||
}
|
||||
void btPlaneSpace1 (const float4* n, float4* p, float4* q);
|
||||
void btPlaneSpace1 (const float4* n, float4* p, float4* q)
|
||||
{
|
||||
if (fabs(n[0].z) > 0.70710678f) {
|
||||
// choose p in y-z plane
|
||||
float a = n[0].y*n[0].y + n[0].z*n[0].z;
|
||||
float k = 1.f/sqrt(a);
|
||||
p[0].x = 0;
|
||||
p[0].y = -n[0].z*k;
|
||||
p[0].z = n[0].y*k;
|
||||
// set q = n x p
|
||||
q[0].x = a*k;
|
||||
q[0].y = -n[0].x*p[0].z;
|
||||
q[0].z = n[0].x*p[0].y;
|
||||
}
|
||||
else {
|
||||
// choose p in x-y plane
|
||||
float a = n[0].x*n[0].x + n[0].y*n[0].y;
|
||||
float k = 1.f/sqrt(a);
|
||||
p[0].x = -n[0].y*k;
|
||||
p[0].y = n[0].x*k;
|
||||
p[0].z = 0;
|
||||
// set q = n x p
|
||||
q[0].x = -n[0].z*p[0].y;
|
||||
q[0].y = n[0].z*p[0].x;
|
||||
q[0].z = a*k;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs);
|
||||
void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs)
|
||||
{
|
||||
float frictionCoeff = ldsCs[0].m_linear.w;
|
||||
int aIdx = ldsCs[0].m_bodyA;
|
||||
int bIdx = ldsCs[0].m_bodyB;
|
||||
|
||||
|
||||
float4 posA = gBodies[aIdx].m_pos;
|
||||
float4 linVelA = gBodies[aIdx].m_linVel;
|
||||
float4 angVelA = gBodies[aIdx].m_angVel;
|
||||
float invMassA = gBodies[aIdx].m_invMass;
|
||||
Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;
|
||||
|
||||
float4 posB = gBodies[bIdx].m_pos;
|
||||
float4 linVelB = gBodies[bIdx].m_linVel;
|
||||
float4 angVelB = gBodies[bIdx].m_angVel;
|
||||
float invMassB = gBodies[bIdx].m_invMass;
|
||||
Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;
|
||||
|
||||
|
||||
{
|
||||
float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
|
||||
float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
|
||||
|
||||
float sum = 0;
|
||||
for(int j=0; j<4; j++)
|
||||
{
|
||||
sum +=ldsCs[0].m_appliedRambdaDt[j];
|
||||
}
|
||||
frictionCoeff = 0.7f;
|
||||
for(int j=0; j<4; j++)
|
||||
{
|
||||
maxRambdaDt[j] = frictionCoeff*sum;
|
||||
minRambdaDt[j] = -maxRambdaDt[j];
|
||||
}
|
||||
|
||||
|
||||
// solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,
|
||||
// posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt );
|
||||
|
||||
|
||||
{
|
||||
|
||||
__global Constraint4* cs = ldsCs;
|
||||
|
||||
if( cs->m_fJacCoeffInv[0] == 0 && cs->m_fJacCoeffInv[0] == 0 ) return;
|
||||
const float4 center = cs->m_center;
|
||||
|
||||
float4 n = -cs->m_linear;
|
||||
|
||||
float4 tangent[2];
|
||||
btPlaneSpace1(&n,&tangent[0],&tangent[1]);
|
||||
float4 angular0, angular1, linear;
|
||||
float4 r0 = center - posA;
|
||||
float4 r1 = center - posB;
|
||||
for(int i=0; i<2; i++)
|
||||
{
|
||||
setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 );
|
||||
float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,
|
||||
linVelA, angVelA, linVelB, angVelB );
|
||||
rambdaDt *= cs->m_fJacCoeffInv[i];
|
||||
|
||||
{
|
||||
float prevSum = cs->m_fAppliedRambdaDt[i];
|
||||
float updated = prevSum;
|
||||
updated += rambdaDt;
|
||||
updated = max2( updated, minRambdaDt[i] );
|
||||
updated = min2( updated, maxRambdaDt[i] );
|
||||
rambdaDt = updated - prevSum;
|
||||
cs->m_fAppliedRambdaDt[i] = updated;
|
||||
}
|
||||
|
||||
float4 linImp0 = invMassA*linear*rambdaDt;
|
||||
float4 linImp1 = invMassB*(-linear)*rambdaDt;
|
||||
float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;
|
||||
float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;
|
||||
|
||||
linVelA += linImp0;
|
||||
angVelA += angImp0;
|
||||
linVelB += linImp1;
|
||||
angVelB += angImp1;
|
||||
}
|
||||
{ // angular damping for point constraint
|
||||
float4 ab = normalize3( posB - posA );
|
||||
float4 ac = normalize3( center - posA );
|
||||
if( dot3F4( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
|
||||
{
|
||||
float angNA = dot3F4( n, angVelA );
|
||||
float angNB = dot3F4( n, angVelB );
|
||||
|
||||
angVelA -= (angNA*0.1f)*n;
|
||||
angVelB -= (angNB*0.1f)*n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (gBodies[aIdx].m_invMass)
|
||||
{
|
||||
gBodies[aIdx].m_linVel = linVelA;
|
||||
gBodies[aIdx].m_angVel = angVelA;
|
||||
} else
|
||||
{
|
||||
gBodies[aIdx].m_linVel = mymake_float4(0,0,0,0);
|
||||
gBodies[aIdx].m_angVel = mymake_float4(0,0,0,0);
|
||||
}
|
||||
if (gBodies[bIdx].m_invMass)
|
||||
{
|
||||
gBodies[bIdx].m_linVel = linVelB;
|
||||
gBodies[bIdx].m_angVel = angVelB;
|
||||
} else
|
||||
{
|
||||
gBodies[bIdx].m_linVel = mymake_float4(0,0,0,0);
|
||||
gBodies[bIdx].m_angVel = mymake_float4(0,0,0,0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int m_valInt0;
|
||||
int m_valInt1;
|
||||
int m_valInt2;
|
||||
int m_valInt3;
|
||||
|
||||
float m_val0;
|
||||
float m_val1;
|
||||
float m_val2;
|
||||
float m_val3;
|
||||
} SolverDebugInfo;
|
||||
|
||||
|
||||
|
||||
|
||||
__kernel
|
||||
__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
|
||||
void BatchSolveKernelFriction(__global Body* gBodies,
|
||||
__global Shape* gShapes,
|
||||
__global Constraint4* gConstraints,
|
||||
__global int* gN,
|
||||
__global int* gOffsets,
|
||||
int maxBatch,
|
||||
int bIdx,
|
||||
int nSplit
|
||||
)
|
||||
{
|
||||
//__local int ldsBatchIdx[WG_SIZE+1];
|
||||
__local int ldsCurBatch;
|
||||
__local int ldsNextBatch;
|
||||
__local int ldsStart;
|
||||
|
||||
int lIdx = GET_LOCAL_IDX;
|
||||
int wgIdx = GET_GROUP_IDX;
|
||||
|
||||
// int gIdx = GET_GLOBAL_IDX;
|
||||
// debugInfo[gIdx].m_valInt0 = gIdx;
|
||||
//debugInfo[gIdx].m_valInt1 = GET_GROUP_SIZE;
|
||||
|
||||
|
||||
int xIdx = (wgIdx/(nSplit/2))*2 + (bIdx&1);
|
||||
int yIdx = (wgIdx%(nSplit/2))*2 + (bIdx>>1);
|
||||
int cellIdx = xIdx+yIdx*nSplit;
|
||||
|
||||
if( gN[cellIdx] == 0 )
|
||||
return;
|
||||
|
||||
const int start = gOffsets[cellIdx];
|
||||
const int end = start + gN[cellIdx];
|
||||
|
||||
|
||||
if( lIdx == 0 )
|
||||
{
|
||||
ldsCurBatch = 0;
|
||||
ldsNextBatch = 0;
|
||||
ldsStart = start;
|
||||
}
|
||||
|
||||
|
||||
GROUP_LDS_BARRIER;
|
||||
|
||||
int idx=ldsStart+lIdx;
|
||||
while (ldsCurBatch < maxBatch)
|
||||
{
|
||||
for(; idx<end; )
|
||||
{
|
||||
if (gConstraints[idx].m_batchIdx == ldsCurBatch)
|
||||
{
|
||||
|
||||
solveFrictionConstraint( gBodies, gShapes, &gConstraints[idx] );
|
||||
|
||||
idx+=64;
|
||||
} else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
GROUP_LDS_BARRIER;
|
||||
if( lIdx == 0 )
|
||||
{
|
||||
ldsCurBatch++;
|
||||
}
|
||||
GROUP_LDS_BARRIER;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
510
src/Bullet3OpenCL/RigidBody/kernels/solveFriction.h
Normal file
510
src/Bullet3OpenCL/RigidBody/kernels/solveFriction.h
Normal file
@@ -0,0 +1,510 @@
|
||||
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
|
||||
static const char* solveFrictionCL= \
|
||||
"/*\n"
|
||||
"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
|
||||
"\n"
|
||||
"This software is provided 'as-is', without any express or implied warranty.\n"
|
||||
"In no event will the authors be held liable for any damages arising from the use of this software.\n"
|
||||
"Permission is granted to anyone to use this software for any purpose, \n"
|
||||
"including commercial applications, and to alter it and redistribute it freely, \n"
|
||||
"subject to the following restrictions:\n"
|
||||
"\n"
|
||||
"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.\n"
|
||||
"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
|
||||
"3. This notice may not be removed or altered from any source distribution.\n"
|
||||
"*/\n"
|
||||
"//Originally written by Takahiro Harada\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"//#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#ifdef cl_ext_atomic_counters_32\n"
|
||||
"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
|
||||
"#else\n"
|
||||
"#define counter32_t volatile global int*\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"typedef unsigned int u32;\n"
|
||||
"typedef unsigned short u16;\n"
|
||||
"typedef unsigned char u8;\n"
|
||||
"\n"
|
||||
"#define GET_GROUP_IDX get_group_id(0)\n"
|
||||
"#define GET_LOCAL_IDX get_local_id(0)\n"
|
||||
"#define GET_GLOBAL_IDX get_global_id(0)\n"
|
||||
"#define GET_GROUP_SIZE get_local_size(0)\n"
|
||||
"#define GET_NUM_GROUPS get_num_groups(0)\n"
|
||||
"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
|
||||
"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
|
||||
"#define AtomInc(x) atom_inc(&(x))\n"
|
||||
"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
|
||||
"#define AppendInc(x, out) out = atomic_inc(x)\n"
|
||||
"#define AtomAdd(x, value) atom_add(&(x), value)\n"
|
||||
"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
|
||||
"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
|
||||
"\n"
|
||||
"#define mymake_float4 (float4)\n"
|
||||
"//#define make_float2 (float2)\n"
|
||||
"//#define make_uint4 (uint4)\n"
|
||||
"//#define make_int4 (int4)\n"
|
||||
"//#define make_uint2 (uint2)\n"
|
||||
"//#define make_int2 (int2)\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define max2 max\n"
|
||||
"#define min2 min\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"// Vector\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 fastNormalize4(float4 v)\n"
|
||||
"{\n"
|
||||
" return fast_normalize(v);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 cross3(float4 a, float4 b)\n"
|
||||
"{\n"
|
||||
" return cross(a,b);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float dot3F4(float4 a, float4 b)\n"
|
||||
"{\n"
|
||||
" float4 a1 = mymake_float4(a.xyz,0.f);\n"
|
||||
" float4 b1 = mymake_float4(b.xyz,0.f);\n"
|
||||
" return dot(a1, b1);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 normalize3(const float4 a)\n"
|
||||
"{\n"
|
||||
" float4 n = mymake_float4(a.x, a.y, a.z, 0.f);\n"
|
||||
" return fastNormalize4( n );\n"
|
||||
"// float length = sqrtf(dot3F4(a, a));\n"
|
||||
"// return 1.f/length * a;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"// Matrix3x3\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_row[3];\n"
|
||||
"}Matrix3x3;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 mtMul1(Matrix3x3 a, float4 b);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 mtMul3(float4 a, Matrix3x3 b);\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 mtMul1(Matrix3x3 a, float4 b)\n"
|
||||
"{\n"
|
||||
" float4 ans;\n"
|
||||
" ans.x = dot3F4( a.m_row[0], b );\n"
|
||||
" ans.y = dot3F4( a.m_row[1], b );\n"
|
||||
" ans.z = dot3F4( a.m_row[2], b );\n"
|
||||
" ans.w = 0.f;\n"
|
||||
" return ans;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 mtMul3(float4 a, Matrix3x3 b)\n"
|
||||
"{\n"
|
||||
" float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
|
||||
" float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
|
||||
" float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
|
||||
"\n"
|
||||
" float4 ans;\n"
|
||||
" ans.x = dot3F4( a, colx );\n"
|
||||
" ans.y = dot3F4( a, coly );\n"
|
||||
" ans.z = dot3F4( a, colz );\n"
|
||||
" return ans;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"// Quaternion\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"\n"
|
||||
"typedef float4 Quaternion;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define WG_SIZE 64\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_pos;\n"
|
||||
" Quaternion m_quat;\n"
|
||||
" float4 m_linVel;\n"
|
||||
" float4 m_angVel;\n"
|
||||
"\n"
|
||||
" u32 m_shapeIdx;\n"
|
||||
" float m_invMass;\n"
|
||||
" float m_restituitionCoeff;\n"
|
||||
" float m_frictionCoeff;\n"
|
||||
"} Body;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" Matrix3x3 m_invInertia;\n"
|
||||
" Matrix3x3 m_initInvInertia;\n"
|
||||
"} Shape;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_linear;\n"
|
||||
" float4 m_worldPos[4];\n"
|
||||
" float4 m_center; \n"
|
||||
" float m_jacCoeffInv[4];\n"
|
||||
" float m_b[4];\n"
|
||||
" float m_appliedRambdaDt[4];\n"
|
||||
"\n"
|
||||
" float m_fJacCoeffInv[2]; \n"
|
||||
" float m_fAppliedRambdaDt[2]; \n"
|
||||
"\n"
|
||||
" u32 m_bodyA;\n"
|
||||
" u32 m_bodyB;\n"
|
||||
"\n"
|
||||
" int m_batchIdx;\n"
|
||||
" u32 m_paddings[1];\n"
|
||||
"} Constraint4;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_worldPos[4];\n"
|
||||
" float4 m_worldNormal;\n"
|
||||
" u32 m_coeffs;\n"
|
||||
" int m_batchIdx;\n"
|
||||
"\n"
|
||||
" int m_bodyAPtrAndSignBit;\n"
|
||||
" int m_bodyBPtrAndSignBit;\n"
|
||||
"} Contact4;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" int m_nConstraints;\n"
|
||||
" int m_start;\n"
|
||||
" int m_batchIdx;\n"
|
||||
" int m_nSplit;\n"
|
||||
"// int m_paddings[1];\n"
|
||||
"} ConstBuffer;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" int m_solveFriction;\n"
|
||||
" int m_maxBatch; // long batch really kills the performance\n"
|
||||
" int m_batchIdx;\n"
|
||||
" int m_nSplit;\n"
|
||||
"// int m_paddings[1];\n"
|
||||
"} ConstBufferBatchSolve;\n"
|
||||
"\n"
|
||||
"void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1);\n"
|
||||
"\n"
|
||||
"void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)\n"
|
||||
"{\n"
|
||||
" *linear = mymake_float4(-n.xyz,0.f);\n"
|
||||
" *angular0 = -cross3(r0, n);\n"
|
||||
" *angular1 = cross3(r1, n);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 );\n"
|
||||
"\n"
|
||||
"float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )\n"
|
||||
"{\n"
|
||||
" return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
|
||||
" float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1);\n"
|
||||
"\n"
|
||||
"float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
|
||||
" float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1)\n"
|
||||
"{\n"
|
||||
" // linear0,1 are normlized\n"
|
||||
" float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;\n"
|
||||
" float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
|
||||
" float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;\n"
|
||||
" float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
|
||||
" return -1.f/(jmj0+jmj1+jmj2+jmj3);\n"
|
||||
"}\n"
|
||||
"void b3PlaneSpace1 (const float4* n, float4* p, float4* q);\n"
|
||||
" void b3PlaneSpace1 (const float4* n, float4* p, float4* q)\n"
|
||||
"{\n"
|
||||
" if (fabs(n[0].z) > 0.70710678f) {\n"
|
||||
" // choose p in y-z plane\n"
|
||||
" float a = n[0].y*n[0].y + n[0].z*n[0].z;\n"
|
||||
" float k = 1.f/sqrt(a);\n"
|
||||
" p[0].x = 0;\n"
|
||||
" p[0].y = -n[0].z*k;\n"
|
||||
" p[0].z = n[0].y*k;\n"
|
||||
" // set q = n x p\n"
|
||||
" q[0].x = a*k;\n"
|
||||
" q[0].y = -n[0].x*p[0].z;\n"
|
||||
" q[0].z = n[0].x*p[0].y;\n"
|
||||
" }\n"
|
||||
" else {\n"
|
||||
" // choose p in x-y plane\n"
|
||||
" float a = n[0].x*n[0].x + n[0].y*n[0].y;\n"
|
||||
" float k = 1.f/sqrt(a);\n"
|
||||
" p[0].x = -n[0].y*k;\n"
|
||||
" p[0].y = n[0].x*k;\n"
|
||||
" p[0].z = 0;\n"
|
||||
" // set q = n x p\n"
|
||||
" q[0].x = -n[0].z*p[0].y;\n"
|
||||
" q[0].y = n[0].z*p[0].x;\n"
|
||||
" q[0].z = a*k;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs);\n"
|
||||
"void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs)\n"
|
||||
"{\n"
|
||||
" float frictionCoeff = ldsCs[0].m_linear.w;\n"
|
||||
" int aIdx = ldsCs[0].m_bodyA;\n"
|
||||
" int bIdx = ldsCs[0].m_bodyB;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" float4 posA = gBodies[aIdx].m_pos;\n"
|
||||
" float4 linVelA = gBodies[aIdx].m_linVel;\n"
|
||||
" float4 angVelA = gBodies[aIdx].m_angVel;\n"
|
||||
" float invMassA = gBodies[aIdx].m_invMass;\n"
|
||||
" Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
|
||||
"\n"
|
||||
" float4 posB = gBodies[bIdx].m_pos;\n"
|
||||
" float4 linVelB = gBodies[bIdx].m_linVel;\n"
|
||||
" float4 angVelB = gBodies[bIdx].m_angVel;\n"
|
||||
" float invMassB = gBodies[bIdx].m_invMass;\n"
|
||||
" Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
|
||||
" \n"
|
||||
"\n"
|
||||
" {\n"
|
||||
" float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};\n"
|
||||
" float minRambdaDt[4] = {0.f,0.f,0.f,0.f};\n"
|
||||
"\n"
|
||||
" float sum = 0;\n"
|
||||
" for(int j=0; j<4; j++)\n"
|
||||
" {\n"
|
||||
" sum +=ldsCs[0].m_appliedRambdaDt[j];\n"
|
||||
" }\n"
|
||||
" frictionCoeff = 0.7f;\n"
|
||||
" for(int j=0; j<4; j++)\n"
|
||||
" {\n"
|
||||
" maxRambdaDt[j] = frictionCoeff*sum;\n"
|
||||
" minRambdaDt[j] = -maxRambdaDt[j];\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" \n"
|
||||
"// solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
|
||||
"// posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt );\n"
|
||||
" \n"
|
||||
" \n"
|
||||
" {\n"
|
||||
" \n"
|
||||
" __global Constraint4* cs = ldsCs;\n"
|
||||
" \n"
|
||||
" if( cs->m_fJacCoeffInv[0] == 0 && cs->m_fJacCoeffInv[0] == 0 ) return;\n"
|
||||
" const float4 center = cs->m_center;\n"
|
||||
" \n"
|
||||
" float4 n = -cs->m_linear;\n"
|
||||
" \n"
|
||||
" float4 tangent[2];\n"
|
||||
" b3PlaneSpace1(&n,&tangent[0],&tangent[1]);\n"
|
||||
" float4 angular0, angular1, linear;\n"
|
||||
" float4 r0 = center - posA;\n"
|
||||
" float4 r1 = center - posB;\n"
|
||||
" for(int i=0; i<2; i++)\n"
|
||||
" {\n"
|
||||
" setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 );\n"
|
||||
" float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,\n"
|
||||
" linVelA, angVelA, linVelB, angVelB );\n"
|
||||
" rambdaDt *= cs->m_fJacCoeffInv[i];\n"
|
||||
" \n"
|
||||
" {\n"
|
||||
" float prevSum = cs->m_fAppliedRambdaDt[i];\n"
|
||||
" float updated = prevSum;\n"
|
||||
" updated += rambdaDt;\n"
|
||||
" updated = max2( updated, minRambdaDt[i] );\n"
|
||||
" updated = min2( updated, maxRambdaDt[i] );\n"
|
||||
" rambdaDt = updated - prevSum;\n"
|
||||
" cs->m_fAppliedRambdaDt[i] = updated;\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
" float4 linImp0 = invMassA*linear*rambdaDt;\n"
|
||||
" float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
|
||||
" float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
|
||||
" float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
|
||||
" \n"
|
||||
" linVelA += linImp0;\n"
|
||||
" angVelA += angImp0;\n"
|
||||
" linVelB += linImp1;\n"
|
||||
" angVelB += angImp1;\n"
|
||||
" }\n"
|
||||
" { // angular damping for point constraint\n"
|
||||
" float4 ab = normalize3( posB - posA );\n"
|
||||
" float4 ac = normalize3( center - posA );\n"
|
||||
" if( dot3F4( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))\n"
|
||||
" {\n"
|
||||
" float angNA = dot3F4( n, angVelA );\n"
|
||||
" float angNB = dot3F4( n, angVelB );\n"
|
||||
" \n"
|
||||
" angVelA -= (angNA*0.1f)*n;\n"
|
||||
" angVelB -= (angNB*0.1f)*n;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" \n"
|
||||
" \n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" if (gBodies[aIdx].m_invMass)\n"
|
||||
" {\n"
|
||||
" gBodies[aIdx].m_linVel = linVelA;\n"
|
||||
" gBodies[aIdx].m_angVel = angVelA;\n"
|
||||
" } else\n"
|
||||
" {\n"
|
||||
" gBodies[aIdx].m_linVel = mymake_float4(0,0,0,0);\n"
|
||||
" gBodies[aIdx].m_angVel = mymake_float4(0,0,0,0);\n"
|
||||
" }\n"
|
||||
" if (gBodies[bIdx].m_invMass)\n"
|
||||
" {\n"
|
||||
" gBodies[bIdx].m_linVel = linVelB;\n"
|
||||
" gBodies[bIdx].m_angVel = angVelB;\n"
|
||||
" } else\n"
|
||||
" {\n"
|
||||
" gBodies[bIdx].m_linVel = mymake_float4(0,0,0,0);\n"
|
||||
" gBodies[bIdx].m_angVel = mymake_float4(0,0,0,0);\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
"\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"typedef struct \n"
|
||||
"{\n"
|
||||
" int m_valInt0;\n"
|
||||
" int m_valInt1;\n"
|
||||
" int m_valInt2;\n"
|
||||
" int m_valInt3;\n"
|
||||
"\n"
|
||||
" float m_val0;\n"
|
||||
" float m_val1;\n"
|
||||
" float m_val2;\n"
|
||||
" float m_val3;\n"
|
||||
"} SolverDebugInfo;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__kernel\n"
|
||||
"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
|
||||
"void BatchSolveKernelFriction(__global Body* gBodies,\n"
|
||||
" __global Shape* gShapes,\n"
|
||||
" __global Constraint4* gConstraints,\n"
|
||||
" __global int* gN,\n"
|
||||
" __global int* gOffsets,\n"
|
||||
" int maxBatch,\n"
|
||||
" int bIdx,\n"
|
||||
" int nSplit\n"
|
||||
" )\n"
|
||||
"{\n"
|
||||
" //__local int ldsBatchIdx[WG_SIZE+1];\n"
|
||||
" __local int ldsCurBatch;\n"
|
||||
" __local int ldsNextBatch;\n"
|
||||
" __local int ldsStart;\n"
|
||||
"\n"
|
||||
" int lIdx = GET_LOCAL_IDX;\n"
|
||||
" int wgIdx = GET_GROUP_IDX;\n"
|
||||
"\n"
|
||||
"// int gIdx = GET_GLOBAL_IDX;\n"
|
||||
"// debugInfo[gIdx].m_valInt0 = gIdx;\n"
|
||||
" //debugInfo[gIdx].m_valInt1 = GET_GROUP_SIZE;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" int xIdx = (wgIdx/(nSplit/2))*2 + (bIdx&1);\n"
|
||||
" int yIdx = (wgIdx%(nSplit/2))*2 + (bIdx>>1);\n"
|
||||
" int cellIdx = xIdx+yIdx*nSplit;\n"
|
||||
" \n"
|
||||
" if( gN[cellIdx] == 0 ) \n"
|
||||
" return;\n"
|
||||
"\n"
|
||||
" const int start = gOffsets[cellIdx];\n"
|
||||
" const int end = start + gN[cellIdx];\n"
|
||||
"\n"
|
||||
" \n"
|
||||
" if( lIdx == 0 )\n"
|
||||
" {\n"
|
||||
" ldsCurBatch = 0;\n"
|
||||
" ldsNextBatch = 0;\n"
|
||||
" ldsStart = start;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" GROUP_LDS_BARRIER;\n"
|
||||
"\n"
|
||||
" int idx=ldsStart+lIdx;\n"
|
||||
" while (ldsCurBatch < maxBatch)\n"
|
||||
" {\n"
|
||||
" for(; idx<end; )\n"
|
||||
" {\n"
|
||||
" if (gConstraints[idx].m_batchIdx == ldsCurBatch)\n"
|
||||
" {\n"
|
||||
"\n"
|
||||
" solveFrictionConstraint( gBodies, gShapes, &gConstraints[idx] );\n"
|
||||
"\n"
|
||||
" idx+=64;\n"
|
||||
" } else\n"
|
||||
" {\n"
|
||||
" break;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" GROUP_LDS_BARRIER;\n"
|
||||
" if( lIdx == 0 )\n"
|
||||
" {\n"
|
||||
" ldsCurBatch++;\n"
|
||||
" }\n"
|
||||
" GROUP_LDS_BARRIER;\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
" \n"
|
||||
"}\n"
|
||||
"\n"
|
||||
;
|
||||
660
src/Bullet3OpenCL/RigidBody/kernels/solverSetup.cl
Normal file
660
src/Bullet3OpenCL/RigidBody/kernels/solverSetup.cl
Normal file
@@ -0,0 +1,660 @@
|
||||
|
||||
/*
|
||||
Copyright (c) 2012 Advanced Micro Devices, Inc.
|
||||
|
||||
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.
|
||||
*/
|
||||
//Originally written by Takahiro Harada
|
||||
|
||||
|
||||
#pragma OPENCL EXTENSION cl_amd_printf : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
|
||||
|
||||
|
||||
#ifdef cl_ext_atomic_counters_32
|
||||
#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
|
||||
#else
|
||||
#define counter32_t volatile global int*
|
||||
#endif
|
||||
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned char u8;
|
||||
|
||||
#define GET_GROUP_IDX get_group_id(0)
|
||||
#define GET_LOCAL_IDX get_local_id(0)
|
||||
#define GET_GLOBAL_IDX get_global_id(0)
|
||||
#define GET_GROUP_SIZE get_local_size(0)
|
||||
#define GET_NUM_GROUPS get_num_groups(0)
|
||||
#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
|
||||
#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
|
||||
#define AtomInc(x) atom_inc(&(x))
|
||||
#define AtomInc1(x, out) out = atom_inc(&(x))
|
||||
#define AppendInc(x, out) out = atomic_inc(x)
|
||||
#define AtomAdd(x, value) atom_add(&(x), value)
|
||||
#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
|
||||
#define AtomXhg(x, value) atom_xchg ( &(x), value )
|
||||
|
||||
|
||||
#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
|
||||
|
||||
#define make_float4 (float4)
|
||||
#define make_float2 (float2)
|
||||
#define make_uint4 (uint4)
|
||||
#define make_int4 (int4)
|
||||
#define make_uint2 (uint2)
|
||||
#define make_int2 (int2)
|
||||
|
||||
|
||||
#define max2 max
|
||||
#define min2 min
|
||||
|
||||
|
||||
///////////////////////////////////////
|
||||
// Vector
|
||||
///////////////////////////////////////
|
||||
__inline
|
||||
float fastDiv(float numerator, float denominator)
|
||||
{
|
||||
return native_divide(numerator, denominator);
|
||||
// return numerator/denominator;
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 fastDiv4(float4 numerator, float4 denominator)
|
||||
{
|
||||
return native_divide(numerator, denominator);
|
||||
}
|
||||
|
||||
__inline
|
||||
float fastSqrtf(float f2)
|
||||
{
|
||||
return native_sqrt(f2);
|
||||
// return sqrt(f2);
|
||||
}
|
||||
|
||||
__inline
|
||||
float fastRSqrt(float f2)
|
||||
{
|
||||
return native_rsqrt(f2);
|
||||
}
|
||||
|
||||
__inline
|
||||
float fastLength4(float4 v)
|
||||
{
|
||||
return fast_length(v);
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 fastNormalize4(float4 v)
|
||||
{
|
||||
return fast_normalize(v);
|
||||
}
|
||||
|
||||
|
||||
__inline
|
||||
float sqrtf(float a)
|
||||
{
|
||||
// return sqrt(a);
|
||||
return native_sqrt(a);
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 cross3(float4 a, float4 b)
|
||||
{
|
||||
return cross(a,b);
|
||||
}
|
||||
|
||||
__inline
|
||||
float dot3F4(float4 a, float4 b)
|
||||
{
|
||||
float4 a1 = make_float4(a.xyz,0.f);
|
||||
float4 b1 = make_float4(b.xyz,0.f);
|
||||
return dot(a1, b1);
|
||||
}
|
||||
|
||||
__inline
|
||||
float length3(const float4 a)
|
||||
{
|
||||
return sqrtf(dot3F4(a,a));
|
||||
}
|
||||
|
||||
__inline
|
||||
float dot4(const float4 a, const float4 b)
|
||||
{
|
||||
return dot( a, b );
|
||||
}
|
||||
|
||||
// for height
|
||||
__inline
|
||||
float dot3w1(const float4 point, const float4 eqn)
|
||||
{
|
||||
return dot3F4(point,eqn) + eqn.w;
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 normalize3(const float4 a)
|
||||
{
|
||||
float4 n = make_float4(a.x, a.y, a.z, 0.f);
|
||||
return fastNormalize4( n );
|
||||
// float length = sqrtf(dot3F4(a, a));
|
||||
// return 1.f/length * a;
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 normalize4(const float4 a)
|
||||
{
|
||||
float length = sqrtf(dot4(a, a));
|
||||
return 1.f/length * a;
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 createEquation(const float4 a, const float4 b, const float4 c)
|
||||
{
|
||||
float4 eqn;
|
||||
float4 ab = b-a;
|
||||
float4 ac = c-a;
|
||||
eqn = normalize3( cross3(ab, ac) );
|
||||
eqn.w = -dot3F4(eqn,a);
|
||||
return eqn;
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
// Matrix3x3
|
||||
///////////////////////////////////////
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_row[3];
|
||||
}Matrix3x3;
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtZero();
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtIdentity();
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtTranspose(Matrix3x3 m);
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);
|
||||
|
||||
__inline
|
||||
float4 mtMul1(Matrix3x3 a, float4 b);
|
||||
|
||||
__inline
|
||||
float4 mtMul3(float4 a, Matrix3x3 b);
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtZero()
|
||||
{
|
||||
Matrix3x3 m;
|
||||
m.m_row[0] = (float4)(0.f);
|
||||
m.m_row[1] = (float4)(0.f);
|
||||
m.m_row[2] = (float4)(0.f);
|
||||
return m;
|
||||
}
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtIdentity()
|
||||
{
|
||||
Matrix3x3 m;
|
||||
m.m_row[0] = (float4)(1,0,0,0);
|
||||
m.m_row[1] = (float4)(0,1,0,0);
|
||||
m.m_row[2] = (float4)(0,0,1,0);
|
||||
return m;
|
||||
}
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtTranspose(Matrix3x3 m)
|
||||
{
|
||||
Matrix3x3 out;
|
||||
out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);
|
||||
out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);
|
||||
out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);
|
||||
return out;
|
||||
}
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)
|
||||
{
|
||||
Matrix3x3 transB;
|
||||
transB = mtTranspose( b );
|
||||
Matrix3x3 ans;
|
||||
// why this doesn't run when 0ing in the for{}
|
||||
a.m_row[0].w = 0.f;
|
||||
a.m_row[1].w = 0.f;
|
||||
a.m_row[2].w = 0.f;
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
// a.m_row[i].w = 0.f;
|
||||
ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);
|
||||
ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);
|
||||
ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);
|
||||
ans.m_row[i].w = 0.f;
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 mtMul1(Matrix3x3 a, float4 b)
|
||||
{
|
||||
float4 ans;
|
||||
ans.x = dot3F4( a.m_row[0], b );
|
||||
ans.y = dot3F4( a.m_row[1], b );
|
||||
ans.z = dot3F4( a.m_row[2], b );
|
||||
ans.w = 0.f;
|
||||
return ans;
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 mtMul3(float4 a, Matrix3x3 b)
|
||||
{
|
||||
float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
|
||||
float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
|
||||
float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
|
||||
|
||||
float4 ans;
|
||||
ans.x = dot3F4( a, colx );
|
||||
ans.y = dot3F4( a, coly );
|
||||
ans.z = dot3F4( a, colz );
|
||||
return ans;
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
// Quaternion
|
||||
///////////////////////////////////////
|
||||
|
||||
typedef float4 Quaternion;
|
||||
|
||||
__inline
|
||||
Quaternion qtMul(Quaternion a, Quaternion b);
|
||||
|
||||
__inline
|
||||
Quaternion qtNormalize(Quaternion in);
|
||||
|
||||
__inline
|
||||
float4 qtRotate(Quaternion q, float4 vec);
|
||||
|
||||
__inline
|
||||
Quaternion qtInvert(Quaternion q);
|
||||
|
||||
__inline
|
||||
Matrix3x3 qtGetRotationMatrix(Quaternion q);
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
Quaternion qtMul(Quaternion a, Quaternion b)
|
||||
{
|
||||
Quaternion ans;
|
||||
ans = cross3( a, b );
|
||||
ans += a.w*b+b.w*a;
|
||||
// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
|
||||
ans.w = a.w*b.w - dot3F4(a, b);
|
||||
return ans;
|
||||
}
|
||||
|
||||
__inline
|
||||
Quaternion qtNormalize(Quaternion in)
|
||||
{
|
||||
return fastNormalize4(in);
|
||||
// in /= length( in );
|
||||
// return in;
|
||||
}
|
||||
__inline
|
||||
float4 qtRotate(Quaternion q, float4 vec)
|
||||
{
|
||||
Quaternion qInv = qtInvert( q );
|
||||
float4 vcpy = vec;
|
||||
vcpy.w = 0.f;
|
||||
float4 out = qtMul(qtMul(q,vcpy),qInv);
|
||||
return out;
|
||||
}
|
||||
|
||||
__inline
|
||||
Quaternion qtInvert(Quaternion q)
|
||||
{
|
||||
return (Quaternion)(-q.xyz, q.w);
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 qtInvRotate(const Quaternion q, float4 vec)
|
||||
{
|
||||
return qtRotate( qtInvert( q ), vec );
|
||||
}
|
||||
|
||||
__inline
|
||||
Matrix3x3 qtGetRotationMatrix(Quaternion quat)
|
||||
{
|
||||
float4 quat2 = (float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);
|
||||
Matrix3x3 out;
|
||||
|
||||
out.m_row[0].x=1-2*quat2.y-2*quat2.z;
|
||||
out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;
|
||||
out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;
|
||||
out.m_row[0].w = 0.f;
|
||||
|
||||
out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;
|
||||
out.m_row[1].y=1-2*quat2.x-2*quat2.z;
|
||||
out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;
|
||||
out.m_row[1].w = 0.f;
|
||||
|
||||
out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;
|
||||
out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;
|
||||
out.m_row[2].z=1-2*quat2.x-2*quat2.y;
|
||||
out.m_row[2].w = 0.f;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define WG_SIZE 64
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_pos;
|
||||
Quaternion m_quat;
|
||||
float4 m_linVel;
|
||||
float4 m_angVel;
|
||||
|
||||
u32 m_shapeIdx;
|
||||
float m_invMass;
|
||||
float m_restituitionCoeff;
|
||||
float m_frictionCoeff;
|
||||
} Body;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Matrix3x3 m_invInertia;
|
||||
Matrix3x3 m_initInvInertia;
|
||||
} Shape;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_linear;
|
||||
float4 m_worldPos[4];
|
||||
float4 m_center;
|
||||
float m_jacCoeffInv[4];
|
||||
float m_b[4];
|
||||
float m_appliedRambdaDt[4];
|
||||
|
||||
float m_fJacCoeffInv[2];
|
||||
float m_fAppliedRambdaDt[2];
|
||||
|
||||
u32 m_bodyA;
|
||||
u32 m_bodyB;
|
||||
|
||||
int m_batchIdx;
|
||||
u32 m_paddings[1];
|
||||
} Constraint4;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_worldPos[4];
|
||||
float4 m_worldNormal;
|
||||
u32 m_coeffs;
|
||||
int m_batchIdx;
|
||||
|
||||
int m_bodyAPtrAndSignBit;
|
||||
int m_bodyBPtrAndSignBit;
|
||||
} Contact4;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int m_nConstraints;
|
||||
int m_start;
|
||||
int m_batchIdx;
|
||||
int m_nSplit;
|
||||
// int m_paddings[1];
|
||||
} ConstBuffer;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int m_solveFriction;
|
||||
int m_maxBatch; // long batch really kills the performance
|
||||
int m_batchIdx;
|
||||
int m_nSplit;
|
||||
// int m_paddings[1];
|
||||
} ConstBufferBatchSolve;
|
||||
|
||||
|
||||
void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)
|
||||
{
|
||||
*linear = make_float4(-n.xyz,0.f);
|
||||
*angular0 = -cross3(r0, n);
|
||||
*angular1 = cross3(r1, n);
|
||||
}
|
||||
|
||||
|
||||
float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )
|
||||
{
|
||||
return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);
|
||||
}
|
||||
|
||||
|
||||
float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,
|
||||
float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1)
|
||||
{
|
||||
// linear0,1 are normlized
|
||||
float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;
|
||||
float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);
|
||||
float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;
|
||||
float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);
|
||||
return -1.f/(jmj0+jmj1+jmj2+jmj3);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int m_valInt0;
|
||||
int m_valInt1;
|
||||
int m_valInt2;
|
||||
int m_valInt3;
|
||||
|
||||
float m_val0;
|
||||
float m_val1;
|
||||
float m_val2;
|
||||
float m_val3;
|
||||
} SolverDebugInfo;
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int m_nContacts;
|
||||
int m_staticIdx;
|
||||
float m_scale;
|
||||
int m_nSplit;
|
||||
} ConstBufferSSD;
|
||||
|
||||
|
||||
void btPlaneSpace1 (float4 n, float4* p, float4* q);
|
||||
void btPlaneSpace1 (float4 n, float4* p, float4* q)
|
||||
{
|
||||
if (fabs(n.z) > 0.70710678f) {
|
||||
// choose p in y-z plane
|
||||
float a = n.y*n.y + n.z*n.z;
|
||||
float k = 1.f/sqrt(a);
|
||||
p[0].x = 0;
|
||||
p[0].y = -n.z*k;
|
||||
p[0].z = n.y*k;
|
||||
// set q = n x p
|
||||
q[0].x = a*k;
|
||||
q[0].y = -n.x*p[0].z;
|
||||
q[0].z = n.x*p[0].y;
|
||||
}
|
||||
else {
|
||||
// choose p in x-y plane
|
||||
float a = n.x*n.x + n.y*n.y;
|
||||
float k = 1.f/sqrt(a);
|
||||
p[0].x = -n.y*k;
|
||||
p[0].y = n.x*k;
|
||||
p[0].z = 0;
|
||||
// set q = n x p
|
||||
q[0].x = -n.z*p[0].y;
|
||||
q[0].y = n.z*p[0].x;
|
||||
q[0].z = a*k;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setConstraint4( const float4 posA, const float4 linVelA, const float4 angVelA, float invMassA, const Matrix3x3 invInertiaA,
|
||||
const float4 posB, const float4 linVelB, const float4 angVelB, float invMassB, const Matrix3x3 invInertiaB,
|
||||
__global Contact4* src, float dt, float positionDrift, float positionConstraintCoeff,
|
||||
Constraint4* dstC )
|
||||
{
|
||||
dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);
|
||||
dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);
|
||||
|
||||
float dtInv = 1.f/dt;
|
||||
for(int ic=0; ic<4; ic++)
|
||||
{
|
||||
dstC->m_appliedRambdaDt[ic] = 0.f;
|
||||
}
|
||||
dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;
|
||||
|
||||
|
||||
dstC->m_linear = -src->m_worldNormal;
|
||||
dstC->m_linear.w = 0.7f ;//src->getFrictionCoeff() );
|
||||
for(int ic=0; ic<4; ic++)
|
||||
{
|
||||
float4 r0 = src->m_worldPos[ic] - posA;
|
||||
float4 r1 = src->m_worldPos[ic] - posB;
|
||||
|
||||
if( ic >= src->m_worldNormal.w )//npoints
|
||||
{
|
||||
dstC->m_jacCoeffInv[ic] = 0.f;
|
||||
continue;
|
||||
}
|
||||
|
||||
float relVelN;
|
||||
{
|
||||
float4 linear, angular0, angular1;
|
||||
setLinearAndAngular(src->m_worldNormal, r0, r1, &linear, &angular0, &angular1);
|
||||
|
||||
dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,
|
||||
invMassA, &invInertiaA, invMassB, &invInertiaB );
|
||||
|
||||
relVelN = calcRelVel(linear, -linear, angular0, angular1,
|
||||
linVelA, angVelA, linVelB, angVelB);
|
||||
|
||||
float e = 0.f;//src->getRestituitionCoeff();
|
||||
if( relVelN*relVelN < 0.004f ) e = 0.f;
|
||||
|
||||
dstC->m_b[ic] = e*relVelN;
|
||||
//float penetration = src->m_worldPos[ic].w;
|
||||
dstC->m_b[ic] += (src->m_worldPos[ic].w + positionDrift)*positionConstraintCoeff*dtInv;
|
||||
dstC->m_appliedRambdaDt[ic] = 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
if( src->m_worldNormal.w > 0 )//npoints
|
||||
{ // prepare friction
|
||||
float4 center = make_float4(0.f);
|
||||
for(int i=0; i<src->m_worldNormal.w; i++)
|
||||
center += src->m_worldPos[i];
|
||||
center /= (float)src->m_worldNormal.w;
|
||||
|
||||
float4 tangent[2];
|
||||
btPlaneSpace1(src->m_worldNormal,&tangent[0],&tangent[1]);
|
||||
|
||||
float4 r[2];
|
||||
r[0] = center - posA;
|
||||
r[1] = center - posB;
|
||||
|
||||
for(int i=0; i<2; i++)
|
||||
{
|
||||
float4 linear, angular0, angular1;
|
||||
setLinearAndAngular(tangent[i], r[0], r[1], &linear, &angular0, &angular1);
|
||||
|
||||
dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,
|
||||
invMassA, &invInertiaA, invMassB, &invInertiaB );
|
||||
dstC->m_fAppliedRambdaDt[i] = 0.f;
|
||||
}
|
||||
dstC->m_center = center;
|
||||
}
|
||||
|
||||
for(int i=0; i<4; i++)
|
||||
{
|
||||
if( i<src->m_worldNormal.w )
|
||||
{
|
||||
dstC->m_worldPos[i] = src->m_worldPos[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
dstC->m_worldPos[i] = make_float4(0.f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int m_nContacts;
|
||||
float m_dt;
|
||||
float m_positionDrift;
|
||||
float m_positionConstraintCoeff;
|
||||
} ConstBufferCTC;
|
||||
|
||||
__kernel
|
||||
__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
|
||||
void ContactToConstraintKernel(__global Contact4* gContact, __global Body* gBodies, __global Shape* gShapes, __global Constraint4* gConstraintOut,
|
||||
int nContacts,
|
||||
float dt,
|
||||
float positionDrift,
|
||||
float positionConstraintCoeff
|
||||
)
|
||||
{
|
||||
int gIdx = GET_GLOBAL_IDX;
|
||||
|
||||
if( gIdx < nContacts )
|
||||
{
|
||||
int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);
|
||||
int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);
|
||||
|
||||
float4 posA = gBodies[aIdx].m_pos;
|
||||
float4 linVelA = gBodies[aIdx].m_linVel;
|
||||
float4 angVelA = gBodies[aIdx].m_angVel;
|
||||
float invMassA = gBodies[aIdx].m_invMass;
|
||||
Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;
|
||||
|
||||
float4 posB = gBodies[bIdx].m_pos;
|
||||
float4 linVelB = gBodies[bIdx].m_linVel;
|
||||
float4 angVelB = gBodies[bIdx].m_angVel;
|
||||
float invMassB = gBodies[bIdx].m_invMass;
|
||||
Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;
|
||||
|
||||
Constraint4 cs;
|
||||
|
||||
setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,
|
||||
&gContact[gIdx], dt, positionDrift, positionConstraintCoeff,
|
||||
&cs );
|
||||
|
||||
cs.m_batchIdx = gContact[gIdx].m_batchIdx;
|
||||
|
||||
gConstraintOut[gIdx] = cs;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
664
src/Bullet3OpenCL/RigidBody/kernels/solverSetup.h
Normal file
664
src/Bullet3OpenCL/RigidBody/kernels/solverSetup.h
Normal file
@@ -0,0 +1,664 @@
|
||||
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
|
||||
static const char* solverSetupCL= \
|
||||
"\n"
|
||||
"/*\n"
|
||||
"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
|
||||
"\n"
|
||||
"This software is provided 'as-is', without any express or implied warranty.\n"
|
||||
"In no event will the authors be held liable for any damages arising from the use of this software.\n"
|
||||
"Permission is granted to anyone to use this software for any purpose, \n"
|
||||
"including commercial applications, and to alter it and redistribute it freely, \n"
|
||||
"subject to the following restrictions:\n"
|
||||
"\n"
|
||||
"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.\n"
|
||||
"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
|
||||
"3. This notice may not be removed or altered from any source distribution.\n"
|
||||
"*/\n"
|
||||
"//Originally written by Takahiro Harada\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#ifdef cl_ext_atomic_counters_32\n"
|
||||
"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
|
||||
"#else\n"
|
||||
"#define counter32_t volatile global int*\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"typedef unsigned int u32;\n"
|
||||
"typedef unsigned short u16;\n"
|
||||
"typedef unsigned char u8;\n"
|
||||
"\n"
|
||||
"#define GET_GROUP_IDX get_group_id(0)\n"
|
||||
"#define GET_LOCAL_IDX get_local_id(0)\n"
|
||||
"#define GET_GLOBAL_IDX get_global_id(0)\n"
|
||||
"#define GET_GROUP_SIZE get_local_size(0)\n"
|
||||
"#define GET_NUM_GROUPS get_num_groups(0)\n"
|
||||
"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
|
||||
"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
|
||||
"#define AtomInc(x) atom_inc(&(x))\n"
|
||||
"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
|
||||
"#define AppendInc(x, out) out = atomic_inc(x)\n"
|
||||
"#define AtomAdd(x, value) atom_add(&(x), value)\n"
|
||||
"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
|
||||
"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
|
||||
"\n"
|
||||
"#define make_float4 (float4)\n"
|
||||
"#define make_float2 (float2)\n"
|
||||
"#define make_uint4 (uint4)\n"
|
||||
"#define make_int4 (int4)\n"
|
||||
"#define make_uint2 (uint2)\n"
|
||||
"#define make_int2 (int2)\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define max2 max\n"
|
||||
"#define min2 min\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"// Vector\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"__inline\n"
|
||||
"float fastDiv(float numerator, float denominator)\n"
|
||||
"{\n"
|
||||
" return native_divide(numerator, denominator); \n"
|
||||
"// return numerator/denominator; \n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 fastDiv4(float4 numerator, float4 denominator)\n"
|
||||
"{\n"
|
||||
" return native_divide(numerator, denominator); \n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float fastSqrtf(float f2)\n"
|
||||
"{\n"
|
||||
" return native_sqrt(f2);\n"
|
||||
"// return sqrt(f2);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float fastRSqrt(float f2)\n"
|
||||
"{\n"
|
||||
" return native_rsqrt(f2);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float fastLength4(float4 v)\n"
|
||||
"{\n"
|
||||
" return fast_length(v);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 fastNormalize4(float4 v)\n"
|
||||
"{\n"
|
||||
" return fast_normalize(v);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float sqrtf(float a)\n"
|
||||
"{\n"
|
||||
"// return sqrt(a);\n"
|
||||
" return native_sqrt(a);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 cross3(float4 a, float4 b)\n"
|
||||
"{\n"
|
||||
" return cross(a,b);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float dot3F4(float4 a, float4 b)\n"
|
||||
"{\n"
|
||||
" float4 a1 = make_float4(a.xyz,0.f);\n"
|
||||
" float4 b1 = make_float4(b.xyz,0.f);\n"
|
||||
" return dot(a1, b1);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float length3(const float4 a)\n"
|
||||
"{\n"
|
||||
" return sqrtf(dot3F4(a,a));\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float dot4(const float4 a, const float4 b)\n"
|
||||
"{\n"
|
||||
" return dot( a, b );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"// for height\n"
|
||||
"__inline\n"
|
||||
"float dot3w1(const float4 point, const float4 eqn)\n"
|
||||
"{\n"
|
||||
" return dot3F4(point,eqn) + eqn.w;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 normalize3(const float4 a)\n"
|
||||
"{\n"
|
||||
" float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
|
||||
" return fastNormalize4( n );\n"
|
||||
"// float length = sqrtf(dot3F4(a, a));\n"
|
||||
"// return 1.f/length * a;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 normalize4(const float4 a)\n"
|
||||
"{\n"
|
||||
" float length = sqrtf(dot4(a, a));\n"
|
||||
" return 1.f/length * a;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 createEquation(const float4 a, const float4 b, const float4 c)\n"
|
||||
"{\n"
|
||||
" float4 eqn;\n"
|
||||
" float4 ab = b-a;\n"
|
||||
" float4 ac = c-a;\n"
|
||||
" eqn = normalize3( cross3(ab, ac) );\n"
|
||||
" eqn.w = -dot3F4(eqn,a);\n"
|
||||
" return eqn;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"// Matrix3x3\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_row[3];\n"
|
||||
"}Matrix3x3;\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtZero();\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtIdentity();\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtTranspose(Matrix3x3 m);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 mtMul1(Matrix3x3 a, float4 b);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 mtMul3(float4 a, Matrix3x3 b);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtZero()\n"
|
||||
"{\n"
|
||||
" Matrix3x3 m;\n"
|
||||
" m.m_row[0] = (float4)(0.f);\n"
|
||||
" m.m_row[1] = (float4)(0.f);\n"
|
||||
" m.m_row[2] = (float4)(0.f);\n"
|
||||
" return m;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtIdentity()\n"
|
||||
"{\n"
|
||||
" Matrix3x3 m;\n"
|
||||
" m.m_row[0] = (float4)(1,0,0,0);\n"
|
||||
" m.m_row[1] = (float4)(0,1,0,0);\n"
|
||||
" m.m_row[2] = (float4)(0,0,1,0);\n"
|
||||
" return m;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtTranspose(Matrix3x3 m)\n"
|
||||
"{\n"
|
||||
" Matrix3x3 out;\n"
|
||||
" out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
|
||||
" out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
|
||||
" out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
|
||||
" return out;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)\n"
|
||||
"{\n"
|
||||
" Matrix3x3 transB;\n"
|
||||
" transB = mtTranspose( b );\n"
|
||||
" Matrix3x3 ans;\n"
|
||||
" // why this doesn't run when 0ing in the for{}\n"
|
||||
" a.m_row[0].w = 0.f;\n"
|
||||
" a.m_row[1].w = 0.f;\n"
|
||||
" a.m_row[2].w = 0.f;\n"
|
||||
" for(int i=0; i<3; i++)\n"
|
||||
" {\n"
|
||||
"// a.m_row[i].w = 0.f;\n"
|
||||
" ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);\n"
|
||||
" ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);\n"
|
||||
" ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);\n"
|
||||
" ans.m_row[i].w = 0.f;\n"
|
||||
" }\n"
|
||||
" return ans;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 mtMul1(Matrix3x3 a, float4 b)\n"
|
||||
"{\n"
|
||||
" float4 ans;\n"
|
||||
" ans.x = dot3F4( a.m_row[0], b );\n"
|
||||
" ans.y = dot3F4( a.m_row[1], b );\n"
|
||||
" ans.z = dot3F4( a.m_row[2], b );\n"
|
||||
" ans.w = 0.f;\n"
|
||||
" return ans;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 mtMul3(float4 a, Matrix3x3 b)\n"
|
||||
"{\n"
|
||||
" float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
|
||||
" float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
|
||||
" float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
|
||||
"\n"
|
||||
" float4 ans;\n"
|
||||
" ans.x = dot3F4( a, colx );\n"
|
||||
" ans.y = dot3F4( a, coly );\n"
|
||||
" ans.z = dot3F4( a, colz );\n"
|
||||
" return ans;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"// Quaternion\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"\n"
|
||||
"typedef float4 Quaternion;\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Quaternion qtMul(Quaternion a, Quaternion b);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Quaternion qtNormalize(Quaternion in);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 qtRotate(Quaternion q, float4 vec);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Quaternion qtInvert(Quaternion q);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 qtGetRotationMatrix(Quaternion q);\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Quaternion qtMul(Quaternion a, Quaternion b)\n"
|
||||
"{\n"
|
||||
" Quaternion ans;\n"
|
||||
" ans = cross3( a, b );\n"
|
||||
" ans += a.w*b+b.w*a;\n"
|
||||
"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
|
||||
" ans.w = a.w*b.w - dot3F4(a, b);\n"
|
||||
" return ans;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Quaternion qtNormalize(Quaternion in)\n"
|
||||
"{\n"
|
||||
" return fastNormalize4(in);\n"
|
||||
"// in /= length( in );\n"
|
||||
"// return in;\n"
|
||||
"}\n"
|
||||
"__inline\n"
|
||||
"float4 qtRotate(Quaternion q, float4 vec)\n"
|
||||
"{\n"
|
||||
" Quaternion qInv = qtInvert( q );\n"
|
||||
" float4 vcpy = vec;\n"
|
||||
" vcpy.w = 0.f;\n"
|
||||
" float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
|
||||
" return out;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Quaternion qtInvert(Quaternion q)\n"
|
||||
"{\n"
|
||||
" return (Quaternion)(-q.xyz, q.w);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 qtInvRotate(const Quaternion q, float4 vec)\n"
|
||||
"{\n"
|
||||
" return qtRotate( qtInvert( q ), vec );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 qtGetRotationMatrix(Quaternion quat)\n"
|
||||
"{\n"
|
||||
" float4 quat2 = (float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
|
||||
" Matrix3x3 out;\n"
|
||||
"\n"
|
||||
" out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
|
||||
" out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
|
||||
" out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
|
||||
" out.m_row[0].w = 0.f;\n"
|
||||
"\n"
|
||||
" out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
|
||||
" out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
|
||||
" out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
|
||||
" out.m_row[1].w = 0.f;\n"
|
||||
"\n"
|
||||
" out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
|
||||
" out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
|
||||
" out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
|
||||
" out.m_row[2].w = 0.f;\n"
|
||||
"\n"
|
||||
" return out;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define WG_SIZE 64\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_pos;\n"
|
||||
" Quaternion m_quat;\n"
|
||||
" float4 m_linVel;\n"
|
||||
" float4 m_angVel;\n"
|
||||
"\n"
|
||||
" u32 m_shapeIdx;\n"
|
||||
" float m_invMass;\n"
|
||||
" float m_restituitionCoeff;\n"
|
||||
" float m_frictionCoeff;\n"
|
||||
"} Body;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" Matrix3x3 m_invInertia;\n"
|
||||
" Matrix3x3 m_initInvInertia;\n"
|
||||
"} Shape;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_linear;\n"
|
||||
" float4 m_worldPos[4];\n"
|
||||
" float4 m_center; \n"
|
||||
" float m_jacCoeffInv[4];\n"
|
||||
" float m_b[4];\n"
|
||||
" float m_appliedRambdaDt[4];\n"
|
||||
"\n"
|
||||
" float m_fJacCoeffInv[2]; \n"
|
||||
" float m_fAppliedRambdaDt[2]; \n"
|
||||
"\n"
|
||||
" u32 m_bodyA;\n"
|
||||
" u32 m_bodyB;\n"
|
||||
"\n"
|
||||
" int m_batchIdx;\n"
|
||||
" u32 m_paddings[1];\n"
|
||||
"} Constraint4;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_worldPos[4];\n"
|
||||
" float4 m_worldNormal;\n"
|
||||
" u32 m_coeffs;\n"
|
||||
" int m_batchIdx;\n"
|
||||
"\n"
|
||||
" int m_bodyAPtrAndSignBit;\n"
|
||||
" int m_bodyBPtrAndSignBit;\n"
|
||||
"} Contact4;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" int m_nConstraints;\n"
|
||||
" int m_start;\n"
|
||||
" int m_batchIdx;\n"
|
||||
" int m_nSplit;\n"
|
||||
"// int m_paddings[1];\n"
|
||||
"} ConstBuffer;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" int m_solveFriction;\n"
|
||||
" int m_maxBatch; // long batch really kills the performance\n"
|
||||
" int m_batchIdx;\n"
|
||||
" int m_nSplit;\n"
|
||||
"// int m_paddings[1];\n"
|
||||
"} ConstBufferBatchSolve;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)\n"
|
||||
"{\n"
|
||||
" *linear = make_float4(-n.xyz,0.f);\n"
|
||||
" *angular0 = -cross3(r0, n);\n"
|
||||
" *angular1 = cross3(r1, n);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )\n"
|
||||
"{\n"
|
||||
" return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
|
||||
" float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1)\n"
|
||||
"{\n"
|
||||
" // linear0,1 are normlized\n"
|
||||
" float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;\n"
|
||||
" float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
|
||||
" float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;\n"
|
||||
" float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
|
||||
" return -1.f/(jmj0+jmj1+jmj2+jmj3);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" \n"
|
||||
"\n"
|
||||
"\n"
|
||||
"typedef struct \n"
|
||||
"{\n"
|
||||
" int m_valInt0;\n"
|
||||
" int m_valInt1;\n"
|
||||
" int m_valInt2;\n"
|
||||
" int m_valInt3;\n"
|
||||
"\n"
|
||||
" float m_val0;\n"
|
||||
" float m_val1;\n"
|
||||
" float m_val2;\n"
|
||||
" float m_val3;\n"
|
||||
"} SolverDebugInfo;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" int m_nContacts;\n"
|
||||
" int m_staticIdx;\n"
|
||||
" float m_scale;\n"
|
||||
" int m_nSplit;\n"
|
||||
"} ConstBufferSSD;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"void b3PlaneSpace1 (float4 n, float4* p, float4* q);\n"
|
||||
" void b3PlaneSpace1 (float4 n, float4* p, float4* q)\n"
|
||||
"{\n"
|
||||
" if (fabs(n.z) > 0.70710678f) {\n"
|
||||
" // choose p in y-z plane\n"
|
||||
" float a = n.y*n.y + n.z*n.z;\n"
|
||||
" float k = 1.f/sqrt(a);\n"
|
||||
" p[0].x = 0;\n"
|
||||
" p[0].y = -n.z*k;\n"
|
||||
" p[0].z = n.y*k;\n"
|
||||
" // set q = n x p\n"
|
||||
" q[0].x = a*k;\n"
|
||||
" q[0].y = -n.x*p[0].z;\n"
|
||||
" q[0].z = n.x*p[0].y;\n"
|
||||
" }\n"
|
||||
" else {\n"
|
||||
" // choose p in x-y plane\n"
|
||||
" float a = n.x*n.x + n.y*n.y;\n"
|
||||
" float k = 1.f/sqrt(a);\n"
|
||||
" p[0].x = -n.y*k;\n"
|
||||
" p[0].y = n.x*k;\n"
|
||||
" p[0].z = 0;\n"
|
||||
" // set q = n x p\n"
|
||||
" q[0].x = -n.z*p[0].y;\n"
|
||||
" q[0].y = n.z*p[0].x;\n"
|
||||
" q[0].z = a*k;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"void setConstraint4( const float4 posA, const float4 linVelA, const float4 angVelA, float invMassA, const Matrix3x3 invInertiaA,\n"
|
||||
" const float4 posB, const float4 linVelB, const float4 angVelB, float invMassB, const Matrix3x3 invInertiaB, \n"
|
||||
" __global Contact4* src, float dt, float positionDrift, float positionConstraintCoeff,\n"
|
||||
" Constraint4* dstC )\n"
|
||||
"{\n"
|
||||
" dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);\n"
|
||||
" dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);\n"
|
||||
"\n"
|
||||
" float dtInv = 1.f/dt;\n"
|
||||
" for(int ic=0; ic<4; ic++)\n"
|
||||
" {\n"
|
||||
" dstC->m_appliedRambdaDt[ic] = 0.f;\n"
|
||||
" }\n"
|
||||
" dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" dstC->m_linear = -src->m_worldNormal;\n"
|
||||
" dstC->m_linear.w = 0.7f ;//src->getFrictionCoeff() );\n"
|
||||
" for(int ic=0; ic<4; ic++)\n"
|
||||
" {\n"
|
||||
" float4 r0 = src->m_worldPos[ic] - posA;\n"
|
||||
" float4 r1 = src->m_worldPos[ic] - posB;\n"
|
||||
"\n"
|
||||
" if( ic >= src->m_worldNormal.w )//npoints\n"
|
||||
" {\n"
|
||||
" dstC->m_jacCoeffInv[ic] = 0.f;\n"
|
||||
" continue;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" float relVelN;\n"
|
||||
" {\n"
|
||||
" float4 linear, angular0, angular1;\n"
|
||||
" setLinearAndAngular(src->m_worldNormal, r0, r1, &linear, &angular0, &angular1);\n"
|
||||
"\n"
|
||||
" dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
|
||||
" invMassA, &invInertiaA, invMassB, &invInertiaB );\n"
|
||||
"\n"
|
||||
" relVelN = calcRelVel(linear, -linear, angular0, angular1,\n"
|
||||
" linVelA, angVelA, linVelB, angVelB);\n"
|
||||
"\n"
|
||||
" float e = 0.f;//src->getRestituitionCoeff();\n"
|
||||
" if( relVelN*relVelN < 0.004f ) e = 0.f;\n"
|
||||
"\n"
|
||||
" dstC->m_b[ic] = e*relVelN;\n"
|
||||
" //float penetration = src->m_worldPos[ic].w;\n"
|
||||
" dstC->m_b[ic] += (src->m_worldPos[ic].w + positionDrift)*positionConstraintCoeff*dtInv;\n"
|
||||
" dstC->m_appliedRambdaDt[ic] = 0.f;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" if( src->m_worldNormal.w > 0 )//npoints\n"
|
||||
" { // prepare friction\n"
|
||||
" float4 center = make_float4(0.f);\n"
|
||||
" for(int i=0; i<src->m_worldNormal.w; i++) \n"
|
||||
" center += src->m_worldPos[i];\n"
|
||||
" center /= (float)src->m_worldNormal.w;\n"
|
||||
"\n"
|
||||
" float4 tangent[2];\n"
|
||||
" b3PlaneSpace1(src->m_worldNormal,&tangent[0],&tangent[1]);\n"
|
||||
" \n"
|
||||
" float4 r[2];\n"
|
||||
" r[0] = center - posA;\n"
|
||||
" r[1] = center - posB;\n"
|
||||
"\n"
|
||||
" for(int i=0; i<2; i++)\n"
|
||||
" {\n"
|
||||
" float4 linear, angular0, angular1;\n"
|
||||
" setLinearAndAngular(tangent[i], r[0], r[1], &linear, &angular0, &angular1);\n"
|
||||
"\n"
|
||||
" dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
|
||||
" invMassA, &invInertiaA, invMassB, &invInertiaB );\n"
|
||||
" dstC->m_fAppliedRambdaDt[i] = 0.f;\n"
|
||||
" }\n"
|
||||
" dstC->m_center = center;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" for(int i=0; i<4; i++)\n"
|
||||
" {\n"
|
||||
" if( i<src->m_worldNormal.w )\n"
|
||||
" {\n"
|
||||
" dstC->m_worldPos[i] = src->m_worldPos[i];\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" dstC->m_worldPos[i] = make_float4(0.f);\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" int m_nContacts;\n"
|
||||
" float m_dt;\n"
|
||||
" float m_positionDrift;\n"
|
||||
" float m_positionConstraintCoeff;\n"
|
||||
"} ConstBufferCTC;\n"
|
||||
"\n"
|
||||
"__kernel\n"
|
||||
"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
|
||||
"void ContactToConstraintKernel(__global Contact4* gContact, __global Body* gBodies, __global Shape* gShapes, __global Constraint4* gConstraintOut, \n"
|
||||
"int nContacts,\n"
|
||||
"float dt,\n"
|
||||
"float positionDrift,\n"
|
||||
"float positionConstraintCoeff\n"
|
||||
")\n"
|
||||
"{\n"
|
||||
" int gIdx = GET_GLOBAL_IDX;\n"
|
||||
" \n"
|
||||
" if( gIdx < nContacts )\n"
|
||||
" {\n"
|
||||
" int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);\n"
|
||||
" int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);\n"
|
||||
"\n"
|
||||
" float4 posA = gBodies[aIdx].m_pos;\n"
|
||||
" float4 linVelA = gBodies[aIdx].m_linVel;\n"
|
||||
" float4 angVelA = gBodies[aIdx].m_angVel;\n"
|
||||
" float invMassA = gBodies[aIdx].m_invMass;\n"
|
||||
" Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
|
||||
"\n"
|
||||
" float4 posB = gBodies[bIdx].m_pos;\n"
|
||||
" float4 linVelB = gBodies[bIdx].m_linVel;\n"
|
||||
" float4 angVelB = gBodies[bIdx].m_angVel;\n"
|
||||
" float invMassB = gBodies[bIdx].m_invMass;\n"
|
||||
" Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
|
||||
"\n"
|
||||
" Constraint4 cs;\n"
|
||||
"\n"
|
||||
" setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,\n"
|
||||
" &gContact[gIdx], dt, positionDrift, positionConstraintCoeff,\n"
|
||||
" &cs );\n"
|
||||
" \n"
|
||||
" cs.m_batchIdx = gContact[gIdx].m_batchIdx;\n"
|
||||
"\n"
|
||||
" gConstraintOut[gIdx] = cs;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
;
|
||||
494
src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.cl
Normal file
494
src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.cl
Normal file
@@ -0,0 +1,494 @@
|
||||
/*
|
||||
Copyright (c) 2012 Advanced Micro Devices, Inc.
|
||||
|
||||
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.
|
||||
*/
|
||||
//Originally written by Takahiro Harada
|
||||
|
||||
|
||||
#pragma OPENCL EXTENSION cl_amd_printf : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
|
||||
|
||||
|
||||
#ifdef cl_ext_atomic_counters_32
|
||||
#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
|
||||
#else
|
||||
#define counter32_t volatile global int*
|
||||
#endif
|
||||
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned char u8;
|
||||
|
||||
#define GET_GROUP_IDX get_group_id(0)
|
||||
#define GET_LOCAL_IDX get_local_id(0)
|
||||
#define GET_GLOBAL_IDX get_global_id(0)
|
||||
#define GET_GROUP_SIZE get_local_size(0)
|
||||
#define GET_NUM_GROUPS get_num_groups(0)
|
||||
#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
|
||||
#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
|
||||
#define AtomInc(x) atom_inc(&(x))
|
||||
#define AtomInc1(x, out) out = atom_inc(&(x))
|
||||
#define AppendInc(x, out) out = atomic_inc(x)
|
||||
#define AtomAdd(x, value) atom_add(&(x), value)
|
||||
#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
|
||||
#define AtomXhg(x, value) atom_xchg ( &(x), value )
|
||||
|
||||
|
||||
#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
|
||||
|
||||
#define make_float4 (float4)
|
||||
#define make_float2 (float2)
|
||||
#define make_uint4 (uint4)
|
||||
#define make_int4 (int4)
|
||||
#define make_uint2 (uint2)
|
||||
#define make_int2 (int2)
|
||||
|
||||
|
||||
#define max2 max
|
||||
#define min2 min
|
||||
|
||||
|
||||
///////////////////////////////////////
|
||||
// Vector
|
||||
///////////////////////////////////////
|
||||
__inline
|
||||
float fastDiv(float numerator, float denominator)
|
||||
{
|
||||
return native_divide(numerator, denominator);
|
||||
// return numerator/denominator;
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 fastDiv4(float4 numerator, float4 denominator)
|
||||
{
|
||||
return native_divide(numerator, denominator);
|
||||
}
|
||||
|
||||
__inline
|
||||
float fastSqrtf(float f2)
|
||||
{
|
||||
return native_sqrt(f2);
|
||||
// return sqrt(f2);
|
||||
}
|
||||
|
||||
__inline
|
||||
float fastRSqrt(float f2)
|
||||
{
|
||||
return native_rsqrt(f2);
|
||||
}
|
||||
|
||||
__inline
|
||||
float fastLength4(float4 v)
|
||||
{
|
||||
return fast_length(v);
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 fastNormalize4(float4 v)
|
||||
{
|
||||
return fast_normalize(v);
|
||||
}
|
||||
|
||||
|
||||
__inline
|
||||
float sqrtf(float a)
|
||||
{
|
||||
// return sqrt(a);
|
||||
return native_sqrt(a);
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 cross3(float4 a, float4 b)
|
||||
{
|
||||
return cross(a,b);
|
||||
}
|
||||
|
||||
__inline
|
||||
float dot3F4(float4 a, float4 b)
|
||||
{
|
||||
float4 a1 = make_float4(a.xyz,0.f);
|
||||
float4 b1 = make_float4(b.xyz,0.f);
|
||||
return dot(a1, b1);
|
||||
}
|
||||
|
||||
__inline
|
||||
float length3(const float4 a)
|
||||
{
|
||||
return sqrtf(dot3F4(a,a));
|
||||
}
|
||||
|
||||
__inline
|
||||
float dot4(const float4 a, const float4 b)
|
||||
{
|
||||
return dot( a, b );
|
||||
}
|
||||
|
||||
// for height
|
||||
__inline
|
||||
float dot3w1(const float4 point, const float4 eqn)
|
||||
{
|
||||
return dot3F4(point,eqn) + eqn.w;
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 normalize3(const float4 a)
|
||||
{
|
||||
float4 n = make_float4(a.x, a.y, a.z, 0.f);
|
||||
return fastNormalize4( n );
|
||||
// float length = sqrtf(dot3F4(a, a));
|
||||
// return 1.f/length * a;
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 normalize4(const float4 a)
|
||||
{
|
||||
float length = sqrtf(dot4(a, a));
|
||||
return 1.f/length * a;
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 createEquation(const float4 a, const float4 b, const float4 c)
|
||||
{
|
||||
float4 eqn;
|
||||
float4 ab = b-a;
|
||||
float4 ac = c-a;
|
||||
eqn = normalize3( cross3(ab, ac) );
|
||||
eqn.w = -dot3F4(eqn,a);
|
||||
return eqn;
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
// Matrix3x3
|
||||
///////////////////////////////////////
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_row[3];
|
||||
}Matrix3x3;
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtZero();
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtIdentity();
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtTranspose(Matrix3x3 m);
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);
|
||||
|
||||
__inline
|
||||
float4 mtMul1(Matrix3x3 a, float4 b);
|
||||
|
||||
__inline
|
||||
float4 mtMul3(float4 a, Matrix3x3 b);
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtZero()
|
||||
{
|
||||
Matrix3x3 m;
|
||||
m.m_row[0] = (float4)(0.f);
|
||||
m.m_row[1] = (float4)(0.f);
|
||||
m.m_row[2] = (float4)(0.f);
|
||||
return m;
|
||||
}
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtIdentity()
|
||||
{
|
||||
Matrix3x3 m;
|
||||
m.m_row[0] = (float4)(1,0,0,0);
|
||||
m.m_row[1] = (float4)(0,1,0,0);
|
||||
m.m_row[2] = (float4)(0,0,1,0);
|
||||
return m;
|
||||
}
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtTranspose(Matrix3x3 m)
|
||||
{
|
||||
Matrix3x3 out;
|
||||
out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);
|
||||
out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);
|
||||
out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);
|
||||
return out;
|
||||
}
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)
|
||||
{
|
||||
Matrix3x3 transB;
|
||||
transB = mtTranspose( b );
|
||||
Matrix3x3 ans;
|
||||
// why this doesn't run when 0ing in the for{}
|
||||
a.m_row[0].w = 0.f;
|
||||
a.m_row[1].w = 0.f;
|
||||
a.m_row[2].w = 0.f;
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
// a.m_row[i].w = 0.f;
|
||||
ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);
|
||||
ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);
|
||||
ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);
|
||||
ans.m_row[i].w = 0.f;
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 mtMul1(Matrix3x3 a, float4 b)
|
||||
{
|
||||
float4 ans;
|
||||
ans.x = dot3F4( a.m_row[0], b );
|
||||
ans.y = dot3F4( a.m_row[1], b );
|
||||
ans.z = dot3F4( a.m_row[2], b );
|
||||
ans.w = 0.f;
|
||||
return ans;
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 mtMul3(float4 a, Matrix3x3 b)
|
||||
{
|
||||
float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
|
||||
float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
|
||||
float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
|
||||
|
||||
float4 ans;
|
||||
ans.x = dot3F4( a, colx );
|
||||
ans.y = dot3F4( a, coly );
|
||||
ans.z = dot3F4( a, colz );
|
||||
return ans;
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
// Quaternion
|
||||
///////////////////////////////////////
|
||||
|
||||
typedef float4 Quaternion;
|
||||
|
||||
__inline
|
||||
Quaternion qtMul(Quaternion a, Quaternion b);
|
||||
|
||||
__inline
|
||||
Quaternion qtNormalize(Quaternion in);
|
||||
|
||||
__inline
|
||||
float4 qtRotate(Quaternion q, float4 vec);
|
||||
|
||||
__inline
|
||||
Quaternion qtInvert(Quaternion q);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
Quaternion qtMul(Quaternion a, Quaternion b)
|
||||
{
|
||||
Quaternion ans;
|
||||
ans = cross3( a, b );
|
||||
ans += a.w*b+b.w*a;
|
||||
// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
|
||||
ans.w = a.w*b.w - dot3F4(a, b);
|
||||
return ans;
|
||||
}
|
||||
|
||||
__inline
|
||||
Quaternion qtNormalize(Quaternion in)
|
||||
{
|
||||
return fastNormalize4(in);
|
||||
// in /= length( in );
|
||||
// return in;
|
||||
}
|
||||
__inline
|
||||
float4 qtRotate(Quaternion q, float4 vec)
|
||||
{
|
||||
Quaternion qInv = qtInvert( q );
|
||||
float4 vcpy = vec;
|
||||
vcpy.w = 0.f;
|
||||
float4 out = qtMul(qtMul(q,vcpy),qInv);
|
||||
return out;
|
||||
}
|
||||
|
||||
__inline
|
||||
Quaternion qtInvert(Quaternion q)
|
||||
{
|
||||
return (Quaternion)(-q.xyz, q.w);
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 qtInvRotate(const Quaternion q, float4 vec)
|
||||
{
|
||||
return qtRotate( qtInvert( q ), vec );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define WG_SIZE 64
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_pos;
|
||||
Quaternion m_quat;
|
||||
float4 m_linVel;
|
||||
float4 m_angVel;
|
||||
|
||||
u32 m_shapeIdx;
|
||||
float m_invMass;
|
||||
float m_restituitionCoeff;
|
||||
float m_frictionCoeff;
|
||||
} Body;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Matrix3x3 m_invInertia;
|
||||
Matrix3x3 m_initInvInertia;
|
||||
} Shape;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_linear;
|
||||
float4 m_worldPos[4];
|
||||
float4 m_center;
|
||||
float m_jacCoeffInv[4];
|
||||
float m_b[4];
|
||||
float m_appliedRambdaDt[4];
|
||||
|
||||
float m_fJacCoeffInv[2];
|
||||
float m_fAppliedRambdaDt[2];
|
||||
|
||||
u32 m_bodyA;
|
||||
u32 m_bodyB;
|
||||
|
||||
int m_batchIdx;
|
||||
u32 m_paddings[1];
|
||||
} Constraint4;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_worldPos[4];
|
||||
float4 m_worldNormal;
|
||||
u32 m_coeffs;
|
||||
int m_batchIdx;
|
||||
|
||||
int m_bodyAPtrAndSignBit;
|
||||
int m_bodyBPtrAndSignBit;
|
||||
} Contact4;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int m_nConstraints;
|
||||
int m_start;
|
||||
int m_batchIdx;
|
||||
int m_nSplit;
|
||||
// int m_paddings[1];
|
||||
} ConstBuffer;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int m_solveFriction;
|
||||
int m_maxBatch; // long batch really kills the performance
|
||||
int m_batchIdx;
|
||||
int m_nSplit;
|
||||
// int m_paddings[1];
|
||||
} ConstBufferBatchSolve;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int m_valInt0;
|
||||
int m_valInt1;
|
||||
int m_valInt2;
|
||||
int m_valInt3;
|
||||
|
||||
float m_val0;
|
||||
float m_val1;
|
||||
float m_val2;
|
||||
float m_val3;
|
||||
} SolverDebugInfo;
|
||||
|
||||
|
||||
|
||||
|
||||
// others
|
||||
__kernel
|
||||
__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
|
||||
void ReorderContactKernel(__global Contact4* in, __global Contact4* out, __global int2* sortData, int4 cb )
|
||||
{
|
||||
int nContacts = cb.x;
|
||||
int gIdx = GET_GLOBAL_IDX;
|
||||
|
||||
if( gIdx < nContacts )
|
||||
{
|
||||
int srcIdx = sortData[gIdx].y;
|
||||
out[gIdx] = in[srcIdx];
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int m_nContacts;
|
||||
int m_staticIdx;
|
||||
float m_scale;
|
||||
int m_nSplit;
|
||||
} ConstBufferSSD;
|
||||
|
||||
__kernel
|
||||
__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
|
||||
void SetSortDataKernel(__global Contact4* gContact, __global Body* gBodies, __global int2* gSortDataOut,
|
||||
int nContacts,
|
||||
float scale,
|
||||
int N_SPLIT
|
||||
)
|
||||
|
||||
{
|
||||
int gIdx = GET_GLOBAL_IDX;
|
||||
|
||||
if( gIdx < nContacts )
|
||||
{
|
||||
int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);
|
||||
int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);
|
||||
|
||||
int idx = (gContact[gIdx].m_bodyAPtrAndSignBit<0)? bIdx: aIdx;
|
||||
float4 p = gBodies[idx].m_pos;
|
||||
int xIdx = (int)((p.x-((p.x<0.f)?1.f:0.f))*scale) & (N_SPLIT-1);
|
||||
int zIdx = (int)((p.z-((p.z<0.f)?1.f:0.f))*scale) & (N_SPLIT-1);
|
||||
|
||||
gSortDataOut[gIdx].x = (xIdx+zIdx*N_SPLIT);
|
||||
gSortDataOut[gIdx].y = gIdx;
|
||||
}
|
||||
else
|
||||
{
|
||||
gSortDataOut[gIdx].x = 0xffffffff;
|
||||
}
|
||||
}
|
||||
|
||||
__kernel
|
||||
__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
|
||||
void CopyConstraintKernel(__global Contact4* gIn, __global Contact4* gOut, int4 cb )
|
||||
{
|
||||
int gIdx = GET_GLOBAL_IDX;
|
||||
if( gIdx < cb.x )
|
||||
{
|
||||
gOut[gIdx] = gIn[gIdx];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
498
src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.h
Normal file
498
src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.h
Normal file
@@ -0,0 +1,498 @@
|
||||
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
|
||||
static const char* solverSetup2CL= \
|
||||
"/*\n"
|
||||
"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
|
||||
"\n"
|
||||
"This software is provided 'as-is', without any express or implied warranty.\n"
|
||||
"In no event will the authors be held liable for any damages arising from the use of this software.\n"
|
||||
"Permission is granted to anyone to use this software for any purpose, \n"
|
||||
"including commercial applications, and to alter it and redistribute it freely, \n"
|
||||
"subject to the following restrictions:\n"
|
||||
"\n"
|
||||
"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.\n"
|
||||
"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
|
||||
"3. This notice may not be removed or altered from any source distribution.\n"
|
||||
"*/\n"
|
||||
"//Originally written by Takahiro Harada\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#ifdef cl_ext_atomic_counters_32\n"
|
||||
"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
|
||||
"#else\n"
|
||||
"#define counter32_t volatile global int*\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"typedef unsigned int u32;\n"
|
||||
"typedef unsigned short u16;\n"
|
||||
"typedef unsigned char u8;\n"
|
||||
"\n"
|
||||
"#define GET_GROUP_IDX get_group_id(0)\n"
|
||||
"#define GET_LOCAL_IDX get_local_id(0)\n"
|
||||
"#define GET_GLOBAL_IDX get_global_id(0)\n"
|
||||
"#define GET_GROUP_SIZE get_local_size(0)\n"
|
||||
"#define GET_NUM_GROUPS get_num_groups(0)\n"
|
||||
"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
|
||||
"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
|
||||
"#define AtomInc(x) atom_inc(&(x))\n"
|
||||
"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
|
||||
"#define AppendInc(x, out) out = atomic_inc(x)\n"
|
||||
"#define AtomAdd(x, value) atom_add(&(x), value)\n"
|
||||
"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
|
||||
"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
|
||||
"\n"
|
||||
"#define make_float4 (float4)\n"
|
||||
"#define make_float2 (float2)\n"
|
||||
"#define make_uint4 (uint4)\n"
|
||||
"#define make_int4 (int4)\n"
|
||||
"#define make_uint2 (uint2)\n"
|
||||
"#define make_int2 (int2)\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define max2 max\n"
|
||||
"#define min2 min\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"// Vector\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"__inline\n"
|
||||
"float fastDiv(float numerator, float denominator)\n"
|
||||
"{\n"
|
||||
" return native_divide(numerator, denominator); \n"
|
||||
"// return numerator/denominator; \n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 fastDiv4(float4 numerator, float4 denominator)\n"
|
||||
"{\n"
|
||||
" return native_divide(numerator, denominator); \n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float fastSqrtf(float f2)\n"
|
||||
"{\n"
|
||||
" return native_sqrt(f2);\n"
|
||||
"// return sqrt(f2);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float fastRSqrt(float f2)\n"
|
||||
"{\n"
|
||||
" return native_rsqrt(f2);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float fastLength4(float4 v)\n"
|
||||
"{\n"
|
||||
" return fast_length(v);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 fastNormalize4(float4 v)\n"
|
||||
"{\n"
|
||||
" return fast_normalize(v);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float sqrtf(float a)\n"
|
||||
"{\n"
|
||||
"// return sqrt(a);\n"
|
||||
" return native_sqrt(a);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 cross3(float4 a, float4 b)\n"
|
||||
"{\n"
|
||||
" return cross(a,b);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float dot3F4(float4 a, float4 b)\n"
|
||||
"{\n"
|
||||
" float4 a1 = make_float4(a.xyz,0.f);\n"
|
||||
" float4 b1 = make_float4(b.xyz,0.f);\n"
|
||||
" return dot(a1, b1);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float length3(const float4 a)\n"
|
||||
"{\n"
|
||||
" return sqrtf(dot3F4(a,a));\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float dot4(const float4 a, const float4 b)\n"
|
||||
"{\n"
|
||||
" return dot( a, b );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"// for height\n"
|
||||
"__inline\n"
|
||||
"float dot3w1(const float4 point, const float4 eqn)\n"
|
||||
"{\n"
|
||||
" return dot3F4(point,eqn) + eqn.w;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 normalize3(const float4 a)\n"
|
||||
"{\n"
|
||||
" float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
|
||||
" return fastNormalize4( n );\n"
|
||||
"// float length = sqrtf(dot3F4(a, a));\n"
|
||||
"// return 1.f/length * a;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 normalize4(const float4 a)\n"
|
||||
"{\n"
|
||||
" float length = sqrtf(dot4(a, a));\n"
|
||||
" return 1.f/length * a;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 createEquation(const float4 a, const float4 b, const float4 c)\n"
|
||||
"{\n"
|
||||
" float4 eqn;\n"
|
||||
" float4 ab = b-a;\n"
|
||||
" float4 ac = c-a;\n"
|
||||
" eqn = normalize3( cross3(ab, ac) );\n"
|
||||
" eqn.w = -dot3F4(eqn,a);\n"
|
||||
" return eqn;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"// Matrix3x3\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_row[3];\n"
|
||||
"}Matrix3x3;\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtZero();\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtIdentity();\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtTranspose(Matrix3x3 m);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 mtMul1(Matrix3x3 a, float4 b);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 mtMul3(float4 a, Matrix3x3 b);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtZero()\n"
|
||||
"{\n"
|
||||
" Matrix3x3 m;\n"
|
||||
" m.m_row[0] = (float4)(0.f);\n"
|
||||
" m.m_row[1] = (float4)(0.f);\n"
|
||||
" m.m_row[2] = (float4)(0.f);\n"
|
||||
" return m;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtIdentity()\n"
|
||||
"{\n"
|
||||
" Matrix3x3 m;\n"
|
||||
" m.m_row[0] = (float4)(1,0,0,0);\n"
|
||||
" m.m_row[1] = (float4)(0,1,0,0);\n"
|
||||
" m.m_row[2] = (float4)(0,0,1,0);\n"
|
||||
" return m;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtTranspose(Matrix3x3 m)\n"
|
||||
"{\n"
|
||||
" Matrix3x3 out;\n"
|
||||
" out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
|
||||
" out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
|
||||
" out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
|
||||
" return out;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)\n"
|
||||
"{\n"
|
||||
" Matrix3x3 transB;\n"
|
||||
" transB = mtTranspose( b );\n"
|
||||
" Matrix3x3 ans;\n"
|
||||
" // why this doesn't run when 0ing in the for{}\n"
|
||||
" a.m_row[0].w = 0.f;\n"
|
||||
" a.m_row[1].w = 0.f;\n"
|
||||
" a.m_row[2].w = 0.f;\n"
|
||||
" for(int i=0; i<3; i++)\n"
|
||||
" {\n"
|
||||
"// a.m_row[i].w = 0.f;\n"
|
||||
" ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);\n"
|
||||
" ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);\n"
|
||||
" ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);\n"
|
||||
" ans.m_row[i].w = 0.f;\n"
|
||||
" }\n"
|
||||
" return ans;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 mtMul1(Matrix3x3 a, float4 b)\n"
|
||||
"{\n"
|
||||
" float4 ans;\n"
|
||||
" ans.x = dot3F4( a.m_row[0], b );\n"
|
||||
" ans.y = dot3F4( a.m_row[1], b );\n"
|
||||
" ans.z = dot3F4( a.m_row[2], b );\n"
|
||||
" ans.w = 0.f;\n"
|
||||
" return ans;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 mtMul3(float4 a, Matrix3x3 b)\n"
|
||||
"{\n"
|
||||
" float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
|
||||
" float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
|
||||
" float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
|
||||
"\n"
|
||||
" float4 ans;\n"
|
||||
" ans.x = dot3F4( a, colx );\n"
|
||||
" ans.y = dot3F4( a, coly );\n"
|
||||
" ans.z = dot3F4( a, colz );\n"
|
||||
" return ans;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"// Quaternion\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"\n"
|
||||
"typedef float4 Quaternion;\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Quaternion qtMul(Quaternion a, Quaternion b);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Quaternion qtNormalize(Quaternion in);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 qtRotate(Quaternion q, float4 vec);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Quaternion qtInvert(Quaternion q);\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Quaternion qtMul(Quaternion a, Quaternion b)\n"
|
||||
"{\n"
|
||||
" Quaternion ans;\n"
|
||||
" ans = cross3( a, b );\n"
|
||||
" ans += a.w*b+b.w*a;\n"
|
||||
"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
|
||||
" ans.w = a.w*b.w - dot3F4(a, b);\n"
|
||||
" return ans;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Quaternion qtNormalize(Quaternion in)\n"
|
||||
"{\n"
|
||||
" return fastNormalize4(in);\n"
|
||||
"// in /= length( in );\n"
|
||||
"// return in;\n"
|
||||
"}\n"
|
||||
"__inline\n"
|
||||
"float4 qtRotate(Quaternion q, float4 vec)\n"
|
||||
"{\n"
|
||||
" Quaternion qInv = qtInvert( q );\n"
|
||||
" float4 vcpy = vec;\n"
|
||||
" vcpy.w = 0.f;\n"
|
||||
" float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
|
||||
" return out;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Quaternion qtInvert(Quaternion q)\n"
|
||||
"{\n"
|
||||
" return (Quaternion)(-q.xyz, q.w);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 qtInvRotate(const Quaternion q, float4 vec)\n"
|
||||
"{\n"
|
||||
" return qtRotate( qtInvert( q ), vec );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define WG_SIZE 64\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_pos;\n"
|
||||
" Quaternion m_quat;\n"
|
||||
" float4 m_linVel;\n"
|
||||
" float4 m_angVel;\n"
|
||||
"\n"
|
||||
" u32 m_shapeIdx;\n"
|
||||
" float m_invMass;\n"
|
||||
" float m_restituitionCoeff;\n"
|
||||
" float m_frictionCoeff;\n"
|
||||
"} Body;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" Matrix3x3 m_invInertia;\n"
|
||||
" Matrix3x3 m_initInvInertia;\n"
|
||||
"} Shape;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_linear;\n"
|
||||
" float4 m_worldPos[4];\n"
|
||||
" float4 m_center; \n"
|
||||
" float m_jacCoeffInv[4];\n"
|
||||
" float m_b[4];\n"
|
||||
" float m_appliedRambdaDt[4];\n"
|
||||
"\n"
|
||||
" float m_fJacCoeffInv[2]; \n"
|
||||
" float m_fAppliedRambdaDt[2]; \n"
|
||||
"\n"
|
||||
" u32 m_bodyA;\n"
|
||||
" u32 m_bodyB;\n"
|
||||
"\n"
|
||||
" int m_batchIdx;\n"
|
||||
" u32 m_paddings[1];\n"
|
||||
"} Constraint4;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_worldPos[4];\n"
|
||||
" float4 m_worldNormal;\n"
|
||||
" u32 m_coeffs;\n"
|
||||
" int m_batchIdx;\n"
|
||||
"\n"
|
||||
" int m_bodyAPtrAndSignBit;\n"
|
||||
" int m_bodyBPtrAndSignBit;\n"
|
||||
"} Contact4;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" int m_nConstraints;\n"
|
||||
" int m_start;\n"
|
||||
" int m_batchIdx;\n"
|
||||
" int m_nSplit;\n"
|
||||
"// int m_paddings[1];\n"
|
||||
"} ConstBuffer;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" int m_solveFriction;\n"
|
||||
" int m_maxBatch; // long batch really kills the performance\n"
|
||||
" int m_batchIdx;\n"
|
||||
" int m_nSplit;\n"
|
||||
"// int m_paddings[1];\n"
|
||||
"} ConstBufferBatchSolve;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" \n"
|
||||
"\n"
|
||||
"\n"
|
||||
"typedef struct \n"
|
||||
"{\n"
|
||||
" int m_valInt0;\n"
|
||||
" int m_valInt1;\n"
|
||||
" int m_valInt2;\n"
|
||||
" int m_valInt3;\n"
|
||||
"\n"
|
||||
" float m_val0;\n"
|
||||
" float m_val1;\n"
|
||||
" float m_val2;\n"
|
||||
" float m_val3;\n"
|
||||
"} SolverDebugInfo;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"// others\n"
|
||||
"__kernel\n"
|
||||
"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
|
||||
"void ReorderContactKernel(__global Contact4* in, __global Contact4* out, __global int2* sortData, int4 cb )\n"
|
||||
"{\n"
|
||||
" int nContacts = cb.x;\n"
|
||||
" int gIdx = GET_GLOBAL_IDX;\n"
|
||||
"\n"
|
||||
" if( gIdx < nContacts )\n"
|
||||
" {\n"
|
||||
" int srcIdx = sortData[gIdx].y;\n"
|
||||
" out[gIdx] = in[srcIdx];\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" int m_nContacts;\n"
|
||||
" int m_staticIdx;\n"
|
||||
" float m_scale;\n"
|
||||
" int m_nSplit;\n"
|
||||
"} ConstBufferSSD;\n"
|
||||
"\n"
|
||||
"__kernel\n"
|
||||
"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
|
||||
"void SetSortDataKernel(__global Contact4* gContact, __global Body* gBodies, __global int2* gSortDataOut, \n"
|
||||
"int nContacts,\n"
|
||||
"float scale,\n"
|
||||
"int N_SPLIT\n"
|
||||
")\n"
|
||||
"\n"
|
||||
"{\n"
|
||||
" int gIdx = GET_GLOBAL_IDX;\n"
|
||||
" \n"
|
||||
" if( gIdx < nContacts )\n"
|
||||
" {\n"
|
||||
" int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);\n"
|
||||
" int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);\n"
|
||||
"\n"
|
||||
" int idx = (gContact[gIdx].m_bodyAPtrAndSignBit<0)? bIdx: aIdx;\n"
|
||||
" float4 p = gBodies[idx].m_pos;\n"
|
||||
" int xIdx = (int)((p.x-((p.x<0.f)?1.f:0.f))*scale) & (N_SPLIT-1);\n"
|
||||
" int zIdx = (int)((p.z-((p.z<0.f)?1.f:0.f))*scale) & (N_SPLIT-1);\n"
|
||||
"\n"
|
||||
" gSortDataOut[gIdx].x = (xIdx+zIdx*N_SPLIT);\n"
|
||||
" gSortDataOut[gIdx].y = gIdx;\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" gSortDataOut[gIdx].x = 0xffffffff;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__kernel\n"
|
||||
"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
|
||||
"void CopyConstraintKernel(__global Contact4* gIn, __global Contact4* gOut, int4 cb )\n"
|
||||
"{\n"
|
||||
" int gIdx = GET_GLOBAL_IDX;\n"
|
||||
" if( gIdx < cb.x )\n"
|
||||
" {\n"
|
||||
" gOut[gIdx] = gIn[gIdx];\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
;
|
||||
971
src/Bullet3OpenCL/RigidBody/kernels/solverUtils.cl
Normal file
971
src/Bullet3OpenCL/RigidBody/kernels/solverUtils.cl
Normal file
@@ -0,0 +1,971 @@
|
||||
/*
|
||||
Copyright (c) 2012 Advanced Micro Devices, Inc.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#pragma OPENCL EXTENSION cl_amd_printf : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
|
||||
#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
|
||||
|
||||
|
||||
#ifdef cl_ext_atomic_counters_32
|
||||
#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
|
||||
#else
|
||||
#define counter32_t volatile global int*
|
||||
#endif
|
||||
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned char u8;
|
||||
|
||||
#define GET_GROUP_IDX get_group_id(0)
|
||||
#define GET_LOCAL_IDX get_local_id(0)
|
||||
#define GET_GLOBAL_IDX get_global_id(0)
|
||||
#define GET_GROUP_SIZE get_local_size(0)
|
||||
#define GET_NUM_GROUPS get_num_groups(0)
|
||||
#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
|
||||
#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
|
||||
#define AtomInc(x) atom_inc(&(x))
|
||||
#define AtomInc1(x, out) out = atom_inc(&(x))
|
||||
#define AppendInc(x, out) out = atomic_inc(x)
|
||||
#define AtomAdd(x, value) atom_add(&(x), value)
|
||||
#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
|
||||
#define AtomXhg(x, value) atom_xchg ( &(x), value )
|
||||
|
||||
|
||||
#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
|
||||
|
||||
#define make_float4 (float4)
|
||||
#define make_float2 (float2)
|
||||
#define make_uint4 (uint4)
|
||||
#define make_int4 (int4)
|
||||
#define make_uint2 (uint2)
|
||||
#define make_int2 (int2)
|
||||
|
||||
|
||||
#define max2 max
|
||||
#define min2 min
|
||||
|
||||
|
||||
///////////////////////////////////////
|
||||
// Vector
|
||||
///////////////////////////////////////
|
||||
__inline
|
||||
float fastDiv(float numerator, float denominator)
|
||||
{
|
||||
return native_divide(numerator, denominator);
|
||||
// return numerator/denominator;
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 fastDiv4(float4 numerator, float4 denominator)
|
||||
{
|
||||
return native_divide(numerator, denominator);
|
||||
}
|
||||
|
||||
__inline
|
||||
float fastSqrtf(float f2)
|
||||
{
|
||||
return native_sqrt(f2);
|
||||
// return sqrt(f2);
|
||||
}
|
||||
|
||||
__inline
|
||||
float fastRSqrt(float f2)
|
||||
{
|
||||
return native_rsqrt(f2);
|
||||
}
|
||||
|
||||
__inline
|
||||
float fastLength4(float4 v)
|
||||
{
|
||||
return fast_length(v);
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 fastNormalize4(float4 v)
|
||||
{
|
||||
return fast_normalize(v);
|
||||
}
|
||||
|
||||
|
||||
__inline
|
||||
float sqrtf(float a)
|
||||
{
|
||||
// return sqrt(a);
|
||||
return native_sqrt(a);
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 cross3(float4 a1, float4 b1)
|
||||
{
|
||||
|
||||
float4 a=make_float4(a1.xyz,0.f);
|
||||
float4 b=make_float4(b1.xyz,0.f);
|
||||
//float4 a=a1;
|
||||
//float4 b=b1;
|
||||
return cross(a,b);
|
||||
}
|
||||
|
||||
__inline
|
||||
float dot3F4(float4 a, float4 b)
|
||||
{
|
||||
float4 a1 = make_float4(a.xyz,0.f);
|
||||
float4 b1 = make_float4(b.xyz,0.f);
|
||||
return dot(a1, b1);
|
||||
}
|
||||
|
||||
__inline
|
||||
float length3(const float4 a)
|
||||
{
|
||||
return sqrtf(dot3F4(a,a));
|
||||
}
|
||||
|
||||
__inline
|
||||
float dot4(const float4 a, const float4 b)
|
||||
{
|
||||
return dot( a, b );
|
||||
}
|
||||
|
||||
// for height
|
||||
__inline
|
||||
float dot3w1(const float4 point, const float4 eqn)
|
||||
{
|
||||
return dot3F4(point,eqn) + eqn.w;
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 normalize3(const float4 a)
|
||||
{
|
||||
float4 n = make_float4(a.x, a.y, a.z, 0.f);
|
||||
return fastNormalize4( n );
|
||||
// float length = sqrtf(dot3F4(a, a));
|
||||
// return 1.f/length * a;
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 normalize4(const float4 a)
|
||||
{
|
||||
float length = sqrtf(dot4(a, a));
|
||||
return 1.f/length * a;
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 createEquation(const float4 a, const float4 b, const float4 c)
|
||||
{
|
||||
float4 eqn;
|
||||
float4 ab = b-a;
|
||||
float4 ac = c-a;
|
||||
eqn = normalize3( cross3(ab, ac) );
|
||||
eqn.w = -dot3F4(eqn,a);
|
||||
return eqn;
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
// Matrix3x3
|
||||
///////////////////////////////////////
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_row[3];
|
||||
}Matrix3x3;
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtZero();
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtIdentity();
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtTranspose(Matrix3x3 m);
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);
|
||||
|
||||
__inline
|
||||
float4 mtMul1(Matrix3x3 a, float4 b);
|
||||
|
||||
__inline
|
||||
float4 mtMul3(float4 a, Matrix3x3 b);
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtZero()
|
||||
{
|
||||
Matrix3x3 m;
|
||||
m.m_row[0] = (float4)(0.f);
|
||||
m.m_row[1] = (float4)(0.f);
|
||||
m.m_row[2] = (float4)(0.f);
|
||||
return m;
|
||||
}
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtIdentity()
|
||||
{
|
||||
Matrix3x3 m;
|
||||
m.m_row[0] = (float4)(1,0,0,0);
|
||||
m.m_row[1] = (float4)(0,1,0,0);
|
||||
m.m_row[2] = (float4)(0,0,1,0);
|
||||
return m;
|
||||
}
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtTranspose(Matrix3x3 m)
|
||||
{
|
||||
Matrix3x3 out;
|
||||
out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);
|
||||
out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);
|
||||
out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);
|
||||
return out;
|
||||
}
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)
|
||||
{
|
||||
Matrix3x3 transB;
|
||||
transB = mtTranspose( b );
|
||||
Matrix3x3 ans;
|
||||
// why this doesn't run when 0ing in the for{}
|
||||
a.m_row[0].w = 0.f;
|
||||
a.m_row[1].w = 0.f;
|
||||
a.m_row[2].w = 0.f;
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
// a.m_row[i].w = 0.f;
|
||||
ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);
|
||||
ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);
|
||||
ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);
|
||||
ans.m_row[i].w = 0.f;
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 mtMul1(Matrix3x3 a, float4 b)
|
||||
{
|
||||
float4 ans;
|
||||
ans.x = dot3F4( a.m_row[0], b );
|
||||
ans.y = dot3F4( a.m_row[1], b );
|
||||
ans.z = dot3F4( a.m_row[2], b );
|
||||
ans.w = 0.f;
|
||||
return ans;
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 mtMul3(float4 a, Matrix3x3 b)
|
||||
{
|
||||
float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
|
||||
float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
|
||||
float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
|
||||
|
||||
float4 ans;
|
||||
ans.x = dot3F4( a, colx );
|
||||
ans.y = dot3F4( a, coly );
|
||||
ans.z = dot3F4( a, colz );
|
||||
return ans;
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
// Quaternion
|
||||
///////////////////////////////////////
|
||||
|
||||
typedef float4 Quaternion;
|
||||
|
||||
__inline
|
||||
Quaternion qtMul(Quaternion a, Quaternion b);
|
||||
|
||||
__inline
|
||||
Quaternion qtNormalize(Quaternion in);
|
||||
|
||||
__inline
|
||||
float4 qtRotate(Quaternion q, float4 vec);
|
||||
|
||||
__inline
|
||||
Quaternion qtInvert(Quaternion q);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
Quaternion qtMul(Quaternion a, Quaternion b)
|
||||
{
|
||||
Quaternion ans;
|
||||
ans = cross3( a, b );
|
||||
ans += a.w*b+b.w*a;
|
||||
// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
|
||||
ans.w = a.w*b.w - dot3F4(a, b);
|
||||
return ans;
|
||||
}
|
||||
|
||||
__inline
|
||||
Quaternion qtNormalize(Quaternion in)
|
||||
{
|
||||
return fastNormalize4(in);
|
||||
// in /= length( in );
|
||||
// return in;
|
||||
}
|
||||
__inline
|
||||
float4 qtRotate(Quaternion q, float4 vec)
|
||||
{
|
||||
Quaternion qInv = qtInvert( q );
|
||||
float4 vcpy = vec;
|
||||
vcpy.w = 0.f;
|
||||
float4 out = qtMul(qtMul(q,vcpy),qInv);
|
||||
return out;
|
||||
}
|
||||
|
||||
__inline
|
||||
Quaternion qtInvert(Quaternion q)
|
||||
{
|
||||
return (Quaternion)(-q.xyz, q.w);
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 qtInvRotate(const Quaternion q, float4 vec)
|
||||
{
|
||||
return qtRotate( qtInvert( q ), vec );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define WG_SIZE 64
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_pos;
|
||||
Quaternion m_quat;
|
||||
float4 m_linVel;
|
||||
float4 m_angVel;
|
||||
|
||||
u32 m_shapeIdx;
|
||||
float m_invMass;
|
||||
float m_restituitionCoeff;
|
||||
float m_frictionCoeff;
|
||||
} Body;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Matrix3x3 m_invInertia;
|
||||
Matrix3x3 m_initInvInertia;
|
||||
} Shape;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_linear;
|
||||
float4 m_worldPos[4];
|
||||
float4 m_center;
|
||||
float m_jacCoeffInv[4];
|
||||
float m_b[4];
|
||||
float m_appliedRambdaDt[4];
|
||||
|
||||
float m_fJacCoeffInv[2];
|
||||
float m_fAppliedRambdaDt[2];
|
||||
|
||||
u32 m_bodyA;
|
||||
u32 m_bodyB;
|
||||
int m_batchIdx;
|
||||
u32 m_paddings;
|
||||
} Constraint4;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_worldPos[4];
|
||||
float4 m_worldNormal;
|
||||
u32 m_coeffs;
|
||||
int m_batchIdx;
|
||||
|
||||
int m_bodyAPtrAndSignBit;
|
||||
int m_bodyBPtrAndSignBit;
|
||||
} Contact4;
|
||||
|
||||
|
||||
__kernel void CountBodiesKernel(__global Contact4* manifoldPtr, __global unsigned int* bodyCount, __global int2* contactConstraintOffsets, int numContactManifolds, int fixedBodyIndex)
|
||||
{
|
||||
int i = GET_GLOBAL_IDX;
|
||||
|
||||
if( i < numContactManifolds)
|
||||
{
|
||||
int pa = manifoldPtr[i].m_bodyAPtrAndSignBit;
|
||||
bool isFixedA = (pa <0) || (pa == fixedBodyIndex);
|
||||
int bodyIndexA = abs(pa);
|
||||
if (!isFixedA)
|
||||
{
|
||||
AtomInc1(bodyCount[bodyIndexA],contactConstraintOffsets[i].x);
|
||||
}
|
||||
barrier(CLK_GLOBAL_MEM_FENCE);
|
||||
int pb = manifoldPtr[i].m_bodyBPtrAndSignBit;
|
||||
bool isFixedB = (pb <0) || (pb == fixedBodyIndex);
|
||||
int bodyIndexB = abs(pb);
|
||||
if (!isFixedB)
|
||||
{
|
||||
AtomInc1(bodyCount[bodyIndexB],contactConstraintOffsets[i].y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void ClearVelocitiesKernel(__global float4* linearVelocities,__global float4* angularVelocities, int numSplitBodies)
|
||||
{
|
||||
int i = GET_GLOBAL_IDX;
|
||||
|
||||
if( i < numSplitBodies)
|
||||
{
|
||||
linearVelocities[i] = make_float4(0);
|
||||
angularVelocities[i] = make_float4(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
__kernel void AverageVelocitiesKernel(__global Body* gBodies,__global int* offsetSplitBodies,__global const unsigned int* bodyCount,
|
||||
__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities, int numBodies)
|
||||
{
|
||||
int i = GET_GLOBAL_IDX;
|
||||
if (i<numBodies)
|
||||
{
|
||||
if (gBodies[i].m_invMass)
|
||||
{
|
||||
int bodyOffset = offsetSplitBodies[i];
|
||||
int count = bodyCount[i];
|
||||
float factor = 1.f/((float)count);
|
||||
float4 averageLinVel = make_float4(0.f);
|
||||
float4 averageAngVel = make_float4(0.f);
|
||||
|
||||
for (int j=0;j<count;j++)
|
||||
{
|
||||
averageLinVel += deltaLinearVelocities[bodyOffset+j]*factor;
|
||||
averageAngVel += deltaAngularVelocities[bodyOffset+j]*factor;
|
||||
}
|
||||
|
||||
for (int j=0;j<count;j++)
|
||||
{
|
||||
deltaLinearVelocities[bodyOffset+j] = averageLinVel;
|
||||
deltaAngularVelocities[bodyOffset+j] = averageAngVel;
|
||||
}
|
||||
|
||||
}//bodies[i].m_invMass
|
||||
}//i<numBodies
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)
|
||||
{
|
||||
*linear = make_float4(-n.xyz,0.f);
|
||||
*angular0 = -cross3(r0, n);
|
||||
*angular1 = cross3(r1, n);
|
||||
}
|
||||
|
||||
|
||||
float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )
|
||||
{
|
||||
return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);
|
||||
}
|
||||
|
||||
|
||||
float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,
|
||||
float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1, float countA, float countB)
|
||||
{
|
||||
// linear0,1 are normlized
|
||||
float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;
|
||||
float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);
|
||||
float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;
|
||||
float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);
|
||||
return -1.f/((jmj0+jmj1)*countA+(jmj2+jmj3)*countB);
|
||||
}
|
||||
|
||||
|
||||
void btPlaneSpace1 (float4 n, float4* p, float4* q);
|
||||
void btPlaneSpace1 (float4 n, float4* p, float4* q)
|
||||
{
|
||||
if (fabs(n.z) > 0.70710678f) {
|
||||
// choose p in y-z plane
|
||||
float a = n.y*n.y + n.z*n.z;
|
||||
float k = 1.f/sqrt(a);
|
||||
p[0].x = 0;
|
||||
p[0].y = -n.z*k;
|
||||
p[0].z = n.y*k;
|
||||
// set q = n x p
|
||||
q[0].x = a*k;
|
||||
q[0].y = -n.x*p[0].z;
|
||||
q[0].z = n.x*p[0].y;
|
||||
}
|
||||
else {
|
||||
// choose p in x-y plane
|
||||
float a = n.x*n.x + n.y*n.y;
|
||||
float k = 1.f/sqrt(a);
|
||||
p[0].x = -n.y*k;
|
||||
p[0].y = n.x*k;
|
||||
p[0].z = 0;
|
||||
// set q = n x p
|
||||
q[0].x = -n.z*p[0].y;
|
||||
q[0].y = n.z*p[0].x;
|
||||
q[0].z = a*k;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void solveContact(__global Constraint4* cs,
|
||||
float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,
|
||||
float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB,
|
||||
float4* dLinVelA, float4* dAngVelA, float4* dLinVelB, float4* dAngVelB)
|
||||
{
|
||||
float minRambdaDt = 0;
|
||||
float maxRambdaDt = FLT_MAX;
|
||||
|
||||
for(int ic=0; ic<4; ic++)
|
||||
{
|
||||
if( cs->m_jacCoeffInv[ic] == 0.f ) continue;
|
||||
|
||||
float4 angular0, angular1, linear;
|
||||
float4 r0 = cs->m_worldPos[ic] - posA;
|
||||
float4 r1 = cs->m_worldPos[ic] - posB;
|
||||
setLinearAndAngular( -cs->m_linear, r0, r1, &linear, &angular0, &angular1 );
|
||||
|
||||
|
||||
|
||||
float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1,
|
||||
*linVelA+*dLinVelA, *angVelA+*dAngVelA, *linVelB+*dLinVelB, *angVelB+*dAngVelB ) + cs->m_b[ic];
|
||||
rambdaDt *= cs->m_jacCoeffInv[ic];
|
||||
|
||||
|
||||
{
|
||||
float prevSum = cs->m_appliedRambdaDt[ic];
|
||||
float updated = prevSum;
|
||||
updated += rambdaDt;
|
||||
updated = max2( updated, minRambdaDt );
|
||||
updated = min2( updated, maxRambdaDt );
|
||||
rambdaDt = updated - prevSum;
|
||||
cs->m_appliedRambdaDt[ic] = updated;
|
||||
}
|
||||
|
||||
|
||||
float4 linImp0 = invMassA*linear*rambdaDt;
|
||||
float4 linImp1 = invMassB*(-linear)*rambdaDt;
|
||||
float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;
|
||||
float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;
|
||||
|
||||
|
||||
if (invMassA)
|
||||
{
|
||||
*dLinVelA += linImp0;
|
||||
*dAngVelA += angImp0;
|
||||
}
|
||||
if (invMassB)
|
||||
{
|
||||
*dLinVelB += linImp1;
|
||||
*dAngVelB += angImp1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// solveContactConstraint( gBodies, gShapes, &gConstraints[i] ,contactConstraintOffsets,offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);
|
||||
|
||||
|
||||
void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs,
|
||||
__global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,
|
||||
__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities)
|
||||
{
|
||||
|
||||
//float frictionCoeff = ldsCs[0].m_linear.w;
|
||||
int aIdx = ldsCs[0].m_bodyA;
|
||||
int bIdx = ldsCs[0].m_bodyB;
|
||||
|
||||
float4 posA = gBodies[aIdx].m_pos;
|
||||
float4 linVelA = gBodies[aIdx].m_linVel;
|
||||
float4 angVelA = gBodies[aIdx].m_angVel;
|
||||
float invMassA = gBodies[aIdx].m_invMass;
|
||||
Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;
|
||||
|
||||
float4 posB = gBodies[bIdx].m_pos;
|
||||
float4 linVelB = gBodies[bIdx].m_linVel;
|
||||
float4 angVelB = gBodies[bIdx].m_angVel;
|
||||
float invMassB = gBodies[bIdx].m_invMass;
|
||||
Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;
|
||||
|
||||
|
||||
float4 dLinVelA = make_float4(0,0,0,0);
|
||||
float4 dAngVelA = make_float4(0,0,0,0);
|
||||
float4 dLinVelB = make_float4(0,0,0,0);
|
||||
float4 dAngVelB = make_float4(0,0,0,0);
|
||||
|
||||
int bodyOffsetA = offsetSplitBodies[aIdx];
|
||||
int constraintOffsetA = contactConstraintOffsets[0].x;
|
||||
int splitIndexA = bodyOffsetA+constraintOffsetA;
|
||||
|
||||
if (invMassA)
|
||||
{
|
||||
dLinVelA = deltaLinearVelocities[splitIndexA];
|
||||
dAngVelA = deltaAngularVelocities[splitIndexA];
|
||||
}
|
||||
|
||||
int bodyOffsetB = offsetSplitBodies[bIdx];
|
||||
int constraintOffsetB = contactConstraintOffsets[0].y;
|
||||
int splitIndexB= bodyOffsetB+constraintOffsetB;
|
||||
|
||||
if (invMassB)
|
||||
{
|
||||
dLinVelB = deltaLinearVelocities[splitIndexB];
|
||||
dAngVelB = deltaAngularVelocities[splitIndexB];
|
||||
}
|
||||
|
||||
solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,
|
||||
posB, &linVelB, &angVelB, invMassB, invInertiaB ,&dLinVelA, &dAngVelA, &dLinVelB, &dAngVelB);
|
||||
|
||||
if (invMassA)
|
||||
{
|
||||
deltaLinearVelocities[splitIndexA] = dLinVelA;
|
||||
deltaAngularVelocities[splitIndexA] = dAngVelA;
|
||||
}
|
||||
if (invMassB)
|
||||
{
|
||||
deltaLinearVelocities[splitIndexB] = dLinVelB;
|
||||
deltaAngularVelocities[splitIndexB] = dAngVelB;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
__kernel void SolveContactJacobiKernel(__global Constraint4* gConstraints, __global Body* gBodies, __global Shape* gShapes ,
|
||||
__global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities,
|
||||
float deltaTime, float positionDrift, float positionConstraintCoeff, int fixedBodyIndex, int numManifolds
|
||||
)
|
||||
{
|
||||
int i = GET_GLOBAL_IDX;
|
||||
if (i<numManifolds)
|
||||
{
|
||||
solveContactConstraint( gBodies, gShapes, &gConstraints[i] ,&contactConstraintOffsets[i],offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs,
|
||||
__global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,
|
||||
__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities)
|
||||
{
|
||||
float frictionCoeff = 0.7f;//ldsCs[0].m_linear.w;
|
||||
int aIdx = ldsCs[0].m_bodyA;
|
||||
int bIdx = ldsCs[0].m_bodyB;
|
||||
|
||||
|
||||
float4 posA = gBodies[aIdx].m_pos;
|
||||
float4 linVelA = gBodies[aIdx].m_linVel;
|
||||
float4 angVelA = gBodies[aIdx].m_angVel;
|
||||
float invMassA = gBodies[aIdx].m_invMass;
|
||||
Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;
|
||||
|
||||
float4 posB = gBodies[bIdx].m_pos;
|
||||
float4 linVelB = gBodies[bIdx].m_linVel;
|
||||
float4 angVelB = gBodies[bIdx].m_angVel;
|
||||
float invMassB = gBodies[bIdx].m_invMass;
|
||||
Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;
|
||||
|
||||
|
||||
float4 dLinVelA = make_float4(0,0,0,0);
|
||||
float4 dAngVelA = make_float4(0,0,0,0);
|
||||
float4 dLinVelB = make_float4(0,0,0,0);
|
||||
float4 dAngVelB = make_float4(0,0,0,0);
|
||||
|
||||
int bodyOffsetA = offsetSplitBodies[aIdx];
|
||||
int constraintOffsetA = contactConstraintOffsets[0].x;
|
||||
int splitIndexA = bodyOffsetA+constraintOffsetA;
|
||||
|
||||
if (invMassA)
|
||||
{
|
||||
dLinVelA = deltaLinearVelocities[splitIndexA];
|
||||
dAngVelA = deltaAngularVelocities[splitIndexA];
|
||||
}
|
||||
|
||||
int bodyOffsetB = offsetSplitBodies[bIdx];
|
||||
int constraintOffsetB = contactConstraintOffsets[0].y;
|
||||
int splitIndexB= bodyOffsetB+constraintOffsetB;
|
||||
|
||||
if (invMassB)
|
||||
{
|
||||
dLinVelB = deltaLinearVelocities[splitIndexB];
|
||||
dAngVelB = deltaAngularVelocities[splitIndexB];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
|
||||
float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
|
||||
|
||||
float sum = 0;
|
||||
for(int j=0; j<4; j++)
|
||||
{
|
||||
sum +=ldsCs[0].m_appliedRambdaDt[j];
|
||||
}
|
||||
frictionCoeff = 0.7f;
|
||||
for(int j=0; j<4; j++)
|
||||
{
|
||||
maxRambdaDt[j] = frictionCoeff*sum;
|
||||
minRambdaDt[j] = -maxRambdaDt[j];
|
||||
}
|
||||
|
||||
|
||||
// solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,
|
||||
// posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt );
|
||||
|
||||
|
||||
{
|
||||
|
||||
__global Constraint4* cs = ldsCs;
|
||||
|
||||
if( cs->m_fJacCoeffInv[0] == 0 && cs->m_fJacCoeffInv[0] == 0 ) return;
|
||||
const float4 center = cs->m_center;
|
||||
|
||||
float4 n = -cs->m_linear;
|
||||
|
||||
float4 tangent[2];
|
||||
btPlaneSpace1(n,&tangent[0],&tangent[1]);
|
||||
float4 angular0, angular1, linear;
|
||||
float4 r0 = center - posA;
|
||||
float4 r1 = center - posB;
|
||||
for(int i=0; i<2; i++)
|
||||
{
|
||||
setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 );
|
||||
float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,
|
||||
linVelA+dLinVelA, angVelA+dAngVelA, linVelB+dLinVelB, angVelB+dAngVelB );
|
||||
rambdaDt *= cs->m_fJacCoeffInv[i];
|
||||
|
||||
{
|
||||
float prevSum = cs->m_fAppliedRambdaDt[i];
|
||||
float updated = prevSum;
|
||||
updated += rambdaDt;
|
||||
updated = max2( updated, minRambdaDt[i] );
|
||||
updated = min2( updated, maxRambdaDt[i] );
|
||||
rambdaDt = updated - prevSum;
|
||||
cs->m_fAppliedRambdaDt[i] = updated;
|
||||
}
|
||||
|
||||
float4 linImp0 = invMassA*linear*rambdaDt;
|
||||
float4 linImp1 = invMassB*(-linear)*rambdaDt;
|
||||
float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;
|
||||
float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;
|
||||
|
||||
dLinVelA += linImp0;
|
||||
dAngVelA += angImp0;
|
||||
dLinVelB += linImp1;
|
||||
dAngVelB += angImp1;
|
||||
}
|
||||
{ // angular damping for point constraint
|
||||
float4 ab = normalize3( posB - posA );
|
||||
float4 ac = normalize3( center - posA );
|
||||
if( dot3F4( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
|
||||
{
|
||||
float angNA = dot3F4( n, angVelA );
|
||||
float angNB = dot3F4( n, angVelB );
|
||||
|
||||
dAngVelA -= (angNA*0.1f)*n;
|
||||
dAngVelB -= (angNB*0.1f)*n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (invMassA)
|
||||
{
|
||||
deltaLinearVelocities[splitIndexA] = dLinVelA;
|
||||
deltaAngularVelocities[splitIndexA] = dAngVelA;
|
||||
}
|
||||
if (invMassB)
|
||||
{
|
||||
deltaLinearVelocities[splitIndexB] = dLinVelB;
|
||||
deltaAngularVelocities[splitIndexB] = dAngVelB;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
__kernel void SolveFrictionJacobiKernel(__global Constraint4* gConstraints, __global Body* gBodies, __global Shape* gShapes ,
|
||||
__global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,
|
||||
__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities,
|
||||
float deltaTime, float positionDrift, float positionConstraintCoeff, int fixedBodyIndex, int numManifolds
|
||||
)
|
||||
{
|
||||
int i = GET_GLOBAL_IDX;
|
||||
if (i<numManifolds)
|
||||
{
|
||||
solveFrictionConstraint( gBodies, gShapes, &gConstraints[i] ,&contactConstraintOffsets[i],offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
__kernel void UpdateBodyVelocitiesKernel(__global Body* gBodies,__global int* offsetSplitBodies,__global const unsigned int* bodyCount,
|
||||
__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities, int numBodies)
|
||||
{
|
||||
int i = GET_GLOBAL_IDX;
|
||||
if (i<numBodies)
|
||||
{
|
||||
if (gBodies[i].m_invMass)
|
||||
{
|
||||
int bodyOffset = offsetSplitBodies[i];
|
||||
int count = bodyCount[i];
|
||||
if (count)
|
||||
{
|
||||
gBodies[i].m_linVel += deltaLinearVelocities[bodyOffset];
|
||||
gBodies[i].m_angVel += deltaAngularVelocities[bodyOffset];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setConstraint4( const float4 posA, const float4 linVelA, const float4 angVelA, float invMassA, const Matrix3x3 invInertiaA,
|
||||
const float4 posB, const float4 linVelB, const float4 angVelB, float invMassB, const Matrix3x3 invInertiaB,
|
||||
__global Contact4* src, float dt, float positionDrift, float positionConstraintCoeff,float countA, float countB,
|
||||
Constraint4* dstC )
|
||||
{
|
||||
dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);
|
||||
dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);
|
||||
|
||||
float dtInv = 1.f/dt;
|
||||
for(int ic=0; ic<4; ic++)
|
||||
{
|
||||
dstC->m_appliedRambdaDt[ic] = 0.f;
|
||||
}
|
||||
dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;
|
||||
|
||||
|
||||
dstC->m_linear = -src->m_worldNormal;
|
||||
dstC->m_linear.w = 0.7f ;//src->getFrictionCoeff() );
|
||||
for(int ic=0; ic<4; ic++)
|
||||
{
|
||||
float4 r0 = src->m_worldPos[ic] - posA;
|
||||
float4 r1 = src->m_worldPos[ic] - posB;
|
||||
|
||||
if( ic >= src->m_worldNormal.w )//npoints
|
||||
{
|
||||
dstC->m_jacCoeffInv[ic] = 0.f;
|
||||
continue;
|
||||
}
|
||||
|
||||
float relVelN;
|
||||
{
|
||||
float4 linear, angular0, angular1;
|
||||
setLinearAndAngular(src->m_worldNormal, r0, r1, &linear, &angular0, &angular1);
|
||||
|
||||
dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,
|
||||
invMassA, &invInertiaA, invMassB, &invInertiaB , countA, countB);
|
||||
|
||||
relVelN = calcRelVel(linear, -linear, angular0, angular1,
|
||||
linVelA, angVelA, linVelB, angVelB);
|
||||
|
||||
float e = 0.f;//src->getRestituitionCoeff();
|
||||
if( relVelN*relVelN < 0.004f ) e = 0.f;
|
||||
|
||||
dstC->m_b[ic] = e*relVelN;
|
||||
//float penetration = src->m_worldPos[ic].w;
|
||||
dstC->m_b[ic] += (src->m_worldPos[ic].w + positionDrift)*positionConstraintCoeff*dtInv;
|
||||
dstC->m_appliedRambdaDt[ic] = 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
if( src->m_worldNormal.w > 0 )//npoints
|
||||
{ // prepare friction
|
||||
float4 center = make_float4(0.f);
|
||||
for(int i=0; i<src->m_worldNormal.w; i++)
|
||||
center += src->m_worldPos[i];
|
||||
center /= (float)src->m_worldNormal.w;
|
||||
|
||||
float4 tangent[2];
|
||||
btPlaneSpace1(src->m_worldNormal,&tangent[0],&tangent[1]);
|
||||
|
||||
float4 r[2];
|
||||
r[0] = center - posA;
|
||||
r[1] = center - posB;
|
||||
|
||||
for(int i=0; i<2; i++)
|
||||
{
|
||||
float4 linear, angular0, angular1;
|
||||
setLinearAndAngular(tangent[i], r[0], r[1], &linear, &angular0, &angular1);
|
||||
|
||||
dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,
|
||||
invMassA, &invInertiaA, invMassB, &invInertiaB ,countA, countB);
|
||||
dstC->m_fAppliedRambdaDt[i] = 0.f;
|
||||
}
|
||||
dstC->m_center = center;
|
||||
}
|
||||
|
||||
for(int i=0; i<4; i++)
|
||||
{
|
||||
if( i<src->m_worldNormal.w )
|
||||
{
|
||||
dstC->m_worldPos[i] = src->m_worldPos[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
dstC->m_worldPos[i] = make_float4(0.f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
__kernel
|
||||
__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
|
||||
void ContactToConstraintSplitKernel(__global const Contact4* gContact, __global const Body* gBodies, __global const Shape* gShapes, __global Constraint4* gConstraintOut,
|
||||
__global const unsigned int* bodyCount,
|
||||
int nContacts,
|
||||
float dt,
|
||||
float positionDrift,
|
||||
float positionConstraintCoeff
|
||||
)
|
||||
{
|
||||
int gIdx = GET_GLOBAL_IDX;
|
||||
|
||||
if( gIdx < nContacts )
|
||||
{
|
||||
int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);
|
||||
int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);
|
||||
|
||||
float4 posA = gBodies[aIdx].m_pos;
|
||||
float4 linVelA = gBodies[aIdx].m_linVel;
|
||||
float4 angVelA = gBodies[aIdx].m_angVel;
|
||||
float invMassA = gBodies[aIdx].m_invMass;
|
||||
Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;
|
||||
|
||||
float4 posB = gBodies[bIdx].m_pos;
|
||||
float4 linVelB = gBodies[bIdx].m_linVel;
|
||||
float4 angVelB = gBodies[bIdx].m_angVel;
|
||||
float invMassB = gBodies[bIdx].m_invMass;
|
||||
Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;
|
||||
|
||||
Constraint4 cs;
|
||||
|
||||
float countA = invMassA ? (float)bodyCount[aIdx] : 1;
|
||||
float countB = invMassB ? (float)bodyCount[bIdx] : 1;
|
||||
|
||||
setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,
|
||||
&gContact[gIdx], dt, positionDrift, positionConstraintCoeff,countA,countB,
|
||||
&cs );
|
||||
|
||||
cs.m_batchIdx = gContact[gIdx].m_batchIdx;
|
||||
|
||||
gConstraintOut[gIdx] = cs;
|
||||
}
|
||||
}
|
||||
974
src/Bullet3OpenCL/RigidBody/kernels/solverUtils.h
Normal file
974
src/Bullet3OpenCL/RigidBody/kernels/solverUtils.h
Normal file
@@ -0,0 +1,974 @@
|
||||
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
|
||||
static const char* solverUtilsCL= \
|
||||
"/*\n"
|
||||
"Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
|
||||
"\n"
|
||||
"This software is provided 'as-is', without any express or implied warranty.\n"
|
||||
"In no event will the authors be held liable for any damages arising from the use of this software.\n"
|
||||
"Permission is granted to anyone to use this software for any purpose, \n"
|
||||
"including commercial applications, and to alter it and redistribute it freely, \n"
|
||||
"subject to the following restrictions:\n"
|
||||
"\n"
|
||||
"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.\n"
|
||||
"2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
|
||||
"3. This notice may not be removed or altered from any source distribution.\n"
|
||||
"*/\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
|
||||
"#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#ifdef cl_ext_atomic_counters_32\n"
|
||||
"#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
|
||||
"#else\n"
|
||||
"#define counter32_t volatile global int*\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"typedef unsigned int u32;\n"
|
||||
"typedef unsigned short u16;\n"
|
||||
"typedef unsigned char u8;\n"
|
||||
"\n"
|
||||
"#define GET_GROUP_IDX get_group_id(0)\n"
|
||||
"#define GET_LOCAL_IDX get_local_id(0)\n"
|
||||
"#define GET_GLOBAL_IDX get_global_id(0)\n"
|
||||
"#define GET_GROUP_SIZE get_local_size(0)\n"
|
||||
"#define GET_NUM_GROUPS get_num_groups(0)\n"
|
||||
"#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
|
||||
"#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
|
||||
"#define AtomInc(x) atom_inc(&(x))\n"
|
||||
"#define AtomInc1(x, out) out = atom_inc(&(x))\n"
|
||||
"#define AppendInc(x, out) out = atomic_inc(x)\n"
|
||||
"#define AtomAdd(x, value) atom_add(&(x), value)\n"
|
||||
"#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
|
||||
"#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
|
||||
"\n"
|
||||
"#define make_float4 (float4)\n"
|
||||
"#define make_float2 (float2)\n"
|
||||
"#define make_uint4 (uint4)\n"
|
||||
"#define make_int4 (int4)\n"
|
||||
"#define make_uint2 (uint2)\n"
|
||||
"#define make_int2 (int2)\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define max2 max\n"
|
||||
"#define min2 min\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"// Vector\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"__inline\n"
|
||||
"float fastDiv(float numerator, float denominator)\n"
|
||||
"{\n"
|
||||
" return native_divide(numerator, denominator); \n"
|
||||
"// return numerator/denominator; \n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 fastDiv4(float4 numerator, float4 denominator)\n"
|
||||
"{\n"
|
||||
" return native_divide(numerator, denominator); \n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float fastSqrtf(float f2)\n"
|
||||
"{\n"
|
||||
" return native_sqrt(f2);\n"
|
||||
"// return sqrt(f2);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float fastRSqrt(float f2)\n"
|
||||
"{\n"
|
||||
" return native_rsqrt(f2);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float fastLength4(float4 v)\n"
|
||||
"{\n"
|
||||
" return fast_length(v);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 fastNormalize4(float4 v)\n"
|
||||
"{\n"
|
||||
" return fast_normalize(v);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float sqrtf(float a)\n"
|
||||
"{\n"
|
||||
"// return sqrt(a);\n"
|
||||
" return native_sqrt(a);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 cross3(float4 a1, float4 b1)\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
" float4 a=make_float4(a1.xyz,0.f);\n"
|
||||
" float4 b=make_float4(b1.xyz,0.f);\n"
|
||||
" //float4 a=a1;\n"
|
||||
" //float4 b=b1;\n"
|
||||
" return cross(a,b);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float dot3F4(float4 a, float4 b)\n"
|
||||
"{\n"
|
||||
" float4 a1 = make_float4(a.xyz,0.f);\n"
|
||||
" float4 b1 = make_float4(b.xyz,0.f);\n"
|
||||
" return dot(a1, b1);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float length3(const float4 a)\n"
|
||||
"{\n"
|
||||
" return sqrtf(dot3F4(a,a));\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float dot4(const float4 a, const float4 b)\n"
|
||||
"{\n"
|
||||
" return dot( a, b );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"// for height\n"
|
||||
"__inline\n"
|
||||
"float dot3w1(const float4 point, const float4 eqn)\n"
|
||||
"{\n"
|
||||
" return dot3F4(point,eqn) + eqn.w;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 normalize3(const float4 a)\n"
|
||||
"{\n"
|
||||
" float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
|
||||
" return fastNormalize4( n );\n"
|
||||
"// float length = sqrtf(dot3F4(a, a));\n"
|
||||
"// return 1.f/length * a;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 normalize4(const float4 a)\n"
|
||||
"{\n"
|
||||
" float length = sqrtf(dot4(a, a));\n"
|
||||
" return 1.f/length * a;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 createEquation(const float4 a, const float4 b, const float4 c)\n"
|
||||
"{\n"
|
||||
" float4 eqn;\n"
|
||||
" float4 ab = b-a;\n"
|
||||
" float4 ac = c-a;\n"
|
||||
" eqn = normalize3( cross3(ab, ac) );\n"
|
||||
" eqn.w = -dot3F4(eqn,a);\n"
|
||||
" return eqn;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"// Matrix3x3\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_row[3];\n"
|
||||
"}Matrix3x3;\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtZero();\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtIdentity();\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtTranspose(Matrix3x3 m);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 mtMul1(Matrix3x3 a, float4 b);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 mtMul3(float4 a, Matrix3x3 b);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtZero()\n"
|
||||
"{\n"
|
||||
" Matrix3x3 m;\n"
|
||||
" m.m_row[0] = (float4)(0.f);\n"
|
||||
" m.m_row[1] = (float4)(0.f);\n"
|
||||
" m.m_row[2] = (float4)(0.f);\n"
|
||||
" return m;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtIdentity()\n"
|
||||
"{\n"
|
||||
" Matrix3x3 m;\n"
|
||||
" m.m_row[0] = (float4)(1,0,0,0);\n"
|
||||
" m.m_row[1] = (float4)(0,1,0,0);\n"
|
||||
" m.m_row[2] = (float4)(0,0,1,0);\n"
|
||||
" return m;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtTranspose(Matrix3x3 m)\n"
|
||||
"{\n"
|
||||
" Matrix3x3 out;\n"
|
||||
" out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
|
||||
" out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
|
||||
" out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
|
||||
" return out;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)\n"
|
||||
"{\n"
|
||||
" Matrix3x3 transB;\n"
|
||||
" transB = mtTranspose( b );\n"
|
||||
" Matrix3x3 ans;\n"
|
||||
" // why this doesn't run when 0ing in the for{}\n"
|
||||
" a.m_row[0].w = 0.f;\n"
|
||||
" a.m_row[1].w = 0.f;\n"
|
||||
" a.m_row[2].w = 0.f;\n"
|
||||
" for(int i=0; i<3; i++)\n"
|
||||
" {\n"
|
||||
"// a.m_row[i].w = 0.f;\n"
|
||||
" ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);\n"
|
||||
" ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);\n"
|
||||
" ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);\n"
|
||||
" ans.m_row[i].w = 0.f;\n"
|
||||
" }\n"
|
||||
" return ans;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 mtMul1(Matrix3x3 a, float4 b)\n"
|
||||
"{\n"
|
||||
" float4 ans;\n"
|
||||
" ans.x = dot3F4( a.m_row[0], b );\n"
|
||||
" ans.y = dot3F4( a.m_row[1], b );\n"
|
||||
" ans.z = dot3F4( a.m_row[2], b );\n"
|
||||
" ans.w = 0.f;\n"
|
||||
" return ans;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 mtMul3(float4 a, Matrix3x3 b)\n"
|
||||
"{\n"
|
||||
" float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
|
||||
" float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
|
||||
" float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
|
||||
"\n"
|
||||
" float4 ans;\n"
|
||||
" ans.x = dot3F4( a, colx );\n"
|
||||
" ans.y = dot3F4( a, coly );\n"
|
||||
" ans.z = dot3F4( a, colz );\n"
|
||||
" return ans;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"// Quaternion\n"
|
||||
"///////////////////////////////////////\n"
|
||||
"\n"
|
||||
"typedef float4 Quaternion;\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Quaternion qtMul(Quaternion a, Quaternion b);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Quaternion qtNormalize(Quaternion in);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 qtRotate(Quaternion q, float4 vec);\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Quaternion qtInvert(Quaternion q);\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Quaternion qtMul(Quaternion a, Quaternion b)\n"
|
||||
"{\n"
|
||||
" Quaternion ans;\n"
|
||||
" ans = cross3( a, b );\n"
|
||||
" ans += a.w*b+b.w*a;\n"
|
||||
"// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
|
||||
" ans.w = a.w*b.w - dot3F4(a, b);\n"
|
||||
" return ans;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Quaternion qtNormalize(Quaternion in)\n"
|
||||
"{\n"
|
||||
" return fastNormalize4(in);\n"
|
||||
"// in /= length( in );\n"
|
||||
"// return in;\n"
|
||||
"}\n"
|
||||
"__inline\n"
|
||||
"float4 qtRotate(Quaternion q, float4 vec)\n"
|
||||
"{\n"
|
||||
" Quaternion qInv = qtInvert( q );\n"
|
||||
" float4 vcpy = vec;\n"
|
||||
" vcpy.w = 0.f;\n"
|
||||
" float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
|
||||
" return out;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Quaternion qtInvert(Quaternion q)\n"
|
||||
"{\n"
|
||||
" return (Quaternion)(-q.xyz, q.w);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 qtInvRotate(const Quaternion q, float4 vec)\n"
|
||||
"{\n"
|
||||
" return qtRotate( qtInvert( q ), vec );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define WG_SIZE 64\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_pos;\n"
|
||||
" Quaternion m_quat;\n"
|
||||
" float4 m_linVel;\n"
|
||||
" float4 m_angVel;\n"
|
||||
"\n"
|
||||
" u32 m_shapeIdx;\n"
|
||||
" float m_invMass;\n"
|
||||
" float m_restituitionCoeff;\n"
|
||||
" float m_frictionCoeff;\n"
|
||||
"} Body;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" Matrix3x3 m_invInertia;\n"
|
||||
" Matrix3x3 m_initInvInertia;\n"
|
||||
"} Shape;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_linear;\n"
|
||||
" float4 m_worldPos[4];\n"
|
||||
" float4 m_center; \n"
|
||||
" float m_jacCoeffInv[4];\n"
|
||||
" float m_b[4];\n"
|
||||
" float m_appliedRambdaDt[4];\n"
|
||||
"\n"
|
||||
" float m_fJacCoeffInv[2]; \n"
|
||||
" float m_fAppliedRambdaDt[2]; \n"
|
||||
"\n"
|
||||
" u32 m_bodyA;\n"
|
||||
" u32 m_bodyB;\n"
|
||||
" int m_batchIdx;\n"
|
||||
" u32 m_paddings;\n"
|
||||
"} Constraint4;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_worldPos[4];\n"
|
||||
" float4 m_worldNormal;\n"
|
||||
" u32 m_coeffs;\n"
|
||||
" int m_batchIdx;\n"
|
||||
"\n"
|
||||
" int m_bodyAPtrAndSignBit;\n"
|
||||
" int m_bodyBPtrAndSignBit;\n"
|
||||
"} Contact4;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__kernel void CountBodiesKernel(__global Contact4* manifoldPtr, __global unsigned int* bodyCount, __global int2* contactConstraintOffsets, int numContactManifolds, int fixedBodyIndex)\n"
|
||||
"{\n"
|
||||
" int i = GET_GLOBAL_IDX;\n"
|
||||
" \n"
|
||||
" if( i < numContactManifolds)\n"
|
||||
" {\n"
|
||||
" int pa = manifoldPtr[i].m_bodyAPtrAndSignBit;\n"
|
||||
" bool isFixedA = (pa <0) || (pa == fixedBodyIndex);\n"
|
||||
" int bodyIndexA = abs(pa);\n"
|
||||
" if (!isFixedA)\n"
|
||||
" {\n"
|
||||
" AtomInc1(bodyCount[bodyIndexA],contactConstraintOffsets[i].x);\n"
|
||||
" }\n"
|
||||
" barrier(CLK_GLOBAL_MEM_FENCE);\n"
|
||||
" int pb = manifoldPtr[i].m_bodyBPtrAndSignBit;\n"
|
||||
" bool isFixedB = (pb <0) || (pb == fixedBodyIndex);\n"
|
||||
" int bodyIndexB = abs(pb);\n"
|
||||
" if (!isFixedB)\n"
|
||||
" {\n"
|
||||
" AtomInc1(bodyCount[bodyIndexB],contactConstraintOffsets[i].y);\n"
|
||||
" } \n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__kernel void ClearVelocitiesKernel(__global float4* linearVelocities,__global float4* angularVelocities, int numSplitBodies)\n"
|
||||
"{\n"
|
||||
" int i = GET_GLOBAL_IDX;\n"
|
||||
" \n"
|
||||
" if( i < numSplitBodies)\n"
|
||||
" {\n"
|
||||
" linearVelocities[i] = make_float4(0);\n"
|
||||
" angularVelocities[i] = make_float4(0);\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__kernel void AverageVelocitiesKernel(__global Body* gBodies,__global int* offsetSplitBodies,__global const unsigned int* bodyCount,\n"
|
||||
"__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities, int numBodies)\n"
|
||||
"{\n"
|
||||
" int i = GET_GLOBAL_IDX;\n"
|
||||
" if (i<numBodies)\n"
|
||||
" {\n"
|
||||
" if (gBodies[i].m_invMass)\n"
|
||||
" {\n"
|
||||
" int bodyOffset = offsetSplitBodies[i];\n"
|
||||
" int count = bodyCount[i];\n"
|
||||
" float factor = 1.f/((float)count);\n"
|
||||
" float4 averageLinVel = make_float4(0.f);\n"
|
||||
" float4 averageAngVel = make_float4(0.f);\n"
|
||||
" \n"
|
||||
" for (int j=0;j<count;j++)\n"
|
||||
" {\n"
|
||||
" averageLinVel += deltaLinearVelocities[bodyOffset+j]*factor;\n"
|
||||
" averageAngVel += deltaAngularVelocities[bodyOffset+j]*factor;\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
" for (int j=0;j<count;j++)\n"
|
||||
" {\n"
|
||||
" deltaLinearVelocities[bodyOffset+j] = averageLinVel;\n"
|
||||
" deltaAngularVelocities[bodyOffset+j] = averageAngVel;\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
" }//bodies[i].m_invMass\n"
|
||||
" }//i<numBodies\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)\n"
|
||||
"{\n"
|
||||
" *linear = make_float4(-n.xyz,0.f);\n"
|
||||
" *angular0 = -cross3(r0, n);\n"
|
||||
" *angular1 = cross3(r1, n);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )\n"
|
||||
"{\n"
|
||||
" return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
|
||||
" float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1, float countA, float countB)\n"
|
||||
"{\n"
|
||||
" // linear0,1 are normlized\n"
|
||||
" float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;\n"
|
||||
" float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
|
||||
" float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;\n"
|
||||
" float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
|
||||
" return -1.f/((jmj0+jmj1)*countA+(jmj2+jmj3)*countB);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"void b3PlaneSpace1 (float4 n, float4* p, float4* q);\n"
|
||||
" void b3PlaneSpace1 (float4 n, float4* p, float4* q)\n"
|
||||
"{\n"
|
||||
" if (fabs(n.z) > 0.70710678f) {\n"
|
||||
" // choose p in y-z plane\n"
|
||||
" float a = n.y*n.y + n.z*n.z;\n"
|
||||
" float k = 1.f/sqrt(a);\n"
|
||||
" p[0].x = 0;\n"
|
||||
" p[0].y = -n.z*k;\n"
|
||||
" p[0].z = n.y*k;\n"
|
||||
" // set q = n x p\n"
|
||||
" q[0].x = a*k;\n"
|
||||
" q[0].y = -n.x*p[0].z;\n"
|
||||
" q[0].z = n.x*p[0].y;\n"
|
||||
" }\n"
|
||||
" else {\n"
|
||||
" // choose p in x-y plane\n"
|
||||
" float a = n.x*n.x + n.y*n.y;\n"
|
||||
" float k = 1.f/sqrt(a);\n"
|
||||
" p[0].x = -n.y*k;\n"
|
||||
" p[0].y = n.x*k;\n"
|
||||
" p[0].z = 0;\n"
|
||||
" // set q = n x p\n"
|
||||
" q[0].x = -n.z*p[0].y;\n"
|
||||
" q[0].y = n.z*p[0].x;\n"
|
||||
" q[0].z = a*k;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"void solveContact(__global Constraint4* cs,\n"
|
||||
" float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,\n"
|
||||
" float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB,\n"
|
||||
" float4* dLinVelA, float4* dAngVelA, float4* dLinVelB, float4* dAngVelB)\n"
|
||||
"{\n"
|
||||
" float minRambdaDt = 0;\n"
|
||||
" float maxRambdaDt = FLT_MAX;\n"
|
||||
"\n"
|
||||
" for(int ic=0; ic<4; ic++)\n"
|
||||
" {\n"
|
||||
" if( cs->m_jacCoeffInv[ic] == 0.f ) continue;\n"
|
||||
"\n"
|
||||
" float4 angular0, angular1, linear;\n"
|
||||
" float4 r0 = cs->m_worldPos[ic] - posA;\n"
|
||||
" float4 r1 = cs->m_worldPos[ic] - posB;\n"
|
||||
" setLinearAndAngular( -cs->m_linear, r0, r1, &linear, &angular0, &angular1 );\n"
|
||||
" \n"
|
||||
"\n"
|
||||
"\n"
|
||||
" float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1, \n"
|
||||
" *linVelA+*dLinVelA, *angVelA+*dAngVelA, *linVelB+*dLinVelB, *angVelB+*dAngVelB ) + cs->m_b[ic];\n"
|
||||
" rambdaDt *= cs->m_jacCoeffInv[ic];\n"
|
||||
"\n"
|
||||
" \n"
|
||||
" {\n"
|
||||
" float prevSum = cs->m_appliedRambdaDt[ic];\n"
|
||||
" float updated = prevSum;\n"
|
||||
" updated += rambdaDt;\n"
|
||||
" updated = max2( updated, minRambdaDt );\n"
|
||||
" updated = min2( updated, maxRambdaDt );\n"
|
||||
" rambdaDt = updated - prevSum;\n"
|
||||
" cs->m_appliedRambdaDt[ic] = updated;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" \n"
|
||||
" float4 linImp0 = invMassA*linear*rambdaDt;\n"
|
||||
" float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
|
||||
" float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
|
||||
" float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
|
||||
"\n"
|
||||
" \n"
|
||||
" if (invMassA)\n"
|
||||
" {\n"
|
||||
" *dLinVelA += linImp0;\n"
|
||||
" *dAngVelA += angImp0;\n"
|
||||
" }\n"
|
||||
" if (invMassB)\n"
|
||||
" {\n"
|
||||
" *dLinVelB += linImp1;\n"
|
||||
" *dAngVelB += angImp1;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"// solveContactConstraint( gBodies, gShapes, &gConstraints[i] ,contactConstraintOffsets,offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs, \n"
|
||||
"__global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,\n"
|
||||
"__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities)\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
" //float frictionCoeff = ldsCs[0].m_linear.w;\n"
|
||||
" int aIdx = ldsCs[0].m_bodyA;\n"
|
||||
" int bIdx = ldsCs[0].m_bodyB;\n"
|
||||
"\n"
|
||||
" float4 posA = gBodies[aIdx].m_pos;\n"
|
||||
" float4 linVelA = gBodies[aIdx].m_linVel;\n"
|
||||
" float4 angVelA = gBodies[aIdx].m_angVel;\n"
|
||||
" float invMassA = gBodies[aIdx].m_invMass;\n"
|
||||
" Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
|
||||
"\n"
|
||||
" float4 posB = gBodies[bIdx].m_pos;\n"
|
||||
" float4 linVelB = gBodies[bIdx].m_linVel;\n"
|
||||
" float4 angVelB = gBodies[bIdx].m_angVel;\n"
|
||||
" float invMassB = gBodies[bIdx].m_invMass;\n"
|
||||
" Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
|
||||
"\n"
|
||||
" \n"
|
||||
" float4 dLinVelA = make_float4(0,0,0,0);\n"
|
||||
" float4 dAngVelA = make_float4(0,0,0,0);\n"
|
||||
" float4 dLinVelB = make_float4(0,0,0,0);\n"
|
||||
" float4 dAngVelB = make_float4(0,0,0,0);\n"
|
||||
" \n"
|
||||
" int bodyOffsetA = offsetSplitBodies[aIdx];\n"
|
||||
" int constraintOffsetA = contactConstraintOffsets[0].x;\n"
|
||||
" int splitIndexA = bodyOffsetA+constraintOffsetA;\n"
|
||||
" \n"
|
||||
" if (invMassA)\n"
|
||||
" {\n"
|
||||
" dLinVelA = deltaLinearVelocities[splitIndexA];\n"
|
||||
" dAngVelA = deltaAngularVelocities[splitIndexA];\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" int bodyOffsetB = offsetSplitBodies[bIdx];\n"
|
||||
" int constraintOffsetB = contactConstraintOffsets[0].y;\n"
|
||||
" int splitIndexB= bodyOffsetB+constraintOffsetB;\n"
|
||||
"\n"
|
||||
" if (invMassB)\n"
|
||||
" {\n"
|
||||
" dLinVelB = deltaLinearVelocities[splitIndexB];\n"
|
||||
" dAngVelB = deltaAngularVelocities[splitIndexB];\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
|
||||
" posB, &linVelB, &angVelB, invMassB, invInertiaB ,&dLinVelA, &dAngVelA, &dLinVelB, &dAngVelB);\n"
|
||||
"\n"
|
||||
" if (invMassA)\n"
|
||||
" {\n"
|
||||
" deltaLinearVelocities[splitIndexA] = dLinVelA;\n"
|
||||
" deltaAngularVelocities[splitIndexA] = dAngVelA;\n"
|
||||
" } \n"
|
||||
" if (invMassB)\n"
|
||||
" {\n"
|
||||
" deltaLinearVelocities[splitIndexB] = dLinVelB;\n"
|
||||
" deltaAngularVelocities[splitIndexB] = dAngVelB;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__kernel void SolveContactJacobiKernel(__global Constraint4* gConstraints, __global Body* gBodies, __global Shape* gShapes ,\n"
|
||||
"__global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities,\n"
|
||||
"float deltaTime, float positionDrift, float positionConstraintCoeff, int fixedBodyIndex, int numManifolds\n"
|
||||
")\n"
|
||||
"{\n"
|
||||
" int i = GET_GLOBAL_IDX;\n"
|
||||
" if (i<numManifolds)\n"
|
||||
" {\n"
|
||||
" solveContactConstraint( gBodies, gShapes, &gConstraints[i] ,&contactConstraintOffsets[i],offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs,\n"
|
||||
" __global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,\n"
|
||||
" __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities)\n"
|
||||
"{\n"
|
||||
" float frictionCoeff = 0.7f;//ldsCs[0].m_linear.w;\n"
|
||||
" int aIdx = ldsCs[0].m_bodyA;\n"
|
||||
" int bIdx = ldsCs[0].m_bodyB;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" float4 posA = gBodies[aIdx].m_pos;\n"
|
||||
" float4 linVelA = gBodies[aIdx].m_linVel;\n"
|
||||
" float4 angVelA = gBodies[aIdx].m_angVel;\n"
|
||||
" float invMassA = gBodies[aIdx].m_invMass;\n"
|
||||
" Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
|
||||
"\n"
|
||||
" float4 posB = gBodies[bIdx].m_pos;\n"
|
||||
" float4 linVelB = gBodies[bIdx].m_linVel;\n"
|
||||
" float4 angVelB = gBodies[bIdx].m_angVel;\n"
|
||||
" float invMassB = gBodies[bIdx].m_invMass;\n"
|
||||
" Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
|
||||
" \n"
|
||||
"\n"
|
||||
" float4 dLinVelA = make_float4(0,0,0,0);\n"
|
||||
" float4 dAngVelA = make_float4(0,0,0,0);\n"
|
||||
" float4 dLinVelB = make_float4(0,0,0,0);\n"
|
||||
" float4 dAngVelB = make_float4(0,0,0,0);\n"
|
||||
" \n"
|
||||
" int bodyOffsetA = offsetSplitBodies[aIdx];\n"
|
||||
" int constraintOffsetA = contactConstraintOffsets[0].x;\n"
|
||||
" int splitIndexA = bodyOffsetA+constraintOffsetA;\n"
|
||||
" \n"
|
||||
" if (invMassA)\n"
|
||||
" {\n"
|
||||
" dLinVelA = deltaLinearVelocities[splitIndexA];\n"
|
||||
" dAngVelA = deltaAngularVelocities[splitIndexA];\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" int bodyOffsetB = offsetSplitBodies[bIdx];\n"
|
||||
" int constraintOffsetB = contactConstraintOffsets[0].y;\n"
|
||||
" int splitIndexB= bodyOffsetB+constraintOffsetB;\n"
|
||||
"\n"
|
||||
" if (invMassB)\n"
|
||||
" {\n"
|
||||
" dLinVelB = deltaLinearVelocities[splitIndexB];\n"
|
||||
" dAngVelB = deltaAngularVelocities[splitIndexB];\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" {\n"
|
||||
" float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};\n"
|
||||
" float minRambdaDt[4] = {0.f,0.f,0.f,0.f};\n"
|
||||
"\n"
|
||||
" float sum = 0;\n"
|
||||
" for(int j=0; j<4; j++)\n"
|
||||
" {\n"
|
||||
" sum +=ldsCs[0].m_appliedRambdaDt[j];\n"
|
||||
" }\n"
|
||||
" frictionCoeff = 0.7f;\n"
|
||||
" for(int j=0; j<4; j++)\n"
|
||||
" {\n"
|
||||
" maxRambdaDt[j] = frictionCoeff*sum;\n"
|
||||
" minRambdaDt[j] = -maxRambdaDt[j];\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" \n"
|
||||
"// solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
|
||||
"// posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt );\n"
|
||||
" \n"
|
||||
" \n"
|
||||
" {\n"
|
||||
" \n"
|
||||
" __global Constraint4* cs = ldsCs;\n"
|
||||
" \n"
|
||||
" if( cs->m_fJacCoeffInv[0] == 0 && cs->m_fJacCoeffInv[0] == 0 ) return;\n"
|
||||
" const float4 center = cs->m_center;\n"
|
||||
" \n"
|
||||
" float4 n = -cs->m_linear;\n"
|
||||
" \n"
|
||||
" float4 tangent[2];\n"
|
||||
" b3PlaneSpace1(n,&tangent[0],&tangent[1]);\n"
|
||||
" float4 angular0, angular1, linear;\n"
|
||||
" float4 r0 = center - posA;\n"
|
||||
" float4 r1 = center - posB;\n"
|
||||
" for(int i=0; i<2; i++)\n"
|
||||
" {\n"
|
||||
" setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 );\n"
|
||||
" float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,\n"
|
||||
" linVelA+dLinVelA, angVelA+dAngVelA, linVelB+dLinVelB, angVelB+dAngVelB );\n"
|
||||
" rambdaDt *= cs->m_fJacCoeffInv[i];\n"
|
||||
" \n"
|
||||
" {\n"
|
||||
" float prevSum = cs->m_fAppliedRambdaDt[i];\n"
|
||||
" float updated = prevSum;\n"
|
||||
" updated += rambdaDt;\n"
|
||||
" updated = max2( updated, minRambdaDt[i] );\n"
|
||||
" updated = min2( updated, maxRambdaDt[i] );\n"
|
||||
" rambdaDt = updated - prevSum;\n"
|
||||
" cs->m_fAppliedRambdaDt[i] = updated;\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
" float4 linImp0 = invMassA*linear*rambdaDt;\n"
|
||||
" float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
|
||||
" float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
|
||||
" float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
|
||||
" \n"
|
||||
" dLinVelA += linImp0;\n"
|
||||
" dAngVelA += angImp0;\n"
|
||||
" dLinVelB += linImp1;\n"
|
||||
" dAngVelB += angImp1;\n"
|
||||
" }\n"
|
||||
" { // angular damping for point constraint\n"
|
||||
" float4 ab = normalize3( posB - posA );\n"
|
||||
" float4 ac = normalize3( center - posA );\n"
|
||||
" if( dot3F4( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))\n"
|
||||
" {\n"
|
||||
" float angNA = dot3F4( n, angVelA );\n"
|
||||
" float angNB = dot3F4( n, angVelB );\n"
|
||||
" \n"
|
||||
" dAngVelA -= (angNA*0.1f)*n;\n"
|
||||
" dAngVelB -= (angNB*0.1f)*n;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" \n"
|
||||
" \n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" if (invMassA)\n"
|
||||
" {\n"
|
||||
" deltaLinearVelocities[splitIndexA] = dLinVelA;\n"
|
||||
" deltaAngularVelocities[splitIndexA] = dAngVelA;\n"
|
||||
" } \n"
|
||||
" if (invMassB)\n"
|
||||
" {\n"
|
||||
" deltaLinearVelocities[splitIndexB] = dLinVelB;\n"
|
||||
" deltaAngularVelocities[splitIndexB] = dAngVelB;\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
"\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__kernel void SolveFrictionJacobiKernel(__global Constraint4* gConstraints, __global Body* gBodies, __global Shape* gShapes ,\n"
|
||||
" __global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,\n"
|
||||
" __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities,\n"
|
||||
" float deltaTime, float positionDrift, float positionConstraintCoeff, int fixedBodyIndex, int numManifolds\n"
|
||||
")\n"
|
||||
"{\n"
|
||||
" int i = GET_GLOBAL_IDX;\n"
|
||||
" if (i<numManifolds)\n"
|
||||
" {\n"
|
||||
" solveFrictionConstraint( gBodies, gShapes, &gConstraints[i] ,&contactConstraintOffsets[i],offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__kernel void UpdateBodyVelocitiesKernel(__global Body* gBodies,__global int* offsetSplitBodies,__global const unsigned int* bodyCount,\n"
|
||||
" __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities, int numBodies)\n"
|
||||
"{\n"
|
||||
" int i = GET_GLOBAL_IDX;\n"
|
||||
" if (i<numBodies)\n"
|
||||
" {\n"
|
||||
" if (gBodies[i].m_invMass)\n"
|
||||
" {\n"
|
||||
" int bodyOffset = offsetSplitBodies[i];\n"
|
||||
" int count = bodyCount[i];\n"
|
||||
" if (count)\n"
|
||||
" {\n"
|
||||
" gBodies[i].m_linVel += deltaLinearVelocities[bodyOffset];\n"
|
||||
" gBodies[i].m_angVel += deltaAngularVelocities[bodyOffset];\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"void setConstraint4( const float4 posA, const float4 linVelA, const float4 angVelA, float invMassA, const Matrix3x3 invInertiaA,\n"
|
||||
" const float4 posB, const float4 linVelB, const float4 angVelB, float invMassB, const Matrix3x3 invInertiaB, \n"
|
||||
" __global Contact4* src, float dt, float positionDrift, float positionConstraintCoeff,float countA, float countB,\n"
|
||||
" Constraint4* dstC )\n"
|
||||
"{\n"
|
||||
" dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);\n"
|
||||
" dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);\n"
|
||||
"\n"
|
||||
" float dtInv = 1.f/dt;\n"
|
||||
" for(int ic=0; ic<4; ic++)\n"
|
||||
" {\n"
|
||||
" dstC->m_appliedRambdaDt[ic] = 0.f;\n"
|
||||
" }\n"
|
||||
" dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" dstC->m_linear = -src->m_worldNormal;\n"
|
||||
" dstC->m_linear.w = 0.7f ;//src->getFrictionCoeff() );\n"
|
||||
" for(int ic=0; ic<4; ic++)\n"
|
||||
" {\n"
|
||||
" float4 r0 = src->m_worldPos[ic] - posA;\n"
|
||||
" float4 r1 = src->m_worldPos[ic] - posB;\n"
|
||||
"\n"
|
||||
" if( ic >= src->m_worldNormal.w )//npoints\n"
|
||||
" {\n"
|
||||
" dstC->m_jacCoeffInv[ic] = 0.f;\n"
|
||||
" continue;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" float relVelN;\n"
|
||||
" {\n"
|
||||
" float4 linear, angular0, angular1;\n"
|
||||
" setLinearAndAngular(src->m_worldNormal, r0, r1, &linear, &angular0, &angular1);\n"
|
||||
"\n"
|
||||
" dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
|
||||
" invMassA, &invInertiaA, invMassB, &invInertiaB , countA, countB);\n"
|
||||
"\n"
|
||||
" relVelN = calcRelVel(linear, -linear, angular0, angular1,\n"
|
||||
" linVelA, angVelA, linVelB, angVelB);\n"
|
||||
"\n"
|
||||
" float e = 0.f;//src->getRestituitionCoeff();\n"
|
||||
" if( relVelN*relVelN < 0.004f ) e = 0.f;\n"
|
||||
"\n"
|
||||
" dstC->m_b[ic] = e*relVelN;\n"
|
||||
" //float penetration = src->m_worldPos[ic].w;\n"
|
||||
" dstC->m_b[ic] += (src->m_worldPos[ic].w + positionDrift)*positionConstraintCoeff*dtInv;\n"
|
||||
" dstC->m_appliedRambdaDt[ic] = 0.f;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" if( src->m_worldNormal.w > 0 )//npoints\n"
|
||||
" { // prepare friction\n"
|
||||
" float4 center = make_float4(0.f);\n"
|
||||
" for(int i=0; i<src->m_worldNormal.w; i++) \n"
|
||||
" center += src->m_worldPos[i];\n"
|
||||
" center /= (float)src->m_worldNormal.w;\n"
|
||||
"\n"
|
||||
" float4 tangent[2];\n"
|
||||
" b3PlaneSpace1(src->m_worldNormal,&tangent[0],&tangent[1]);\n"
|
||||
" \n"
|
||||
" float4 r[2];\n"
|
||||
" r[0] = center - posA;\n"
|
||||
" r[1] = center - posB;\n"
|
||||
"\n"
|
||||
" for(int i=0; i<2; i++)\n"
|
||||
" {\n"
|
||||
" float4 linear, angular0, angular1;\n"
|
||||
" setLinearAndAngular(tangent[i], r[0], r[1], &linear, &angular0, &angular1);\n"
|
||||
"\n"
|
||||
" dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
|
||||
" invMassA, &invInertiaA, invMassB, &invInertiaB ,countA, countB);\n"
|
||||
" dstC->m_fAppliedRambdaDt[i] = 0.f;\n"
|
||||
" }\n"
|
||||
" dstC->m_center = center;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" for(int i=0; i<4; i++)\n"
|
||||
" {\n"
|
||||
" if( i<src->m_worldNormal.w )\n"
|
||||
" {\n"
|
||||
" dstC->m_worldPos[i] = src->m_worldPos[i];\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" dstC->m_worldPos[i] = make_float4(0.f);\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__kernel\n"
|
||||
"__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
|
||||
"void ContactToConstraintSplitKernel(__global const Contact4* gContact, __global const Body* gBodies, __global const Shape* gShapes, __global Constraint4* gConstraintOut, \n"
|
||||
"__global const unsigned int* bodyCount,\n"
|
||||
"int nContacts,\n"
|
||||
"float dt,\n"
|
||||
"float positionDrift,\n"
|
||||
"float positionConstraintCoeff\n"
|
||||
")\n"
|
||||
"{\n"
|
||||
" int gIdx = GET_GLOBAL_IDX;\n"
|
||||
" \n"
|
||||
" if( gIdx < nContacts )\n"
|
||||
" {\n"
|
||||
" int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);\n"
|
||||
" int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);\n"
|
||||
"\n"
|
||||
" float4 posA = gBodies[aIdx].m_pos;\n"
|
||||
" float4 linVelA = gBodies[aIdx].m_linVel;\n"
|
||||
" float4 angVelA = gBodies[aIdx].m_angVel;\n"
|
||||
" float invMassA = gBodies[aIdx].m_invMass;\n"
|
||||
" Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
|
||||
"\n"
|
||||
" float4 posB = gBodies[bIdx].m_pos;\n"
|
||||
" float4 linVelB = gBodies[bIdx].m_linVel;\n"
|
||||
" float4 angVelB = gBodies[bIdx].m_angVel;\n"
|
||||
" float invMassB = gBodies[bIdx].m_invMass;\n"
|
||||
" Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
|
||||
"\n"
|
||||
" Constraint4 cs;\n"
|
||||
"\n"
|
||||
" float countA = invMassA ? (float)bodyCount[aIdx] : 1;\n"
|
||||
" float countB = invMassB ? (float)bodyCount[bIdx] : 1;\n"
|
||||
"\n"
|
||||
" setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,\n"
|
||||
" &gContact[gIdx], dt, positionDrift, positionConstraintCoeff,countA,countB,\n"
|
||||
" &cs );\n"
|
||||
" \n"
|
||||
" cs.m_batchIdx = gContact[gIdx].m_batchIdx;\n"
|
||||
"\n"
|
||||
" gConstraintOut[gIdx] = cs;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
;
|
||||
195
src/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.cl
Normal file
195
src/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.cl
Normal file
@@ -0,0 +1,195 @@
|
||||
|
||||
#define SHAPE_CONVEX_HULL 3
|
||||
|
||||
typedef float4 Quaternion;
|
||||
|
||||
__inline
|
||||
float4 cross3(float4 a, float4 b)
|
||||
{
|
||||
return cross(a,b);
|
||||
}
|
||||
|
||||
__inline
|
||||
float dot3F4(float4 a, float4 b)
|
||||
{
|
||||
float4 a1 = (float4)(a.xyz,0.f);
|
||||
float4 b1 = (float4)(b.xyz,0.f);
|
||||
return dot(a1, b1);
|
||||
}
|
||||
|
||||
|
||||
__inline
|
||||
Quaternion qtMul(Quaternion a, Quaternion b)
|
||||
{
|
||||
Quaternion ans;
|
||||
ans = cross3( a, b );
|
||||
ans += a.w*b+b.w*a;
|
||||
ans.w = a.w*b.w - dot3F4(a, b);
|
||||
return ans;
|
||||
}
|
||||
|
||||
__inline
|
||||
Quaternion qtInvert(Quaternion q)
|
||||
{
|
||||
return (Quaternion)(-q.xyz, q.w);
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 qtRotate(Quaternion q, float4 vec)
|
||||
{
|
||||
Quaternion qInv = qtInvert( q );
|
||||
float4 vcpy = vec;
|
||||
vcpy.w = 0.f;
|
||||
float4 out = qtMul(qtMul(q,vcpy),qInv);
|
||||
return out;
|
||||
}
|
||||
|
||||
__inline
|
||||
float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)
|
||||
{
|
||||
return qtRotate( *orientation, *p ) + (*translation);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_row[3];
|
||||
} Matrix3x3;
|
||||
|
||||
typedef unsigned int u32;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 m_pos;
|
||||
float4 m_quat;
|
||||
float4 m_linVel;
|
||||
float4 m_angVel;
|
||||
|
||||
u32 m_collidableIdx;
|
||||
float m_invMass;
|
||||
float m_restituitionCoeff;
|
||||
float m_frictionCoeff;
|
||||
} Body;
|
||||
|
||||
typedef struct Collidable
|
||||
{
|
||||
int m_unused1;
|
||||
int m_unused2;
|
||||
int m_shapeType;
|
||||
int m_shapeIndex;
|
||||
} Collidable;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Matrix3x3 m_invInertia;
|
||||
Matrix3x3 m_initInvInertia;
|
||||
} Shape;
|
||||
|
||||
|
||||
__inline
|
||||
Matrix3x3 qtGetRotationMatrix(float4 quat)
|
||||
{
|
||||
float4 quat2 = (float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);
|
||||
Matrix3x3 out;
|
||||
|
||||
out.m_row[0].x=fabs(1-2*quat2.y-2*quat2.z);
|
||||
out.m_row[0].y=fabs(2*quat.x*quat.y-2*quat.w*quat.z);
|
||||
out.m_row[0].z=fabs(2*quat.x*quat.z+2*quat.w*quat.y);
|
||||
out.m_row[0].w = 0.f;
|
||||
|
||||
out.m_row[1].x=fabs(2*quat.x*quat.y+2*quat.w*quat.z);
|
||||
out.m_row[1].y=fabs(1-2*quat2.x-2*quat2.z);
|
||||
out.m_row[1].z=fabs(2*quat.y*quat.z-2*quat.w*quat.x);
|
||||
out.m_row[1].w = 0.f;
|
||||
|
||||
out.m_row[2].x=fabs(2*quat.x*quat.z-2*quat.w*quat.y);
|
||||
out.m_row[2].y=fabs(2*quat.y*quat.z+2*quat.w*quat.x);
|
||||
out.m_row[2].z=fabs(1-2*quat2.x-2*quat2.y);
|
||||
out.m_row[2].w = 0.f;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float fx;
|
||||
float fy;
|
||||
float fz;
|
||||
int uw;
|
||||
} btAABBCL;
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtTranspose(Matrix3x3 m)
|
||||
{
|
||||
Matrix3x3 out;
|
||||
out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);
|
||||
out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);
|
||||
out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
__inline
|
||||
Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)
|
||||
{
|
||||
Matrix3x3 transB;
|
||||
transB = mtTranspose( b );
|
||||
Matrix3x3 ans;
|
||||
// why this doesn't run when 0ing in the for{}
|
||||
a.m_row[0].w = 0.f;
|
||||
a.m_row[1].w = 0.f;
|
||||
a.m_row[2].w = 0.f;
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
// a.m_row[i].w = 0.f;
|
||||
ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);
|
||||
ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);
|
||||
ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);
|
||||
ans.m_row[i].w = 0.f;
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
|
||||
__kernel void initializeGpuAabbsFull( const int numNodes, __global Body* gBodies,__global Collidable* collidables, __global btAABBCL* plocalShapeAABB, __global btAABBCL* pAABB)
|
||||
{
|
||||
int nodeID = get_global_id(0);
|
||||
|
||||
if( nodeID < numNodes )
|
||||
{
|
||||
float4 position = gBodies[nodeID].m_pos;
|
||||
float4 orientation = gBodies[nodeID].m_quat;
|
||||
|
||||
|
||||
int collidableIndex = gBodies[nodeID].m_collidableIdx;
|
||||
int shapeIndex = collidables[collidableIndex].m_shapeIndex;
|
||||
|
||||
if (shapeIndex>=0)
|
||||
{
|
||||
btAABBCL minAabb = plocalShapeAABB[collidableIndex*2];
|
||||
btAABBCL maxAabb = plocalShapeAABB[collidableIndex*2+1];
|
||||
|
||||
float4 halfExtents = ((float4)(maxAabb.fx - minAabb.fx,maxAabb.fy - minAabb.fy,maxAabb.fz - minAabb.fz,0.f))*0.5f;
|
||||
float4 localCenter = ((float4)(maxAabb.fx + minAabb.fx,maxAabb.fy + minAabb.fy,maxAabb.fz + minAabb.fz,0.f))*0.5f;
|
||||
|
||||
float4 worldCenter = transform(&localCenter,&position,&orientation);
|
||||
|
||||
Matrix3x3 abs_b = qtGetRotationMatrix(orientation);
|
||||
float4 extent = (float4) ( dot(abs_b.m_row[0],halfExtents),dot(abs_b.m_row[1],halfExtents),dot(abs_b.m_row[2],halfExtents),0.f);
|
||||
|
||||
|
||||
pAABB[nodeID*2].fx = worldCenter.x-extent.x;
|
||||
pAABB[nodeID*2].fy = worldCenter.y-extent.y;
|
||||
pAABB[nodeID*2].fz = worldCenter.z-extent.z;
|
||||
pAABB[nodeID*2].uw = nodeID;
|
||||
|
||||
pAABB[nodeID*2+1].fx = worldCenter.x+extent.x;
|
||||
pAABB[nodeID*2+1].fy = worldCenter.y+extent.y;
|
||||
pAABB[nodeID*2+1].fz = worldCenter.z+extent.z;
|
||||
pAABB[nodeID*2+1].uw = gBodies[nodeID].m_invMass==0.f? 0 : 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
199
src/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.h
Normal file
199
src/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.h
Normal file
@@ -0,0 +1,199 @@
|
||||
//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
|
||||
static const char* updateAabbsKernelCL= \
|
||||
"\n"
|
||||
"#define SHAPE_CONVEX_HULL 3\n"
|
||||
"\n"
|
||||
"typedef float4 Quaternion;\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 cross3(float4 a, float4 b)\n"
|
||||
"{\n"
|
||||
" return cross(a,b);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float dot3F4(float4 a, float4 b)\n"
|
||||
"{\n"
|
||||
" float4 a1 = (float4)(a.xyz,0.f);\n"
|
||||
" float4 b1 = (float4)(b.xyz,0.f);\n"
|
||||
" return dot(a1, b1);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Quaternion qtMul(Quaternion a, Quaternion b)\n"
|
||||
"{\n"
|
||||
" Quaternion ans;\n"
|
||||
" ans = cross3( a, b );\n"
|
||||
" ans += a.w*b+b.w*a;\n"
|
||||
" ans.w = a.w*b.w - dot3F4(a, b);\n"
|
||||
" return ans;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Quaternion qtInvert(Quaternion q)\n"
|
||||
"{\n"
|
||||
" return (Quaternion)(-q.xyz, q.w);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 qtRotate(Quaternion q, float4 vec)\n"
|
||||
"{\n"
|
||||
" Quaternion qInv = qtInvert( q );\n"
|
||||
" float4 vcpy = vec;\n"
|
||||
" vcpy.w = 0.f;\n"
|
||||
" float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
|
||||
" return out;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
|
||||
"{\n"
|
||||
" return qtRotate( *orientation, *p ) + (*translation);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_row[3];\n"
|
||||
"} Matrix3x3;\n"
|
||||
"\n"
|
||||
"typedef unsigned int u32;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" float4 m_pos;\n"
|
||||
" float4 m_quat;\n"
|
||||
" float4 m_linVel;\n"
|
||||
" float4 m_angVel;\n"
|
||||
"\n"
|
||||
" u32 m_collidableIdx;\n"
|
||||
" float m_invMass;\n"
|
||||
" float m_restituitionCoeff;\n"
|
||||
" float m_frictionCoeff;\n"
|
||||
"} Body;\n"
|
||||
"\n"
|
||||
"typedef struct Collidable\n"
|
||||
"{\n"
|
||||
" int m_unused1;\n"
|
||||
" int m_unused2;\n"
|
||||
" int m_shapeType;\n"
|
||||
" int m_shapeIndex;\n"
|
||||
"} Collidable;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" Matrix3x3 m_invInertia;\n"
|
||||
" Matrix3x3 m_initInvInertia;\n"
|
||||
"} Shape;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 qtGetRotationMatrix(float4 quat)\n"
|
||||
"{\n"
|
||||
" float4 quat2 = (float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
|
||||
" Matrix3x3 out;\n"
|
||||
"\n"
|
||||
" out.m_row[0].x=fabs(1-2*quat2.y-2*quat2.z);\n"
|
||||
" out.m_row[0].y=fabs(2*quat.x*quat.y-2*quat.w*quat.z);\n"
|
||||
" out.m_row[0].z=fabs(2*quat.x*quat.z+2*quat.w*quat.y);\n"
|
||||
" out.m_row[0].w = 0.f;\n"
|
||||
"\n"
|
||||
" out.m_row[1].x=fabs(2*quat.x*quat.y+2*quat.w*quat.z);\n"
|
||||
" out.m_row[1].y=fabs(1-2*quat2.x-2*quat2.z);\n"
|
||||
" out.m_row[1].z=fabs(2*quat.y*quat.z-2*quat.w*quat.x);\n"
|
||||
" out.m_row[1].w = 0.f;\n"
|
||||
"\n"
|
||||
" out.m_row[2].x=fabs(2*quat.x*quat.z-2*quat.w*quat.y);\n"
|
||||
" out.m_row[2].y=fabs(2*quat.y*quat.z+2*quat.w*quat.x);\n"
|
||||
" out.m_row[2].z=fabs(1-2*quat2.x-2*quat2.y);\n"
|
||||
" out.m_row[2].w = 0.f;\n"
|
||||
"\n"
|
||||
" return out;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"typedef struct \n"
|
||||
"{\n"
|
||||
" float fx;\n"
|
||||
" float fy;\n"
|
||||
" float fz;\n"
|
||||
" int uw;\n"
|
||||
"} b3AABBCL;\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtTranspose(Matrix3x3 m)\n"
|
||||
"{\n"
|
||||
" Matrix3x3 out;\n"
|
||||
" out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
|
||||
" out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
|
||||
" out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
|
||||
" return out;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__inline\n"
|
||||
"Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)\n"
|
||||
"{\n"
|
||||
" Matrix3x3 transB;\n"
|
||||
" transB = mtTranspose( b );\n"
|
||||
" Matrix3x3 ans;\n"
|
||||
" // why this doesn't run when 0ing in the for{}\n"
|
||||
" a.m_row[0].w = 0.f;\n"
|
||||
" a.m_row[1].w = 0.f;\n"
|
||||
" a.m_row[2].w = 0.f;\n"
|
||||
" for(int i=0; i<3; i++)\n"
|
||||
" {\n"
|
||||
"// a.m_row[i].w = 0.f;\n"
|
||||
" ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);\n"
|
||||
" ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);\n"
|
||||
" ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);\n"
|
||||
" ans.m_row[i].w = 0.f;\n"
|
||||
" }\n"
|
||||
" return ans;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"__kernel void initializeGpuAabbsFull( const int numNodes, __global Body* gBodies,__global Collidable* collidables, __global b3AABBCL* plocalShapeAABB, __global b3AABBCL* pAABB)\n"
|
||||
"{\n"
|
||||
" int nodeID = get_global_id(0);\n"
|
||||
" \n"
|
||||
" if( nodeID < numNodes )\n"
|
||||
" {\n"
|
||||
" float4 position = gBodies[nodeID].m_pos;\n"
|
||||
" float4 orientation = gBodies[nodeID].m_quat;\n"
|
||||
" \n"
|
||||
" \n"
|
||||
" int collidableIndex = gBodies[nodeID].m_collidableIdx;\n"
|
||||
" int shapeIndex = collidables[collidableIndex].m_shapeIndex;\n"
|
||||
" \n"
|
||||
" if (shapeIndex>=0)\n"
|
||||
" {\n"
|
||||
" b3AABBCL minAabb = plocalShapeAABB[collidableIndex*2];\n"
|
||||
" b3AABBCL maxAabb = plocalShapeAABB[collidableIndex*2+1];\n"
|
||||
" \n"
|
||||
" float4 halfExtents = ((float4)(maxAabb.fx - minAabb.fx,maxAabb.fy - minAabb.fy,maxAabb.fz - minAabb.fz,0.f))*0.5f;\n"
|
||||
" float4 localCenter = ((float4)(maxAabb.fx + minAabb.fx,maxAabb.fy + minAabb.fy,maxAabb.fz + minAabb.fz,0.f))*0.5f;\n"
|
||||
" \n"
|
||||
" float4 worldCenter = transform(&localCenter,&position,&orientation);\n"
|
||||
" \n"
|
||||
" Matrix3x3 abs_b = qtGetRotationMatrix(orientation);\n"
|
||||
" float4 extent = (float4) ( dot(abs_b.m_row[0],halfExtents),dot(abs_b.m_row[1],halfExtents),dot(abs_b.m_row[2],halfExtents),0.f);\n"
|
||||
" \n"
|
||||
" \n"
|
||||
" pAABB[nodeID*2].fx = worldCenter.x-extent.x;\n"
|
||||
" pAABB[nodeID*2].fy = worldCenter.y-extent.y;\n"
|
||||
" pAABB[nodeID*2].fz = worldCenter.z-extent.z;\n"
|
||||
" pAABB[nodeID*2].uw = nodeID;\n"
|
||||
" \n"
|
||||
" pAABB[nodeID*2+1].fx = worldCenter.x+extent.x;\n"
|
||||
" pAABB[nodeID*2+1].fy = worldCenter.y+extent.y;\n"
|
||||
" pAABB[nodeID*2+1].fz = worldCenter.z+extent.z;\n"
|
||||
" pAABB[nodeID*2+1].uw = gBodies[nodeID].m_invMass==0.f? 0 : 1;\n"
|
||||
" }\n"
|
||||
" } \n"
|
||||
"}\n"
|
||||
"\n"
|
||||
;
|
||||
Reference in New Issue
Block a user