mirror of
https://github.com/bulletphysics/bullet3
synced 2024-12-14 22:00:05 +00:00
ab8f16961e
Apply clang-format-all.sh using the _clang-format file through all the cpp/.h files. make sure not to apply it to certain serialization structures, since some parser expects the * as part of the name, instead of type. This commit contains no other changes aside from adding and applying clang-format-all.sh
722 lines
20 KiB
C++
722 lines
20 KiB
C++
//those header files need to be at the top, because of conflict __global and STL
|
|
|
|
#include "PairBench.h"
|
|
#include "Bullet3Common/b3Quaternion.h"
|
|
|
|
#include "Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.h"
|
|
#include "Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.h"
|
|
#include "Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.h"
|
|
#include "../Utils/b3Clock.h"
|
|
|
|
//#include "../GpuDemoInternalData.h"
|
|
#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
|
|
|
|
#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
|
|
|
|
#include "../OpenGLWindow/OpenGLInclude.h"
|
|
#include "../OpenGLWindow/ShapeData.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include "pairsKernel.h"
|
|
|
|
extern int gPreferredOpenCLDeviceIndex;
|
|
extern int gPreferredOpenCLPlatformIndex;
|
|
|
|
#include "../CommonInterfaces/CommonExampleInterface.h"
|
|
#include "../CommonInterfaces/CommonGUIHelperInterface.h"
|
|
#include "../CommonInterfaces/CommonRenderInterface.h"
|
|
#include "../CommonInterfaces/CommonCameraInterface.h"
|
|
#include "../CommonInterfaces/CommonGraphicsAppInterface.h"
|
|
#include "../CommonInterfaces/CommonWindowInterface.h"
|
|
#include "../CommonOpenCL/CommonOpenCLBase.h"
|
|
#include "../OpenGLWindow/GLInstancingRenderer.h"
|
|
#include "../OpenGLWindow/GLInstanceRendererInternalData.h"
|
|
|
|
char* gPairBenchFileName = 0;
|
|
|
|
class PairBench : public CommonOpenCLBase
|
|
{
|
|
struct PairBenchInternalData* m_data;
|
|
|
|
public:
|
|
PairBench(GUIHelperInterface* helper);
|
|
virtual ~PairBench();
|
|
|
|
virtual void initPhysics();
|
|
virtual void exitPhysics();
|
|
|
|
void createBroadphase(int xdim, int ydim, int zdim);
|
|
void deleteBroadphase();
|
|
|
|
virtual void stepSimulation(float deltaTime);
|
|
|
|
virtual void renderScene();
|
|
|
|
virtual void resetCamera()
|
|
{
|
|
float dist = 10;
|
|
|
|
if (gPairBenchFileName)
|
|
{
|
|
dist = 830;
|
|
}
|
|
else
|
|
{
|
|
dist = 130;
|
|
}
|
|
|
|
float pitch = -33;
|
|
float yaw = 62;
|
|
float targetPos[4] = {15.5, 12.5, 15.5, 0};
|
|
m_guiHelper->resetCamera(dist, yaw, pitch, targetPos[0], targetPos[1], targetPos[2]);
|
|
}
|
|
};
|
|
|
|
//we use an offset, just for testing to make sure there is no assumption in the broadphase that 'index' starts at 0
|
|
#define TEST_INDEX_OFFSET 1024
|
|
|
|
extern bool useShadowMap;
|
|
float maxExtents = -1e30f;
|
|
int largeCount = 0;
|
|
|
|
float timeStepPos = 0.000166666;
|
|
float mAmplitude = 251.f;
|
|
int dimensions[3] = {10, 10, 10}; //initialized with x_dim/y_dim/z_dim
|
|
const char* axisNames[3] = {"# x-axis", "# y-axis", "# z-axis"};
|
|
extern bool gReset;
|
|
|
|
static int curUseLargeAabbOption = 0;
|
|
const char* useLargeAabbOptions[] =
|
|
{
|
|
"NoLargeAabb",
|
|
"UseLargeAabb",
|
|
};
|
|
|
|
struct BroadphaseEntry
|
|
{
|
|
const char* m_name;
|
|
b3GpuBroadphaseInterface::CreateFunc* m_createFunc;
|
|
};
|
|
|
|
static PairBench* sPairDemo = 0;
|
|
|
|
#define BP_COMBO_INDEX 123
|
|
|
|
static int curSelectedBroadphase = 0;
|
|
static BroadphaseEntry allBroadphases[] =
|
|
{
|
|
{"Gpu Grid", b3GpuGridBroadphase::CreateFunc},
|
|
{"Parallel Linear BVH", b3GpuParallelLinearBvhBroadphase::CreateFunc},
|
|
{"CPU Brute Force", b3GpuSapBroadphase::CreateFuncBruteForceCpu},
|
|
{"GPU Brute Force", b3GpuSapBroadphase::CreateFuncBruteForceGpu},
|
|
{"GPU 1-SAP Original", b3GpuSapBroadphase::CreateFuncOriginal},
|
|
{"GPU 1-SAP Barrier", b3GpuSapBroadphase::CreateFuncBarrier},
|
|
{"GPU 1-SAP LDS", b3GpuSapBroadphase::CreateFuncLocalMemory}};
|
|
|
|
struct PairBenchInternalData
|
|
{
|
|
b3GpuBroadphaseInterface* m_broadphaseGPU;
|
|
b3GpuBroadphaseInterface* m_validationBroadphase;
|
|
|
|
cl_kernel m_moveObjectsKernel;
|
|
cl_kernel m_sineWaveKernel;
|
|
cl_kernel m_colorPairsKernel;
|
|
cl_kernel m_updateAabbSimple;
|
|
|
|
b3OpenCLArray<b3Vector4>* m_instancePosOrnColor;
|
|
b3OpenCLArray<float>* m_bodyTimes;
|
|
PairBenchInternalData()
|
|
: m_broadphaseGPU(0),
|
|
m_moveObjectsKernel(0),
|
|
m_sineWaveKernel(0),
|
|
m_colorPairsKernel(0),
|
|
m_instancePosOrnColor(0),
|
|
m_bodyTimes(0),
|
|
m_updateAabbSimple(0)
|
|
{
|
|
}
|
|
|
|
int m_oldYposition;
|
|
};
|
|
|
|
PairBench::PairBench(GUIHelperInterface* helper)
|
|
: CommonOpenCLBase(helper)
|
|
{
|
|
m_data = new PairBenchInternalData;
|
|
|
|
m_data->m_validationBroadphase = 0;
|
|
}
|
|
PairBench::~PairBench()
|
|
{
|
|
delete m_data;
|
|
}
|
|
|
|
static inline float parseFloat(const char*& token)
|
|
{
|
|
token += strspn(token, " \t");
|
|
float f = (float)atof(token);
|
|
token += strcspn(token, " \t\r");
|
|
return f;
|
|
}
|
|
|
|
enum PairToggleButtons
|
|
{
|
|
MY_RESET = 1024,
|
|
};
|
|
|
|
#define PAIRS_CL_PROGRAM_PATH "Demos3/GpuDemos/broadphase/pairsKernel.cl"
|
|
|
|
void PairBench::initPhysics()
|
|
{
|
|
dimensions[0] = 10;
|
|
dimensions[1] = 10;
|
|
dimensions[2] = 10;
|
|
|
|
//m_guiHelper->getRenderInterface() = ci.m_guiHelper->getRenderInterface();
|
|
sPairDemo = this;
|
|
useShadowMap = false;
|
|
|
|
initCL(gPreferredOpenCLDeviceIndex, gPreferredOpenCLPlatformIndex);
|
|
|
|
if (m_clData->m_clContext)
|
|
{
|
|
cl_int err;
|
|
cl_program pairBenchProg = b3OpenCLUtils::compileCLProgramFromString(m_clData->m_clContext, m_clData->m_clDevice, pairsKernelsCL, &err, "", PAIRS_CL_PROGRAM_PATH);
|
|
int errNum = 0;
|
|
m_data->m_moveObjectsKernel = b3OpenCLUtils::compileCLKernelFromString(m_clData->m_clContext, m_clData->m_clDevice, pairsKernelsCL, "moveObjectsKernel", &errNum, pairBenchProg);
|
|
m_data->m_sineWaveKernel = b3OpenCLUtils::compileCLKernelFromString(m_clData->m_clContext, m_clData->m_clDevice, pairsKernelsCL, "sineWaveKernel", &errNum, pairBenchProg);
|
|
m_data->m_colorPairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_clData->m_clContext, m_clData->m_clDevice, pairsKernelsCL, "colorPairsKernel2", &errNum, pairBenchProg);
|
|
m_data->m_updateAabbSimple = b3OpenCLUtils::compileCLKernelFromString(m_clData->m_clContext, m_clData->m_clDevice, pairsKernelsCL, "updateAabbSimple", &errNum, pairBenchProg);
|
|
|
|
//Method for validating the overlapping pairs requires that the
|
|
//reference broadphase does not maintain internal state aside from AABB data.
|
|
//That is, overwriting the AABB state in the broadphase using
|
|
// b3GpuBroadphaseInterface::getAllAabbsGPU(),
|
|
// b3GpuBroadphaseInterface::getSmallAabbIndicesGPU(), and
|
|
// b3GpuBroadphaseInterface::getLargeAabbIndicesGPU()
|
|
//and then calling b3GpuBroadphaseInterface::calculateOverlappingPairs() should
|
|
//always produce the same result regardless of the current state of the broadphase.
|
|
m_data->m_validationBroadphase = b3GpuParallelLinearBvhBroadphase::CreateFunc(m_clData->m_clContext, m_clData->m_clDevice, m_clData->m_clQueue);
|
|
}
|
|
|
|
createBroadphase(dimensions[0], dimensions[1], dimensions[2]);
|
|
}
|
|
|
|
void PairBench::createBroadphase(int arraySizeX, int arraySizeY, int arraySizeZ)
|
|
{
|
|
m_data->m_broadphaseGPU = (allBroadphases[curSelectedBroadphase].m_createFunc)(m_clData->m_clContext, m_clData->m_clDevice, m_clData->m_clQueue);
|
|
|
|
int strideInBytes = 9 * sizeof(float);
|
|
int numVertices = sizeof(cube_vertices) / strideInBytes;
|
|
int numIndices = sizeof(cube_vertices) / sizeof(int);
|
|
int shapeId = m_guiHelper->getRenderInterface()->registerShape(&cube_vertices[0], numVertices, cube_indices, numIndices);
|
|
int group = 1;
|
|
int mask = 1;
|
|
int index = TEST_INDEX_OFFSET;
|
|
|
|
if (gPairBenchFileName)
|
|
{
|
|
//char* fileName = "32006GPUAABBs.txt";
|
|
char relativeFileName[1024];
|
|
const char* prefix[] = {"./data/", "../data/", "../../data/", "../../../data/", "../../../../data/"};
|
|
int prefixIndex = -1;
|
|
{
|
|
int numPrefixes = sizeof(prefix) / sizeof(char*);
|
|
|
|
for (int i = 0; i < numPrefixes; i++)
|
|
{
|
|
FILE* f = 0;
|
|
sprintf(relativeFileName, "%s%s", prefix[i], gPairBenchFileName);
|
|
f = fopen(relativeFileName, "rb");
|
|
if (f)
|
|
{
|
|
fseek(f, 0L, SEEK_END);
|
|
int size = ftell(f);
|
|
rewind(f);
|
|
char* buf = (char*)malloc(size);
|
|
|
|
int actualReadBytes = 0;
|
|
|
|
while (actualReadBytes < size)
|
|
{
|
|
int left = size - actualReadBytes;
|
|
int chunk = 8192;
|
|
int numPlannedRead = left < chunk ? left : chunk;
|
|
actualReadBytes += fread(&buf[actualReadBytes], 1, numPlannedRead, f);
|
|
}
|
|
|
|
fclose(f);
|
|
|
|
char pattern[1024];
|
|
pattern[0] = 0x0a;
|
|
pattern[1] = 0;
|
|
size_t const patlen = strlen(pattern);
|
|
size_t patcnt = 0;
|
|
char* oriptr;
|
|
char* patloc;
|
|
|
|
for (oriptr = buf; (patloc = strstr(oriptr, pattern)); oriptr = patloc + patlen)
|
|
{
|
|
if (patloc)
|
|
{
|
|
*patloc = 0;
|
|
const char* token = oriptr;
|
|
|
|
b3Vector3 aabbMin;
|
|
b3Vector3 aabbMax;
|
|
|
|
aabbMin.x = parseFloat(token);
|
|
aabbMin.y = parseFloat(token);
|
|
aabbMin.z = parseFloat(token);
|
|
aabbMin.w = 0.f;
|
|
aabbMax.x = parseFloat(token);
|
|
aabbMax.y = parseFloat(token);
|
|
aabbMax.z = parseFloat(token);
|
|
aabbMax.w = 0.f;
|
|
|
|
aabbMin *= 0.1;
|
|
aabbMax *= 0.1;
|
|
|
|
b3Vector3 extents = aabbMax - aabbMin;
|
|
|
|
//printf("%s\n", oriptr);
|
|
|
|
b3Vector3 position = 0.5 * (aabbMax + aabbMin);
|
|
b3Quaternion orn(0, 0, 0, 1);
|
|
|
|
b3Vector4 scaling = b3MakeVector4(0.5 * extents.x, 0.5 * extents.y, 0.5 * extents.z, 1); //b3MakeVector4(1,1,1,1);
|
|
|
|
float l = extents.length();
|
|
if (l > 500)
|
|
{
|
|
b3Vector4 color = b3MakeVector4(0, 1, 0, 0.1);
|
|
int id;
|
|
id = m_guiHelper->getRenderInterface()->registerGraphicsInstance(shapeId, position, orn, color, scaling);
|
|
m_data->m_broadphaseGPU->createLargeProxy(aabbMin, aabbMax, index, group, mask);
|
|
}
|
|
else
|
|
{
|
|
b3Vector4 color = b3MakeVector4(1, 0, 0, 1);
|
|
int id;
|
|
id = m_guiHelper->getRenderInterface()->registerGraphicsInstance(shapeId, position, orn, color, scaling);
|
|
m_data->m_broadphaseGPU->createProxy(aabbMin, aabbMax, index, group, mask);
|
|
index++;
|
|
}
|
|
|
|
patcnt++;
|
|
}
|
|
}
|
|
prefixIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (prefixIndex < 0)
|
|
{
|
|
b3Printf("Cannot find %s\n", gPairBenchFileName);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < arraySizeX; i++)
|
|
{
|
|
for (int j = 0; j < arraySizeY; j++)
|
|
{
|
|
for (int k = 0; k < arraySizeZ; k++)
|
|
{
|
|
b3Vector3 position = b3MakeVector3(k * 3, i * 3, j * 3);
|
|
b3Quaternion orn(0, 0, 0, 1);
|
|
|
|
b3Vector4 color = b3MakeVector4(0, 1, 0, 1);
|
|
b3Vector4 scaling = b3MakeVector4(1, 1, 1, 1);
|
|
bool large = false;
|
|
|
|
if (curUseLargeAabbOption)
|
|
{
|
|
if (i == 0 && j == 0 && k == 0)
|
|
{
|
|
large = true;
|
|
scaling[0] = 1000;
|
|
scaling[1] = 1000;
|
|
scaling[2] = 1000;
|
|
}
|
|
}
|
|
/*if (j==0)
|
|
{
|
|
large=true;
|
|
scaling[1] = 10000;
|
|
}
|
|
if (k==0)
|
|
{
|
|
large=true;
|
|
scaling[2] = 10000;
|
|
}*/
|
|
|
|
int id;
|
|
id = m_guiHelper->getRenderInterface()->registerGraphicsInstance(shapeId, position, orn, color, scaling);
|
|
|
|
b3Vector3 aabbMin = position - scaling;
|
|
b3Vector3 aabbMax = position + scaling;
|
|
|
|
if (large)
|
|
{
|
|
m_data->m_broadphaseGPU->createLargeProxy(aabbMin, aabbMax, index, group, mask);
|
|
}
|
|
else
|
|
{
|
|
m_data->m_broadphaseGPU->createProxy(aabbMin, aabbMax, index, group, mask);
|
|
}
|
|
index++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_guiHelper->getRenderInterface()->writeTransforms();
|
|
m_data->m_broadphaseGPU->writeAabbsToGpu();
|
|
}
|
|
|
|
void PairBench::deleteBroadphase()
|
|
{
|
|
delete m_data->m_broadphaseGPU;
|
|
m_data->m_broadphaseGPU = 0;
|
|
delete m_data->m_instancePosOrnColor;
|
|
m_data->m_instancePosOrnColor = 0;
|
|
delete m_data->m_bodyTimes;
|
|
m_data->m_bodyTimes = 0;
|
|
|
|
m_data->m_broadphaseGPU = 0;
|
|
m_guiHelper->getRenderInterface()->removeAllInstances();
|
|
}
|
|
|
|
void PairBench::exitPhysics()
|
|
{
|
|
//reset the state to 'on'
|
|
useShadowMap = true;
|
|
if (m_data->m_validationBroadphase)
|
|
{
|
|
delete m_data->m_validationBroadphase;
|
|
m_data->m_validationBroadphase = 0;
|
|
}
|
|
|
|
sPairDemo = 0;
|
|
|
|
exitCL();
|
|
}
|
|
|
|
void PairBench::renderScene()
|
|
{
|
|
m_guiHelper->getRenderInterface()->renderScene();
|
|
}
|
|
|
|
struct OverlappingPairSortPredicate
|
|
{
|
|
inline bool operator()(const b3Int4& a, const b3Int4& b) const
|
|
{
|
|
if (a.x != b.x) return (a.x < b.x);
|
|
if (a.y != b.y) return (a.y < b.y);
|
|
if (a.z != b.z) return (a.z < b.z);
|
|
return (a.w < b.w);
|
|
}
|
|
};
|
|
|
|
void PairBench::stepSimulation(float deltaTime)
|
|
{
|
|
//color all objects blue
|
|
|
|
GLInstanceRendererInternalData* internalData = m_guiHelper->getRenderInterface()->getInternalData();
|
|
|
|
if (internalData == 0)
|
|
return;
|
|
|
|
//bool animate=true;
|
|
int numObjects = 0;
|
|
{
|
|
B3_PROFILE("Num Objects");
|
|
numObjects = internalData->m_totalNumInstances;
|
|
}
|
|
b3Vector4* positions = 0;
|
|
if (numObjects)
|
|
{
|
|
B3_PROFILE("Sync");
|
|
GLuint vbo = internalData->m_vbo;
|
|
|
|
int arraySizeInBytes = numObjects * (3) * sizeof(b3Vector4);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
// cl_bool blocking= CL_TRUE;
|
|
char* hostPtr = 0;
|
|
{
|
|
B3_PROFILE("glMapBufferRange");
|
|
hostPtr = (char*)glMapBufferRange(GL_ARRAY_BUFFER, internalData->m_maxShapeCapacityInBytes, arraySizeInBytes, GL_MAP_WRITE_BIT | GL_MAP_READ_BIT); //GL_READ_WRITE);//GL_WRITE_ONLY
|
|
}
|
|
GLint err = glGetError();
|
|
assert(err == GL_NO_ERROR);
|
|
positions = (b3Vector4*)hostPtr;
|
|
|
|
if (m_data->m_instancePosOrnColor && m_data->m_instancePosOrnColor->size() != 3 * numObjects)
|
|
{
|
|
delete m_data->m_instancePosOrnColor;
|
|
m_data->m_instancePosOrnColor = 0;
|
|
}
|
|
if (!m_data->m_instancePosOrnColor)
|
|
{
|
|
m_data->m_instancePosOrnColor = new b3OpenCLArray<b3Vector4>(m_clData->m_clContext, m_clData->m_clQueue);
|
|
m_data->m_instancePosOrnColor->resize(3 * numObjects);
|
|
m_data->m_instancePosOrnColor->copyFromHostPointer(positions, 3 * numObjects, 0);
|
|
m_data->m_bodyTimes = new b3OpenCLArray<float>(m_clData->m_clContext, m_clData->m_clQueue);
|
|
m_data->m_bodyTimes->resize(numObjects);
|
|
b3AlignedObjectArray<float> tmp;
|
|
tmp.resize(numObjects);
|
|
for (int i = 0; i < numObjects; i++)
|
|
{
|
|
tmp[i] = float(i) * (1024.f / numObjects);
|
|
}
|
|
m_data->m_bodyTimes->copyFromHost(tmp);
|
|
}
|
|
|
|
if (!gPairBenchFileName)
|
|
{
|
|
if (1)
|
|
{
|
|
if (1)
|
|
{
|
|
b3LauncherCL launcher(m_clData->m_clQueue, m_data->m_sineWaveKernel, "m_sineWaveKernel");
|
|
launcher.setBuffer(m_data->m_instancePosOrnColor->getBufferCL());
|
|
launcher.setBuffer(m_data->m_bodyTimes->getBufferCL());
|
|
|
|
launcher.setConst(timeStepPos);
|
|
launcher.setConst(mAmplitude);
|
|
launcher.setConst(numObjects);
|
|
launcher.launch1D(numObjects);
|
|
clFinish(m_clData->m_clQueue);
|
|
}
|
|
else
|
|
{
|
|
b3LauncherCL launcher(m_clData->m_clQueue, m_data->m_moveObjectsKernel, "m_moveObjectsKernel");
|
|
launcher.setBuffer(m_data->m_instancePosOrnColor->getBufferCL());
|
|
launcher.setConst(numObjects);
|
|
launcher.launch1D(numObjects);
|
|
clFinish(m_clData->m_clQueue);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool updateOnGpu = true;
|
|
|
|
if (1)
|
|
{
|
|
if (updateOnGpu)
|
|
{
|
|
B3_PROFILE("updateOnGpu");
|
|
b3LauncherCL launcher(m_clData->m_clQueue, m_data->m_updateAabbSimple, "m_updateAabbSimple");
|
|
launcher.setBuffer(m_data->m_instancePosOrnColor->getBufferCL());
|
|
launcher.setConst(numObjects);
|
|
launcher.setBuffer(m_data->m_broadphaseGPU->getAabbBufferWS());
|
|
launcher.launch1D(numObjects);
|
|
clFinish(m_clData->m_clQueue);
|
|
}
|
|
else
|
|
{
|
|
B3_PROFILE("updateOnCpu");
|
|
if (!gPairBenchFileName)
|
|
{
|
|
// int allAabbs = m_data->m_broadphaseGPU->getAllAabbsCPU().size();
|
|
|
|
b3AlignedObjectArray<b3Vector4> posOrnColorsCpu;
|
|
if (m_data->m_instancePosOrnColor)
|
|
m_data->m_instancePosOrnColor->copyToHost(posOrnColorsCpu);
|
|
|
|
for (int nodeId = 0; nodeId < numObjects; nodeId++)
|
|
{
|
|
{
|
|
b3Vector3 position = posOrnColorsCpu[nodeId];
|
|
|
|
b3SapAabb orgAabb = m_data->m_broadphaseGPU->getAllAabbsCPU()[nodeId];
|
|
b3Vector3 halfExtents = 0.5f * (orgAabb.m_maxVec - orgAabb.m_minVec);
|
|
int orgNodeIndex = orgAabb.m_minIndices[3];
|
|
int orgBroadphaseIndex = orgAabb.m_signedMaxIndices[3];
|
|
|
|
m_data->m_broadphaseGPU->getAllAabbsCPU()[nodeId].m_minVec = position - halfExtents;
|
|
m_data->m_broadphaseGPU->getAllAabbsCPU()[nodeId].m_minIndices[3] = orgNodeIndex;
|
|
m_data->m_broadphaseGPU->getAllAabbsCPU()[nodeId].m_maxVec = position + halfExtents;
|
|
m_data->m_broadphaseGPU->getAllAabbsCPU()[nodeId].m_signedMaxIndices[3] = orgBroadphaseIndex;
|
|
}
|
|
}
|
|
m_data->m_broadphaseGPU->writeAabbsToGpu();
|
|
}
|
|
}
|
|
}
|
|
|
|
int prealloc = 3 * 1024 * 1024;
|
|
int maxOverlap = b3Min(prealloc, 16 * numObjects);
|
|
|
|
unsigned long dt = 0;
|
|
if (numObjects)
|
|
{
|
|
b3Clock cl;
|
|
dt = cl.getTimeMicroseconds();
|
|
B3_PROFILE("calculateOverlappingPairs");
|
|
//int sz = sizeof(b3Int4)*64*numObjects;
|
|
|
|
m_data->m_broadphaseGPU->calculateOverlappingPairs(maxOverlap);
|
|
int numPairs;
|
|
numPairs = m_data->m_broadphaseGPU->getNumOverlap();
|
|
//printf("numPairs = %d\n", numPairs);
|
|
dt = cl.getTimeMicroseconds() - dt;
|
|
}
|
|
|
|
const bool VALIDATE_BROADPHASE = false; //Check that overlapping pairs of 2 broadphases are the same
|
|
if (numObjects && VALIDATE_BROADPHASE)
|
|
{
|
|
B3_PROFILE("validate broadphases");
|
|
|
|
{
|
|
B3_PROFILE("calculateOverlappingPairs m_validationBroadphase");
|
|
//m_data->m_validationBroadphase->getAllAabbsCPU() = m_data->m_broadphaseGPU->getAllAabbsCPU();
|
|
|
|
m_data->m_validationBroadphase->getAllAabbsGPU().copyFromOpenCLArray(m_data->m_broadphaseGPU->getAllAabbsGPU());
|
|
m_data->m_validationBroadphase->getSmallAabbIndicesGPU().copyFromOpenCLArray(m_data->m_broadphaseGPU->getSmallAabbIndicesGPU());
|
|
m_data->m_validationBroadphase->getLargeAabbIndicesGPU().copyFromOpenCLArray(m_data->m_broadphaseGPU->getLargeAabbIndicesGPU());
|
|
|
|
m_data->m_validationBroadphase->calculateOverlappingPairs(maxOverlap);
|
|
}
|
|
|
|
static b3AlignedObjectArray<b3Int4> overlappingPairs;
|
|
static b3AlignedObjectArray<b3Int4> overlappingPairsReference;
|
|
m_data->m_broadphaseGPU->getOverlappingPairsGPU().copyToHost(overlappingPairs);
|
|
m_data->m_validationBroadphase->getOverlappingPairsGPU().copyToHost(overlappingPairsReference);
|
|
|
|
//Reorder pairs so that (pair.x < pair.y) is always true
|
|
{
|
|
B3_PROFILE("reorder pairs");
|
|
|
|
for (int i = 0; i < overlappingPairs.size(); ++i)
|
|
{
|
|
b3Int4 pair = overlappingPairs[i];
|
|
if (pair.x > pair.y)
|
|
{
|
|
b3Swap(pair.x, pair.y);
|
|
b3Swap(pair.z, pair.w);
|
|
overlappingPairs[i] = pair;
|
|
}
|
|
}
|
|
for (int i = 0; i < overlappingPairsReference.size(); ++i)
|
|
{
|
|
b3Int4 pair = overlappingPairsReference[i];
|
|
if (pair.x > pair.y)
|
|
{
|
|
b3Swap(pair.x, pair.y);
|
|
b3Swap(pair.z, pair.w);
|
|
overlappingPairsReference[i] = pair;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
{
|
|
B3_PROFILE("Sort overlapping pairs from most to least significant bit");
|
|
|
|
overlappingPairs.quickSort(OverlappingPairSortPredicate());
|
|
overlappingPairsReference.quickSort(OverlappingPairSortPredicate());
|
|
}
|
|
|
|
//Compare
|
|
{
|
|
B3_PROFILE("compare pairs");
|
|
|
|
int numPairs = overlappingPairs.size();
|
|
int numPairsReference = overlappingPairsReference.size();
|
|
|
|
bool success = true;
|
|
|
|
if (numPairs == numPairsReference)
|
|
{
|
|
for (int i = 0; i < numPairsReference; ++i)
|
|
{
|
|
const b3Int4& pairA = overlappingPairs[i];
|
|
const b3Int4& pairB = overlappingPairsReference[i];
|
|
if (pairA.x != pairB.x || pairA.y != pairB.y || pairA.z != pairB.z || pairA.w != pairB.w)
|
|
{
|
|
b3Error("Error: one or more overlappingPairs differs from reference.\n");
|
|
success = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
b3Error("Error: numPairs %d != numPairsReference %d \n", numPairs, numPairsReference);
|
|
success = false;
|
|
}
|
|
|
|
printf("Broadphase validation: %d \n", success);
|
|
}
|
|
}
|
|
|
|
/*
|
|
if (m_data->m_gui)
|
|
{
|
|
B3_PROFILE("update Gui");
|
|
int allAabbs = m_data->m_broadphaseGPU->getAllAabbsCPU().size();
|
|
int numOverlap = m_data->m_broadphaseGPU->getNumOverlap();
|
|
|
|
float time = dt/1000.f;
|
|
//printf("time = %f\n", time);
|
|
|
|
char msg[1024];
|
|
sprintf(msg,"#objects = %d, #overlapping pairs = %d, time = %f ms", allAabbs,numOverlap,time );
|
|
//printf("msg=%s\n",msg);
|
|
m_data->m_gui->setStatusBarMessage(msg,true);
|
|
}
|
|
*/
|
|
|
|
if (numObjects)
|
|
{
|
|
B3_PROFILE("animate");
|
|
GLint err = glGetError();
|
|
assert(err == GL_NO_ERROR);
|
|
//color overlapping objects in red
|
|
|
|
if (m_data->m_broadphaseGPU->getNumOverlap())
|
|
{
|
|
bool colorPairsOnHost = false;
|
|
if (colorPairsOnHost)
|
|
{
|
|
}
|
|
else
|
|
{
|
|
int numPairs = m_data->m_broadphaseGPU->getNumOverlap();
|
|
cl_mem pairBuf = m_data->m_broadphaseGPU->getOverlappingPairBuffer();
|
|
|
|
b3LauncherCL launcher(m_clData->m_clQueue, m_data->m_colorPairsKernel, "m_colorPairsKernel");
|
|
launcher.setBuffer(m_data->m_instancePosOrnColor->getBufferCL());
|
|
launcher.setConst(numObjects);
|
|
launcher.setBuffer(pairBuf);
|
|
int indexOffset = TEST_INDEX_OFFSET;
|
|
launcher.setConst(indexOffset);
|
|
launcher.setConst(numPairs);
|
|
launcher.launch1D(numPairs);
|
|
clFinish(m_clData->m_clQueue);
|
|
}
|
|
}
|
|
|
|
if (numObjects)
|
|
{
|
|
m_data->m_instancePosOrnColor->copyToHostPointer(positions, 3 * numObjects, 0);
|
|
}
|
|
|
|
glUnmapBuffer(GL_ARRAY_BUFFER);
|
|
err = glGetError();
|
|
assert(err == GL_NO_ERROR);
|
|
}
|
|
}
|
|
|
|
class CommonExampleInterface* PairBenchOpenCLCreateFunc(struct CommonExampleOptions& options)
|
|
{
|
|
return new PairBench(options.m_guiHelper);
|
|
}
|