more bt* to b3*

This commit is contained in:
erwin coumans
2013-04-16 17:08:59 -07:00
parent faabffc23d
commit e646754228
116 changed files with 2466 additions and 3034 deletions

View File

@@ -2,7 +2,7 @@
#include "b3GpuBatchingPgsSolver.h"
#include "../../parallel_primitives/host/btRadixSort32CL.h"
#include "BulletCommon/btQuickprof.h"
#include "BulletCommon/b3Quickprof.h"
#include "../../parallel_primitives/host/btLauncherCL.h"
#include "../../parallel_primitives/host/btBoundSearchCL.h"
#include "../../parallel_primitives/host/btPrefixScanCL.h"
@@ -76,9 +76,9 @@ struct btGpuBatchingPgsSolverInternalData
btOpenCLArray<b3Contact4>* m_pBufContactOutGPU;
btAlignedObjectArray<unsigned int> m_idxBuffer;
btAlignedObjectArray<btSortData> m_sortData;
btAlignedObjectArray<b3Contact4> m_old;
b3AlignedObjectArray<unsigned int> m_idxBuffer;
b3AlignedObjectArray<btSortData> m_sortData;
b3AlignedObjectArray<b3Contact4> m_old;
};
@@ -519,7 +519,7 @@ void b3GpuBatchingPgsSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem
btOpenCLArray<btSortData>& keyValuesInOut = *(m_data->m_solverGPU->m_sortDataBuffer);
this->m_data->m_solverGPU->m_sort32->execute(keyValuesInOut);
/*btAlignedObjectArray<btSortData> hostValues;
/*b3AlignedObjectArray<btSortData> hostValues;
keyValuesInOut.copyToHost(hostValues);
printf("hostValues.size=%d\n",hostValues.size());
*/
@@ -596,15 +596,15 @@ void b3GpuBatchingPgsSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem
} else
{
BT_PROFILE("cpu batchContacts");
btAlignedObjectArray<b3Contact4> cpuContacts;
b3AlignedObjectArray<b3Contact4> cpuContacts;
btOpenCLArray<b3Contact4>* contactsIn = m_data->m_solverGPU->m_contactBuffer2;
contactsIn->copyToHost(cpuContacts);
btOpenCLArray<unsigned int>* countsNative = m_data->m_solverGPU->m_numConstraints;
btOpenCLArray<unsigned int>* offsetsNative = m_data->m_solverGPU->m_offsets;
btAlignedObjectArray<unsigned int> nNativeHost;
btAlignedObjectArray<unsigned int> offsetsNativeHost;
b3AlignedObjectArray<unsigned int> nNativeHost;
b3AlignedObjectArray<unsigned int> offsetsNativeHost;
{
BT_PROFILE("countsNative/offsetsNative copyToHost");
@@ -641,7 +641,7 @@ void b3GpuBatchingPgsSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem
}
{
BT_PROFILE("m_contactBuffer->copyFromHost");
m_data->m_solverGPU->m_contactBuffer2->copyFromHost((btAlignedObjectArray<b3Contact4>&)cpuContacts);
m_data->m_solverGPU->m_contactBuffer2->copyFromHost((b3AlignedObjectArray<b3Contact4>&)cpuContacts);
}
}
@@ -724,19 +724,19 @@ static bool sortfnc(const btSortData& a,const btSortData& b)
btAlignedObjectArray<int> bodyUsed;
b3AlignedObjectArray<int> bodyUsed;
btAlignedObjectArray<unsigned int> idxBuffer;
btAlignedObjectArray<btSortData> sortData;
btAlignedObjectArray<b3Contact4> old;
b3AlignedObjectArray<unsigned int> idxBuffer;
b3AlignedObjectArray<btSortData> sortData;
b3AlignedObjectArray<b3Contact4> old;
inline int b3GpuBatchingPgsSolver::sortConstraintByBatch( b3Contact4* cs, int n, int simdWidth , int staticIdx, int numBodies)
{
btAlignedObjectArray<int> bodyUsed;
b3AlignedObjectArray<int> bodyUsed;
bodyUsed.resize(numBodies);
for (int q=0;q<numBodies;q++)
bodyUsed[q]=0;

View File

@@ -1,15 +1,15 @@
#ifndef BT_CONSTRAINT4_h
#define BT_CONSTRAINT4_h
#include "BulletCommon/btVector3.h"
#include "BulletCommon/b3Vector3.h"
ATTRIBUTE_ALIGNED16(struct) b3GpuConstraint4
{
BT_DECLARE_ALIGNED_ALLOCATOR();
btVector3 m_linear;//normal?
btVector3 m_worldPos[4];
btVector3 m_center; // friction
b3Vector3 m_linear;//normal?
b3Vector3 m_worldPos[4];
b3Vector3 m_center; // friction
float m_jacCoeffInv[4];
float m_b[4];
float m_appliedRambdaDt[4];

View File

@@ -13,57 +13,57 @@
struct btGpuNarrowPhaseInternalData
{
btAlignedObjectArray<b3ConvexUtility*>* m_convexData;
b3AlignedObjectArray<b3ConvexUtility*>* m_convexData;
btAlignedObjectArray<b3ConvexPolyhedronCL> m_convexPolyhedra;
btAlignedObjectArray<btVector3> m_uniqueEdges;
btAlignedObjectArray<btVector3> m_convexVertices;
btAlignedObjectArray<int> m_convexIndices;
b3AlignedObjectArray<b3ConvexPolyhedronCL> m_convexPolyhedra;
b3AlignedObjectArray<b3Vector3> m_uniqueEdges;
b3AlignedObjectArray<b3Vector3> m_convexVertices;
b3AlignedObjectArray<int> m_convexIndices;
btOpenCLArray<b3ConvexPolyhedronCL>* m_convexPolyhedraGPU;
btOpenCLArray<btVector3>* m_uniqueEdgesGPU;
btOpenCLArray<btVector3>* m_convexVerticesGPU;
btOpenCLArray<b3Vector3>* m_uniqueEdgesGPU;
btOpenCLArray<b3Vector3>* m_convexVerticesGPU;
btOpenCLArray<int>* m_convexIndicesGPU;
btOpenCLArray<btVector3>* m_worldVertsB1GPU;
btOpenCLArray<b3Vector3>* m_worldVertsB1GPU;
btOpenCLArray<btInt4>* m_clippingFacesOutGPU;
btOpenCLArray<btVector3>* m_worldNormalsAGPU;
btOpenCLArray<btVector3>* m_worldVertsA1GPU;
btOpenCLArray<btVector3>* m_worldVertsB2GPU;
btOpenCLArray<b3Vector3>* m_worldNormalsAGPU;
btOpenCLArray<b3Vector3>* m_worldVertsA1GPU;
btOpenCLArray<b3Vector3>* m_worldVertsB2GPU;
btAlignedObjectArray<btGpuChildShape> m_cpuChildShapes;
b3AlignedObjectArray<btGpuChildShape> m_cpuChildShapes;
btOpenCLArray<btGpuChildShape>* m_gpuChildShapes;
btAlignedObjectArray<btGpuFace> m_convexFaces;
b3AlignedObjectArray<btGpuFace> m_convexFaces;
btOpenCLArray<btGpuFace>* m_convexFacesGPU;
GpuSatCollision* m_gpuSatCollision;
btAlignedObjectArray<btInt2>* m_pBufPairsCPU;
b3AlignedObjectArray<btInt2>* m_pBufPairsCPU;
btOpenCLArray<btInt2>* m_convexPairsOutGPU;
btOpenCLArray<btInt2>* m_planePairs;
btOpenCLArray<b3Contact4>* m_pBufContactOutGPU;
btAlignedObjectArray<b3Contact4>* m_pBufContactOutCPU;
b3AlignedObjectArray<b3Contact4>* m_pBufContactOutCPU;
btAlignedObjectArray<b3RigidBodyCL>* m_bodyBufferCPU;
b3AlignedObjectArray<b3RigidBodyCL>* m_bodyBufferCPU;
btOpenCLArray<b3RigidBodyCL>* m_bodyBufferGPU;
btAlignedObjectArray<btInertiaCL>* m_inertiaBufferCPU;
b3AlignedObjectArray<btInertiaCL>* m_inertiaBufferCPU;
btOpenCLArray<btInertiaCL>* m_inertiaBufferGPU;
int m_numAcceleratedShapes;
int m_numAcceleratedRigidBodies;
btAlignedObjectArray<b3Collidable> m_collidablesCPU;
b3AlignedObjectArray<b3Collidable> m_collidablesCPU;
btOpenCLArray<b3Collidable>* m_collidablesGPU;
btOpenCLArray<b3SapAabb>* m_localShapeAABBGPU;
btAlignedObjectArray<b3SapAabb>* m_localShapeAABBCPU;
b3AlignedObjectArray<b3SapAabb>* m_localShapeAABBCPU;
btAlignedObjectArray<class b3OptimizedBvh*> m_bvhData;
b3AlignedObjectArray<class b3OptimizedBvh*> m_bvhData;
btOpenCLArray<btQuantizedBvhNode>* m_treeNodesGPU;
btOpenCLArray<btBvhSubtreeInfo>* m_subTreesGPU;
@@ -89,18 +89,18 @@ m_queue(queue)
m_data->m_config = config;
m_data->m_gpuSatCollision = new GpuSatCollision(ctx,device,queue);
m_data->m_pBufPairsCPU = new btAlignedObjectArray<btInt2>;
m_data->m_pBufPairsCPU = new b3AlignedObjectArray<btInt2>;
m_data->m_pBufPairsCPU->resize(config.m_maxBroadphasePairs);
m_data->m_convexPairsOutGPU = new btOpenCLArray<btInt2>(ctx,queue,config.m_maxBroadphasePairs,false);
m_data->m_planePairs = new btOpenCLArray<btInt2>(ctx,queue,config.m_maxBroadphasePairs,false);
m_data->m_pBufContactOutCPU = new btAlignedObjectArray<b3Contact4>();
m_data->m_pBufContactOutCPU = new b3AlignedObjectArray<b3Contact4>();
m_data->m_pBufContactOutCPU->resize(config.m_maxBroadphasePairs);
m_data->m_bodyBufferCPU = new btAlignedObjectArray<b3RigidBodyCL>();
m_data->m_bodyBufferCPU = new b3AlignedObjectArray<b3RigidBodyCL>();
m_data->m_bodyBufferCPU->resize(config.m_maxConvexBodies);
m_data->m_inertiaBufferCPU = new btAlignedObjectArray<btInertiaCL>();
m_data->m_inertiaBufferCPU = new b3AlignedObjectArray<btInertiaCL>();
m_data->m_inertiaBufferCPU->resize(config.m_maxConvexBodies);
m_data->m_pBufContactOutGPU = new btOpenCLArray<b3Contact4>(ctx,queue, config.m_maxContactCapacity,true);
@@ -108,7 +108,7 @@ m_queue(queue)
m_data->m_inertiaBufferGPU = new btOpenCLArray<btInertiaCL>(ctx,queue,config.m_maxConvexBodies,false);
m_data->m_collidablesGPU = new btOpenCLArray<b3Collidable>(ctx,queue,config.m_maxConvexShapes);
m_data->m_localShapeAABBCPU = new btAlignedObjectArray<b3SapAabb>;
m_data->m_localShapeAABBCPU = new b3AlignedObjectArray<b3SapAabb>;
m_data->m_localShapeAABBGPU = new btOpenCLArray<b3SapAabb>(ctx,queue,config.m_maxConvexShapes);
@@ -119,20 +119,20 @@ m_queue(queue)
m_data->m_gpuChildShapes = new btOpenCLArray<btGpuChildShape>(ctx,queue,config.m_maxCompoundChildShapes,false);
m_data->m_convexPolyhedraGPU = new btOpenCLArray<b3ConvexPolyhedronCL>(ctx,queue,config.m_maxConvexShapes,false);
m_data->m_uniqueEdgesGPU = new btOpenCLArray<btVector3>(ctx,queue,config.m_maxConvexUniqueEdges,true);
m_data->m_convexVerticesGPU = new btOpenCLArray<btVector3>(ctx,queue,config.m_maxConvexVertices,true);
m_data->m_uniqueEdgesGPU = new btOpenCLArray<b3Vector3>(ctx,queue,config.m_maxConvexUniqueEdges,true);
m_data->m_convexVerticesGPU = new btOpenCLArray<b3Vector3>(ctx,queue,config.m_maxConvexVertices,true);
m_data->m_convexIndicesGPU = new btOpenCLArray<int>(ctx,queue,config.m_maxConvexIndices,true);
m_data->m_worldVertsB1GPU = new btOpenCLArray<btVector3>(ctx,queue,config.m_maxConvexBodies*config.m_maxVerticesPerFace);
m_data->m_worldVertsB1GPU = new btOpenCLArray<b3Vector3>(ctx,queue,config.m_maxConvexBodies*config.m_maxVerticesPerFace);
m_data->m_clippingFacesOutGPU = new btOpenCLArray<btInt4>(ctx,queue,config.m_maxConvexBodies);
m_data->m_worldNormalsAGPU = new btOpenCLArray<btVector3>(ctx,queue,config.m_maxConvexBodies);
m_data->m_worldVertsA1GPU = new btOpenCLArray<btVector3>(ctx,queue,config.m_maxConvexBodies*config.m_maxVerticesPerFace);
m_data->m_worldVertsB2GPU = new btOpenCLArray<btVector3>(ctx,queue,config.m_maxConvexBodies*config.m_maxVerticesPerFace);
m_data->m_worldNormalsAGPU = new btOpenCLArray<b3Vector3>(ctx,queue,config.m_maxConvexBodies);
m_data->m_worldVertsA1GPU = new btOpenCLArray<b3Vector3>(ctx,queue,config.m_maxConvexBodies*config.m_maxVerticesPerFace);
m_data->m_worldVertsB2GPU = new btOpenCLArray<b3Vector3>(ctx,queue,config.m_maxConvexBodies*config.m_maxVerticesPerFace);
m_data->m_convexData = new btAlignedObjectArray<b3ConvexUtility* >();
m_data->m_convexData = new b3AlignedObjectArray<b3ConvexUtility* >();
m_data->m_convexData->resize(config.m_maxConvexShapes);
@@ -209,8 +209,8 @@ int b3GpuNarrowPhase::registerSphereShape(float radius)
if (col.m_shapeIndex>=0)
{
b3SapAabb aabb;
btVector3 myAabbMin(-radius,-radius,-radius);
btVector3 myAabbMax(radius,radius,radius);
b3Vector3 myAabbMin(-radius,-radius,-radius);
b3Vector3 myAabbMax(radius,radius,radius);
aabb.m_min[0] = myAabbMin[0];//s_convexHeightField->m_aabb.m_min.x;
aabb.m_min[1] = myAabbMin[1];//s_convexHeightField->m_aabb.m_min.y;
@@ -231,7 +231,7 @@ int b3GpuNarrowPhase::registerSphereShape(float radius)
}
int b3GpuNarrowPhase::registerFace(const btVector3& faceNormal, float faceConstant)
int b3GpuNarrowPhase::registerFace(const b3Vector3& faceNormal, float faceConstant)
{
int faceOffset = m_data->m_convexFaces.size();
btGpuFace& face = m_data->m_convexFaces.expand();
@@ -243,7 +243,7 @@ int b3GpuNarrowPhase::registerFace(const btVector3& faceNormal, float faceConsta
return faceOffset;
}
int b3GpuNarrowPhase::registerPlaneShape(const btVector3& planeNormal, float planeConstant)
int b3GpuNarrowPhase::registerPlaneShape(const b3Vector3& planeNormal, float planeConstant)
{
int collidableIndex = allocateCollidable();
@@ -346,13 +346,13 @@ int b3GpuNarrowPhase::registerConvexHullShape(b3ConvexUtility* convexPtr,b3Colli
int b3GpuNarrowPhase::registerConvexHullShape(const float* vertices, int strideInBytes, int numVertices, const float* scaling)
{
btAlignedObjectArray<btVector3> verts;
b3AlignedObjectArray<b3Vector3> verts;
unsigned char* vts = (unsigned char*) vertices;
for (int i=0;i<numVertices;i++)
{
float* vertex = (float*) &vts[i*strideInBytes];
verts.push_back(btVector3(vertex[0]*scaling[0],vertex[1]*scaling[1],vertex[2]*scaling[2]));
verts.push_back(b3Vector3(vertex[0]*scaling[0],vertex[1]*scaling[1],vertex[2]*scaling[2]));
}
b3ConvexUtility* utilPtr = new b3ConvexUtility();
@@ -375,7 +375,7 @@ int b3GpuNarrowPhase::registerConvexHullShape(b3ConvexUtility* utilPtr)
{
btVector3 localCenter(0,0,0);
b3Vector3 localCenter(0,0,0);
for (int i=0;i<utilPtr->m_vertices.size();i++)
localCenter+=utilPtr->m_vertices[i];
localCenter*= (1.f/utilPtr->m_vertices.size());
@@ -388,8 +388,8 @@ int b3GpuNarrowPhase::registerConvexHullShape(b3ConvexUtility* utilPtr)
{
b3SapAabb aabb;
btVector3 myAabbMin(1e30f,1e30f,1e30f);
btVector3 myAabbMax(-1e30f,-1e30f,-1e30f);
b3Vector3 myAabbMin(1e30f,1e30f,1e30f);
b3Vector3 myAabbMax(-1e30f,-1e30f,-1e30f);
for (int i=0;i<utilPtr->m_vertices.size();i++)
{
@@ -414,7 +414,7 @@ int b3GpuNarrowPhase::registerConvexHullShape(b3ConvexUtility* utilPtr)
}
int b3GpuNarrowPhase::registerCompoundShape(btAlignedObjectArray<btGpuChildShape>* childShapes)
int b3GpuNarrowPhase::registerCompoundShape(b3AlignedObjectArray<btGpuChildShape>* childShapes)
{
int collidableIndex = allocateCollidable();
@@ -438,8 +438,8 @@ int b3GpuNarrowPhase::registerCompoundShape(btAlignedObjectArray<btGpuChildShap
b3SapAabb aabbWS;
btVector3 myAabbMin(1e30f,1e30f,1e30f);
btVector3 myAabbMax(-1e30f,-1e30f,-1e30f);
b3Vector3 myAabbMin(1e30f,1e30f,1e30f);
b3Vector3 myAabbMax(-1e30f,-1e30f,-1e30f);
//compute local AABB of the compound of all children
for (int i=0;i<childShapes->size();i++)
@@ -448,17 +448,17 @@ int b3GpuNarrowPhase::registerCompoundShape(btAlignedObjectArray<btGpuChildShap
b3Collidable& childCol = getCollidableCpu(childColIndex);
b3SapAabb aabbLoc =m_data->m_localShapeAABBCPU->at(childColIndex);
btVector3 childLocalAabbMin(aabbLoc.m_min[0],aabbLoc.m_min[1],aabbLoc.m_min[2]);
btVector3 childLocalAabbMax(aabbLoc.m_max[0],aabbLoc.m_max[1],aabbLoc.m_max[2]);
btVector3 aMin,aMax;
btScalar margin(0.f);
btTransform childTr;
b3Vector3 childLocalAabbMin(aabbLoc.m_min[0],aabbLoc.m_min[1],aabbLoc.m_min[2]);
b3Vector3 childLocalAabbMax(aabbLoc.m_max[0],aabbLoc.m_max[1],aabbLoc.m_max[2]);
b3Vector3 aMin,aMax;
b3Scalar margin(0.f);
b3Transform childTr;
childTr.setIdentity();
childTr.setOrigin(btVector3(childShapes->at(i).m_childPosition[0],
childTr.setOrigin(b3Vector3(childShapes->at(i).m_childPosition[0],
childShapes->at(i).m_childPosition[1],
childShapes->at(i).m_childPosition[2]));
childTr.setRotation(btQuaternion(childShapes->at(i).m_childOrientation[0],
childTr.setRotation(b3Quaternion(childShapes->at(i).m_childOrientation[0],
childShapes->at(i).m_childOrientation[1],
childShapes->at(i).m_childOrientation[2],
childShapes->at(i).m_childOrientation[3]));
@@ -485,7 +485,7 @@ int b3GpuNarrowPhase::registerCompoundShape(btAlignedObjectArray<btGpuChildShap
}
int b3GpuNarrowPhase::registerConcaveMesh(btAlignedObjectArray<btVector3>* vertices, btAlignedObjectArray<int>* indices,const float* scaling1)
int b3GpuNarrowPhase::registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices,const float* scaling1)
{
//right now we only support one single mesh, it is on the todo to merge all mesh data etc
btAssert(m_data->m_treeNodesGPU ==0);
@@ -496,7 +496,7 @@ int b3GpuNarrowPhase::registerConcaveMesh(btAlignedObjectArray<btVector3>* vert
exit (0);
}
btVector3 scaling(scaling1[0],scaling1[1],scaling1[2]);
b3Vector3 scaling(scaling1[0],scaling1[1],scaling1[2]);
int collidableIndex = allocateCollidable();
b3Collidable& col = getCollidableCpu(collidableIndex);
@@ -507,12 +507,12 @@ int b3GpuNarrowPhase::registerConcaveMesh(btAlignedObjectArray<btVector3>* vert
b3SapAabb aabb;
btVector3 myAabbMin(1e30f,1e30f,1e30f);
btVector3 myAabbMax(-1e30f,-1e30f,-1e30f);
b3Vector3 myAabbMin(1e30f,1e30f,1e30f);
b3Vector3 myAabbMax(-1e30f,-1e30f,-1e30f);
for (int i=0;i<vertices->size();i++)
{
btVector3 vtx(vertices->at(i)*scaling);
b3Vector3 vtx(vertices->at(i)*scaling);
myAabbMin.setMin(vtx);
myAabbMax.setMax(vtx);
}
@@ -530,7 +530,7 @@ int b3GpuNarrowPhase::registerConcaveMesh(btAlignedObjectArray<btVector3>* vert
m_data->m_localShapeAABBGPU->push_back(aabb);
b3OptimizedBvh* bvh = new b3OptimizedBvh();
//void b3OptimizedBvh::build(b3StridingMeshInterface* triangles, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax)
//void b3OptimizedBvh::build(b3StridingMeshInterface* triangles, bool useQuantizedAabbCompression, const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax)
bool useQuantizedAabbCompression = true;
b3TriangleIndexVertexArray* meshInterface=new b3TriangleIndexVertexArray();
@@ -538,12 +538,12 @@ int b3GpuNarrowPhase::registerConcaveMesh(btAlignedObjectArray<btVector3>* vert
mesh.m_numTriangles = indices->size()/3;
mesh.m_numVertices = vertices->size();
mesh.m_vertexBase = (const unsigned char *)&vertices->at(0).getX();
mesh.m_vertexStride = sizeof(btVector3);
mesh.m_vertexStride = sizeof(b3Vector3);
mesh.m_triangleIndexStride = 3 * sizeof(int);// or sizeof(int)
mesh.m_triangleIndexBase = (const unsigned char *)&indices->at(0);
meshInterface->addIndexedMesh(mesh);
bvh->build(meshInterface, useQuantizedAabbCompression, (btVector3&)aabb.m_min, (btVector3&)aabb.m_max);
bvh->build(meshInterface, useQuantizedAabbCompression, (b3Vector3&)aabb.m_min, (b3Vector3&)aabb.m_max);
m_data->m_bvhData.push_back(bvh);
int numNodes = bvh->getQuantizedNodeArray().size();
btOpenCLArray<btQuantizedBvhNode>* treeNodesGPU = new btOpenCLArray<btQuantizedBvhNode>(this->m_context,this->m_queue,numNodes);
@@ -560,21 +560,21 @@ int b3GpuNarrowPhase::registerConcaveMesh(btAlignedObjectArray<btVector3>* vert
return collidableIndex;
}
int b3GpuNarrowPhase::registerConcaveMeshShape(btAlignedObjectArray<btVector3>* vertices, btAlignedObjectArray<int>* indices,b3Collidable& col, const float* scaling1)
int b3GpuNarrowPhase::registerConcaveMeshShape(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices,b3Collidable& col, const float* scaling1)
{
btVector3 scaling(scaling1[0],scaling1[1],scaling1[2]);
b3Vector3 scaling(scaling1[0],scaling1[1],scaling1[2]);
m_data->m_convexData->resize(m_data->m_numAcceleratedShapes+1);
m_data->m_convexPolyhedra.resize(m_data->m_numAcceleratedShapes+1);
b3ConvexPolyhedronCL& convex = m_data->m_convexPolyhedra.at(m_data->m_convexPolyhedra.size()-1);
convex.mC = btVector3(0,0,0);
convex.mE = btVector3(0,0,0);
convex.m_extents= btVector3(0,0,0);
convex.m_localCenter = btVector3(0,0,0);
convex.mC = b3Vector3(0,0,0);
convex.mE = b3Vector3(0,0,0);
convex.m_extents= b3Vector3(0,0,0);
convex.m_localCenter = b3Vector3(0,0,0);
convex.m_radius = 0.f;
convex.m_numUniqueEdges = 0;
@@ -593,12 +593,12 @@ int b3GpuNarrowPhase::registerConcaveMeshShape(btAlignedObjectArray<btVector3>*
{
//printf("i=%d out of %d", i,convex.m_numFaces);
}
btVector3 vert0(vertices->at(indices->at(i*3))*scaling);
btVector3 vert1(vertices->at(indices->at(i*3+1))*scaling);
btVector3 vert2(vertices->at(indices->at(i*3+2))*scaling);
b3Vector3 vert0(vertices->at(indices->at(i*3))*scaling);
b3Vector3 vert1(vertices->at(indices->at(i*3+1))*scaling);
b3Vector3 vert2(vertices->at(indices->at(i*3+2))*scaling);
btVector3 normal = ((vert1-vert0).cross(vert2-vert0)).normalize();
btScalar c = -(normal.dot(vert0));
b3Vector3 normal = ((vert1-vert0).cross(vert2-vert0)).normalize();
b3Scalar c = -(normal.dot(vert0));
m_data->m_convexFaces[convex.m_faceOffset+i].m_plane[0] = normal.getX();
m_data->m_convexFaces[convex.m_faceOffset+i].m_plane[1] = normal.getY();
@@ -753,8 +753,8 @@ const b3SapAabb& b3GpuNarrowPhase::getLocalSpaceAabb(int collidableIndex) const
int b3GpuNarrowPhase::registerRigidBody(int collidableIndex, float mass, const float* position, const float* orientation , const float* aabbMinPtr, const float* aabbMaxPtr,bool writeToGpu)
{
btVector3 aabbMin(aabbMinPtr[0],aabbMinPtr[1],aabbMinPtr[2]);
btVector3 aabbMax (aabbMaxPtr[0],aabbMaxPtr[1],aabbMaxPtr[2]);
b3Vector3 aabbMin(aabbMinPtr[0],aabbMinPtr[1],aabbMinPtr[2]);
b3Vector3 aabbMax (aabbMaxPtr[0],aabbMaxPtr[1],aabbMaxPtr[2]);
btAssert(m_data->m_numAcceleratedRigidBodies< (m_data->m_config.m_maxConvexBodies-1));
@@ -807,9 +807,9 @@ int b3GpuNarrowPhase::registerRigidBody(int collidableIndex, float mass, const f
//approximate using the aabb of the shape
//Aabb aabb = (*m_data->m_shapePointers)[shapeIndex]->m_aabb;
btVector3 halfExtents = (aabbMax-aabbMin);//*0.5f;//fake larger inertia makes demos more stable ;-)
b3Vector3 halfExtents = (aabbMax-aabbMin);//*0.5f;//fake larger inertia makes demos more stable ;-)
btVector3 localInertia;
b3Vector3 localInertia;
float lx=2.f*halfExtents[0];
float ly=2.f*halfExtents[1];
@@ -819,7 +819,7 @@ int b3GpuNarrowPhase::registerRigidBody(int collidableIndex, float mass, const f
(mass/12.0f) * (lx*lx + lz*lz),
(mass/12.0f) * (lx*lx + ly*ly));
btVector3 invLocalInertia;
b3Vector3 invLocalInertia;
invLocalInertia[0] = 1.f/localInertia[0];
invLocalInertia[1] = 1.f/localInertia[1];
invLocalInertia[2] = 1.f/localInertia[2];
@@ -830,7 +830,7 @@ int b3GpuNarrowPhase::registerRigidBody(int collidableIndex, float mass, const f
0, invLocalInertia[1], 0,
0, 0, invLocalInertia[2]);
btMatrix3x3 m (body.m_quat);
b3Matrix3x3 m (body.m_quat);
shapeInfo.m_invInertiaWorld = m.scaled(invLocalInertia) * m.transpose();

View File

@@ -3,8 +3,8 @@
#include "../../gpu_narrowphase/host/b3Collidable.h"
#include "basic_initialize/b3OpenCLInclude.h"
#include "BulletCommon/btAlignedObjectArray.h"
#include "BulletCommon/btVector3.h"
#include "BulletCommon/b3AlignedObjectArray.h"
#include "BulletCommon/b3Vector3.h"
class b3GpuNarrowPhase
{
@@ -20,7 +20,7 @@ protected:
cl_command_queue m_queue;
int registerConvexHullShape(class b3ConvexUtility* convexPtr, b3Collidable& col);
int registerConcaveMeshShape(btAlignedObjectArray<btVector3>* vertices, btAlignedObjectArray<int>* indices, b3Collidable& col, const float* scaling);
int registerConcaveMeshShape(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, b3Collidable& col, const float* scaling);
public:
@@ -32,12 +32,12 @@ public:
virtual ~b3GpuNarrowPhase(void);
int registerSphereShape(float radius);
int registerPlaneShape(const btVector3& planeNormal, float planeConstant);
int registerPlaneShape(const b3Vector3& planeNormal, float planeConstant);
int registerCompoundShape(btAlignedObjectArray<btGpuChildShape>* childShapes);
int registerFace(const btVector3& faceNormal, float faceConstant);
int registerCompoundShape(b3AlignedObjectArray<btGpuChildShape>* childShapes);
int registerFace(const b3Vector3& faceNormal, float faceConstant);
int registerConcaveMesh(btAlignedObjectArray<btVector3>* vertices, btAlignedObjectArray<int>* indices,const float* scaling);
int registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices,const float* scaling);
//do they need to be merged?

View File

@@ -20,7 +20,7 @@
#include "b3GpuBatchingPgsSolver.h"
#include "b3Solver.h"
#include "BulletCommon/btQuickprof.h"
#include "BulletCommon/b3Quickprof.h"
#include "b3Config.h"
b3GpuRigidBodyPipeline::b3GpuRigidBodyPipeline(cl_context ctx,cl_device_id device, cl_command_queue q,class b3GpuNarrowPhase* narrowphase, class b3GpuSapBroadphase* broadphaseSap )
@@ -133,9 +133,9 @@ void b3GpuRigidBodyPipeline::stepSimulation(float deltaTime)
bool forceHost = false;
if (forceHost)
{
btAlignedObjectArray<b3RigidBodyCL> hostBodies;
btAlignedObjectArray<btInertiaCL> hostInertias;
btAlignedObjectArray<b3Contact4> hostContacts;
b3AlignedObjectArray<b3RigidBodyCL> hostBodies;
b3AlignedObjectArray<btInertiaCL> hostInertias;
b3AlignedObjectArray<b3Contact4> hostContacts;
{
BT_PROFILE("copyToHost");
@@ -161,11 +161,11 @@ void b3GpuRigidBodyPipeline::stepSimulation(float deltaTime)
}
} else
{
btAlignedObjectArray<b3RigidBodyCL> hostBodies;
b3AlignedObjectArray<b3RigidBodyCL> hostBodies;
gpuBodies.copyToHost(hostBodies);
btAlignedObjectArray<btInertiaCL> hostInertias;
b3AlignedObjectArray<btInertiaCL> hostInertias;
gpuInertias.copyToHost(hostInertias);
btAlignedObjectArray<b3Contact4> hostContacts;
b3AlignedObjectArray<b3Contact4> hostContacts;
gpuContacts.copyToHost(hostContacts);
{
m_data->m_solver->solveContacts(m_data->m_narrowphase->getNumBodiesGpu(),&hostBodies[0],&hostInertias[0],numContacts,&hostContacts[0]);
@@ -207,7 +207,7 @@ void b3GpuRigidBodyPipeline::integrate(float timeStep)
float angularDamp = 0.99f;
launcher.setConst(angularDamp);
btVector3 gravity(0.f,-9.8f,0.f);
b3Vector3 gravity(0.f,-9.8f,0.f);
launcher.setConst(gravity);
launcher.launch1D(numBodies);
@@ -256,18 +256,18 @@ int b3GpuRigidBodyPipeline::getNumBodies() const
int b3GpuRigidBodyPipeline::registerPhysicsInstance(float mass, const float* position, const float* orientation, int collidableIndex, int userIndex)
{
btVector3 aabbMin(0,0,0),aabbMax(0,0,0);
b3Vector3 aabbMin(0,0,0),aabbMax(0,0,0);
if (collidableIndex>=0)
{
b3SapAabb localAabb = m_data->m_narrowphase->getLocalSpaceAabb(collidableIndex);
btVector3 localAabbMin(localAabb.m_min[0],localAabb.m_min[1],localAabb.m_min[2]);
btVector3 localAabbMax(localAabb.m_max[0],localAabb.m_max[1],localAabb.m_max[2]);
b3Vector3 localAabbMin(localAabb.m_min[0],localAabb.m_min[1],localAabb.m_min[2]);
b3Vector3 localAabbMax(localAabb.m_max[0],localAabb.m_max[1],localAabb.m_max[2]);
btScalar margin = 0.01f;
btTransform t;
b3Scalar margin = 0.01f;
b3Transform t;
t.setIdentity();
t.setOrigin(btVector3(position[0],position[1],position[2]));
t.setRotation(btQuaternion(orientation[0],orientation[1],orientation[2],orientation[3]));
t.setOrigin(b3Vector3(position[0],position[1],position[2]));
t.setRotation(b3Quaternion(orientation[0],orientation[1],orientation[2],orientation[3]));
btTransformAabb(localAabbMin,localAabbMax, margin,t,aabbMin,aabbMax);
if (mass)
{

View File

@@ -23,10 +23,10 @@ public:
//int registerConvexPolyhedron(const float* vertices, int strideInBytes, int numVertices, const float* scaling);
//int registerSphereShape(float radius);
//int registerPlaneShape(const btVector3& planeNormal, float planeConstant);
//int registerPlaneShape(const b3Vector3& planeNormal, float planeConstant);
//int registerConcaveMesh(btAlignedObjectArray<btVector3>* vertices, btAlignedObjectArray<int>* indices, const float* scaling);
//int registerCompoundShape(btAlignedObjectArray<btGpuChildShape>* childShapes);
//int registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, const float* scaling);
//int registerCompoundShape(b3AlignedObjectArray<btGpuChildShape>* childShapes);
int registerPhysicsInstance(float mass, const float* position, const float* orientation, int collisionShapeIndex, int userData);

View File

@@ -2,7 +2,7 @@
#define BT_GPU_RIGIDBODY_PIPELINE_INTERNAL_DATA_H
#include "../../basic_initialize/b3OpenCLInclude.h"
#include "BulletCommon/btAlignedObjectArray.h"
#include "BulletCommon/b3AlignedObjectArray.h"
#include "../../parallel_primitives/host/btOpenCLArray.h"
#include "../../gpu_narrowphase/host/b3Collidable.h"

View File

@@ -39,9 +39,9 @@ bool useNewBatchingKernel = false;
#include "../kernels/batchingKernelsNew.h"
#include "BulletCommon/btQuickprof.h"
#include "BulletCommon/b3Quickprof.h"
#include "../../parallel_primitives/host/btLauncherCL.h"
#include "BulletCommon/btVector3.h"
#include "BulletCommon/b3Vector3.h"
struct SolverDebugInfo
{
@@ -282,8 +282,8 @@ b3Solver::~b3Solver()
static
inline
float calcRelVel(const btVector3& l0, const btVector3& l1, const btVector3& a0, const btVector3& a1,
const btVector3& linVel0, const btVector3& angVel0, const btVector3& linVel1, const btVector3& angVel1)
float calcRelVel(const b3Vector3& l0, const b3Vector3& l1, const b3Vector3& a0, const b3Vector3& a1,
const b3Vector3& linVel0, const b3Vector3& angVel0, const b3Vector3& linVel1, const b3Vector3& angVel1)
{
return btDot(l0, linVel0) + btDot(a0, angVel0) + btDot(l1, linVel1) + btDot(a1, angVel1);
}
@@ -291,8 +291,8 @@ b3Solver::~b3Solver()
static
inline
void setLinearAndAngular(const btVector3& n, const btVector3& r0, const btVector3& r1,
btVector3& linear, btVector3& angular0, btVector3& angular1)
void setLinearAndAngular(const b3Vector3& n, const b3Vector3& r0, const b3Vector3& r1,
b3Vector3& linear, b3Vector3& angular0, b3Vector3& angular1)
{
linear = -n;
angular0 = -btCross(r0, n);
@@ -304,15 +304,15 @@ template<bool JACOBI>
static
__inline
void solveContact(b3GpuConstraint4& cs,
const btVector3& posA, btVector3& linVelA, btVector3& angVelA, float invMassA, const btMatrix3x3& invInertiaA,
const btVector3& posB, btVector3& linVelB, btVector3& angVelB, float invMassB, const btMatrix3x3& invInertiaB,
const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
float maxRambdaDt[4], float minRambdaDt[4])
{
btVector3 dLinVelA; dLinVelA.setZero();
btVector3 dAngVelA; dAngVelA.setZero();
btVector3 dLinVelB; dLinVelB.setZero();
btVector3 dAngVelB; dAngVelB.setZero();
b3Vector3 dLinVelA; dLinVelA.setZero();
b3Vector3 dAngVelA; dAngVelA.setZero();
b3Vector3 dLinVelB; dLinVelB.setZero();
b3Vector3 dAngVelB; dAngVelB.setZero();
for(int ic=0; ic<4; ic++)
{
@@ -320,12 +320,12 @@ void solveContact(b3GpuConstraint4& cs,
if( cs.m_jacCoeffInv[ic] == 0.f ) continue;
{
btVector3 angular0, angular1, linear;
btVector3 r0 = cs.m_worldPos[ic] - (btVector3&)posA;
btVector3 r1 = cs.m_worldPos[ic] - (btVector3&)posB;
setLinearAndAngular( (const btVector3 &)-cs.m_linear, (const btVector3 &)r0, (const btVector3 &)r1, linear, angular0, angular1 );
b3Vector3 angular0, angular1, linear;
b3Vector3 r0 = cs.m_worldPos[ic] - (b3Vector3&)posA;
b3Vector3 r1 = cs.m_worldPos[ic] - (b3Vector3&)posB;
setLinearAndAngular( (const b3Vector3 &)-cs.m_linear, (const b3Vector3 &)r0, (const b3Vector3 &)r1, linear, angular0, angular1 );
float rambdaDt = calcRelVel((const btVector3 &)cs.m_linear,(const btVector3 &) -cs.m_linear, angular0, angular1,
float rambdaDt = calcRelVel((const b3Vector3 &)cs.m_linear,(const b3Vector3 &) -cs.m_linear, angular0, angular1,
linVelA, angVelA, linVelB, angVelB ) + cs.m_b[ic];
rambdaDt *= cs.m_jacCoeffInv[ic];
@@ -339,10 +339,10 @@ void solveContact(b3GpuConstraint4& cs,
cs.m_appliedRambdaDt[ic] = updated;
}
btVector3 linImp0 = invMassA*linear*rambdaDt;
btVector3 linImp1 = invMassB*(-linear)*rambdaDt;
btVector3 angImp0 = (invInertiaA* angular0)*rambdaDt;
btVector3 angImp1 = (invInertiaB* angular1)*rambdaDt;
b3Vector3 linImp0 = invMassA*linear*rambdaDt;
b3Vector3 linImp1 = invMassB*(-linear)*rambdaDt;
b3Vector3 angImp0 = (invInertiaA* angular0)*rambdaDt;
b3Vector3 angImp1 = (invInertiaB* angular1)*rambdaDt;
#ifdef _WIN32
btAssert(_finite(linImp0.getX()));
btAssert(_finite(linImp1.getX()));
@@ -381,30 +381,30 @@ void solveContact(b3GpuConstraint4& cs,
static
__inline
void solveFriction(b3GpuConstraint4& cs,
const btVector3& posA, btVector3& linVelA, btVector3& angVelA, float invMassA, const btMatrix3x3& invInertiaA,
const btVector3& posB, btVector3& linVelB, btVector3& angVelB, float invMassB, const btMatrix3x3& invInertiaB,
const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
float maxRambdaDt[4], float minRambdaDt[4])
{
if( cs.m_fJacCoeffInv[0] == 0 && cs.m_fJacCoeffInv[0] == 0 ) return;
const btVector3& center = (const btVector3&)cs.m_center;
const b3Vector3& center = (const b3Vector3&)cs.m_center;
btVector3 n = -(const btVector3&)cs.m_linear;
b3Vector3 n = -(const b3Vector3&)cs.m_linear;
btVector3 tangent[2];
b3Vector3 tangent[2];
#if 1
btPlaneSpace1 (n, tangent[0],tangent[1]);
#else
btVector3 r = cs.m_worldPos[0]-center;
b3Vector3 r = cs.m_worldPos[0]-center;
tangent[0] = cross3( n, r );
tangent[1] = cross3( tangent[0], n );
tangent[0] = normalize3( tangent[0] );
tangent[1] = normalize3( tangent[1] );
#endif
btVector3 angular0, angular1, linear;
btVector3 r0 = center - posA;
btVector3 r1 = center - posB;
b3Vector3 angular0, angular1, linear;
b3Vector3 r0 = center - posA;
b3Vector3 r1 = center - posB;
for(int i=0; i<2; i++)
{
setLinearAndAngular( tangent[i], r0, r1, linear, angular0, angular1 );
@@ -422,10 +422,10 @@ void solveContact(b3GpuConstraint4& cs,
cs.m_fAppliedRambdaDt[i] = updated;
}
btVector3 linImp0 = invMassA*linear*rambdaDt;
btVector3 linImp1 = invMassB*(-linear)*rambdaDt;
btVector3 angImp0 = (invInertiaA* angular0)*rambdaDt;
btVector3 angImp1 = (invInertiaB* angular1)*rambdaDt;
b3Vector3 linImp0 = invMassA*linear*rambdaDt;
b3Vector3 linImp1 = invMassB*(-linear)*rambdaDt;
b3Vector3 angImp0 = (invInertiaA* angular0)*rambdaDt;
b3Vector3 angImp1 = (invInertiaB* angular1)*rambdaDt;
#ifdef _WIN32
btAssert(_finite(linImp0.getX()));
btAssert(_finite(linImp1.getX()));
@@ -437,8 +437,8 @@ void solveContact(b3GpuConstraint4& cs,
}
{ // angular damping for point constraint
btVector3 ab = ( posB - posA ).normalized();
btVector3 ac = ( center - posA ).normalized();
b3Vector3 ab = ( posB - posA ).normalized();
b3Vector3 ac = ( center - posA ).normalized();
if( btDot( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
{
float angNA = btDot( n, angVelA );
@@ -454,7 +454,7 @@ void solveContact(b3GpuConstraint4& cs,
struct SolveTask// : public ThreadPool::Task
{
SolveTask(btAlignedObjectArray<b3RigidBodyCL>& bodies, btAlignedObjectArray<btInertiaCL>& shapes, btAlignedObjectArray<b3GpuConstraint4>& constraints,
SolveTask(b3AlignedObjectArray<b3RigidBodyCL>& bodies, b3AlignedObjectArray<btInertiaCL>& shapes, b3AlignedObjectArray<b3GpuConstraint4>& constraints,
int start, int nConstraints)
: m_bodies( bodies ), m_shapes( shapes ), m_constraints( constraints ), m_start( start ), m_nConstraints( nConstraints ),
m_solveFriction( true ){}
@@ -480,8 +480,8 @@ struct SolveTask// : public ThreadPool::Task
float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
solveContact<false>( m_constraints[i], (btVector3&)bodyA.m_pos, (btVector3&)bodyA.m_linVel, (btVector3&)bodyA.m_angVel, bodyA.m_invMass, (const btMatrix3x3 &)m_shapes[aIdx].m_invInertiaWorld,
(btVector3&)bodyB.m_pos, (btVector3&)bodyB.m_linVel, (btVector3&)bodyB.m_angVel, bodyB.m_invMass, (const btMatrix3x3 &)m_shapes[bIdx].m_invInertiaWorld,
solveContact<false>( m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, (const b3Matrix3x3 &)m_shapes[aIdx].m_invInertiaWorld,
(b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, (const b3Matrix3x3 &)m_shapes[bIdx].m_invInertiaWorld,
maxRambdaDt, minRambdaDt );
}
@@ -502,8 +502,8 @@ struct SolveTask// : public ThreadPool::Task
minRambdaDt[j] = -maxRambdaDt[j];
}
solveFriction( m_constraints[i], (btVector3&)bodyA.m_pos, (btVector3&)bodyA.m_linVel, (btVector3&)bodyA.m_angVel, bodyA.m_invMass,(const btMatrix3x3 &) m_shapes[aIdx].m_invInertiaWorld,
(btVector3&)bodyB.m_pos, (btVector3&)bodyB.m_linVel, (btVector3&)bodyB.m_angVel, bodyB.m_invMass,(const btMatrix3x3 &) m_shapes[bIdx].m_invInertiaWorld,
solveFriction( m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass,(const b3Matrix3x3 &) m_shapes[aIdx].m_invInertiaWorld,
(b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass,(const b3Matrix3x3 &) m_shapes[bIdx].m_invInertiaWorld,
maxRambdaDt, minRambdaDt );
}
@@ -512,9 +512,9 @@ struct SolveTask// : public ThreadPool::Task
}
btAlignedObjectArray<b3RigidBodyCL>& m_bodies;
btAlignedObjectArray<btInertiaCL>& m_shapes;
btAlignedObjectArray<b3GpuConstraint4>& m_constraints;
b3AlignedObjectArray<b3RigidBodyCL>& m_bodies;
b3AlignedObjectArray<btInertiaCL>& m_shapes;
b3AlignedObjectArray<b3GpuConstraint4>& m_constraints;
int m_start;
int m_nConstraints;
bool m_solveFriction;
@@ -525,11 +525,11 @@ void b3Solver::solveContactConstraintHost( btOpenCLArray<b3RigidBodyCL>* bodyBu
btOpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n ,int maxNumBatches)
{
btAlignedObjectArray<b3RigidBodyCL> bodyNative;
b3AlignedObjectArray<b3RigidBodyCL> bodyNative;
bodyBuf->copyToHost(bodyNative);
btAlignedObjectArray<btInertiaCL> shapeNative;
b3AlignedObjectArray<btInertiaCL> shapeNative;
shapeBuf->copyToHost(shapeNative);
btAlignedObjectArray<b3GpuConstraint4> constraintNative;
b3AlignedObjectArray<b3GpuConstraint4> constraintNative;
constraint->copyToHost(constraintNative);
for(int iter=0; iter<m_nIterations; iter++)