Ported Bullet to the mod loader system; needs further work

This commit is contained in:
Robert MacGregor 2015-06-27 14:01:25 -04:00
parent 527474ff24
commit 06810b6cca
353 changed files with 80265 additions and 0 deletions

View file

@ -0,0 +1,727 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_SOFT_BODY_SOLVER_DATA_H
#define BT_SOFT_BODY_SOLVER_DATA_H
#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
#include "vectormath/vmInclude.h"
class btSoftBodyLinkData
{
public:
/**
* Class representing a link as a set of three indices into the vertex array.
*/
class LinkNodePair
{
public:
int vertex0;
int vertex1;
LinkNodePair()
{
vertex0 = 0;
vertex1 = 0;
}
LinkNodePair( int v0, int v1 )
{
vertex0 = v0;
vertex1 = v1;
}
};
/**
* Class describing a link for input into the system.
*/
class LinkDescription
{
protected:
int m_vertex0;
int m_vertex1;
float m_linkLinearStiffness;
float m_linkStrength;
public:
LinkDescription()
{
m_vertex0 = 0;
m_vertex1 = 0;
m_linkLinearStiffness = 1.0;
m_linkStrength = 1.0;
}
LinkDescription( int newVertex0, int newVertex1, float linkLinearStiffness )
{
m_vertex0 = newVertex0;
m_vertex1 = newVertex1;
m_linkLinearStiffness = linkLinearStiffness;
m_linkStrength = 1.0;
}
LinkNodePair getVertexPair() const
{
LinkNodePair nodes;
nodes.vertex0 = m_vertex0;
nodes.vertex1 = m_vertex1;
return nodes;
}
void setVertex0( int vertex )
{
m_vertex0 = vertex;
}
void setVertex1( int vertex )
{
m_vertex1 = vertex;
}
void setLinkLinearStiffness( float linearStiffness )
{
m_linkLinearStiffness = linearStiffness;
}
void setLinkStrength( float strength )
{
m_linkStrength = strength;
}
int getVertex0() const
{
return m_vertex0;
}
int getVertex1() const
{
return m_vertex1;
}
float getLinkStrength() const
{
return m_linkStrength;
}
float getLinkLinearStiffness() const
{
return m_linkLinearStiffness;
}
};
protected:
// NOTE:
// Vertex reference data is stored relative to global array, not relative to individual cloth.
// Values must be correct if being passed into single-cloth VBOs or when migrating from one solver
// to another.
btAlignedObjectArray< LinkNodePair > m_links; // Vertex pair for the link
btAlignedObjectArray< float > m_linkStrength; // Strength of each link
// (inverseMassA + inverseMassB)/ linear stiffness coefficient
btAlignedObjectArray< float > m_linksMassLSC;
btAlignedObjectArray< float > m_linksRestLengthSquared;
// Current vector length of link
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_linksCLength;
// 1/(current length * current length * massLSC)
btAlignedObjectArray< float > m_linksLengthRatio;
btAlignedObjectArray< float > m_linksRestLength;
btAlignedObjectArray< float > m_linksMaterialLinearStiffnessCoefficient;
public:
btSoftBodyLinkData()
{
}
virtual ~btSoftBodyLinkData()
{
}
virtual void clear()
{
m_links.resize(0);
m_linkStrength.resize(0);
m_linksMassLSC.resize(0);
m_linksRestLengthSquared.resize(0);
m_linksLengthRatio.resize(0);
m_linksRestLength.resize(0);
m_linksMaterialLinearStiffnessCoefficient.resize(0);
}
int getNumLinks()
{
return m_links.size();
}
/** Allocate enough space in all link-related arrays to fit numLinks links */
virtual void createLinks( int numLinks )
{
int previousSize = m_links.size();
int newSize = previousSize + numLinks;
// Resize all the arrays that store link data
m_links.resize( newSize );
m_linkStrength.resize( newSize );
m_linksMassLSC.resize( newSize );
m_linksRestLengthSquared.resize( newSize );
m_linksCLength.resize( newSize );
m_linksLengthRatio.resize( newSize );
m_linksRestLength.resize( newSize );
m_linksMaterialLinearStiffnessCoefficient.resize( newSize );
}
/** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */
virtual void setLinkAt( const LinkDescription &link, int linkIndex )
{
m_links[linkIndex] = link.getVertexPair();
m_linkStrength[linkIndex] = link.getLinkStrength();
m_linksMassLSC[linkIndex] = 0.f;
m_linksRestLengthSquared[linkIndex] = 0.f;
m_linksCLength[linkIndex] = Vectormath::Aos::Vector3(0.f, 0.f, 0.f);
m_linksLengthRatio[linkIndex] = 0.f;
m_linksRestLength[linkIndex] = 0.f;
m_linksMaterialLinearStiffnessCoefficient[linkIndex] = link.getLinkLinearStiffness();
}
/**
* Return true if data is on the accelerator.
* The CPU version of this class will return true here because
* the CPU is the same as the accelerator.
*/
virtual bool onAccelerator()
{
return true;
}
/**
* Move data from host memory to the accelerator.
* The CPU version will always return that it has moved it.
*/
virtual bool moveToAccelerator()
{
return true;
}
/**
* Move data from host memory from the accelerator.
* The CPU version will always return that it has moved it.
*/
virtual bool moveFromAccelerator()
{
return true;
}
/**
* Return reference to the vertex index pair for link linkIndex as stored on the host.
*/
LinkNodePair &getVertexPair( int linkIndex )
{
return m_links[linkIndex];
}
/**
* Return reference to strength of link linkIndex as stored on the host.
*/
float &getStrength( int linkIndex )
{
return m_linkStrength[linkIndex];
}
/**
* Return a reference to the strength of the link corrected for link sorting.
* This is important if we are using data on an accelerator which has the data sorted in some fashion.
*/
virtual float &getStrengthCorrected( int linkIndex )
{
return getStrength( linkIndex );
}
/**
* Return reference to the rest length of link linkIndex as stored on the host.
*/
float &getRestLength( int linkIndex )
{
return m_linksRestLength[linkIndex];
}
/**
* Return reference to linear stiffness coefficient for link linkIndex as stored on the host.
*/
float &getLinearStiffnessCoefficient( int linkIndex )
{
return m_linksMaterialLinearStiffnessCoefficient[linkIndex];
}
/**
* Return reference to the MassLSC value for link linkIndex as stored on the host.
*/
float &getMassLSC( int linkIndex )
{
return m_linksMassLSC[linkIndex];
}
/**
* Return reference to rest length squared for link linkIndex as stored on the host.
*/
float &getRestLengthSquared( int linkIndex )
{
return m_linksRestLengthSquared[linkIndex];
}
/**
* Return reference to current length of link linkIndex as stored on the host.
*/
Vectormath::Aos::Vector3 &getCurrentLength( int linkIndex )
{
return m_linksCLength[linkIndex];
}
/**
* Return the link length ratio from for link linkIndex as stored on the host.
*/
float &getLinkLengthRatio( int linkIndex )
{
return m_linksLengthRatio[linkIndex];
}
};
/**
* Wrapper for vertex data information.
* By wrapping it like this we stand a good chance of being able to optimise for storage format easily.
* It should also help us make sure all the data structures remain consistent.
*/
class btSoftBodyVertexData
{
public:
/**
* Class describing a vertex for input into the system.
*/
class VertexDescription
{
private:
Vectormath::Aos::Point3 m_position;
/** Inverse mass. If this is 0f then the mass was 0 because that simplifies calculations. */
float m_inverseMass;
public:
VertexDescription()
{
m_position = Vectormath::Aos::Point3( 0.f, 0.f, 0.f );
m_inverseMass = 0.f;
}
VertexDescription( const Vectormath::Aos::Point3 &position, float mass )
{
m_position = position;
if( mass > 0.f )
m_inverseMass = 1.0f/mass;
else
m_inverseMass = 0.f;
}
void setPosition( const Vectormath::Aos::Point3 &position )
{
m_position = position;
}
void setInverseMass( float inverseMass )
{
m_inverseMass = inverseMass;
}
void setMass( float mass )
{
if( mass > 0.f )
m_inverseMass = 1.0f/mass;
else
m_inverseMass = 0.f;
}
Vectormath::Aos::Point3 getPosition() const
{
return m_position;
}
float getInverseMass() const
{
return m_inverseMass;
}
float getMass() const
{
if( m_inverseMass == 0.f )
return 0.f;
else
return 1.0f/m_inverseMass;
}
};
protected:
// identifier for the individual cloth
// For the CPU we don't really need this as we can grab the cloths and iterate over only their vertices
// For a parallel accelerator knowing on a per-vertex basis which cloth we're part of will help for obtaining
// per-cloth data
// For sorting etc it might also be helpful to be able to use in-array data such as this.
btAlignedObjectArray< int > m_clothIdentifier;
btAlignedObjectArray< Vectormath::Aos::Point3 > m_vertexPosition; // vertex positions
btAlignedObjectArray< Vectormath::Aos::Point3 > m_vertexPreviousPosition; // vertex positions
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_vertexVelocity; // Velocity
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_vertexForceAccumulator; // Force accumulator
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_vertexNormal; // Normals
btAlignedObjectArray< float > m_vertexInverseMass; // Inverse mass
btAlignedObjectArray< float > m_vertexArea; // Area controlled by the vertex
btAlignedObjectArray< int > m_vertexTriangleCount; // Number of triangles touching this vertex
public:
btSoftBodyVertexData()
{
}
virtual ~btSoftBodyVertexData()
{
}
virtual void clear()
{
m_clothIdentifier.resize(0);
m_vertexPosition.resize(0);
m_vertexPreviousPosition.resize(0);
m_vertexVelocity.resize(0);
m_vertexForceAccumulator.resize(0);
m_vertexNormal.resize(0);
m_vertexInverseMass.resize(0);
m_vertexArea.resize(0);
m_vertexTriangleCount.resize(0);
}
int getNumVertices()
{
return m_vertexPosition.size();
}
int getClothIdentifier( int vertexIndex )
{
return m_clothIdentifier[vertexIndex];
}
void setVertexAt( const VertexDescription &vertex, int vertexIndex )
{
m_vertexPosition[vertexIndex] = vertex.getPosition();
m_vertexPreviousPosition[vertexIndex] = vertex.getPosition();
m_vertexVelocity[vertexIndex] = Vectormath::Aos::Vector3(0.f, 0.f, 0.f);
m_vertexForceAccumulator[vertexIndex] = Vectormath::Aos::Vector3(0.f, 0.f, 0.f);
m_vertexNormal[vertexIndex] = Vectormath::Aos::Vector3(0.f, 0.f, 0.f);
m_vertexInverseMass[vertexIndex] = vertex.getInverseMass();
m_vertexArea[vertexIndex] = 0.f;
m_vertexTriangleCount[vertexIndex] = 0;
}
/** Create numVertices new vertices for cloth clothIdentifier */
void createVertices( int numVertices, int clothIdentifier )
{
int previousSize = m_vertexPosition.size();
int newSize = previousSize + numVertices;
// Resize all the arrays that store vertex data
m_clothIdentifier.resize( newSize );
m_vertexPosition.resize( newSize );
m_vertexPreviousPosition.resize( newSize );
m_vertexVelocity.resize( newSize );
m_vertexForceAccumulator.resize( newSize );
m_vertexNormal.resize( newSize );
m_vertexInverseMass.resize( newSize );
m_vertexArea.resize( newSize );
m_vertexTriangleCount.resize( newSize );
for( int vertexIndex = previousSize; vertexIndex < newSize; ++vertexIndex )
m_clothIdentifier[vertexIndex] = clothIdentifier;
}
// Get and set methods in header so they can be inlined
/**
* Return a reference to the position of vertex vertexIndex as stored on the host.
*/
Vectormath::Aos::Point3 &getPosition( int vertexIndex )
{
return m_vertexPosition[vertexIndex];
}
/**
* Return a reference to the previous position of vertex vertexIndex as stored on the host.
*/
Vectormath::Aos::Point3 &getPreviousPosition( int vertexIndex )
{
return m_vertexPreviousPosition[vertexIndex];
}
/**
* Return a reference to the velocity of vertex vertexIndex as stored on the host.
*/
Vectormath::Aos::Vector3 &getVelocity( int vertexIndex )
{
return m_vertexVelocity[vertexIndex];
}
/**
* Return a reference to the force accumulator of vertex vertexIndex as stored on the host.
*/
Vectormath::Aos::Vector3 &getForceAccumulator( int vertexIndex )
{
return m_vertexForceAccumulator[vertexIndex];
}
/**
* Return a reference to the normal of vertex vertexIndex as stored on the host.
*/
Vectormath::Aos::Vector3 &getNormal( int vertexIndex )
{
return m_vertexNormal[vertexIndex];
}
/**
* Return a reference to the inverse mass of vertex vertexIndex as stored on the host.
*/
float &getInverseMass( int vertexIndex )
{
return m_vertexInverseMass[vertexIndex];
}
/**
* Get access to the area controlled by this vertex.
*/
float &getArea( int vertexIndex )
{
return m_vertexArea[vertexIndex];
}
/**
* Get access to the array of how many triangles touch each vertex.
*/
int &getTriangleCount( int vertexIndex )
{
return m_vertexTriangleCount[vertexIndex];
}
/**
* Return true if data is on the accelerator.
* The CPU version of this class will return true here because
* the CPU is the same as the accelerator.
*/
virtual bool onAccelerator()
{
return true;
}
/**
* Move data from host memory to the accelerator.
* The CPU version will always return that it has moved it.
*/
virtual bool moveToAccelerator()
{
return true;
}
/**
* Move data from host memory from the accelerator.
* The CPU version will always return that it has moved it.
*/
virtual bool moveFromAccelerator()
{
return true;
}
btAlignedObjectArray< Vectormath::Aos::Point3 > &getVertexPositions()
{
return m_vertexPosition;
}
};
class btSoftBodyTriangleData
{
public:
/**
* Class representing a triangle as a set of three indices into the
* vertex array.
*/
class TriangleNodeSet
{
public:
int vertex0;
int vertex1;
int vertex2;
int _padding;
TriangleNodeSet( )
{
vertex0 = 0;
vertex1 = 0;
vertex2 = 0;
_padding = -1;
}
TriangleNodeSet( int newVertex0, int newVertex1, int newVertex2 )
{
vertex0 = newVertex0;
vertex1 = newVertex1;
vertex2 = newVertex2;
}
};
class TriangleDescription
{
protected:
int m_vertex0;
int m_vertex1;
int m_vertex2;
public:
TriangleDescription()
{
m_vertex0 = 0;
m_vertex1 = 0;
m_vertex2 = 0;
}
TriangleDescription( int newVertex0, int newVertex1, int newVertex2 )
{
m_vertex0 = newVertex0;
m_vertex1 = newVertex1;
m_vertex2 = newVertex2;
}
TriangleNodeSet getVertexSet() const
{
btSoftBodyTriangleData::TriangleNodeSet nodes;
nodes.vertex0 = m_vertex0;
nodes.vertex1 = m_vertex1;
nodes.vertex2 = m_vertex2;
return nodes;
}
};
protected:
// NOTE:
// Vertex reference data is stored relative to global array, not relative to individual cloth.
// Values must be correct if being passed into single-cloth VBOs or when migrating from one solver
// to another.
btAlignedObjectArray< TriangleNodeSet > m_vertexIndices;
btAlignedObjectArray< float > m_area;
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_normal;
public:
btSoftBodyTriangleData()
{
}
virtual ~btSoftBodyTriangleData()
{
}
virtual void clear()
{
m_vertexIndices.resize(0);
m_area.resize(0);
m_normal.resize(0);
}
int getNumTriangles()
{
return m_vertexIndices.size();
}
virtual void setTriangleAt( const TriangleDescription &triangle, int triangleIndex )
{
m_vertexIndices[triangleIndex] = triangle.getVertexSet();
}
virtual void createTriangles( int numTriangles )
{
int previousSize = m_vertexIndices.size();
int newSize = previousSize + numTriangles;
// Resize all the arrays that store triangle data
m_vertexIndices.resize( newSize );
m_area.resize( newSize );
m_normal.resize( newSize );
}
/**
* Return the vertex index set for triangle triangleIndex as stored on the host.
*/
const TriangleNodeSet &getVertexSet( int triangleIndex )
{
return m_vertexIndices[triangleIndex];
}
/**
* Get access to the triangle area.
*/
float &getTriangleArea( int triangleIndex )
{
return m_area[triangleIndex];
}
/**
* Get access to the normal vector for this triangle.
*/
Vectormath::Aos::Vector3 &getNormal( int triangleIndex )
{
return m_normal[triangleIndex];
}
/**
* Return true if data is on the accelerator.
* The CPU version of this class will return true here because
* the CPU is the same as the accelerator.
*/
virtual bool onAccelerator()
{
return true;
}
/**
* Move data from host memory to the accelerator.
* The CPU version will always return that it has moved it.
*/
virtual bool moveToAccelerator()
{
return true;
}
/**
* Move data from host memory from the accelerator.
* The CPU version will always return that it has moved it.
*/
virtual bool moveFromAccelerator()
{
return true;
}
};
#endif // #ifndef BT_SOFT_BODY_SOLVER_DATA_H

View file

@ -0,0 +1,344 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_ACCELERATED_SOFT_BODY_CPU_SOLVER_H
#define BT_ACCELERATED_SOFT_BODY_CPU_SOLVER_H
#include "vectormath/vmInclude.h"
#include "BulletSoftBody/btSoftBodySolvers.h"
#include "BulletSoftBody/btSoftBodySolverVertexBuffer.h"
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolverData.h"
class btCPUSoftBodySolver : public btSoftBodySolver
{
protected:
/**
* Entry in the collision shape array.
* Specifies the shape type, the transform matrix and the necessary details of the collisionShape.
*/
struct CollisionShapeDescription
{
int softBodyIdentifier;
int collisionShapeType;
Vectormath::Aos::Transform3 shapeTransform;
union
{
struct Sphere
{
float radius;
} sphere;
struct Capsule
{
float radius;
float halfHeight;
} capsule;
} shapeInformation;
CollisionShapeDescription()
{
collisionShapeType = 0;
}
};
/**
* SoftBody class to maintain information about a soft body instance
* within a solver.
* This data addresses the main solver arrays.
*/
class btAcceleratedSoftBodyInterface
{
protected:
/** Current number of vertices that are part of this cloth */
int m_numVertices;
/** Maximum number of vertices allocated to be part of this cloth */
int m_maxVertices;
/** Current number of triangles that are part of this cloth */
int m_numTriangles;
/** Maximum number of triangles allocated to be part of this cloth */
int m_maxTriangles;
/** Index of first vertex in the world allocated to this cloth */
int m_firstVertex;
/** Index of first triangle in the world allocated to this cloth */
int m_firstTriangle;
/** Index of first link in the world allocated to this cloth */
int m_firstLink;
/** Maximum number of links allocated to this cloth */
int m_maxLinks;
/** Current number of links allocated to this cloth */
int m_numLinks;
/** The actual soft body this data represents */
btSoftBody *m_softBody;
public:
btAcceleratedSoftBodyInterface( btSoftBody *softBody ) :
m_softBody( softBody )
{
m_numVertices = 0;
m_maxVertices = 0;
m_numTriangles = 0;
m_maxTriangles = 0;
m_firstVertex = 0;
m_firstTriangle = 0;
m_firstLink = 0;
m_maxLinks = 0;
m_numLinks = 0;
}
int getNumVertices()
{
return m_numVertices;
}
int getNumTriangles()
{
return m_numTriangles;
}
int getMaxVertices()
{
return m_maxVertices;
}
int getMaxTriangles()
{
return m_maxTriangles;
}
int getFirstVertex()
{
return m_firstVertex;
}
int getFirstTriangle()
{
return m_firstTriangle;
}
// TODO: All of these set functions will have to do checks and
// update the world because restructuring of the arrays will be necessary
// Reasonable use of "friend"?
void setNumVertices( int numVertices )
{
m_numVertices = numVertices;
}
void setNumTriangles( int numTriangles )
{
m_numTriangles = numTriangles;
}
void setMaxVertices( int maxVertices )
{
m_maxVertices = maxVertices;
}
void setMaxTriangles( int maxTriangles )
{
m_maxTriangles = maxTriangles;
}
void setFirstVertex( int firstVertex )
{
m_firstVertex = firstVertex;
}
void setFirstTriangle( int firstTriangle )
{
m_firstTriangle = firstTriangle;
}
void setMaxLinks( int maxLinks )
{
m_maxLinks = maxLinks;
}
void setNumLinks( int numLinks )
{
m_numLinks = numLinks;
}
void setFirstLink( int firstLink )
{
m_firstLink = firstLink;
}
int getMaxLinks()
{
return m_maxLinks;
}
int getNumLinks()
{
return m_numLinks;
}
int getFirstLink()
{
return m_firstLink;
}
btSoftBody* getSoftBody()
{
return m_softBody;
}
#if 0
void setAcceleration( Vectormath::Aos::Vector3 acceleration )
{
m_currentSolver->setPerClothAcceleration( m_clothIdentifier, acceleration );
}
void setWindVelocity( Vectormath::Aos::Vector3 windVelocity )
{
m_currentSolver->setPerClothWindVelocity( m_clothIdentifier, windVelocity );
}
/**
* Set the density of the air in which the cloth is situated.
*/
void setAirDensity( btScalar density )
{
m_currentSolver->setPerClothMediumDensity( m_clothIdentifier, static_cast<float>(density) );
}
/**
* Add a collision object to this soft body.
*/
void addCollisionObject( btCollisionObject *collisionObject )
{
m_currentSolver->addCollisionObjectForSoftBody( m_clothIdentifier, collisionObject );
}
#endif
};
struct CollisionObjectIndices
{
int firstObject;
int endObject;
};
btSoftBodyLinkData m_linkData;
btSoftBodyVertexData m_vertexData;
btSoftBodyTriangleData m_triangleData;
/** Variable to define whether we need to update solver constants on the next iteration */
bool m_updateSolverConstants;
/**
* Cloths owned by this solver.
* Only our cloths are in this array.
*/
btAlignedObjectArray< btAcceleratedSoftBodyInterface * > m_softBodySet;
/** Acceleration value to be applied to all non-static vertices in the solver.
* Index n is cloth n, array sized by number of cloths in the world not the solver.
*/
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothAcceleration;
/** Wind velocity to be applied normal to all non-static vertices in the solver.
* Index n is cloth n, array sized by number of cloths in the world not the solver.
*/
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothWindVelocity;
/** Velocity damping factor */
btAlignedObjectArray< float > m_perClothDampingFactor;
/** Velocity correction coefficient */
btAlignedObjectArray< float > m_perClothVelocityCorrectionCoefficient;
/** Lift parameter for wind effect on cloth. */
btAlignedObjectArray< float > m_perClothLiftFactor;
/** Drag parameter for wind effect on cloth. */
btAlignedObjectArray< float > m_perClothDragFactor;
/** Density of the medium in which each cloth sits */
btAlignedObjectArray< float > m_perClothMediumDensity;
/**
* Collision shape details: pair of index of first collision shape for the cloth and number of collision objects.
*/
btAlignedObjectArray< CollisionObjectIndices > m_perClothCollisionObjects;
/**
* Collision shapes being passed across to the cloths in this solver.
*/
btAlignedObjectArray< CollisionShapeDescription > m_collisionObjectDetails;
void prepareCollisionConstraints();
Vectormath::Aos::Vector3 ProjectOnAxis( const Vectormath::Aos::Vector3 &v, const Vectormath::Aos::Vector3 &a );
void ApplyClampedForce( float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce );
float computeTriangleArea(
const Vectormath::Aos::Point3 &vertex0,
const Vectormath::Aos::Point3 &vertex1,
const Vectormath::Aos::Point3 &vertex2 );
void applyForces( float solverdt );
void integrate( float solverdt );
void updateConstants( float timeStep );
btAcceleratedSoftBodyInterface *findSoftBodyInterface( const btSoftBody* const softBody );
public:
btCPUSoftBodySolver();
virtual ~btCPUSoftBodySolver();
virtual btSoftBodyLinkData &getLinkData();
virtual btSoftBodyVertexData &getVertexData();
virtual btSoftBodyTriangleData &getTriangleData();
/**
* Add a collision object to be used by the indicated softbody.
*/
virtual void addCollisionObjectForSoftBody( int clothIdentifier, btCollisionObject *collisionObject );
virtual bool checkInitialized();
virtual void updateSoftBodies( );
virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies );
virtual void solveConstraints( float solverdt );
virtual void predictMotion( float solverdt );
virtual void copySoftBodyToVertexBuffer( const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer );
};
#endif // #ifndef BT_ACCELERATED_SOFT_BODY_CPU_SOLVER_H

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,481 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_ACCELERATED_SOFT_BODY_DX11_SOLVER_H
#define BT_ACCELERATED_SOFT_BODY_DX11_SOLVER_H
#include "vectormath/vmInclude.h"
#include "BulletSoftBody/btSoftBodySolvers.h"
#include "btSoftBodySolverVertexBuffer_DX11.h"
#include "btSoftBodySolverLinkData_DX11.h"
#include "btSoftBodySolverVertexData_DX11.h"
#include "btSoftBodySolverTriangleData_DX11.h"
/**
* SoftBody class to maintain information about a soft body instance
* within a solver.
* This data addresses the main solver arrays.
*/
class btDX11AcceleratedSoftBodyInterface
{
protected:
/** Current number of vertices that are part of this cloth */
int m_numVertices;
/** Maximum number of vertices allocated to be part of this cloth */
int m_maxVertices;
/** Current number of triangles that are part of this cloth */
int m_numTriangles;
/** Maximum number of triangles allocated to be part of this cloth */
int m_maxTriangles;
/** Index of first vertex in the world allocated to this cloth */
int m_firstVertex;
/** Index of first triangle in the world allocated to this cloth */
int m_firstTriangle;
/** Index of first link in the world allocated to this cloth */
int m_firstLink;
/** Maximum number of links allocated to this cloth */
int m_maxLinks;
/** Current number of links allocated to this cloth */
int m_numLinks;
/** The actual soft body this data represents */
btSoftBody *m_softBody;
public:
btDX11AcceleratedSoftBodyInterface( btSoftBody *softBody ) :
m_softBody( softBody )
{
m_numVertices = 0;
m_maxVertices = 0;
m_numTriangles = 0;
m_maxTriangles = 0;
m_firstVertex = 0;
m_firstTriangle = 0;
m_firstLink = 0;
m_maxLinks = 0;
m_numLinks = 0;
}
int getNumVertices()
{
return m_numVertices;
}
int getNumTriangles()
{
return m_numTriangles;
}
int getMaxVertices()
{
return m_maxVertices;
}
int getMaxTriangles()
{
return m_maxTriangles;
}
int getFirstVertex()
{
return m_firstVertex;
}
int getFirstTriangle()
{
return m_firstTriangle;
}
// TODO: All of these set functions will have to do checks and
// update the world because restructuring of the arrays will be necessary
// Reasonable use of "friend"?
void setNumVertices( int numVertices )
{
m_numVertices = numVertices;
}
void setNumTriangles( int numTriangles )
{
m_numTriangles = numTriangles;
}
void setMaxVertices( int maxVertices )
{
m_maxVertices = maxVertices;
}
void setMaxTriangles( int maxTriangles )
{
m_maxTriangles = maxTriangles;
}
void setFirstVertex( int firstVertex )
{
m_firstVertex = firstVertex;
}
void setFirstTriangle( int firstTriangle )
{
m_firstTriangle = firstTriangle;
}
void setMaxLinks( int maxLinks )
{
m_maxLinks = maxLinks;
}
void setNumLinks( int numLinks )
{
m_numLinks = numLinks;
}
void setFirstLink( int firstLink )
{
m_firstLink = firstLink;
}
int getMaxLinks()
{
return m_maxLinks;
}
int getNumLinks()
{
return m_numLinks;
}
int getFirstLink()
{
return m_firstLink;
}
btSoftBody* getSoftBody()
{
return m_softBody;
}
#if 0
void setAcceleration( Vectormath::Aos::Vector3 acceleration )
{
m_currentSolver->setPerClothAcceleration( m_clothIdentifier, acceleration );
}
void setWindVelocity( Vectormath::Aos::Vector3 windVelocity )
{
m_currentSolver->setPerClothWindVelocity( m_clothIdentifier, windVelocity );
}
/**
* Set the density of the air in which the cloth is situated.
*/
void setAirDensity( btScalar density )
{
m_currentSolver->setPerClothMediumDensity( m_clothIdentifier, static_cast<float>(density) );
}
/**
* Add a collision object to this soft body.
*/
void addCollisionObject( btCollisionObject *collisionObject )
{
m_currentSolver->addCollisionObjectForSoftBody( m_clothIdentifier, collisionObject );
}
#endif
};
class btDX11SoftBodySolver : public btSoftBodySolver
{
public:
class KernelDesc
{
protected:
public:
ID3D11ComputeShader* kernel;
ID3D11Buffer* constBuffer;
KernelDesc()
{
kernel = 0;
constBuffer = 0;
}
virtual ~KernelDesc()
{
// TODO: this should probably destroy its kernel but we need to be careful
// in case KernelDescs are copied
}
};
struct PrepareLinksCB
{
int numLinks;
int padding0;
int padding1;
int padding2;
};
struct SolvePositionsFromLinksKernelCB
{
int startLink;
int numLinks;
float kst;
float ti;
};
struct IntegrateCB
{
int numNodes;
float solverdt;
int padding1;
int padding2;
};
struct UpdatePositionsFromVelocitiesCB
{
int numNodes;
float solverSDT;
int padding1;
int padding2;
};
struct UpdateVelocitiesFromPositionsWithoutVelocitiesCB
{
int numNodes;
float isolverdt;
int padding1;
int padding2;
};
struct UpdateVelocitiesFromPositionsWithVelocitiesCB
{
int numNodes;
float isolverdt;
int padding1;
int padding2;
};
struct UpdateSoftBodiesCB
{
int numNodes;
int startFace;
int numFaces;
float epsilon;
};
struct OutputToVertexArrayCB
{
int startNode;
int numNodes;
int positionOffset;
int positionStride;
int normalOffset;
int normalStride;
int padding1;
int padding2;
};
struct ApplyForcesCB
{
unsigned int numNodes;
float solverdt;
float epsilon;
int padding3;
};
struct AddVelocityCB
{
int startNode;
int lastNode;
float velocityX;
float velocityY;
float velocityZ;
int padding1;
int padding2;
int padding3;
};
struct VSolveLinksCB
{
int startLink;
int numLinks;
float kst;
int padding;
};
private:
ID3D11Device * m_dx11Device;
ID3D11DeviceContext* m_dx11Context;
/** Link data for all cloths. Note that this will be sorted batch-wise for efficient computation and m_linkAddresses will maintain the addressing. */
btSoftBodyLinkDataDX11 m_linkData;
btSoftBodyVertexDataDX11 m_vertexData;
btSoftBodyTriangleDataDX11 m_triangleData;
/** Variable to define whether we need to update solver constants on the next iteration */
bool m_updateSolverConstants;
bool m_shadersInitialized;
/**
* Cloths owned by this solver.
* Only our cloths are in this array.
*/
btAlignedObjectArray< btDX11AcceleratedSoftBodyInterface * > m_softBodySet;
/** Acceleration value to be applied to all non-static vertices in the solver.
* Index n is cloth n, array sized by number of cloths in the world not the solver.
*/
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothAcceleration;
btDX11Buffer<Vectormath::Aos::Vector3> m_dx11PerClothAcceleration;
/** Wind velocity to be applied normal to all non-static vertices in the solver.
* Index n is cloth n, array sized by number of cloths in the world not the solver.
*/
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothWindVelocity;
btDX11Buffer<Vectormath::Aos::Vector3> m_dx11PerClothWindVelocity;
/** Velocity damping factor */
btAlignedObjectArray< float > m_perClothDampingFactor;
btDX11Buffer<float> m_dx11PerClothDampingFactor;
/** Velocity correction coefficient */
btAlignedObjectArray< float > m_perClothVelocityCorrectionCoefficient;
btDX11Buffer<float> m_dx11PerClothVelocityCorrectionCoefficient;
/** Lift parameter for wind effect on cloth. */
btAlignedObjectArray< float > m_perClothLiftFactor;
btDX11Buffer<float> m_dx11PerClothLiftFactor;
/** Drag parameter for wind effect on cloth. */
btAlignedObjectArray< float > m_perClothDragFactor;
btDX11Buffer<float> m_dx11PerClothDragFactor;
/** Density of the medium in which each cloth sits */
btAlignedObjectArray< float > m_perClothMediumDensity;
btDX11Buffer<float> m_dx11PerClothMediumDensity;
KernelDesc prepareLinksKernel;
KernelDesc solvePositionsFromLinksKernel;
KernelDesc vSolveLinksKernel;
KernelDesc integrateKernel;
KernelDesc addVelocityKernel;
KernelDesc updatePositionsFromVelocitiesKernel;
KernelDesc updateVelocitiesFromPositionsWithoutVelocitiesKernel;
KernelDesc updateVelocitiesFromPositionsWithVelocitiesKernel;
KernelDesc resetNormalsAndAreasKernel;
KernelDesc normalizeNormalsAndAreasKernel;
KernelDesc updateSoftBodiesKernel;
KernelDesc outputToVertexArrayWithNormalsKernel;
KernelDesc outputToVertexArrayWithoutNormalsKernel;
KernelDesc outputToVertexArrayKernel;
KernelDesc applyForcesKernel;
KernelDesc collideSphereKernel;
KernelDesc collideCylinderKernel;
/**
* Integrate motion on the solver.
*/
virtual void integrate( float solverdt );
float computeTriangleArea(
const Vectormath::Aos::Point3 &vertex0,
const Vectormath::Aos::Point3 &vertex1,
const Vectormath::Aos::Point3 &vertex2 );
/**
* Compile a compute shader kernel from a string and return the appropriate KernelDesc object.
*/
KernelDesc compileComputeShaderFromString( const char* shaderString, const char* shaderName, int constBufferSize );
bool buildShaders();
void resetNormalsAndAreas( int numVertices );
void normalizeNormalsAndAreas( int numVertices );
void executeUpdateSoftBodies( int firstTriangle, int numTriangles );
Vectormath::Aos::Vector3 ProjectOnAxis( const Vectormath::Aos::Vector3 &v, const Vectormath::Aos::Vector3 &a );
void ApplyClampedForce( float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce );
virtual void applyForces( float solverdt );
void updateConstants( float timeStep );
btDX11AcceleratedSoftBodyInterface *findSoftBodyInterface( const btSoftBody* const softBody );
//////////////////////////////////////
// Kernel dispatches
void prepareLinks();
void updatePositionsFromVelocities( float solverdt );
void solveLinksForPosition( int startLink, int numLinks, float kst, float ti );
void solveLinksForVelocity( int startLink, int numLinks, float kst );
void updateVelocitiesFromPositionsWithVelocities( float isolverdt );
void updateVelocitiesFromPositionsWithoutVelocities( float isolverdt );
// End kernel dispatches
/////////////////////////////////////
public:
btDX11SoftBodySolver(ID3D11Device * dx11Device, ID3D11DeviceContext* dx11Context);
virtual ~btDX11SoftBodySolver();
virtual btSoftBodyLinkData &getLinkData();
virtual btSoftBodyVertexData &getVertexData();
virtual btSoftBodyTriangleData &getTriangleData();
virtual bool checkInitialized();
virtual void updateSoftBodies( );
virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies );
virtual void solveConstraints( float solverdt );
virtual void predictMotion( float solverdt );
virtual void copySoftBodyToVertexBuffer( const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer );
};
#endif // #ifndef BT_ACCELERATED_SOFT_BODY_DX11_SOLVER_H

View file

@ -0,0 +1,432 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "vectormath/vmInclude.h"
#include "BulletSoftBody/btSoftBodySolvers.h"
#include "btSoftBodySolverVertexBuffer_DX11.h"
#include "btSoftBodySolverLinkData_DX11SIMDAware.h"
#include "btSoftBodySolverVertexData_DX11.h"
#include "btSoftBodySolverTriangleData_DX11.h"
#ifndef BT_SOFT_BODY_DX11_SOLVER_SIMDAWARE_H
#define BT_SOFT_BODY_DX11_SOLVER_SIMDAWARE_H
class btDX11SIMDAwareSoftBodySolver : public btSoftBodySolver
{
public:
/**
* SoftBody class to maintain information about a soft body instance
* within a solver.
* This data addresses the main solver arrays.
*/
class btAcceleratedSoftBodyInterface
{
protected:
/** Current number of vertices that are part of this cloth */
int m_numVertices;
/** Maximum number of vertices allocated to be part of this cloth */
int m_maxVertices;
/** Current number of triangles that are part of this cloth */
int m_numTriangles;
/** Maximum number of triangles allocated to be part of this cloth */
int m_maxTriangles;
/** Index of first vertex in the world allocated to this cloth */
int m_firstVertex;
/** Index of first triangle in the world allocated to this cloth */
int m_firstTriangle;
/** Index of first link in the world allocated to this cloth */
int m_firstLink;
/** Maximum number of links allocated to this cloth */
int m_maxLinks;
/** Current number of links allocated to this cloth */
int m_numLinks;
/** The actual soft body this data represents */
btSoftBody *m_softBody;
public:
btAcceleratedSoftBodyInterface( btSoftBody *softBody ) :
m_softBody( softBody )
{
m_numVertices = 0;
m_maxVertices = 0;
m_numTriangles = 0;
m_maxTriangles = 0;
m_firstVertex = 0;
m_firstTriangle = 0;
m_firstLink = 0;
m_maxLinks = 0;
m_numLinks = 0;
}
int getNumVertices()
{
return m_numVertices;
}
int getNumTriangles()
{
return m_numTriangles;
}
int getMaxVertices()
{
return m_maxVertices;
}
int getMaxTriangles()
{
return m_maxTriangles;
}
int getFirstVertex()
{
return m_firstVertex;
}
int getFirstTriangle()
{
return m_firstTriangle;
}
void setNumVertices( int numVertices )
{
m_numVertices = numVertices;
}
void setNumTriangles( int numTriangles )
{
m_numTriangles = numTriangles;
}
void setMaxVertices( int maxVertices )
{
m_maxVertices = maxVertices;
}
void setMaxTriangles( int maxTriangles )
{
m_maxTriangles = maxTriangles;
}
void setFirstVertex( int firstVertex )
{
m_firstVertex = firstVertex;
}
void setFirstTriangle( int firstTriangle )
{
m_firstTriangle = firstTriangle;
}
void setMaxLinks( int maxLinks )
{
m_maxLinks = maxLinks;
}
void setNumLinks( int numLinks )
{
m_numLinks = numLinks;
}
void setFirstLink( int firstLink )
{
m_firstLink = firstLink;
}
int getMaxLinks()
{
return m_maxLinks;
}
int getNumLinks()
{
return m_numLinks;
}
int getFirstLink()
{
return m_firstLink;
}
btSoftBody* getSoftBody()
{
return m_softBody;
}
};
class KernelDesc
{
protected:
public:
ID3D11ComputeShader* kernel;
ID3D11Buffer* constBuffer;
KernelDesc()
{
kernel = 0;
constBuffer = 0;
}
virtual ~KernelDesc()
{
// TODO: this should probably destroy its kernel but we need to be careful
// in case KernelDescs are copied
}
};
struct SolvePositionsFromLinksKernelCB
{
int startWave;
int numWaves;
float kst;
float ti;
};
struct IntegrateCB
{
int numNodes;
float solverdt;
int padding1;
int padding2;
};
struct UpdatePositionsFromVelocitiesCB
{
int numNodes;
float solverSDT;
int padding1;
int padding2;
};
struct UpdateVelocitiesFromPositionsWithoutVelocitiesCB
{
int numNodes;
float isolverdt;
int padding1;
int padding2;
};
struct UpdateVelocitiesFromPositionsWithVelocitiesCB
{
int numNodes;
float isolverdt;
int padding1;
int padding2;
};
struct UpdateSoftBodiesCB
{
int numNodes;
int startFace;
int numFaces;
float epsilon;
};
struct OutputToVertexArrayCB
{
int startNode;
int numNodes;
int positionOffset;
int positionStride;
int normalOffset;
int normalStride;
int padding1;
int padding2;
};
struct ApplyForcesCB
{
unsigned int numNodes;
float solverdt;
float epsilon;
int padding3;
};
struct AddVelocityCB
{
int startNode;
int lastNode;
float velocityX;
float velocityY;
float velocityZ;
int padding1;
int padding2;
int padding3;
};
private:
ID3D11Device * m_dx11Device;
ID3D11DeviceContext* m_dx11Context;
/** Link data for all cloths. Note that this will be sorted batch-wise for efficient computation and m_linkAddresses will maintain the addressing. */
btSoftBodyLinkDataDX11SIMDAware m_linkData;
btSoftBodyVertexDataDX11 m_vertexData;
btSoftBodyTriangleDataDX11 m_triangleData;
/** Variable to define whether we need to update solver constants on the next iteration */
bool m_updateSolverConstants;
bool m_shadersInitialized;
/**
* Cloths owned by this solver.
* Only our cloths are in this array.
*/
btAlignedObjectArray< btAcceleratedSoftBodyInterface * > m_softBodySet;
/** Acceleration value to be applied to all non-static vertices in the solver.
* Index n is cloth n, array sized by number of cloths in the world not the solver.
*/
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothAcceleration;
btDX11Buffer<Vectormath::Aos::Vector3> m_dx11PerClothAcceleration;
/** Wind velocity to be applied normal to all non-static vertices in the solver.
* Index n is cloth n, array sized by number of cloths in the world not the solver.
*/
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothWindVelocity;
btDX11Buffer<Vectormath::Aos::Vector3> m_dx11PerClothWindVelocity;
/** Velocity damping factor */
btAlignedObjectArray< float > m_perClothDampingFactor;
btDX11Buffer<float> m_dx11PerClothDampingFactor;
/** Velocity correction coefficient */
btAlignedObjectArray< float > m_perClothVelocityCorrectionCoefficient;
btDX11Buffer<float> m_dx11PerClothVelocityCorrectionCoefficient;
/** Lift parameter for wind effect on cloth. */
btAlignedObjectArray< float > m_perClothLiftFactor;
btDX11Buffer<float> m_dx11PerClothLiftFactor;
/** Drag parameter for wind effect on cloth. */
btAlignedObjectArray< float > m_perClothDragFactor;
btDX11Buffer<float> m_dx11PerClothDragFactor;
/** Density of the medium in which each cloth sits */
btAlignedObjectArray< float > m_perClothMediumDensity;
btDX11Buffer<float> m_dx11PerClothMediumDensity;
KernelDesc solvePositionsFromLinksKernel;
KernelDesc integrateKernel;
KernelDesc addVelocityKernel;
KernelDesc updatePositionsFromVelocitiesKernel;
KernelDesc updateVelocitiesFromPositionsWithoutVelocitiesKernel;
KernelDesc updateVelocitiesFromPositionsWithVelocitiesKernel;
KernelDesc resetNormalsAndAreasKernel;
KernelDesc normalizeNormalsAndAreasKernel;
KernelDesc updateSoftBodiesKernel;
KernelDesc outputToVertexArrayWithNormalsKernel;
KernelDesc outputToVertexArrayWithoutNormalsKernel;
KernelDesc outputToVertexArrayKernel;
KernelDesc applyForcesKernel;
KernelDesc collideSphereKernel;
KernelDesc collideCylinderKernel;
/**
* Integrate motion on the solver.
*/
virtual void integrate( float solverdt );
float computeTriangleArea(
const Vectormath::Aos::Point3 &vertex0,
const Vectormath::Aos::Point3 &vertex1,
const Vectormath::Aos::Point3 &vertex2 );
/**
* Compile a compute shader kernel from a string and return the appropriate KernelDesc object.
*/
KernelDesc compileComputeShaderFromString( const char* shaderString, const char* shaderName, int constBufferSize, D3D10_SHADER_MACRO *compileMacros = 0 );
bool buildShaders();
void resetNormalsAndAreas( int numVertices );
void normalizeNormalsAndAreas( int numVertices );
void executeUpdateSoftBodies( int firstTriangle, int numTriangles );
Vectormath::Aos::Vector3 ProjectOnAxis( const Vectormath::Aos::Vector3 &v, const Vectormath::Aos::Vector3 &a );
void ApplyClampedForce( float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce );
virtual void applyForces( float solverdt );
void updateConstants( float timeStep );
btAcceleratedSoftBodyInterface *findSoftBodyInterface( const btSoftBody* const softBody );
//////////////////////////////////////
// Kernel dispatches
void prepareLinks();
void updatePositionsFromVelocities( float solverdt );
void solveLinksForPosition( int startLink, int numLinks, float kst, float ti );
void solveLinksForVelocity( int startLink, int numLinks, float kst );
void updateVelocitiesFromPositionsWithVelocities( float isolverdt );
void updateVelocitiesFromPositionsWithoutVelocities( float isolverdt );
// End kernel dispatches
/////////////////////////////////////
void releaseKernels();
public:
btDX11SIMDAwareSoftBodySolver(ID3D11Device * dx11Device, ID3D11DeviceContext* dx11Context);
virtual ~btDX11SIMDAwareSoftBodySolver();
virtual btSoftBodyLinkData &getLinkData();
virtual btSoftBodyVertexData &getVertexData();
virtual btSoftBodyTriangleData &getTriangleData();
virtual bool checkInitialized();
virtual void updateSoftBodies( );
virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies );
virtual void solveConstraints( float solverdt );
virtual void predictMotion( float solverdt );
virtual void copySoftBodyToVertexBuffer( const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer );
};
#endif // #ifndef BT_SOFT_BODY_DX11_SOLVER_SIMDAWARE_H

View file

@ -0,0 +1,284 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="MinSizeRel|Win32">
<Configuration>MinSizeRel</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="RelWithDebInfo|Win32">
<Configuration>RelWithDebInfo</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGUID>{14266978-3E62-4DC3-AAEF-CB815EEB708D}</ProjectGUID>
<Keyword>Win32Proj</Keyword>
<Platform>Win32</Platform>
<ProjectName>BulletSoftBodySolvers_OpenCL_Mini</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">C:\Documents and Settings\Robert MacGregor\Desktop\bullet-2.77\lib\Debug\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">BulletSoftBodySolvers_OpenCL_Mini.dir\Debug\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">BulletSoftBodySolvers_OpenCL_Mini</TargetName>
<TargetExt Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.lib</TargetExt>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">C:\Documents and Settings\Robert MacGregor\Desktop\bullet-2.77\lib\Release\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">BulletSoftBodySolvers_OpenCL_Mini.dir\Release\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">BulletSoftBodySolvers_OpenCL_Mini</TargetName>
<TargetExt Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.lib</TargetExt>
<OutDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">C:\Documents and Settings\Robert MacGregor\Desktop\bullet-2.77\lib\MinSizeRel\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">BulletSoftBodySolvers_OpenCL_Mini.dir\MinSizeRel\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">BulletSoftBodySolvers_OpenCL_Mini</TargetName>
<TargetExt Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">.lib</TargetExt>
<OutDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">C:\Documents and Settings\Robert MacGregor\Desktop\bullet-2.77\lib\RelWithDebInfo\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">BulletSoftBodySolvers_OpenCL_Mini.dir\RelWithDebInfo\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">BulletSoftBodySolvers_OpenCL_Mini</TargetName>
<TargetExt Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">.lib</TargetExt>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<AdditionalOptions> /Zm1000 %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/Glut;C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<CompileAs>CompileAsCpp</CompileAs>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
<ExceptionHandling>Sync</ExceptionHandling>
<FloatingPointModel>Fast</FloatingPointModel>
<InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
<Optimization>Disabled</Optimization>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AssemblerListingLocation>Debug</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/lib/Debug/BulletSoftBodySolvers_OpenCL_Mini.pdb</ProgramDataBaseFileName>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/Glut;C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<Midl>
<AdditionalIncludeDirectories>C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/Glut;C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<OutputDirectory>$(IntDir)</OutputDirectory>
<HeaderFileName>%(Filename).h</HeaderFileName>
<TypeLibraryName>%(Filename).tlb</TypeLibraryName>
<InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
<ProxyFileName>%(Filename)_p.c</ProxyFileName>
</Midl>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalOptions> /Zm1000 %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/Glut;C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsCpp</CompileAs>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
<ExceptionHandling>Sync</ExceptionHandling>
<FloatingPointModel>Fast</FloatingPointModel>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<Optimization>MaxSpeed</Optimization>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat></DebugInformationFormat>
<PreprocessorDefinitions>WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AssemblerListingLocation>Release</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/lib/Release/BulletSoftBodySolvers_OpenCL_Mini.pdb</ProgramDataBaseFileName>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/Glut;C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<Midl>
<AdditionalIncludeDirectories>C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/Glut;C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<OutputDirectory>$(IntDir)</OutputDirectory>
<HeaderFileName>%(Filename).h</HeaderFileName>
<TypeLibraryName>%(Filename).tlb</TypeLibraryName>
<InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
<ProxyFileName>%(Filename)_p.c</ProxyFileName>
</Midl>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
<ClCompile>
<AdditionalOptions> /Zm1000 %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/Glut;C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsCpp</CompileAs>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
<ExceptionHandling>Sync</ExceptionHandling>
<FloatingPointModel>Fast</FloatingPointModel>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<Optimization>MinSpace</Optimization>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat></DebugInformationFormat>
<PreprocessorDefinitions>WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AssemblerListingLocation>MinSizeRel</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/lib/MinSizeRel/BulletSoftBodySolvers_OpenCL_Mini.pdb</ProgramDataBaseFileName>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/Glut;C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<Midl>
<AdditionalIncludeDirectories>C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/Glut;C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<OutputDirectory>$(IntDir)</OutputDirectory>
<HeaderFileName>%(Filename).h</HeaderFileName>
<TypeLibraryName>%(Filename).tlb</TypeLibraryName>
<InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
<ProxyFileName>%(Filename)_p.c</ProxyFileName>
</Midl>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
<ClCompile>
<AdditionalOptions> /Zm1000 %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/Glut;C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsCpp</CompileAs>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
<ExceptionHandling>Sync</ExceptionHandling>
<FloatingPointModel>Fast</FloatingPointModel>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<Optimization>MaxSpeed</Optimization>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AssemblerListingLocation>RelWithDebInfo</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/lib/RelWithDebInfo/BulletSoftBodySolvers_OpenCL_Mini.pdb</ProgramDataBaseFileName>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/Glut;C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<Midl>
<AdditionalIncludeDirectories>C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/Glut;C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<OutputDirectory>$(IntDir)</OutputDirectory>
<HeaderFileName>%(Filename).h</HeaderFileName>
<TypeLibraryName>%(Filename).tlb</TypeLibraryName>
<InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
<ProxyFileName>%(Filename)_p.c</ProxyFileName>
</Midl>
</ItemDefinitionGroup>
<ItemGroup>
<CustomBuild Include="CMakeLists.txt">
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt</Message>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
"C:\Program Files\CMake 2.8\bin\cmake.exe" "-HC:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77" "-BC:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77" --check-stamp-file "C:\Documents and Settings\Robert MacGregor\Desktop\bullet-2.77\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp"
if %errorlevel% neq 0 goto :cmEnd
:cmEnd
endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
:cmErrorLevel
exit /b %1
:cmDone
if %errorlevel% neq 0 goto :VCEnd</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt;C:\Documents and Settings\Robert MacGregor\Desktop\bullet-2.77\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;C:\Documents and Settings\Robert MacGregor\Desktop\bullet-2.77\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">C:\Documents and Settings\Robert MacGregor\Desktop\bullet-2.77\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp</Outputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt</Message>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
"C:\Program Files\CMake 2.8\bin\cmake.exe" "-HC:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77" "-BC:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77" --check-stamp-file "C:\Documents and Settings\Robert MacGregor\Desktop\bullet-2.77\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp"
if %errorlevel% neq 0 goto :cmEnd
:cmEnd
endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
:cmErrorLevel
exit /b %1
:cmDone
if %errorlevel% neq 0 goto :VCEnd</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt;C:\Documents and Settings\Robert MacGregor\Desktop\bullet-2.77\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;C:\Documents and Settings\Robert MacGregor\Desktop\bullet-2.77\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">C:\Documents and Settings\Robert MacGregor\Desktop\bullet-2.77\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp</Outputs>
<Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt</Message>
<Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
"C:\Program Files\CMake 2.8\bin\cmake.exe" "-HC:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77" "-BC:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77" --check-stamp-file "C:\Documents and Settings\Robert MacGregor\Desktop\bullet-2.77\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp"
if %errorlevel% neq 0 goto :cmEnd
:cmEnd
endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
:cmErrorLevel
exit /b %1
:cmDone
if %errorlevel% neq 0 goto :VCEnd</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt;C:\Documents and Settings\Robert MacGregor\Desktop\bullet-2.77\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;C:\Documents and Settings\Robert MacGregor\Desktop\bullet-2.77\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">C:\Documents and Settings\Robert MacGregor\Desktop\bullet-2.77\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp</Outputs>
<Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt</Message>
<Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
"C:\Program Files\CMake 2.8\bin\cmake.exe" "-HC:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77" "-BC:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77" --check-stamp-file "C:\Documents and Settings\Robert MacGregor\Desktop\bullet-2.77\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp"
if %errorlevel% neq 0 goto :cmEnd
:cmEnd
endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
:cmErrorLevel
exit /b %1
:cmDone
if %errorlevel% neq 0 goto :VCEnd</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt;C:\Documents and Settings\Robert MacGregor\Desktop\bullet-2.77\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;C:\Documents and Settings\Robert MacGregor\Desktop\bullet-2.77\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">C:\Documents and Settings\Robert MacGregor\Desktop\bullet-2.77\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp</Outputs>
</CustomBuild>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\btSoftBodySolver_OpenCL.h" />
<ClInclude Include="..\..\CPU\btSoftBodySolverData.h" />
<ClInclude Include="..\btSoftBodySolverVertexData_OpenCL.h" />
<ClInclude Include="..\btSoftBodySolverTriangleData_OpenCL.h" />
<ClInclude Include="..\btSoftBodySolverLinkData_OpenCL.h" />
<ClInclude Include="..\btSoftBodySolverBuffer_OpenCL.h" />
<ClCompile Include="..\btSoftBodySolver_OpenCL.cpp" />
<None Include="..\OpenCLC10\UpdateNormals.cl" />
<None Include="..\OpenCLC10\Integrate.cl" />
<None Include="..\OpenCLC10\UpdatePositions.cl" />
<None Include="..\OpenCLC10\UpdateNodes.cl" />
<None Include="..\OpenCLC10\SolvePositions.cl" />
<None Include="..\OpenCLC10\UpdatePositionsFromVelocities.cl" />
<None Include="..\OpenCLC10\ApplyForces.cl" />
<None Include="..\OpenCLC10\PrepareLinks.cl" />
<None Include="..\OpenCLC10\VSolveLinks.cl" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/ZERO_CHECK.vcxproj">
<Project>C0E57694-ABCD-4C08-B9A4-F249AD836120</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="..\btSoftBodySolver_OpenCL.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\btSoftBodySolver_OpenCL.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\CPU\btSoftBodySolverData.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\btSoftBodySolverVertexData_OpenCL.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\btSoftBodySolverTriangleData_OpenCL.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\btSoftBodySolverLinkData_OpenCL.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\btSoftBodySolverBuffer_OpenCL.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="CMakeLists.txt" />
</ItemGroup>
<ItemGroup>
<None Include="..\OpenCLC10\UpdateNormals.cl" />
<None Include="..\OpenCLC10\Integrate.cl" />
<None Include="..\OpenCLC10\UpdatePositions.cl" />
<None Include="..\OpenCLC10\UpdateNodes.cl" />
<None Include="..\OpenCLC10\SolvePositions.cl" />
<None Include="..\OpenCLC10\UpdatePositionsFromVelocities.cl" />
<None Include="..\OpenCLC10\ApplyForces.cl" />
<None Include="..\OpenCLC10\PrepareLinks.cl" />
<None Include="..\OpenCLC10\VSolveLinks.cl" />
</ItemGroup>
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{C487BFC5-6BC8-47B3-88D6-C5D9B883A3BD}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{30F7A2E9-D73F-45A4-9CAC-B039D62294E1}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

View file

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
</Project>

View file

@ -0,0 +1 @@
# CMake generation timestamp file this directory.

View file

@ -0,0 +1,2 @@
# CMake generation dependency list for this directory.
C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt

View file

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

View file

@ -0,0 +1,40 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include <MiniCL/cl_MiniCL_Defs.h>
#define MSTRINGIFY(A) A
#include "../OpenCLC10/ApplyForces.cl"
#include "../OpenCLC10/Integrate.cl"
#include "../OpenCLC10/PrepareLinks.cl"
#include "../OpenCLC10/SolvePositions.cl"
#include "../OpenCLC10/UpdateNodes.cl"
#include "../OpenCLC10/UpdateNormals.cl"
#include "../OpenCLC10/UpdatePositions.cl"
#include "../OpenCLC10/UpdatePositionsFromVelocities.cl"
//#include "../OpenCLC10/VSolveLinks.cl"
MINICL_REGISTER(PrepareLinksKernel)
MINICL_REGISTER(UpdatePositionsFromVelocitiesKernel)
MINICL_REGISTER(SolvePositionsFromLinksKernel)
MINICL_REGISTER(updateVelocitiesFromPositionsWithVelocitiesKernel)
MINICL_REGISTER(updateVelocitiesFromPositionsWithoutVelocitiesKernel)
MINICL_REGISTER(IntegrateKernel)
MINICL_REGISTER(ApplyForcesKernel)
MINICL_REGISTER(ResetNormalsAndAreasKernel)
MINICL_REGISTER(NormalizeNormalsAndAreasKernel)
MINICL_REGISTER(UpdateSoftBodiesKernel)

View file

@ -0,0 +1,29 @@
# Install script for directory: C:/Documents and Settings/Robert MacGregor/Desktop/bullet-2.77/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL
# Set the install prefix
IF(NOT DEFINED CMAKE_INSTALL_PREFIX)
SET(CMAKE_INSTALL_PREFIX "C:/Program Files/BULLET_PHYSICS")
ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX)
STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
# Set the install configuration name.
IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
IF(BUILD_TYPE)
STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
ELSE(BUILD_TYPE)
SET(CMAKE_INSTALL_CONFIG_NAME "Release")
ENDIF(BUILD_TYPE)
MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
# Set the component getting installed.
IF(NOT CMAKE_INSTALL_COMPONENT)
IF(COMPONENT)
MESSAGE(STATUS "Install component: \"${COMPONENT}\"")
SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
ELSE(COMPONENT)
SET(CMAKE_INSTALL_COMPONENT)
ENDIF(COMPONENT)
ENDIF(NOT CMAKE_INSTALL_COMPONENT)

View file

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

View file

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

View file

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

View file

@ -0,0 +1,62 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_SOFT_BODY_SOLVER_OUTPUT_CL_TO_GL_H
#define BT_SOFT_BODY_SOLVER_OUTPUT_CL_TO_GL_H
#include "btSoftBodySolver_OpenCL.h"
/**
* Class to manage movement of data from a solver to a given target.
* This version is the CL to GL interop version.
*/
class btSoftBodySolverOutputCLtoGL : public btSoftBodySolverOutput
{
protected:
cl_command_queue m_cqCommandQue;
cl_context m_cxMainContext;
CLFunctions clFunctions;
cl_kernel outputToVertexArrayWithNormalsKernel;
cl_kernel outputToVertexArrayWithoutNormalsKernel;
bool m_shadersInitialized;
virtual bool checkInitialized();
virtual bool buildShaders();
void releaseKernels();
public:
btSoftBodySolverOutputCLtoGL(cl_command_queue cqCommandQue, cl_context cxMainContext) :
m_cqCommandQue( cqCommandQue ),
m_cxMainContext( cxMainContext ),
clFunctions(cqCommandQue, cxMainContext),
outputToVertexArrayWithNormalsKernel( 0 ),
outputToVertexArrayWithoutNormalsKernel( 0 ),
m_shadersInitialized( false )
{
}
virtual ~btSoftBodySolverOutputCLtoGL()
{
releaseKernels();
}
/** Output current computed vertex data to the vertex buffers for all cloths in the solver. */
virtual void copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer );
};
#endif // #ifndef BT_SOFT_BODY_SOLVER_OUTPUT_CL_TO_GL_H

View file

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

View file

@ -0,0 +1,166 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_OPENGL_H
#define BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_OPENGL_H
#include "BulletSoftBody/btSoftBodySolverVertexBuffer.h"
#ifdef USE_MINICL
#include "MiniCL/cl.h"
#else //USE_MINICL
#ifdef __APPLE__
#include <OpenCL/OpenCL.h>
#else
#include <CL/cl.h>
#include <CL/cl_gl.h>
#endif //__APPLE__
#endif//USE_MINICL
#ifdef _WIN32//for glut.h
#include <windows.h>
#endif
//think different
#if defined(__APPLE__) && !defined (VMDMESA)
#include <OpenGL/OpenGL.h>
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <GLUT/glut.h>
#else
#ifdef _WINDOWS
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#else
#include <GL/glut.h>
#endif //_WINDOWS
#endif //APPLE
class btOpenGLInteropVertexBufferDescriptor : public btVertexBufferDescriptor
{
protected:
/** OpenCL context */
cl_context m_context;
/** OpenCL command queue */
cl_command_queue m_commandQueue;
/** OpenCL interop buffer */
cl_mem m_buffer;
/** VBO in GL that is the basis of the interop buffer */
GLuint m_openGLVBO;
public:
/**
* context is the OpenCL context this interop buffer will work in.
* queue is the command queue that kernels and data movement will be enqueued into.
* openGLVBO is the OpenGL vertex buffer data will be copied into.
* vertexOffset is the offset in floats to the first vertex.
* vertexStride is the stride in floats between vertices.
*/
btOpenGLInteropVertexBufferDescriptor( cl_command_queue cqCommandQue, cl_context context, GLuint openGLVBO, int vertexOffset, int vertexStride )
{
#ifndef USE_MINICL
cl_int ciErrNum = CL_SUCCESS;
m_context = context;
m_commandQueue = cqCommandQue;
m_vertexOffset = vertexOffset;
m_vertexStride = vertexStride;
m_openGLVBO = openGLVBO;
m_buffer = clCreateFromGLBuffer(m_context, CL_MEM_WRITE_ONLY, openGLVBO, &ciErrNum);
if( ciErrNum != CL_SUCCESS )
{
btAssert( 0 && "clEnqueueAcquireGLObjects(copySoftBodyToVertexBuffer)");
}
m_hasVertexPositions = true;
#else
btAssert(0);//MiniCL shouldn't get here
#endif
}
/**
* context is the OpenCL context this interop buffer will work in.
* queue is the command queue that kernels and data movement will be enqueued into.
* openGLVBO is the OpenGL vertex buffer data will be copied into.
* vertexOffset is the offset in floats to the first vertex.
* vertexStride is the stride in floats between vertices.
* normalOffset is the offset in floats to the first normal.
* normalStride is the stride in floats between normals.
*/
btOpenGLInteropVertexBufferDescriptor( cl_command_queue cqCommandQue, cl_context context, GLuint openGLVBO, int vertexOffset, int vertexStride, int normalOffset, int normalStride )
{
#ifndef USE_MINICL
cl_int ciErrNum = CL_SUCCESS;
m_context = context;
m_commandQueue = cqCommandQue;
m_openGLVBO = openGLVBO;
m_buffer = clCreateFromGLBuffer(m_context, CL_MEM_WRITE_ONLY, openGLVBO, &ciErrNum);
if( ciErrNum != CL_SUCCESS )
{
btAssert( 0 && "clEnqueueAcquireGLObjects(copySoftBodyToVertexBuffer)");
}
m_vertexOffset = vertexOffset;
m_vertexStride = vertexStride;
m_hasVertexPositions = true;
m_normalOffset = normalOffset;
m_normalStride = normalStride;
m_hasNormals = true;
#else
btAssert(0);
#endif //USE_MINICL
}
virtual ~btOpenGLInteropVertexBufferDescriptor()
{
clReleaseMemObject( m_buffer );
}
/**
* Return the type of the vertex buffer descriptor.
*/
virtual BufferTypes getBufferType() const
{
return OPENGL_BUFFER;
}
virtual cl_context getContext() const
{
return m_context;
}
virtual cl_mem getBuffer() const
{
return m_buffer;
}
};
#endif // #ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_OPENGL_H

View file

@ -0,0 +1,52 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolverData.h"
#include "btSoftBodySolverBuffer_OpenCL.h"
#ifndef BT_SOFT_BODY_SOLVER_VERTEX_DATA_OPENCL_H
#define BT_SOFT_BODY_SOLVER_VERTEX_DATA_OPENCL_H
class btSoftBodyVertexDataOpenCL : public btSoftBodyVertexData
{
protected:
bool m_onGPU;
cl_command_queue m_queue;
public:
btOpenCLBuffer<int> m_clClothIdentifier;
btOpenCLBuffer<Vectormath::Aos::Point3> m_clVertexPosition;
btOpenCLBuffer<Vectormath::Aos::Point3> m_clVertexPreviousPosition;
btOpenCLBuffer<Vectormath::Aos::Vector3> m_clVertexVelocity;
btOpenCLBuffer<Vectormath::Aos::Vector3> m_clVertexForceAccumulator;
btOpenCLBuffer<Vectormath::Aos::Vector3> m_clVertexNormal;
btOpenCLBuffer<float> m_clVertexInverseMass;
btOpenCLBuffer<float> m_clVertexArea;
btOpenCLBuffer<int> m_clVertexTriangleCount;
public:
btSoftBodyVertexDataOpenCL( cl_command_queue queue, cl_context ctx);
virtual ~btSoftBodyVertexDataOpenCL();
virtual bool onAccelerator();
virtual bool moveToAccelerator();
virtual bool moveFromAccelerator();
};
#endif // #ifndef BT_SOFT_BODY_SOLVER_VERTEX_DATA_OPENCL_H

View file

@ -0,0 +1,344 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_SOFT_BODY_SOLVER_OPENCL_H
#define BT_SOFT_BODY_SOLVER_OPENCL_H
#include "stddef.h" //for size_t
#include "vectormath/vmInclude.h"
#include "BulletSoftBody/btSoftBodySolvers.h"
#include "btSoftBodySolverBuffer_OpenCL.h"
#include "btSoftBodySolverLinkData_OpenCL.h"
#include "btSoftBodySolverVertexData_OpenCL.h"
#include "btSoftBodySolverTriangleData_OpenCL.h"
/**
* SoftBody class to maintain information about a soft body instance
* within a solver.
* This data addresses the main solver arrays.
*/
class btOpenCLAcceleratedSoftBodyInterface
{
protected:
/** Current number of vertices that are part of this cloth */
int m_numVertices;
/** Maximum number of vertices allocated to be part of this cloth */
int m_maxVertices;
/** Current number of triangles that are part of this cloth */
int m_numTriangles;
/** Maximum number of triangles allocated to be part of this cloth */
int m_maxTriangles;
/** Index of first vertex in the world allocated to this cloth */
int m_firstVertex;
/** Index of first triangle in the world allocated to this cloth */
int m_firstTriangle;
/** Index of first link in the world allocated to this cloth */
int m_firstLink;
/** Maximum number of links allocated to this cloth */
int m_maxLinks;
/** Current number of links allocated to this cloth */
int m_numLinks;
/** The actual soft body this data represents */
btSoftBody *m_softBody;
public:
btOpenCLAcceleratedSoftBodyInterface( btSoftBody *softBody ) :
m_softBody( softBody )
{
m_numVertices = 0;
m_maxVertices = 0;
m_numTriangles = 0;
m_maxTriangles = 0;
m_firstVertex = 0;
m_firstTriangle = 0;
m_firstLink = 0;
m_maxLinks = 0;
m_numLinks = 0;
}
int getNumVertices()
{
return m_numVertices;
}
int getNumTriangles()
{
return m_numTriangles;
}
int getMaxVertices()
{
return m_maxVertices;
}
int getMaxTriangles()
{
return m_maxTriangles;
}
int getFirstVertex()
{
return m_firstVertex;
}
int getFirstTriangle()
{
return m_firstTriangle;
}
// TODO: All of these set functions will have to do checks and
// update the world because restructuring of the arrays will be necessary
// Reasonable use of "friend"?
void setNumVertices( int numVertices )
{
m_numVertices = numVertices;
}
void setNumTriangles( int numTriangles )
{
m_numTriangles = numTriangles;
}
void setMaxVertices( int maxVertices )
{
m_maxVertices = maxVertices;
}
void setMaxTriangles( int maxTriangles )
{
m_maxTriangles = maxTriangles;
}
void setFirstVertex( int firstVertex )
{
m_firstVertex = firstVertex;
}
void setFirstTriangle( int firstTriangle )
{
m_firstTriangle = firstTriangle;
}
void setMaxLinks( int maxLinks )
{
m_maxLinks = maxLinks;
}
void setNumLinks( int numLinks )
{
m_numLinks = numLinks;
}
void setFirstLink( int firstLink )
{
m_firstLink = firstLink;
}
int getMaxLinks()
{
return m_maxLinks;
}
int getNumLinks()
{
return m_numLinks;
}
int getFirstLink()
{
return m_firstLink;
}
btSoftBody* getSoftBody()
{
return m_softBody;
}
};
class btOpenCLSoftBodySolver : public btSoftBodySolver
{
private:
btSoftBodyLinkDataOpenCL m_linkData;
btSoftBodyVertexDataOpenCL m_vertexData;
btSoftBodyTriangleDataOpenCL m_triangleData;
/** Variable to define whether we need to update solver constants on the next iteration */
bool m_updateSolverConstants;
bool m_shadersInitialized;
/**
* Cloths owned by this solver.
* Only our cloths are in this array.
*/
btAlignedObjectArray< btOpenCLAcceleratedSoftBodyInterface * > m_softBodySet;
/** Acceleration value to be applied to all non-static vertices in the solver.
* Index n is cloth n, array sized by number of cloths in the world not the solver.
*/
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothAcceleration;
btOpenCLBuffer<Vectormath::Aos::Vector3> m_clPerClothAcceleration;
/** Wind velocity to be applied normal to all non-static vertices in the solver.
* Index n is cloth n, array sized by number of cloths in the world not the solver.
*/
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothWindVelocity;
btOpenCLBuffer<Vectormath::Aos::Vector3> m_clPerClothWindVelocity;
/** Velocity damping factor */
btAlignedObjectArray< float > m_perClothDampingFactor;
btOpenCLBuffer<float> m_clPerClothDampingFactor;
/** Velocity correction coefficient */
btAlignedObjectArray< float > m_perClothVelocityCorrectionCoefficient;
btOpenCLBuffer<float> m_clPerClothVelocityCorrectionCoefficient;
/** Lift parameter for wind effect on cloth. */
btAlignedObjectArray< float > m_perClothLiftFactor;
btOpenCLBuffer<float> m_clPerClothLiftFactor;
/** Drag parameter for wind effect on cloth. */
btAlignedObjectArray< float > m_perClothDragFactor;
btOpenCLBuffer<float> m_clPerClothDragFactor;
/** Density of the medium in which each cloth sits */
btAlignedObjectArray< float > m_perClothMediumDensity;
btOpenCLBuffer<float> m_clPerClothMediumDensity;
cl_kernel prepareLinksKernel;
cl_kernel solvePositionsFromLinksKernel;
cl_kernel updateConstantsKernel;
cl_kernel integrateKernel;
cl_kernel addVelocityKernel;
cl_kernel updatePositionsFromVelocitiesKernel;
cl_kernel updateVelocitiesFromPositionsWithoutVelocitiesKernel;
cl_kernel updateVelocitiesFromPositionsWithVelocitiesKernel;
cl_kernel vSolveLinksKernel;
cl_kernel resetNormalsAndAreasKernel;
cl_kernel normalizeNormalsAndAreasKernel;
cl_kernel updateSoftBodiesKernel;
cl_kernel outputToVertexArrayWithNormalsKernel;
cl_kernel outputToVertexArrayWithoutNormalsKernel;
cl_kernel outputToVertexArrayKernel;
cl_kernel applyForcesKernel;
cl_kernel collideSphereKernel;
cl_kernel collideCylinderKernel;
cl_command_queue m_cqCommandQue;
cl_context m_cxMainContext;
size_t m_defaultWorkGroupSize;
/**
* Compile a compute shader kernel from a string and return the appropriate cl_kernel object.
*/
cl_kernel compileCLKernelFromString( const char *shaderString, const char *shaderName );
bool buildShaders();
void resetNormalsAndAreas( int numVertices );
void normalizeNormalsAndAreas( int numVertices );
void executeUpdateSoftBodies( int firstTriangle, int numTriangles );
Vectormath::Aos::Vector3 ProjectOnAxis( const Vectormath::Aos::Vector3 &v, const Vectormath::Aos::Vector3 &a );
void ApplyClampedForce( float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce );
btOpenCLAcceleratedSoftBodyInterface *findSoftBodyInterface( const btSoftBody* const softBody );
virtual void applyForces( float solverdt );
/**
* Integrate motion on the solver.
*/
virtual void integrate( float solverdt );
void updateConstants( float timeStep );
float computeTriangleArea(
const Vectormath::Aos::Point3 &vertex0,
const Vectormath::Aos::Point3 &vertex1,
const Vectormath::Aos::Point3 &vertex2 );
//////////////////////////////////////
// Kernel dispatches
void prepareLinks();
void solveLinksForVelocity( int startLink, int numLinks, float kst );
void updatePositionsFromVelocities( float solverdt );
void solveLinksForPosition( int startLink, int numLinks, float kst, float ti );
void updateVelocitiesFromPositionsWithVelocities( float isolverdt );
void updateVelocitiesFromPositionsWithoutVelocities( float isolverdt );
// End kernel dispatches
/////////////////////////////////////
public:
btOpenCLSoftBodySolver(cl_command_queue queue,cl_context ctx);
virtual ~btOpenCLSoftBodySolver();
virtual btSoftBodyLinkData &getLinkData();
virtual btSoftBodyVertexData &getVertexData();
virtual btSoftBodyTriangleData &getTriangleData();
virtual bool checkInitialized();
virtual void updateSoftBodies( );
virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies );
virtual void solveConstraints( float solverdt );
virtual void predictMotion( float solverdt );
virtual void copySoftBodyToVertexBuffer( const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer );
virtual void setDefaultWorkgroupSize(size_t workGroupSize)
{
m_defaultWorkGroupSize = workGroupSize;
}
virtual size_t getDefaultWorkGroupSize() const
{
return m_defaultWorkGroupSize;
}
}; // btOpenCLSoftBodySolver
#endif // #ifndef BT_SOFT_BODY_SOLVER_OPENCL_H

View file

@ -0,0 +1,81 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_SOFT_BODY_SOLVER_OPENCL_SIMDAWARE_H
#define BT_SOFT_BODY_SOLVER_OPENCL_SIMDAWARE_H
#include "stddef.h" //for size_t
#include "vectormath/vmInclude.h"
#include "btSoftBodySolver_OpenCL.h"
#include "btSoftBodySolverBuffer_OpenCL.h"
#include "btSoftBodySolverLinkData_OpenCLSIMDAware.h"
#include "btSoftBodySolverVertexData_OpenCL.h"
#include "btSoftBodySolverTriangleData_OpenCL.h"
class btOpenCLSoftBodySolverSIMDAware : public btOpenCLSoftBodySolver
{
protected:
btSoftBodyLinkDataOpenCLSIMDAware m_linkData;
virtual bool buildShaders();
void updateConstants( float timeStep );
float computeTriangleArea(
const Vectormath::Aos::Point3 &vertex0,
const Vectormath::Aos::Point3 &vertex1,
const Vectormath::Aos::Point3 &vertex2 );
//////////////////////////////////////
// Kernel dispatches
void solveLinksForPosition( int startLink, int numLinks, float kst, float ti );
void solveCollisionsAndUpdateVelocities( float isolverdt );
// End kernel dispatches
/////////////////////////////////////
public:
btOpenCLSoftBodySolverSIMDAware(cl_command_queue queue,cl_context ctx, bool bUpdateAchchoredNodePos = false);
virtual ~btOpenCLSoftBodySolverSIMDAware();
virtual SolverTypes getSolverType() const
{
return CL_SIMD_SOLVER;
}
virtual btSoftBodyLinkData &getLinkData();
virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate=false);
virtual void solveConstraints( float solverdt );
}; // btOpenCLSoftBodySolverSIMDAware
#endif // #ifndef BT_SOFT_BODY_SOLVER_OPENCL_SIMDAWARE_H

View file

@ -0,0 +1,748 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_SOFT_BODY_SOLVER_DATA_H
#define BT_SOFT_BODY_SOLVER_DATA_H
#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
#include "vectormath/vmInclude.h"
class btSoftBodyLinkData
{
public:
/**
* Class representing a link as a set of three indices into the vertex array.
*/
class LinkNodePair
{
public:
int vertex0;
int vertex1;
LinkNodePair()
{
vertex0 = 0;
vertex1 = 0;
}
LinkNodePair( int v0, int v1 )
{
vertex0 = v0;
vertex1 = v1;
}
};
/**
* Class describing a link for input into the system.
*/
class LinkDescription
{
protected:
int m_vertex0;
int m_vertex1;
float m_linkLinearStiffness;
float m_linkStrength;
public:
LinkDescription()
{
m_vertex0 = 0;
m_vertex1 = 0;
m_linkLinearStiffness = 1.0;
m_linkStrength = 1.0;
}
LinkDescription( int newVertex0, int newVertex1, float linkLinearStiffness )
{
m_vertex0 = newVertex0;
m_vertex1 = newVertex1;
m_linkLinearStiffness = linkLinearStiffness;
m_linkStrength = 1.0;
}
LinkNodePair getVertexPair() const
{
LinkNodePair nodes;
nodes.vertex0 = m_vertex0;
nodes.vertex1 = m_vertex1;
return nodes;
}
void setVertex0( int vertex )
{
m_vertex0 = vertex;
}
void setVertex1( int vertex )
{
m_vertex1 = vertex;
}
void setLinkLinearStiffness( float linearStiffness )
{
m_linkLinearStiffness = linearStiffness;
}
void setLinkStrength( float strength )
{
m_linkStrength = strength;
}
int getVertex0() const
{
return m_vertex0;
}
int getVertex1() const
{
return m_vertex1;
}
float getLinkStrength() const
{
return m_linkStrength;
}
float getLinkLinearStiffness() const
{
return m_linkLinearStiffness;
}
};
protected:
// NOTE:
// Vertex reference data is stored relative to global array, not relative to individual cloth.
// Values must be correct if being passed into single-cloth VBOs or when migrating from one solver
// to another.
btAlignedObjectArray< LinkNodePair > m_links; // Vertex pair for the link
btAlignedObjectArray< float > m_linkStrength; // Strength of each link
// (inverseMassA + inverseMassB)/ linear stiffness coefficient
btAlignedObjectArray< float > m_linksMassLSC;
btAlignedObjectArray< float > m_linksRestLengthSquared;
// Current vector length of link
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_linksCLength;
// 1/(current length * current length * massLSC)
btAlignedObjectArray< float > m_linksLengthRatio;
btAlignedObjectArray< float > m_linksRestLength;
btAlignedObjectArray< float > m_linksMaterialLinearStiffnessCoefficient;
public:
btSoftBodyLinkData()
{
}
virtual ~btSoftBodyLinkData()
{
}
virtual void clear()
{
m_links.resize(0);
m_linkStrength.resize(0);
m_linksMassLSC.resize(0);
m_linksRestLengthSquared.resize(0);
m_linksLengthRatio.resize(0);
m_linksRestLength.resize(0);
m_linksMaterialLinearStiffnessCoefficient.resize(0);
}
int getNumLinks()
{
return m_links.size();
}
/** Allocate enough space in all link-related arrays to fit numLinks links */
virtual void createLinks( int numLinks )
{
int previousSize = m_links.size();
int newSize = previousSize + numLinks;
// Resize all the arrays that store link data
m_links.resize( newSize );
m_linkStrength.resize( newSize );
m_linksMassLSC.resize( newSize );
m_linksRestLengthSquared.resize( newSize );
m_linksCLength.resize( newSize );
m_linksLengthRatio.resize( newSize );
m_linksRestLength.resize( newSize );
m_linksMaterialLinearStiffnessCoefficient.resize( newSize );
}
/** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */
virtual void setLinkAt( const LinkDescription &link, int linkIndex )
{
m_links[linkIndex] = link.getVertexPair();
m_linkStrength[linkIndex] = link.getLinkStrength();
m_linksMassLSC[linkIndex] = 0.f;
m_linksRestLengthSquared[linkIndex] = 0.f;
m_linksCLength[linkIndex] = Vectormath::Aos::Vector3(0.f, 0.f, 0.f);
m_linksLengthRatio[linkIndex] = 0.f;
m_linksRestLength[linkIndex] = 0.f;
m_linksMaterialLinearStiffnessCoefficient[linkIndex] = link.getLinkLinearStiffness();
}
/**
* Return true if data is on the accelerator.
* The CPU version of this class will return true here because
* the CPU is the same as the accelerator.
*/
virtual bool onAccelerator()
{
return true;
}
/**
* Move data from host memory to the accelerator.
* The CPU version will always return that it has moved it.
*/
virtual bool moveToAccelerator()
{
return true;
}
/**
* Move data from host memory from the accelerator.
* The CPU version will always return that it has moved it.
*/
virtual bool moveFromAccelerator()
{
return true;
}
/**
* Return reference to the vertex index pair for link linkIndex as stored on the host.
*/
LinkNodePair &getVertexPair( int linkIndex )
{
return m_links[linkIndex];
}
/**
* Return reference to strength of link linkIndex as stored on the host.
*/
float &getStrength( int linkIndex )
{
return m_linkStrength[linkIndex];
}
/**
* Return a reference to the strength of the link corrected for link sorting.
* This is important if we are using data on an accelerator which has the data sorted in some fashion.
*/
virtual float &getStrengthCorrected( int linkIndex )
{
return getStrength( linkIndex );
}
/**
* Return reference to the rest length of link linkIndex as stored on the host.
*/
float &getRestLength( int linkIndex )
{
return m_linksRestLength[linkIndex];
}
/**
* Return reference to linear stiffness coefficient for link linkIndex as stored on the host.
*/
float &getLinearStiffnessCoefficient( int linkIndex )
{
return m_linksMaterialLinearStiffnessCoefficient[linkIndex];
}
/**
* Return reference to the MassLSC value for link linkIndex as stored on the host.
*/
float &getMassLSC( int linkIndex )
{
return m_linksMassLSC[linkIndex];
}
/**
* Return reference to rest length squared for link linkIndex as stored on the host.
*/
float &getRestLengthSquared( int linkIndex )
{
return m_linksRestLengthSquared[linkIndex];
}
/**
* Return reference to current length of link linkIndex as stored on the host.
*/
Vectormath::Aos::Vector3 &getCurrentLength( int linkIndex )
{
return m_linksCLength[linkIndex];
}
/**
* Return the link length ratio from for link linkIndex as stored on the host.
*/
float &getLinkLengthRatio( int linkIndex )
{
return m_linksLengthRatio[linkIndex];
}
};
/**
* Wrapper for vertex data information.
* By wrapping it like this we stand a good chance of being able to optimise for storage format easily.
* It should also help us make sure all the data structures remain consistent.
*/
class btSoftBodyVertexData
{
public:
/**
* Class describing a vertex for input into the system.
*/
class VertexDescription
{
private:
Vectormath::Aos::Point3 m_position;
/** Inverse mass. If this is 0f then the mass was 0 because that simplifies calculations. */
float m_inverseMass;
public:
VertexDescription()
{
m_position = Vectormath::Aos::Point3( 0.f, 0.f, 0.f );
m_inverseMass = 0.f;
}
VertexDescription( const Vectormath::Aos::Point3 &position, float mass )
{
m_position = position;
if( mass > 0.f )
m_inverseMass = 1.0f/mass;
else
m_inverseMass = 0.f;
}
void setPosition( const Vectormath::Aos::Point3 &position )
{
m_position = position;
}
void setInverseMass( float inverseMass )
{
m_inverseMass = inverseMass;
}
void setMass( float mass )
{
if( mass > 0.f )
m_inverseMass = 1.0f/mass;
else
m_inverseMass = 0.f;
}
Vectormath::Aos::Point3 getPosition() const
{
return m_position;
}
float getInverseMass() const
{
return m_inverseMass;
}
float getMass() const
{
if( m_inverseMass == 0.f )
return 0.f;
else
return 1.0f/m_inverseMass;
}
};
protected:
// identifier for the individual cloth
// For the CPU we don't really need this as we can grab the cloths and iterate over only their vertices
// For a parallel accelerator knowing on a per-vertex basis which cloth we're part of will help for obtaining
// per-cloth data
// For sorting etc it might also be helpful to be able to use in-array data such as this.
btAlignedObjectArray< int > m_clothIdentifier;
btAlignedObjectArray< Vectormath::Aos::Point3 > m_vertexPosition; // vertex positions
btAlignedObjectArray< Vectormath::Aos::Point3 > m_vertexPreviousPosition; // vertex positions
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_vertexVelocity; // Velocity
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_vertexForceAccumulator; // Force accumulator
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_vertexNormal; // Normals
btAlignedObjectArray< float > m_vertexInverseMass; // Inverse mass
btAlignedObjectArray< float > m_vertexArea; // Area controlled by the vertex
btAlignedObjectArray< int > m_vertexTriangleCount; // Number of triangles touching this vertex
public:
btSoftBodyVertexData()
{
}
virtual ~btSoftBodyVertexData()
{
}
virtual void clear()
{
m_clothIdentifier.resize(0);
m_vertexPosition.resize(0);
m_vertexPreviousPosition.resize(0);
m_vertexVelocity.resize(0);
m_vertexForceAccumulator.resize(0);
m_vertexNormal.resize(0);
m_vertexInverseMass.resize(0);
m_vertexArea.resize(0);
m_vertexTriangleCount.resize(0);
}
int getNumVertices()
{
return m_vertexPosition.size();
}
int getClothIdentifier( int vertexIndex )
{
return m_clothIdentifier[vertexIndex];
}
void setVertexAt( const VertexDescription &vertex, int vertexIndex )
{
m_vertexPosition[vertexIndex] = vertex.getPosition();
m_vertexPreviousPosition[vertexIndex] = vertex.getPosition();
m_vertexVelocity[vertexIndex] = Vectormath::Aos::Vector3(0.f, 0.f, 0.f);
m_vertexForceAccumulator[vertexIndex] = Vectormath::Aos::Vector3(0.f, 0.f, 0.f);
m_vertexNormal[vertexIndex] = Vectormath::Aos::Vector3(0.f, 0.f, 0.f);
m_vertexInverseMass[vertexIndex] = vertex.getInverseMass();
m_vertexArea[vertexIndex] = 0.f;
m_vertexTriangleCount[vertexIndex] = 0;
}
/**
* Create numVertices new vertices for cloth clothIdentifier
* maxVertices allows a buffer zone of extra vertices for alignment or tearing reasons.
*/
void createVertices( int numVertices, int clothIdentifier, int maxVertices = 0 )
{
int previousSize = m_vertexPosition.size();
if( maxVertices == 0 )
maxVertices = numVertices;
int newSize = previousSize + maxVertices;
// Resize all the arrays that store vertex data
m_clothIdentifier.resize( newSize );
m_vertexPosition.resize( newSize );
m_vertexPreviousPosition.resize( newSize );
m_vertexVelocity.resize( newSize );
m_vertexForceAccumulator.resize( newSize );
m_vertexNormal.resize( newSize );
m_vertexInverseMass.resize( newSize );
m_vertexArea.resize( newSize );
m_vertexTriangleCount.resize( newSize );
for( int vertexIndex = previousSize; vertexIndex < newSize; ++vertexIndex )
m_clothIdentifier[vertexIndex] = clothIdentifier;
for( int vertexIndex = (previousSize + numVertices); vertexIndex < newSize; ++vertexIndex )
m_clothIdentifier[vertexIndex] = -1;
}
// Get and set methods in header so they can be inlined
/**
* Return a reference to the position of vertex vertexIndex as stored on the host.
*/
Vectormath::Aos::Point3 &getPosition( int vertexIndex )
{
return m_vertexPosition[vertexIndex];
}
Vectormath::Aos::Point3 getPosition( int vertexIndex ) const
{
return m_vertexPosition[vertexIndex];
}
/**
* Return a reference to the previous position of vertex vertexIndex as stored on the host.
*/
Vectormath::Aos::Point3 &getPreviousPosition( int vertexIndex )
{
return m_vertexPreviousPosition[vertexIndex];
}
/**
* Return a reference to the velocity of vertex vertexIndex as stored on the host.
*/
Vectormath::Aos::Vector3 &getVelocity( int vertexIndex )
{
return m_vertexVelocity[vertexIndex];
}
/**
* Return a reference to the force accumulator of vertex vertexIndex as stored on the host.
*/
Vectormath::Aos::Vector3 &getForceAccumulator( int vertexIndex )
{
return m_vertexForceAccumulator[vertexIndex];
}
/**
* Return a reference to the normal of vertex vertexIndex as stored on the host.
*/
Vectormath::Aos::Vector3 &getNormal( int vertexIndex )
{
return m_vertexNormal[vertexIndex];
}
Vectormath::Aos::Vector3 getNormal( int vertexIndex ) const
{
return m_vertexNormal[vertexIndex];
}
/**
* Return a reference to the inverse mass of vertex vertexIndex as stored on the host.
*/
float &getInverseMass( int vertexIndex )
{
return m_vertexInverseMass[vertexIndex];
}
/**
* Get access to the area controlled by this vertex.
*/
float &getArea( int vertexIndex )
{
return m_vertexArea[vertexIndex];
}
/**
* Get access to the array of how many triangles touch each vertex.
*/
int &getTriangleCount( int vertexIndex )
{
return m_vertexTriangleCount[vertexIndex];
}
/**
* Return true if data is on the accelerator.
* The CPU version of this class will return true here because
* the CPU is the same as the accelerator.
*/
virtual bool onAccelerator()
{
return true;
}
/**
* Move data from host memory to the accelerator.
* The CPU version will always return that it has moved it.
*/
virtual bool moveToAccelerator()
{
return true;
}
/**
* Move data to host memory from the accelerator if bCopy is false.
* If bCopy is true, copy data to host memory from the accelerator so that data
* won't be moved to accelerator when moveToAccelerator() is called next time.
* If bCopyMinimum is true, only vertex position and normal are copied.
* bCopyMinimum will be meaningful only if bCopy is true.
* The CPU version will always return that it has moved it.
*/
virtual bool moveFromAccelerator(bool bCopy = false, bool bCopyMinimum = true)
{
return true;
}
btAlignedObjectArray< Vectormath::Aos::Point3 > &getVertexPositions()
{
return m_vertexPosition;
}
};
class btSoftBodyTriangleData
{
public:
/**
* Class representing a triangle as a set of three indices into the
* vertex array.
*/
class TriangleNodeSet
{
public:
int vertex0;
int vertex1;
int vertex2;
int _padding;
TriangleNodeSet( )
{
vertex0 = 0;
vertex1 = 0;
vertex2 = 0;
_padding = -1;
}
TriangleNodeSet( int newVertex0, int newVertex1, int newVertex2 )
{
vertex0 = newVertex0;
vertex1 = newVertex1;
vertex2 = newVertex2;
}
};
class TriangleDescription
{
protected:
int m_vertex0;
int m_vertex1;
int m_vertex2;
public:
TriangleDescription()
{
m_vertex0 = 0;
m_vertex1 = 0;
m_vertex2 = 0;
}
TriangleDescription( int newVertex0, int newVertex1, int newVertex2 )
{
m_vertex0 = newVertex0;
m_vertex1 = newVertex1;
m_vertex2 = newVertex2;
}
TriangleNodeSet getVertexSet() const
{
btSoftBodyTriangleData::TriangleNodeSet nodes;
nodes.vertex0 = m_vertex0;
nodes.vertex1 = m_vertex1;
nodes.vertex2 = m_vertex2;
return nodes;
}
};
protected:
// NOTE:
// Vertex reference data is stored relative to global array, not relative to individual cloth.
// Values must be correct if being passed into single-cloth VBOs or when migrating from one solver
// to another.
btAlignedObjectArray< TriangleNodeSet > m_vertexIndices;
btAlignedObjectArray< float > m_area;
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_normal;
public:
btSoftBodyTriangleData()
{
}
virtual ~btSoftBodyTriangleData()
{
}
virtual void clear()
{
m_vertexIndices.resize(0);
m_area.resize(0);
m_normal.resize(0);
}
int getNumTriangles()
{
return m_vertexIndices.size();
}
virtual void setTriangleAt( const TriangleDescription &triangle, int triangleIndex )
{
m_vertexIndices[triangleIndex] = triangle.getVertexSet();
}
virtual void createTriangles( int numTriangles )
{
int previousSize = m_vertexIndices.size();
int newSize = previousSize + numTriangles;
// Resize all the arrays that store triangle data
m_vertexIndices.resize( newSize );
m_area.resize( newSize );
m_normal.resize( newSize );
}
/**
* Return the vertex index set for triangle triangleIndex as stored on the host.
*/
const TriangleNodeSet &getVertexSet( int triangleIndex )
{
return m_vertexIndices[triangleIndex];
}
/**
* Get access to the triangle area.
*/
float &getTriangleArea( int triangleIndex )
{
return m_area[triangleIndex];
}
/**
* Get access to the normal vector for this triangle.
*/
Vectormath::Aos::Vector3 &getNormal( int triangleIndex )
{
return m_normal[triangleIndex];
}
/**
* Return true if data is on the accelerator.
* The CPU version of this class will return true here because
* the CPU is the same as the accelerator.
*/
virtual bool onAccelerator()
{
return true;
}
/**
* Move data from host memory to the accelerator.
* The CPU version will always return that it has moved it.
*/
virtual bool moveToAccelerator()
{
return true;
}
/**
* Move data from host memory from the accelerator.
* The CPU version will always return that it has moved it.
*/
virtual bool moveFromAccelerator()
{
return true;
}
};
#endif // #ifndef BT_SOFT_BODY_SOLVER_DATA_H

View file

@ -0,0 +1,116 @@
/*
Copyright (C) 2009 Sony Computer Entertainment Inc.
All rights reserved.
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef __HEAP_MANAGER_H__
#define __HEAP_MANAGER_H__
#ifdef __SPU__
#define HEAP_STACK_SIZE 32
#else
#define HEAP_STACK_SIZE 64
#endif
#define MIN_ALLOC_SIZE 16
class HeapManager
{
private:
ATTRIBUTE_ALIGNED16(unsigned char *mHeap);
ATTRIBUTE_ALIGNED16(unsigned int mHeapBytes);
ATTRIBUTE_ALIGNED16(unsigned char *mPoolStack[HEAP_STACK_SIZE]);
ATTRIBUTE_ALIGNED16(unsigned int mCurStack);
public:
enum {ALIGN16,ALIGN128};
HeapManager(unsigned char *buf,int bytes)
{
mHeap = buf;
mHeapBytes = bytes;
clear();
}
~HeapManager()
{
}
int getAllocated()
{
return (int)(mPoolStack[mCurStack]-mHeap);
}
int getRest()
{
return mHeapBytes-getAllocated();
}
void *allocate(size_t bytes,int alignment = ALIGN16)
{
if(bytes <= 0) bytes = MIN_ALLOC_SIZE;
btAssert(mCurStack < (HEAP_STACK_SIZE-1));
#if defined(_WIN64) || defined(__LP64__) || defined(__x86_64__)
unsigned long long p = (unsigned long long )mPoolStack[mCurStack];
if(alignment == ALIGN128) {
p = ((p+127) & 0xffffffffffffff80);
bytes = (bytes+127) & 0xffffffffffffff80;
}
else {
bytes = (bytes+15) & 0xfffffffffffffff0;
}
btAssert(bytes <=(mHeapBytes-(p-(unsigned long long )mHeap)) );
#else
unsigned long p = (unsigned long )mPoolStack[mCurStack];
if(alignment == ALIGN128) {
p = ((p+127) & 0xffffff80);
bytes = (bytes+127) & 0xffffff80;
}
else {
bytes = (bytes+15) & 0xfffffff0;
}
btAssert(bytes <=(mHeapBytes-(p-(unsigned long)mHeap)) );
#endif
unsigned char * bla = (unsigned char *)(p + bytes);
mPoolStack[++mCurStack] = bla;
return (void*)p;
}
void deallocate(void *p)
{
(void) p;
mCurStack--;
}
void clear()
{
mPoolStack[0] = mHeap;
mCurStack = 0;
}
// void printStack()
// {
// for(unsigned int i=0;i<=mCurStack;i++) {
// PRINTF("memStack %2d 0x%x\n",i,(uint32_t)mPoolStack[i]);
// }
// }
};
#endif

View file

@ -0,0 +1,90 @@
#ifndef TYPE_DEFINITIONS_H
#define TYPE_DEFINITIONS_H
///This file provides some platform/compiler checks for common definitions
#include "LinearMath/btScalar.h"
#include "LinearMath/btMinMax.h"
#include "vectormath/vmInclude.h"
#ifdef _WIN32
typedef union
{
unsigned int u;
void *p;
} addr64;
#define USE_WIN32_THREADING 1
#if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300)
#else
#endif //__MINGW32__
typedef unsigned char uint8_t;
#ifndef __PHYSICS_COMMON_H__
#ifndef __PFX_COMMON_H__
#ifndef __BT_SKIP_UINT64_H
typedef unsigned long int uint64_t;
#endif //__BT_SKIP_UINT64_H
#endif //__PFX_COMMON_H__
typedef unsigned int uint32_t;
#endif //__PHYSICS_COMMON_H__
typedef unsigned short uint16_t;
#include <malloc.h>
#define memalign(alignment, size) malloc(size);
#include <string.h> //memcpy
#include <stdio.h>
#define spu_printf printf
#else
#include <stdint.h>
#include <stdlib.h>
#include <string.h> //for memcpy
#if defined (__CELLOS_LV2__)
// Playstation 3 Cell SDK
#include <spu_printf.h>
#else
// posix system
#define USE_PTHREADS (1)
#ifdef USE_LIBSPE2
#include <stdio.h>
#define spu_printf printf
#define DWORD unsigned int
typedef union
{
unsigned long long ull;
unsigned int ui[2];
void *p;
} addr64;
#endif // USE_LIBSPE2
#endif //__CELLOS_LV2__
#endif
#ifdef __SPU__
#include <stdio.h>
#define printf spu_printf
#endif
/* Included here because we need uint*_t typedefs */
#include "PpuAddressSpace.h"
#endif //TYPE_DEFINITIONS_H

View file

@ -0,0 +1,137 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "LinearMath/btScalar.h"
#include "PlatformDefinitions.h"
#ifdef USE_PTHREADS //platform specific defines are defined in PlatformDefinitions.h
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 600 //for definition of pthread_barrier_t, see http://pages.cs.wisc.edu/~travitch/pthreads_primer.html
#endif //_XOPEN_SOURCE
#include <pthread.h>
#include <semaphore.h>
#ifndef POSIX_THREAD_SUPPORT_H
#define POSIX_THREAD_SUPPORT_H
#include "LinearMath/btAlignedObjectArray.h"
#include "btThreadSupportInterface.h"
typedef void (*PosixThreadFunc)(void* userPtr,void* lsMemory);
typedef void* (*PosixlsMemorySetupFunc)();
// PosixThreadSupport helps to initialize/shutdown libspe2, start/stop SPU tasks and communication
class PosixThreadSupport : public btThreadSupportInterface
{
public:
typedef enum sStatus {
STATUS_BUSY,
STATUS_READY,
STATUS_FINISHED
} Status;
// placeholder, until libspe2 support is there
struct btSpuStatus
{
uint32_t m_taskId;
uint32_t m_commandId;
uint32_t m_status;
PosixThreadFunc m_userThreadFunc;
void* m_userPtr; //for taskDesc etc
void* m_lsMemory; //initialized using PosixLocalStoreMemorySetupFunc
pthread_t thread;
sem_t* startSemaphore;
unsigned long threadUsed;
};
private:
btAlignedObjectArray<btSpuStatus> m_activeSpuStatus;
public:
///Setup and initialize SPU/CELL/Libspe2
struct ThreadConstructionInfo
{
ThreadConstructionInfo(char* uniqueName,
PosixThreadFunc userThreadFunc,
PosixlsMemorySetupFunc lsMemoryFunc,
int numThreads=1,
int threadStackSize=65535
)
:m_uniqueName(uniqueName),
m_userThreadFunc(userThreadFunc),
m_lsMemoryFunc(lsMemoryFunc),
m_numThreads(numThreads),
m_threadStackSize(threadStackSize)
{
}
char* m_uniqueName;
PosixThreadFunc m_userThreadFunc;
PosixlsMemorySetupFunc m_lsMemoryFunc;
int m_numThreads;
int m_threadStackSize;
};
PosixThreadSupport(ThreadConstructionInfo& threadConstructionInfo);
///cleanup/shutdown Libspe2
virtual ~PosixThreadSupport();
void startThreads(ThreadConstructionInfo& threadInfo);
///send messages to SPUs
virtual void sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t uiArgument1);
///check for messages from SPUs
virtual void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1);
///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded)
virtual void startSPU();
///tell the task scheduler we are done with the SPU tasks
virtual void stopSPU();
virtual void setNumTasks(int numTasks) {}
virtual int getNumTasks() const
{
return m_activeSpuStatus.size();
}
virtual btBarrier* createBarrier();
virtual btCriticalSection* createCriticalSection();
virtual void* getThreadLocalMemory(int taskId)
{
return m_activeSpuStatus[taskId].m_lsMemory;
}
};
#endif // POSIX_THREAD_SUPPORT_H
#endif // USE_PTHREADS

View file

@ -0,0 +1,37 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2010 Erwin Coumans http://bulletphysics.org
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef __PPU_ADDRESS_SPACE_H
#define __PPU_ADDRESS_SPACE_H
#ifdef _WIN32
//stop those casting warnings until we have a better solution for ppu_address_t / void* / uint64 conversions
#pragma warning (disable: 4311)
#pragma warning (disable: 4312)
#endif //_WIN32
#if defined(_WIN64)
typedef unsigned __int64 ppu_address_t;
#elif defined(__LP64__) || defined(__x86_64__)
typedef uint64_t ppu_address_t;
#else
typedef uint32_t ppu_address_t;
#endif //defined(_WIN64)
#endif //__PPU_ADDRESS_SPACE_H

View file

@ -0,0 +1,96 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "LinearMath/btScalar.h"
#include "PlatformDefinitions.h"
#ifndef SEQUENTIAL_THREAD_SUPPORT_H
#define SEQUENTIAL_THREAD_SUPPORT_H
#include "LinearMath/btAlignedObjectArray.h"
#include "btThreadSupportInterface.h"
typedef void (*SequentialThreadFunc)(void* userPtr,void* lsMemory);
typedef void* (*SequentiallsMemorySetupFunc)();
///The SequentialThreadSupport is a portable non-parallel implementation of the btThreadSupportInterface
///This is useful for debugging and porting SPU Tasks to other platforms.
class SequentialThreadSupport : public btThreadSupportInterface
{
public:
struct btSpuStatus
{
uint32_t m_taskId;
uint32_t m_commandId;
uint32_t m_status;
SequentialThreadFunc m_userThreadFunc;
void* m_userPtr; //for taskDesc etc
void* m_lsMemory; //initialized using SequentiallsMemorySetupFunc
};
private:
btAlignedObjectArray<btSpuStatus> m_activeSpuStatus;
btAlignedObjectArray<void*> m_completeHandles;
public:
struct SequentialThreadConstructionInfo
{
SequentialThreadConstructionInfo (char* uniqueName,
SequentialThreadFunc userThreadFunc,
SequentiallsMemorySetupFunc lsMemoryFunc
)
:m_uniqueName(uniqueName),
m_userThreadFunc(userThreadFunc),
m_lsMemoryFunc(lsMemoryFunc)
{
}
char* m_uniqueName;
SequentialThreadFunc m_userThreadFunc;
SequentiallsMemorySetupFunc m_lsMemoryFunc;
};
SequentialThreadSupport(SequentialThreadConstructionInfo& threadConstructionInfo);
virtual ~SequentialThreadSupport();
void startThreads(SequentialThreadConstructionInfo& threadInfo);
///send messages to SPUs
virtual void sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t uiArgument1);
///check for messages from SPUs
virtual void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1);
///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded)
virtual void startSPU();
///tell the task scheduler we are done with the SPU tasks
virtual void stopSPU();
virtual void setNumTasks(int numTasks);
virtual int getNumTasks() const
{
return 1;
}
virtual btBarrier* createBarrier();
virtual btCriticalSection* createCriticalSection();
};
#endif //SEQUENTIAL_THREAD_SUPPORT_H

View file

@ -0,0 +1,40 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SPU_COLLISION_OBJECT_WRAPPER_H
#define SPU_COLLISION_OBJECT_WRAPPER_H
#include "PlatformDefinitions.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
ATTRIBUTE_ALIGNED16(class) SpuCollisionObjectWrapper
{
protected:
int m_shapeType;
float m_margin;
ppu_address_t m_collisionObjectPtr;
public:
SpuCollisionObjectWrapper ();
SpuCollisionObjectWrapper (const btCollisionObject* collisionObject);
int getShapeType () const;
float getCollisionMargin () const;
ppu_address_t getCollisionObjectPtr () const;
};
#endif //SPU_COLLISION_OBJECT_WRAPPER_H

View file

@ -0,0 +1,163 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SPU_COLLISION_TASK_PROCESS_H
#define SPU_COLLISION_TASK_PROCESS_H
#include <assert.h>
#include "LinearMath/btScalar.h"
#include "PlatformDefinitions.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" // for definitions processCollisionTask and createCollisionLocalStoreMemory
#include "btThreadSupportInterface.h"
//#include "SPUAssert.h"
#include <string.h>
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h"
#include "LinearMath/btAlignedAllocator.h"
#include <stdio.h>
#define DEBUG_SpuCollisionTaskProcess 1
#define CMD_GATHER_AND_PROCESS_PAIRLIST 1
class btCollisionObject;
class btPersistentManifold;
class btDispatcher;
/////Task Description for SPU collision detection
//struct SpuGatherAndProcessPairsTaskDesc
//{
// uint64_t inPtr;//m_pairArrayPtr;
// //mutex variable
// uint32_t m_someMutexVariableInMainMemory;
//
// uint64_t m_dispatcher;
//
// uint32_t numOnLastPage;
//
// uint16_t numPages;
// uint16_t taskId;
//
// struct CollisionTask_LocalStoreMemory* m_lsMemory;
//}
//
//#if defined(__CELLOS_LV2__) || defined(USE_LIBSPE2)
//__attribute__ ((aligned (16)))
//#endif
//;
///MidphaseWorkUnitInput stores individual primitive versus mesh collision detection input, to be processed by the SPU.
ATTRIBUTE_ALIGNED16(struct) SpuGatherAndProcessWorkUnitInput
{
uint64_t m_pairArrayPtr;
int m_startIndex;
int m_endIndex;
};
/// SpuCollisionTaskProcess handles SPU processing of collision pairs.
/// Maintains a set of task buffers.
/// When the task is full, the task is issued for SPUs to process. Contact output goes into btPersistentManifold
/// associated with each task.
/// When PPU issues a task, it will look for completed task buffers
/// PPU will do postprocessing, dependent on workunit output (not likely)
class SpuCollisionTaskProcess
{
unsigned char *m_workUnitTaskBuffers;
// track task buffers that are being used, and total busy tasks
btAlignedObjectArray<bool> m_taskBusy;
btAlignedObjectArray<SpuGatherAndProcessPairsTaskDesc> m_spuGatherTaskDesc;
class btThreadSupportInterface* m_threadInterface;
unsigned int m_maxNumOutstandingTasks;
unsigned int m_numBusyTasks;
// the current task and the current entry to insert a new work unit
unsigned int m_currentTask;
unsigned int m_currentPage;
unsigned int m_currentPageEntry;
bool m_useEpa;
#ifdef DEBUG_SpuCollisionTaskProcess
bool m_initialized;
#endif
void issueTask2();
//void postProcess(unsigned int taskId, int outputSize);
public:
SpuCollisionTaskProcess(btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks);
~SpuCollisionTaskProcess();
///call initialize in the beginning of the frame, before addCollisionPairToTask
void initialize2(bool useEpa = false);
///batch up additional work to a current task for SPU processing. When batch is full, it issues the task.
void addWorkToTask(void* pairArrayPtr,int startIndex,int endIndex);
///call flush to submit potential outstanding work to SPUs and wait for all involved SPUs to be finished
void flush2();
/// set the maximum number of SPU tasks allocated
void setNumTasks(int maxNumTasks);
int getNumTasks() const
{
return m_maxNumOutstandingTasks;
}
};
#define MIDPHASE_TASK_PTR(task) (&m_workUnitTaskBuffers[0] + MIDPHASE_WORKUNIT_TASK_SIZE*task)
#define MIDPHASE_ENTRY_PTR(task,page,entry) (MIDPHASE_TASK_PTR(task) + MIDPHASE_WORKUNIT_PAGE_SIZE*page + sizeof(SpuGatherAndProcessWorkUnitInput)*entry)
#define MIDPHASE_OUTPUT_PTR(task) (&m_contactOutputBuffers[0] + MIDPHASE_MAX_CONTACT_BUFFER_SIZE*task)
#define MIDPHASE_TREENODES_PTR(task) (&m_complexShapeBuffers[0] + MIDPHASE_COMPLEX_SHAPE_BUFFER_SIZE*task)
#define MIDPHASE_WORKUNIT_PAGE_SIZE (16)
//#define MIDPHASE_WORKUNIT_PAGE_SIZE (128)
#define MIDPHASE_NUM_WORKUNIT_PAGES 1
#define MIDPHASE_WORKUNIT_TASK_SIZE (MIDPHASE_WORKUNIT_PAGE_SIZE*MIDPHASE_NUM_WORKUNIT_PAGES)
#define MIDPHASE_NUM_WORKUNITS_PER_PAGE (MIDPHASE_WORKUNIT_PAGE_SIZE / sizeof(SpuGatherAndProcessWorkUnitInput))
#define MIDPHASE_NUM_WORKUNITS_PER_TASK (MIDPHASE_NUM_WORKUNITS_PER_PAGE*MIDPHASE_NUM_WORKUNIT_PAGES)
#endif // SPU_COLLISION_TASK_PROCESS_H

View file

@ -0,0 +1,120 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SPU_CONTACTMANIFOLD_COLLISION_ALGORITHM_H
#define SPU_CONTACTMANIFOLD_COLLISION_ALGORITHM_H
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
#include "LinearMath/btTransformUtil.h"
class btPersistentManifold;
//#define USE_SEPDISTANCE_UTIL 1
/// SpuContactManifoldCollisionAlgorithm provides contact manifold and should be processed on SPU.
ATTRIBUTE_ALIGNED16(class) SpuContactManifoldCollisionAlgorithm : public btCollisionAlgorithm
{
btVector3 m_shapeDimensions0;
btVector3 m_shapeDimensions1;
btPersistentManifold* m_manifoldPtr;
int m_shapeType0;
int m_shapeType1;
float m_collisionMargin0;
float m_collisionMargin1;
btCollisionObject* m_collisionObject0;
btCollisionObject* m_collisionObject1;
public:
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
SpuContactManifoldCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
#ifdef USE_SEPDISTANCE_UTIL
btConvexSeparatingDistanceUtil m_sepDistance;
#endif //USE_SEPDISTANCE_UTIL
virtual ~SpuContactManifoldCollisionAlgorithm();
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr)
manifoldArray.push_back(m_manifoldPtr);
}
btPersistentManifold* getContactManifoldPtr()
{
return m_manifoldPtr;
}
btCollisionObject* getCollisionObject0()
{
return m_collisionObject0;
}
btCollisionObject* getCollisionObject1()
{
return m_collisionObject1;
}
int getShapeType0() const
{
return m_shapeType0;
}
int getShapeType1() const
{
return m_shapeType1;
}
float getCollisionMargin0() const
{
return m_collisionMargin0;
}
float getCollisionMargin1() const
{
return m_collisionMargin1;
}
const btVector3& getShapeDimensions0() const
{
return m_shapeDimensions0;
}
const btVector3& getShapeDimensions1() const
{
return m_shapeDimensions1;
}
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(SpuContactManifoldCollisionAlgorithm));
return new(mem) SpuContactManifoldCollisionAlgorithm(ci,body0,body1);
}
};
};
#endif //SPU_CONTACTMANIFOLD_COLLISION_ALGORITHM_H

View file

@ -0,0 +1,110 @@
#ifndef DOUBLE_BUFFER_H
#define DOUBLE_BUFFER_H
#include "SpuFakeDma.h"
#include "LinearMath/btScalar.h"
///DoubleBuffer
template<class T, int size>
class DoubleBuffer
{
#if defined(__SPU__) || defined(USE_LIBSPE2)
ATTRIBUTE_ALIGNED128( T m_buffer0[size] ) ;
ATTRIBUTE_ALIGNED128( T m_buffer1[size] ) ;
#else
T m_buffer0[size];
T m_buffer1[size];
#endif
T *m_frontBuffer;
T *m_backBuffer;
unsigned int m_dmaTag;
bool m_dmaPending;
public:
bool isPending() const { return m_dmaPending;}
DoubleBuffer();
void init ();
// dma get and put commands
void backBufferDmaGet(uint64_t ea, unsigned int numBytes, unsigned int tag);
void backBufferDmaPut(uint64_t ea, unsigned int numBytes, unsigned int tag);
// gets pointer to a buffer
T *getFront();
T *getBack();
// if back buffer dma was started, wait for it to complete
// then move back to front and vice versa
T *swapBuffers();
};
template<class T, int size>
DoubleBuffer<T,size>::DoubleBuffer()
{
init ();
}
template<class T, int size>
void DoubleBuffer<T,size>::init()
{
this->m_dmaPending = false;
this->m_frontBuffer = &this->m_buffer0[0];
this->m_backBuffer = &this->m_buffer1[0];
}
template<class T, int size>
void
DoubleBuffer<T,size>::backBufferDmaGet(uint64_t ea, unsigned int numBytes, unsigned int tag)
{
m_dmaPending = true;
m_dmaTag = tag;
if (numBytes)
{
m_backBuffer = (T*)cellDmaLargeGetReadOnly(m_backBuffer, ea, numBytes, tag, 0, 0);
}
}
template<class T, int size>
void
DoubleBuffer<T,size>::backBufferDmaPut(uint64_t ea, unsigned int numBytes, unsigned int tag)
{
m_dmaPending = true;
m_dmaTag = tag;
cellDmaLargePut(m_backBuffer, ea, numBytes, tag, 0, 0);
}
template<class T, int size>
T *
DoubleBuffer<T,size>::getFront()
{
return m_frontBuffer;
}
template<class T, int size>
T *
DoubleBuffer<T,size>::getBack()
{
return m_backBuffer;
}
template<class T, int size>
T *
DoubleBuffer<T,size>::swapBuffers()
{
if (m_dmaPending)
{
cellDmaWaitTagStatusAll(1<<m_dmaTag);
m_dmaPending = false;
}
T *tmp = m_backBuffer;
m_backBuffer = m_frontBuffer;
m_frontBuffer = tmp;
return m_frontBuffer;
}
#endif

View file

@ -0,0 +1,135 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef FAKE_DMA_H
#define FAKE_DMA_H
#include "PlatformDefinitions.h"
#include "LinearMath/btScalar.h"
#ifdef __SPU__
#ifndef USE_LIBSPE2
#include <cell/dma.h>
#include <stdint.h>
#define DMA_TAG(xfer) (xfer + 1)
#define DMA_MASK(xfer) (1 << DMA_TAG(xfer))
#else // !USE_LIBSPE2
#define DMA_TAG(xfer) (xfer + 1)
#define DMA_MASK(xfer) (1 << DMA_TAG(xfer))
#include <spu_mfcio.h>
#define DEBUG_DMA
#ifdef DEBUG_DMA
#define dUASSERT(a,b) if (!(a)) { printf(b);}
#define uintsize ppu_address_t
#define cellDmaLargeGet(ls, ea, size, tag, tid, rid) if ( (((uintsize)ls%16) != ((uintsize)ea%16)) || ((((uintsize)ea%16) || ((uintsize)ls%16)) && (( ((uintsize)ls%16) != ((uintsize)size%16) ) || ( ((uintsize)ea%16) != ((uintsize)size%16) ) ) ) || ( ((uintsize)size%16) && ((uintsize)size!=1) && ((uintsize)size!=2) && ((uintsize)size!=4) && ((uintsize)size!=8) ) || (size >= 16384) || !(uintsize)ls || !(uintsize)ea) { \
dUASSERT( (((uintsize)ea % 16) == 0) || (size < 16), "XDR Address not aligned: "); \
dUASSERT( (((uintsize)ls % 16) == 0) || (size < 16), "LS Address not aligned: "); \
dUASSERT( ((((uintsize)ls % size) == 0) && (((uintsize)ea % size) == 0)) || (size > 16), "Not naturally aligned: "); \
dUASSERT((size == 1) || (size == 2) || (size == 4) || (size == 8) || ((size % 16) == 0), "size not a multiple of 16byte: "); \
dUASSERT(size < 16384, "size too big: "); \
dUASSERT( ((uintsize)ea%16)==((uintsize)ls%16), "wrong Quadword alignment of LS and EA: "); \
dUASSERT(ea != 0, "Nullpointer EA: "); dUASSERT(ls != 0, "Nullpointer LS: ");\
printf("GET %s:%d from: 0x%x, to: 0x%x - %d bytes\n", __FILE__, __LINE__, (unsigned int)ea,(unsigned int)ls,(unsigned int)size);\
} \
mfc_get(ls, ea, size, tag, tid, rid)
#define cellDmaGet(ls, ea, size, tag, tid, rid) if ( (((uintsize)ls%16) != ((uintsize)ea%16)) || ((((uintsize)ea%16) || ((uintsize)ls%16)) && (( ((uintsize)ls%16) != ((uintsize)size%16) ) || ( ((uintsize)ea%16) != ((uintsize)size%16) ) ) ) || ( ((uintsize)size%16) && ((uintsize)size!=1) && ((uintsize)size!=2) && ((uintsize)size!=4) && ((uintsize)size!=8) ) || (size >= 16384) || !(uintsize)ls || !(uintsize)ea) { \
dUASSERT( (((uintsize)ea % 16) == 0) || (size < 16), "XDR Address not aligned: "); \
dUASSERT( (((uintsize)ls % 16) == 0) || (size < 16), "LS Address not aligned: "); \
dUASSERT( ((((uintsize)ls % size) == 0) && (((uintsize)ea % size) == 0)) || (size > 16), "Not naturally aligned: "); \
dUASSERT((size == 1) || (size == 2) || (size == 4) || (size == 8) || ((size % 16) == 0), "size not a multiple of 16byte: "); \
dUASSERT(size < 16384, "size too big: "); \
dUASSERT( ((uintsize)ea%16)==((uintsize)ls%16), "wrong Quadword alignment of LS and EA: "); \
dUASSERT(ea != 0, "Nullpointer EA: "); dUASSERT(ls != 0, "Nullpointer LS: ");\
printf("GET %s:%d from: 0x%x, to: 0x%x - %d bytes\n", __FILE__, __LINE__, (unsigned int)ea,(unsigned int)ls,(unsigned int)size);\
} \
mfc_get(ls, ea, size, tag, tid, rid)
#define cellDmaLargePut(ls, ea, size, tag, tid, rid) if ( (((uintsize)ls%16) != ((uintsize)ea%16)) || ((((uintsize)ea%16) || ((uintsize)ls%16)) && (( ((uintsize)ls%16) != ((uintsize)size%16) ) || ( ((uintsize)ea%16) != ((uintsize)size%16) ) ) ) || ( ((uintsize)size%16) && ((uintsize)size!=1) && ((uintsize)size!=2) && ((uintsize)size!=4) && ((uintsize)size!=8) ) || (size >= 16384) || !(uintsize)ls || !(uintsize)ea) { \
dUASSERT( (((uintsize)ea % 16) == 0) || (size < 16), "XDR Address not aligned: "); \
dUASSERT( (((uintsize)ls % 16) == 0) || (size < 16), "LS Address not aligned: "); \
dUASSERT( ((((uintsize)ls % size) == 0) && (((uintsize)ea % size) == 0)) || (size > 16), "Not naturally aligned: "); \
dUASSERT((size == 1) || (size == 2) || (size == 4) || (size == 8) || ((size % 16) == 0), "size not a multiple of 16byte: "); \
dUASSERT(size < 16384, "size too big: "); \
dUASSERT( ((uintsize)ea%16)==((uintsize)ls%16), "wrong Quadword alignment of LS and EA: "); \
dUASSERT(ea != 0, "Nullpointer EA: "); dUASSERT(ls != 0, "Nullpointer LS: ");\
printf("PUT %s:%d from: 0x%x, to: 0x%x - %d bytes\n", __FILE__, __LINE__, (unsigned int)ls,(unsigned int)ea,(unsigned int)size); \
} \
mfc_put(ls, ea, size, tag, tid, rid)
#define cellDmaSmallGet(ls, ea, size, tag, tid, rid) if ( (((uintsize)ls%16) != ((uintsize)ea%16)) || ((((uintsize)ea%16) || ((uintsize)ls%16)) && (( ((uintsize)ls%16) != ((uintsize)size%16) ) || ( ((uintsize)ea%16) != ((uintsize)size%16) ) ) ) || ( ((uintsize)size%16) && ((uintsize)size!=1) && ((uintsize)size!=2) && ((uintsize)size!=4) && ((uintsize)size!=8) ) || (size >= 16384) || !(uintsize)ls || !(uintsize)ea) { \
dUASSERT( (((uintsize)ea % 16) == 0) || (size < 16), "XDR Address not aligned: "); \
dUASSERT( (((uintsize)ls % 16) == 0) || (size < 16), "LS Address not aligned: "); \
dUASSERT( ((((uintsize)ls % size) == 0) && (((uintsize)ea % size) == 0)) || (size > 16), "Not naturally aligned: "); \
dUASSERT((size == 1) || (size == 2) || (size == 4) || (size == 8) || ((size % 16) == 0), "size not a multiple of 16byte: "); \
dUASSERT(size < 16384, "size too big: "); \
dUASSERT( ((uintsize)ea%16)==((uintsize)ls%16), "wrong Quadword alignment of LS and EA: "); \
dUASSERT(ea != 0, "Nullpointer EA: "); dUASSERT(ls != 0, "Nullpointer LS: ");\
printf("GET %s:%d from: 0x%x, to: 0x%x - %d bytes\n", __FILE__, __LINE__, (unsigned int)ea,(unsigned int)ls,(unsigned int)size);\
} \
mfc_get(ls, ea, size, tag, tid, rid)
#define cellDmaWaitTagStatusAll(ignore) mfc_write_tag_mask(ignore) ; mfc_read_tag_status_all()
#else
#define cellDmaLargeGet(ls, ea, size, tag, tid, rid) mfc_get(ls, ea, size, tag, tid, rid)
#define cellDmaGet(ls, ea, size, tag, tid, rid) mfc_get(ls, ea, size, tag, tid, rid)
#define cellDmaLargePut(ls, ea, size, tag, tid, rid) mfc_put(ls, ea, size, tag, tid, rid)
#define cellDmaSmallGet(ls, ea, size, tag, tid, rid) mfc_get(ls, ea, size, tag, tid, rid)
#define cellDmaWaitTagStatusAll(ignore) mfc_write_tag_mask(ignore) ; mfc_read_tag_status_all()
#endif // DEBUG_DMA
#endif // USE_LIBSPE2
#else // !__SPU__
//Simulate DMA using memcpy or direct access on non-CELL platforms that don't have DMAs and SPUs (Win32, Mac, Linux etc)
//Potential to add networked simulation using this interface
#define DMA_TAG(a) (a)
#define DMA_MASK(a) (a)
/// cellDmaLargeGet Win32 replacements for Cell DMA to allow simulating most of the SPU code (just memcpy)
int cellDmaLargeGet(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid);
int cellDmaGet(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid);
/// cellDmaLargePut Win32 replacements for Cell DMA to allow simulating most of the SPU code (just memcpy)
int cellDmaLargePut(const void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid);
/// cellDmaWaitTagStatusAll Win32 replacements for Cell DMA to allow simulating most of the SPU code (just memcpy)
void cellDmaWaitTagStatusAll(int ignore);
#endif //__CELLOS_LV2__
///stallingUnalignedDmaSmallGet internally uses DMA_TAG(1)
int stallingUnalignedDmaSmallGet(void *ls, uint64_t ea, uint32_t size);
void* cellDmaLargeGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid);
void* cellDmaGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid);
void* cellDmaSmallGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid);
#endif //FAKE_DMA_H

View file

@ -0,0 +1,72 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SPU_GATHERING_COLLISION__DISPATCHER_H
#define SPU_GATHERING_COLLISION__DISPATCHER_H
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
///Tuning value to optimized SPU utilization
///Too small value means Task overhead is large compared to computation (too fine granularity)
///Too big value might render some SPUs are idle, while a few other SPUs are doing all work.
//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 8
//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 16
//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 64
#define SPU_BATCHSIZE_BROADPHASE_PAIRS 128
//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 256
//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 512
//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 1024
class SpuCollisionTaskProcess;
///SpuGatheringCollisionDispatcher can use SPU to gather and calculate collision detection
///Time of Impact, Closest Points and Penetration Depth.
class SpuGatheringCollisionDispatcher : public btCollisionDispatcher
{
SpuCollisionTaskProcess* m_spuCollisionTaskProcess;
protected:
class btThreadSupportInterface* m_threadInterface;
unsigned int m_maxNumOutstandingTasks;
public:
//can be used by SPU collision algorithms
SpuCollisionTaskProcess* getSpuCollisionTaskProcess()
{
return m_spuCollisionTaskProcess;
}
SpuGatheringCollisionDispatcher (class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks,btCollisionConfiguration* collisionConfiguration);
virtual ~SpuGatheringCollisionDispatcher();
bool supportsDispatchPairOnSpu(int proxyType0,int proxyType1);
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ;
};
#endif //SPU_GATHERING_COLLISION__DISPATCHER_H

View file

@ -0,0 +1,180 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SPU_LIBSPE2_SUPPORT_H
#define SPU_LIBSPE2_SUPPORT_H
#include <LinearMath/btScalar.h> //for uint32_t etc.
#ifdef USE_LIBSPE2
#include <stdlib.h>
#include <stdio.h>
//#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h"
#include "PlatformDefinitions.h"
//extern struct SpuGatherAndProcessPairsTaskDesc;
enum
{
Spu_Mailbox_Event_Nothing = 0,
Spu_Mailbox_Event_Task = 1,
Spu_Mailbox_Event_Shutdown = 2,
Spu_Mailbox_Event_ForceDword = 0xFFFFFFFF
};
enum
{
Spu_Status_Free = 0,
Spu_Status_Occupied = 1,
Spu_Status_Startup = 2,
Spu_Status_ForceDword = 0xFFFFFFFF
};
struct btSpuStatus
{
uint32_t m_taskId;
uint32_t m_commandId;
uint32_t m_status;
addr64 m_taskDesc;
addr64 m_lsMemory;
}
__attribute__ ((aligned (128)))
;
#ifndef __SPU__
#include "LinearMath/btAlignedObjectArray.h"
#include "SpuCollisionTaskProcess.h"
#include "SpuSampleTaskProcess.h"
#include "btThreadSupportInterface.h"
#include <libspe2.h>
#include <pthread.h>
#include <sched.h>
#define MAX_SPUS 4
typedef struct ppu_pthread_data
{
spe_context_ptr_t context;
pthread_t pthread;
unsigned int entry;
unsigned int flags;
addr64 argp;
addr64 envp;
spe_stop_info_t stopinfo;
} ppu_pthread_data_t;
static void *ppu_pthread_function(void *arg)
{
ppu_pthread_data_t * datap = (ppu_pthread_data_t *)arg;
/*
int rc;
do
{*/
spe_context_run(datap->context, &datap->entry, datap->flags, datap->argp.p, datap->envp.p, &datap->stopinfo);
if (datap->stopinfo.stop_reason == SPE_EXIT)
{
if (datap->stopinfo.result.spe_exit_code != 0)
{
perror("FAILED: SPE returned a non-zero exit status: \n");
exit(1);
}
}
else
{
perror("FAILED: SPE abnormally terminated\n");
exit(1);
}
//} while (rc > 0); // loop until exit or error, and while any stop & signal
pthread_exit(NULL);
}
///SpuLibspe2Support helps to initialize/shutdown libspe2, start/stop SPU tasks and communication
class SpuLibspe2Support : public btThreadSupportInterface
{
btAlignedObjectArray<btSpuStatus> m_activeSpuStatus;
public:
//Setup and initialize SPU/CELL/Libspe2
SpuLibspe2Support(spe_program_handle_t *speprog,int numThreads);
// SPE program handle ptr.
spe_program_handle_t *program;
// SPE program data
ppu_pthread_data_t data[MAX_SPUS];
//cleanup/shutdown Libspe2
~SpuLibspe2Support();
///send messages to SPUs
void sendRequest(uint32_t uiCommand, uint32_t uiArgument0, uint32_t uiArgument1=0);
//check for messages from SPUs
void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1);
//start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded)
virtual void startSPU();
//tell the task scheduler we are done with the SPU tasks
virtual void stopSPU();
virtual void setNumTasks(int numTasks)
{
//changing the number of tasks after initialization is not implemented (yet)
}
private:
///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded)
void internal_startSPU();
int numThreads;
};
#endif // NOT __SPU__
#endif //USE_LIBSPE2
#endif //SPU_LIBSPE2_SUPPORT_H

View file

@ -0,0 +1,167 @@
/*
Copyright (C) 2006, 2008 Sony Computer Entertainment Inc.
All rights reserved.
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef __BOX_H__
#define __BOX_H__
#ifndef PE_REF
#define PE_REF(a) a&
#endif
#include <math.h>
#include "vectormath/vmInclude.h"
#include "../PlatformDefinitions.h"
enum FeatureType { F, E, V };
//----------------------------------------------------------------------------
// Box
//----------------------------------------------------------------------------
///The Box is an internal class used by the boxBoxDistance calculation.
class Box
{
public:
vmVector3 mHalf;
inline Box()
{}
inline Box(PE_REF(vmVector3) half_);
inline Box(float hx, float hy, float hz);
inline void Set(PE_REF(vmVector3) half_);
inline void Set(float hx, float hy, float hz);
inline vmVector3 GetAABB(const vmMatrix3& rotation) const;
};
inline
Box::Box(PE_REF(vmVector3) half_)
{
Set(half_);
}
inline
Box::Box(float hx, float hy, float hz)
{
Set(hx, hy, hz);
}
inline
void
Box::Set(PE_REF(vmVector3) half_)
{
mHalf = half_;
}
inline
void
Box::Set(float hx, float hy, float hz)
{
mHalf = vmVector3(hx, hy, hz);
}
inline
vmVector3
Box::GetAABB(const vmMatrix3& rotation) const
{
return absPerElem(rotation) * mHalf;
}
//-------------------------------------------------------------------------------------------------
// BoxPoint
//-------------------------------------------------------------------------------------------------
///The BoxPoint class is an internally used class to contain feature information for boxBoxDistance calculation.
class BoxPoint
{
public:
BoxPoint() : localPoint(0.0f) {}
vmPoint3 localPoint;
FeatureType featureType;
int featureIdx;
inline void setVertexFeature(int plusX, int plusY, int plusZ);
inline void setEdgeFeature(int dim0, int plus0, int dim1, int plus1);
inline void setFaceFeature(int dim, int plus);
inline void getVertexFeature(int & plusX, int & plusY, int & plusZ) const;
inline void getEdgeFeature(int & dim0, int & plus0, int & dim1, int & plus1) const;
inline void getFaceFeature(int & dim, int & plus) const;
};
inline
void
BoxPoint::setVertexFeature(int plusX, int plusY, int plusZ)
{
featureType = V;
featureIdx = plusX << 2 | plusY << 1 | plusZ;
}
inline
void
BoxPoint::setEdgeFeature(int dim0, int plus0, int dim1, int plus1)
{
featureType = E;
if (dim0 > dim1) {
featureIdx = plus1 << 5 | dim1 << 3 | plus0 << 2 | dim0;
} else {
featureIdx = plus0 << 5 | dim0 << 3 | plus1 << 2 | dim1;
}
}
inline
void
BoxPoint::setFaceFeature(int dim, int plus)
{
featureType = F;
featureIdx = plus << 2 | dim;
}
inline
void
BoxPoint::getVertexFeature(int & plusX, int & plusY, int & plusZ) const
{
plusX = featureIdx >> 2;
plusY = featureIdx >> 1 & 1;
plusZ = featureIdx & 1;
}
inline
void
BoxPoint::getEdgeFeature(int & dim0, int & plus0, int & dim1, int & plus1) const
{
plus0 = featureIdx >> 5;
dim0 = featureIdx >> 3 & 3;
plus1 = featureIdx >> 2 & 1;
dim1 = featureIdx & 3;
}
inline
void
BoxPoint::getFaceFeature(int & dim, int & plus) const
{
plus = featureIdx >> 2;
dim = featureIdx & 3;
}
#endif /* __BOX_H__ */

View file

@ -0,0 +1,128 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef __SPU_COLLISION_SHAPES_H
#define __SPU_COLLISION_SHAPES_H
#include "../SpuDoubleBuffer.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
#include "BulletCollision/CollisionShapes/btCylinderShape.h"
#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h"
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
#define MAX_NUM_SPU_CONVEX_POINTS 128 //@fallback to PPU if a btConvexHullShape has more than MAX_NUM_SPU_CONVEX_POINTS points
#define MAX_SPU_COMPOUND_SUBSHAPES 16 //@fallback on PPU if compound has more than MAX_SPU_COMPOUND_SUBSHAPES child shapes
#define MAX_SHAPE_SIZE 256 //@todo: assert on this
ATTRIBUTE_ALIGNED16(struct) SpuConvexPolyhedronVertexData
{
void* gSpuConvexShapePtr;
btVector3* gConvexPoints;
int gNumConvexPoints;
int unused;
ATTRIBUTE_ALIGNED16(btVector3 g_convexPointBuffer[MAX_NUM_SPU_CONVEX_POINTS]);
};
ATTRIBUTE_ALIGNED16(struct) CollisionShape_LocalStoreMemory
{
ATTRIBUTE_ALIGNED16(char collisionShape[MAX_SHAPE_SIZE]);
};
ATTRIBUTE_ALIGNED16(struct) CompoundShape_LocalStoreMemory
{
// Compound data
ATTRIBUTE_ALIGNED16(btCompoundShapeChild gSubshapes[MAX_SPU_COMPOUND_SUBSHAPES]);
ATTRIBUTE_ALIGNED16(char gSubshapeShape[MAX_SPU_COMPOUND_SUBSHAPES][MAX_SHAPE_SIZE]);
};
ATTRIBUTE_ALIGNED16(struct) bvhMeshShape_LocalStoreMemory
{
//ATTRIBUTE_ALIGNED16(btOptimizedBvh gOptimizedBvh);
ATTRIBUTE_ALIGNED16(char gOptimizedBvh[sizeof(btOptimizedBvh)+16]);
btOptimizedBvh* getOptimizedBvh()
{
return (btOptimizedBvh*) gOptimizedBvh;
}
ATTRIBUTE_ALIGNED16(btTriangleIndexVertexArray gTriangleMeshInterfaceStorage);
btTriangleIndexVertexArray* gTriangleMeshInterfacePtr;
///only a single mesh part for now, we can add support for multiple parts, but quantized trees don't support this at the moment
ATTRIBUTE_ALIGNED16(btIndexedMesh gIndexMesh);
#define MAX_SPU_SUBTREE_HEADERS 32
//1024
ATTRIBUTE_ALIGNED16(btBvhSubtreeInfo gSubtreeHeaders[MAX_SPU_SUBTREE_HEADERS]);
ATTRIBUTE_ALIGNED16(btQuantizedBvhNode gSubtreeNodes[MAX_SUBTREE_SIZE_IN_BYTES/sizeof(btQuantizedBvhNode)]);
};
void computeAabb (btVector3& aabbMin, btVector3& aabbMax, btConvexInternalShape* convexShape, ppu_address_t convexShapePtr, int shapeType, const btTransform& xform);
void dmaBvhShapeData (bvhMeshShape_LocalStoreMemory* bvhMeshShape, btBvhTriangleMeshShape* triMeshShape);
void dmaBvhIndexedMesh (btIndexedMesh* IndexMesh, IndexedMeshArray& indexArray, int index, uint32_t dmaTag);
void dmaBvhSubTreeHeaders (btBvhSubtreeInfo* subTreeHeaders, ppu_address_t subTreePtr, int batchSize, uint32_t dmaTag);
void dmaBvhSubTreeNodes (btQuantizedBvhNode* nodes, const btBvhSubtreeInfo& subtree, QuantizedNodeArray& nodeArray, int dmaTag);
int getShapeTypeSize(int shapeType);
void dmaConvexVertexData (SpuConvexPolyhedronVertexData* convexVertexData, btConvexHullShape* convexShapeSPU);
void dmaCollisionShape (void* collisionShapeLocation, ppu_address_t collisionShapePtr, uint32_t dmaTag, int shapeType);
void dmaCompoundShapeInfo (CompoundShape_LocalStoreMemory* compoundShapeLocation, btCompoundShape* spuCompoundShape, uint32_t dmaTag);
void dmaCompoundSubShapes (CompoundShape_LocalStoreMemory* compoundShapeLocation, btCompoundShape* spuCompoundShape, uint32_t dmaTag);
#define USE_BRANCHFREE_TEST 1
#ifdef USE_BRANCHFREE_TEST
SIMD_FORCE_INLINE unsigned int spuTestQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
{
#if defined(__CELLOS_LV2__) && defined (__SPU__)
vec_ushort8 vecMin = {aabbMin1[0],aabbMin2[0],aabbMin1[2],aabbMin2[2],aabbMin1[1],aabbMin2[1],0,0};
vec_ushort8 vecMax = {aabbMax2[0],aabbMax1[0],aabbMax2[2],aabbMax1[2],aabbMax2[1],aabbMax1[1],0,0};
vec_ushort8 isGt = spu_cmpgt(vecMin,vecMax);
return spu_extract(spu_gather(isGt),0)==0;
#else
return btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0])
& (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2])
& (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])),
1, 0);
#endif
}
#else
SIMD_FORCE_INLINE unsigned int spuTestQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
{
unsigned int overlap = 1;
overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? 0 : overlap;
overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? 0 : overlap;
overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? 0 : overlap;
return overlap;
}
#endif
void spuWalkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,const btQuantizedBvhNode* rootNode,int startNodeIndex,int endNodeIndex);
#endif

View file

@ -0,0 +1,106 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SPU_CONTACT_RESULT2_H
#define SPU_CONTACT_RESULT2_H
#ifndef _WIN32
#include <stdint.h>
#endif
#include "../SpuDoubleBuffer.h"
#include "LinearMath/btTransform.h"
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
class btCollisionShape;
struct SpuCollisionPairInput
{
ppu_address_t m_collisionShapes[2];
btCollisionShape* m_spuCollisionShapes[2];
ppu_address_t m_persistentManifoldPtr;
btVector3 m_primitiveDimensions0;
btVector3 m_primitiveDimensions1;
int m_shapeType0;
int m_shapeType1;
float m_collisionMargin0;
float m_collisionMargin1;
btTransform m_worldTransform0;
btTransform m_worldTransform1;
bool m_isSwapped;
bool m_useEpa;
};
struct SpuClosestPointInput : public btDiscreteCollisionDetectorInterface::ClosestPointInput
{
struct SpuConvexPolyhedronVertexData* m_convexVertexData[2];
};
///SpuContactResult exports the contact points using double-buffered DMA transfers, only when needed
///So when an existing contact point is duplicated, no transfer/refresh is performed.
class SpuContactResult : public btDiscreteCollisionDetectorInterface::Result
{
btTransform m_rootWorldTransform0;
btTransform m_rootWorldTransform1;
ppu_address_t m_manifoldAddress;
btPersistentManifold* m_spuManifold;
bool m_RequiresWriteBack;
btScalar m_combinedFriction;
btScalar m_combinedRestitution;
bool m_isSwapped;
DoubleBuffer<btPersistentManifold, 1> g_manifoldDmaExport;
public:
SpuContactResult();
virtual ~SpuContactResult();
btPersistentManifold* GetSpuManifold() const
{
return m_spuManifold;
}
virtual void setShapeIdentifiersA(int partId0,int index0);
virtual void setShapeIdentifiersB(int partId1,int index1);
void setContactInfo(btPersistentManifold* spuManifold, ppu_address_t manifoldAddress,const btTransform& worldTrans0,const btTransform& worldTrans1, btScalar restitution0,btScalar restitution1, btScalar friction0,btScalar friction01, bool isSwapped);
void writeDoubleBufferedManifold(btPersistentManifold* lsManifold, btPersistentManifold* mmManifold);
virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth);
void flush();
};
#endif //SPU_CONTACT_RESULT2_H

View file

@ -0,0 +1,51 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SPU_CONVEX_PENETRATION_DEPTH_H
#define SPU_CONVEX_PENETRATION_DEPTH_H
class btStackAlloc;
class btIDebugDraw;
#include "BulletCollision/NarrowphaseCollision/btConvexPenetrationDepthSolver.h"
#include "LinearMath/btTransform.h"
///ConvexPenetrationDepthSolver provides an interface for penetration depth calculation.
class SpuConvexPenetrationDepthSolver : public btConvexPenetrationDepthSolver
{
public:
virtual ~SpuConvexPenetrationDepthSolver() {};
virtual bool calcPenDepth( SpuVoronoiSimplexSolver& simplexSolver,
void* convexA,void* convexB,int shapeTypeA, int shapeTypeB, float marginA, float marginB,
btTransform& transA,const btTransform& transB,
btVector3& v, btVector3& pa, btVector3& pb,
class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc,
struct SpuConvexPolyhedronVertexData* convexVertexDataA,
struct SpuConvexPolyhedronVertexData* convexVertexDataB
) const = 0;
};
#endif //SPU_CONVEX_PENETRATION_DEPTH_H

View file

@ -0,0 +1,140 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SPU_GATHERING_COLLISION_TASK_H
#define SPU_GATHERING_COLLISION_TASK_H
#include "../PlatformDefinitions.h"
//#define DEBUG_SPU_COLLISION_DETECTION 1
///Task Description for SPU collision detection
struct SpuGatherAndProcessPairsTaskDesc
{
ppu_address_t m_inPairPtr;//m_pairArrayPtr;
//mutex variable
uint32_t m_someMutexVariableInMainMemory;
ppu_address_t m_dispatcher;
uint32_t numOnLastPage;
uint16_t numPages;
uint16_t taskId;
bool m_useEpa;
struct CollisionTask_LocalStoreMemory* m_lsMemory;
}
#if defined(__CELLOS_LV2__) || defined(USE_LIBSPE2)
__attribute__ ((aligned (128)))
#endif
;
void processCollisionTask(void* userPtr, void* lsMemory);
void* createCollisionLocalStoreMemory();
#if defined(USE_LIBSPE2) && defined(__SPU__)
#include "../SpuLibspe2Support.h"
#include <spu_intrinsics.h>
#include <spu_mfcio.h>
#include <SpuFakeDma.h>
//#define DEBUG_LIBSPE2_SPU_TASK
int main(unsigned long long speid, addr64 argp, addr64 envp)
{
printf("SPU: hello \n");
ATTRIBUTE_ALIGNED128(btSpuStatus status);
ATTRIBUTE_ALIGNED16( SpuGatherAndProcessPairsTaskDesc taskDesc ) ;
unsigned int received_message = Spu_Mailbox_Event_Nothing;
bool shutdown = false;
cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(3));
status.m_status = Spu_Status_Free;
status.m_lsMemory.p = createCollisionLocalStoreMemory();
cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(3));
while ( btLikely( !shutdown ) )
{
received_message = spu_read_in_mbox();
if( btLikely( received_message == Spu_Mailbox_Event_Task ))
{
#ifdef DEBUG_LIBSPE2_SPU_TASK
printf("SPU: received Spu_Mailbox_Event_Task\n");
#endif //DEBUG_LIBSPE2_SPU_TASK
// refresh the status
cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(3));
btAssert(status.m_status==Spu_Status_Occupied);
cellDmaGet(&taskDesc, status.m_taskDesc.p, sizeof(SpuGatherAndProcessPairsTaskDesc), DMA_TAG(3), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(3));
#ifdef DEBUG_LIBSPE2_SPU_TASK
printf("SPU:processCollisionTask\n");
#endif //DEBUG_LIBSPE2_SPU_TASK
processCollisionTask((void*)&taskDesc, taskDesc.m_lsMemory);
#ifdef DEBUG_LIBSPE2_SPU_TASK
printf("SPU:finished processCollisionTask\n");
#endif //DEBUG_LIBSPE2_SPU_TASK
}
else
{
#ifdef DEBUG_LIBSPE2_SPU_TASK
printf("SPU: received ShutDown\n");
#endif //DEBUG_LIBSPE2_SPU_TASK
if( btLikely( received_message == Spu_Mailbox_Event_Shutdown ) )
{
shutdown = true;
}
else
{
//printf("SPU - Sth. recieved\n");
}
}
// set to status free and wait for next task
status.m_status = Spu_Status_Free;
cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(3));
}
printf("SPU: shutdown\n");
return 0;
}
#endif // USE_LIBSPE2
#endif //SPU_GATHERING_COLLISION_TASK_H

View file

@ -0,0 +1,19 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/

View file

@ -0,0 +1,48 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef MINKOWSKI_PENETRATION_DEPTH_SOLVER_H
#define MINKOWSKI_PENETRATION_DEPTH_SOLVER_H
#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h"
class btStackAlloc;
class btIDebugDraw;
class btVoronoiSimplexSolver;
class btConvexShape;
///MinkowskiPenetrationDepthSolver implements bruteforce penetration depth estimation.
///Implementation is based on sampling the depth using support mapping, and using GJK step to get the witness points.
class SpuMinkowskiPenetrationDepthSolver : public btConvexPenetrationDepthSolver
{
public:
SpuMinkowskiPenetrationDepthSolver() {}
virtual ~SpuMinkowskiPenetrationDepthSolver() {};
virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver,
const btConvexShape* convexA,const btConvexShape* convexB,
const btTransform& transA,const btTransform& transB,
btVector3& v, btVector3& pa, btVector3& pb,
class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc
);
};
#endif //MINKOWSKI_PENETRATION_DEPTH_SOLVER_H

View file

@ -0,0 +1,70 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef _SPU_PREFERRED_PENETRATION_DIRECTIONS_H
#define _SPU_PREFERRED_PENETRATION_DIRECTIONS_H
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
int spuGetNumPreferredPenetrationDirections(int shapeType, void* shape)
{
switch (shapeType)
{
case TRIANGLE_SHAPE_PROXYTYPE:
{
return 2;
//spu_printf("2\n");
break;
}
default:
{
#if __ASSERT
spu_printf("spuGetNumPreferredPenetrationDirections() - Unsupported bound type: %d.\n", shapeType);
#endif // __ASSERT
}
}
return 0;
}
void spuGetPreferredPenetrationDirection(int shapeType, void* shape, int index, btVector3& penetrationVector)
{
switch (shapeType)
{
case TRIANGLE_SHAPE_PROXYTYPE:
{
btVector3* vertices = (btVector3*)shape;
///calcNormal
penetrationVector = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]);
penetrationVector.normalize();
if (index)
penetrationVector *= btScalar(-1.);
break;
}
default:
{
#if __ASSERT
spu_printf("spuGetNumPreferredPenetrationDirections() - Unsupported bound type: %d.\n", shapeType);
#endif // __ASSERT
}
}
}
#endif //_SPU_PREFERRED_PENETRATION_DIRECTIONS_H

View file

@ -0,0 +1,65 @@
/*
Copyright (C) 2006, 2008 Sony Computer Entertainment Inc.
All rights reserved.
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef __BOXBOXDISTANCE_H__
#define __BOXBOXDISTANCE_H__
#include "Box.h"
//---------------------------------------------------------------------------
// boxBoxDistance:
//
// description:
// this computes info that can be used for the collision response of two boxes. when the boxes
// do not overlap, the points are set to the closest points of the boxes, and a positive
// distance between them is returned. if the boxes do overlap, a negative distance is returned
// and the points are set to two points that would touch after the boxes are translated apart.
// the contact normal gives the direction to repel or separate the boxes when they touch or
// overlap (it's being approximated here as one of the 15 "separating axis" directions).
//
// returns:
// positive or negative distance between two boxes.
//
// args:
// vmVector3& normal: set to a unit contact normal pointing from box A to box B.
//
// BoxPoint& boxPointA, BoxPoint& boxPointB:
// set to a closest point or point of penetration on each box.
//
// Box boxA, Box boxB:
// boxes, represented as 3 half-widths
//
// const vmTransform3& transformA, const vmTransform3& transformB:
// box transformations, in world coordinates
//
// float distanceThreshold:
// the algorithm will exit early if it finds that the boxes are more distant than this
// threshold, and not compute a contact normal or points. if this distance returned
// exceeds the threshold, all the other output data may not have been computed. by
// default, this is set to MAX_FLOAT so it will have no effect.
//
//---------------------------------------------------------------------------
float
boxBoxDistance(vmVector3& normal, BoxPoint& boxPointA, BoxPoint& boxPointB,
PE_REF(Box) boxA, const vmTransform3 & transformA, PE_REF(Box) boxB,
const vmTransform3 & transformB,
float distanceThreshold = FLT_MAX );
#endif /* __BOXBOXDISTANCE_H__ */

View file

@ -0,0 +1,54 @@
/*
Bullet Continuous Collision Detection and Physics Library, Copyright (c) 2007 Erwin Coumans
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SPU_SAMPLE_TASK_H
#define SPU_SAMPLE_TASK_H
#include "../PlatformDefinitions.h"
#include "LinearMath/btScalar.h"
#include "LinearMath/btVector3.h"
#include "LinearMath/btMatrix3x3.h"
#include "LinearMath/btAlignedAllocator.h"
enum
{
CMD_SAMPLE_INTEGRATE_BODIES = 1,
CMD_SAMPLE_PREDICT_MOTION_BODIES
};
ATTRIBUTE_ALIGNED16(struct) SpuSampleTaskDesc
{
BT_DECLARE_ALIGNED_ALLOCATOR();
uint32_t m_sampleCommand;
uint32_t m_taskId;
uint64_t m_mainMemoryPtr;
int m_sampleValue;
};
void processSampleTask(void* userPtr, void* lsMemory);
void* createSampleLocalStoreMemory();
#endif //SPU_SAMPLE_TASK_H

View file

@ -0,0 +1,153 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SPU_SAMPLE_TASK_PROCESS_H
#define SPU_SAMPLE_TASK_PROCESS_H
#include <assert.h>
#include "PlatformDefinitions.h"
#include <stdlib.h>
#include "LinearMath/btAlignedObjectArray.h"
#include "SpuSampleTask/SpuSampleTask.h"
//just add your commands here, try to keep them globally unique for debugging purposes
#define CMD_SAMPLE_TASK_COMMAND 10
/// SpuSampleTaskProcess handles SPU processing of collision pairs.
/// When PPU issues a task, it will look for completed task buffers
/// PPU will do postprocessing, dependent on workunit output (not likely)
class SpuSampleTaskProcess
{
// track task buffers that are being used, and total busy tasks
btAlignedObjectArray<bool> m_taskBusy;
btAlignedObjectArray<SpuSampleTaskDesc>m_spuSampleTaskDesc;
int m_numBusyTasks;
// the current task and the current entry to insert a new work unit
int m_currentTask;
bool m_initialized;
void postProcess(int taskId, int outputSize);
class btThreadSupportInterface* m_threadInterface;
int m_maxNumOutstandingTasks;
public:
SpuSampleTaskProcess(btThreadSupportInterface* threadInterface, int maxNumOutstandingTasks);
~SpuSampleTaskProcess();
///call initialize in the beginning of the frame, before addCollisionPairToTask
void initialize();
void issueTask(void* sampleMainMemPtr,int sampleValue,int sampleCommand);
///call flush to submit potential outstanding work to SPUs and wait for all involved SPUs to be finished
void flush();
};
#if defined(USE_LIBSPE2) && defined(__SPU__)
////////////////////MAIN/////////////////////////////
#include "../SpuLibspe2Support.h"
#include <spu_intrinsics.h>
#include <spu_mfcio.h>
#include <SpuFakeDma.h>
void * SamplelsMemoryFunc();
void SampleThreadFunc(void* userPtr,void* lsMemory);
//#define DEBUG_LIBSPE2_MAINLOOP
int main(unsigned long long speid, addr64 argp, addr64 envp)
{
printf("SPU is up \n");
ATTRIBUTE_ALIGNED128(btSpuStatus status);
ATTRIBUTE_ALIGNED16( SpuSampleTaskDesc taskDesc ) ;
unsigned int received_message = Spu_Mailbox_Event_Nothing;
bool shutdown = false;
cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(3));
status.m_status = Spu_Status_Free;
status.m_lsMemory.p = SamplelsMemoryFunc();
cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(3));
while (!shutdown)
{
received_message = spu_read_in_mbox();
switch(received_message)
{
case Spu_Mailbox_Event_Shutdown:
shutdown = true;
break;
case Spu_Mailbox_Event_Task:
// refresh the status
#ifdef DEBUG_LIBSPE2_MAINLOOP
printf("SPU recieved Task \n");
#endif //DEBUG_LIBSPE2_MAINLOOP
cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(3));
btAssert(status.m_status==Spu_Status_Occupied);
cellDmaGet(&taskDesc, status.m_taskDesc.p, sizeof(SpuSampleTaskDesc), DMA_TAG(3), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(3));
SampleThreadFunc((void*)&taskDesc, reinterpret_cast<void*> (taskDesc.m_mainMemoryPtr) );
break;
case Spu_Mailbox_Event_Nothing:
default:
break;
}
// set to status free and wait for next task
status.m_status = Spu_Status_Free;
cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(3));
}
return 0;
}
//////////////////////////////////////////////////////
#endif
#endif // SPU_SAMPLE_TASK_PROCESS_H

View file

@ -0,0 +1,148 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2007 Starbreeze Studios
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.
Written by: Marten Svanfeldt
*/
#ifndef SPU_SYNC_H
#define SPU_SYNC_H
#include "PlatformDefinitions.h"
#if defined(WIN32)
#define WIN32_LEAN_AND_MEAN
#ifdef _XBOX
#include <Xtl.h>
#else
#include <Windows.h>
#endif
///The btSpinlock is a structure to allow multi-platform synchronization. This allows to port the SPU tasks to other platforms.
class btSpinlock
{
public:
//typedef volatile LONG SpinVariable;
typedef CRITICAL_SECTION SpinVariable;
btSpinlock (SpinVariable* var)
: spinVariable (var)
{}
void Init ()
{
//*spinVariable = 0;
InitializeCriticalSection(spinVariable);
}
void Lock ()
{
EnterCriticalSection(spinVariable);
}
void Unlock ()
{
LeaveCriticalSection(spinVariable);
}
private:
SpinVariable* spinVariable;
};
#elif defined (__CELLOS_LV2__)
//#include <cell/atomic.h>
#include <cell/sync/mutex.h>
///The btSpinlock is a structure to allow multi-platform synchronization. This allows to port the SPU tasks to other platforms.
class btSpinlock
{
public:
typedef CellSyncMutex SpinVariable;
btSpinlock (SpinVariable* var)
: spinVariable (var)
{}
void Init ()
{
#ifndef __SPU__
//*spinVariable = 1;
cellSyncMutexInitialize(spinVariable);
#endif
}
void Lock ()
{
#ifdef __SPU__
// lock semaphore
/*while (cellAtomicTestAndDecr32(atomic_buf, (uint64_t)spinVariable) == 0)
{
};*/
cellSyncMutexLock((uint64_t)spinVariable);
#endif
}
void Unlock ()
{
#ifdef __SPU__
//cellAtomicIncr32(atomic_buf, (uint64_t)spinVariable);
cellSyncMutexUnlock((uint64_t)spinVariable);
#endif
}
private:
SpinVariable* spinVariable;
ATTRIBUTE_ALIGNED128(uint32_t atomic_buf[32]);
};
#else
//create a dummy implementation (without any locking) useful for serial processing
class btSpinlock
{
public:
typedef int SpinVariable;
btSpinlock (SpinVariable* var)
: spinVariable (var)
{}
void Init ()
{
}
void Lock ()
{
}
void Unlock ()
{
}
private:
SpinVariable* spinVariable;
};
#endif
#endif

View file

@ -0,0 +1,78 @@
/*
Copyright (C) 2009 Sony Computer Entertainment Inc.
All rights reserved.
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef __T_RB_DYN_BODY_H__
#define __T_RB_DYN_BODY_H__
#include "vectormath/vmInclude.h"
using namespace Vectormath::Aos;
#include "TrbStateVec.h"
class CollObject;
class TrbDynBody
{
public:
TrbDynBody()
{
fMass = 0.0f;
fCollObject = NULL;
fElasticity = 0.2f;
fFriction = 0.8f;
}
// Get methods
float getMass() const {return fMass;};
float getElasticity() const {return fElasticity;}
float getFriction() const {return fFriction;}
CollObject* getCollObject() const {return fCollObject;}
const Matrix3 &getBodyInertia() const {return fIBody;}
const Matrix3 &getBodyInertiaInv() const {return fIBodyInv;}
float getMassInv() const {return fMassInv;}
// Set methods
void setMass(float mass) {fMass=mass;fMassInv=mass>0.0f?1.0f/mass:0.0f;}
void setBodyInertia(const Matrix3 bodyInertia) {fIBody = bodyInertia;fIBodyInv = inverse(bodyInertia);}
void setElasticity(float elasticity) {fElasticity = elasticity;}
void setFriction(float friction) {fFriction = friction;}
void setCollObject(CollObject *collObj) {fCollObject = collObj;}
void setBodyInertiaInv(const Matrix3 bodyInertiaInv)
{
fIBody = inverse(bodyInertiaInv);
fIBodyInv = bodyInertiaInv;
}
void setMassInv(float invMass) {
fMass= invMass>0.0f ? 1.0f/invMass :0.0f;
fMassInv=invMass;
}
private:
// Rigid Body constants
float fMass; // Rigid Body mass
float fMassInv; // Inverse of mass
Matrix3 fIBody; // Inertia matrix in body's coords
Matrix3 fIBodyInv; // Inertia matrix inverse in body's coords
float fElasticity; // Coefficient of restitution
float fFriction; // Coefficient of friction
public:
CollObject* fCollObject; // Collision object corresponding the RB
} __attribute__ ((aligned(16)));
#endif /* __T_RB_DYN_BODY_H__ */

View file

@ -0,0 +1,334 @@
/*
Copyright (C) 2009 Sony Computer Entertainment Inc.
All rights reserved.
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef __TRBSTATEVEC_H__
#define __TRBSTATEVEC_H__
#include <stdlib.h>
#include "vectormath/vmInclude.h"
#include "PlatformDefinitions.h"
static inline vmVector3 read_Vector3(const float* p)
{
vmVector3 v;
loadXYZ(v, p);
return v;
}
static inline vmQuat read_Quat(const float* p)
{
vmQuat vq;
loadXYZW(vq, p);
return vq;
}
static inline void store_Vector3(const vmVector3 &src, float* p)
{
vmVector3 v = src;
storeXYZ(v, p);
}
static inline void store_Quat(const vmQuat &src, float* p)
{
vmQuat vq = src;
storeXYZW(vq, p);
}
// Motion Type
enum {
PfxMotionTypeFixed = 0,
PfxMotionTypeActive,
PfxMotionTypeKeyframe,
PfxMotionTypeOneWay,
PfxMotionTypeTrigger,
PfxMotionTypeCount
};
#define PFX_MOTION_MASK_DYNAMIC 0x0a // Active,OneWay
#define PFX_MOTION_MASK_STATIC 0x95 // Fixed,Keyframe,Trigger,Sleeping
#define PFX_MOTION_MASK_SLEEP 0x0e // Can sleep
#define PFX_MOTION_MASK_TYPE 0x7f
//
// Rigid Body state
//
#ifdef __CELLOS_LV2__
ATTRIBUTE_ALIGNED128(class) TrbState
#else
ATTRIBUTE_ALIGNED16(class) TrbState
#endif
{
public:
TrbState()
{
setMotionType(PfxMotionTypeActive);
contactFilterSelf=contactFilterTarget=0xffffffff;
deleted = 0;
mSleeping = 0;
useSleep = 1;
trbBodyIdx=0;
mSleepCount=0;
useCcd = 0;
useContactCallback = 0;
useSleepCallback = 0;
linearDamping = 1.0f;
angularDamping = 0.99f;
}
TrbState(const uint8_t m, const vmVector3& x, const vmQuat& q, const vmVector3& v, const vmVector3& omega );
uint16_t mSleepCount;
uint8_t mMotionType;
uint8_t deleted : 1;
uint8_t mSleeping : 1;
uint8_t useSleep : 1;
uint8_t useCcd : 1;
uint8_t useContactCallback : 1;
uint8_t useSleepCallback : 1;
uint16_t trbBodyIdx;
uint32_t contactFilterSelf;
uint32_t contactFilterTarget;
float center[3]; // AABB center(World)
float half[3]; // AABB half(World)
float linearDamping;
float angularDamping;
float deltaLinearVelocity[3];
float deltaAngularVelocity[3];
float fX[3]; // position
float fQ[4]; // orientation
float fV[3]; // velocity
float fOmega[3]; // angular velocity
inline void setZero(); // Zeroes out the elements
inline void setIdentity(); // Sets the rotation to identity and zeroes out the other elements
bool isDeleted() const {return deleted==1;}
uint16_t getRigidBodyId() const {return trbBodyIdx;}
void setRigidBodyId(uint16_t i) {trbBodyIdx = i;}
uint32_t getContactFilterSelf() const {return contactFilterSelf;}
void setContactFilterSelf(uint32_t filter) {contactFilterSelf = filter;}
uint32_t getContactFilterTarget() const {return contactFilterTarget;}
void setContactFilterTarget(uint32_t filter) {contactFilterTarget = filter;}
float getLinearDamping() const {return linearDamping;}
float getAngularDamping() const {return angularDamping;}
void setLinearDamping(float damping) {linearDamping=damping;}
void setAngularDamping(float damping) {angularDamping=damping;}
uint8_t getMotionType() const {return mMotionType;}
void setMotionType(uint8_t t) {mMotionType = t;mSleeping=0;mSleepCount=0;}
uint8_t getMotionMask() const {return (1<<mMotionType)|(mSleeping<<7);}
bool isAsleep() const {return mSleeping==1;}
bool isAwake() const {return mSleeping==0;}
void wakeup() {mSleeping=0;mSleepCount=0;}
void sleep() {if(useSleep) {mSleeping=1;mSleepCount=0;}}
uint8_t getUseSleep() const {return useSleep;}
void setUseSleep(uint8_t b) {useSleep=b;}
uint8_t getUseCcd() const {return useCcd;}
void setUseCcd(uint8_t b) {useCcd=b;}
uint8_t getUseContactCallback() const {return useContactCallback;}
void setUseContactCallback(uint8_t b) {useContactCallback=b;}
uint8_t getUseSleepCallback() const {return useSleepCallback;}
void setUseSleepCallback(uint8_t b) {useSleepCallback=b;}
void incrementSleepCount() {mSleepCount++;}
void resetSleepCount() {mSleepCount=0;}
uint16_t getSleepCount() const {return mSleepCount;}
vmVector3 getPosition() const {return read_Vector3(fX);}
vmQuat getOrientation() const {return read_Quat(fQ);}
vmVector3 getLinearVelocity() const {return read_Vector3(fV);}
vmVector3 getAngularVelocity() const {return read_Vector3(fOmega);}
vmVector3 getDeltaLinearVelocity() const {return read_Vector3(deltaLinearVelocity);}
vmVector3 getDeltaAngularVelocity() const {return read_Vector3(deltaAngularVelocity);}
void setPosition(const vmVector3 &pos) {store_Vector3(pos, fX);}
void setLinearVelocity(const vmVector3 &vel) {store_Vector3(vel, fV);}
void setAngularVelocity(const vmVector3 &vel) {store_Vector3(vel, fOmega);}
void setDeltaLinearVelocity(const vmVector3 &vel) {store_Vector3(vel, deltaLinearVelocity);}
void setDeltaAngularVelocity(const vmVector3 &vel) {store_Vector3(vel, deltaAngularVelocity);}
void setOrientation(const vmQuat &rot) {store_Quat(rot, fQ);}
inline void setAuxils(const vmVector3 &centerLocal,const vmVector3 &halfLocal);
inline void setAuxilsCcd(const vmVector3 &centerLocal,const vmVector3 &halfLocal,float timeStep);
inline void reset();
};
inline
TrbState::TrbState(const uint8_t m, const vmVector3& x, const vmQuat& q, const vmVector3& v, const vmVector3& omega)
{
setMotionType(m);
fX[0] = x[0];
fX[1] = x[1];
fX[2] = x[2];
fQ[0] = q[0];
fQ[1] = q[1];
fQ[2] = q[2];
fQ[3] = q[3];
fV[0] = v[0];
fV[1] = v[1];
fV[2] = v[2];
fOmega[0] = omega[0];
fOmega[1] = omega[1];
fOmega[2] = omega[2];
contactFilterSelf=contactFilterTarget=0xffff;
trbBodyIdx=0;
mSleeping = 0;
deleted = 0;
useSleep = 1;
useCcd = 0;
useContactCallback = 0;
useSleepCallback = 0;
mSleepCount=0;
linearDamping = 1.0f;
angularDamping = 0.99f;
}
inline void
TrbState::setIdentity()
{
fX[0] = 0.0f;
fX[1] = 0.0f;
fX[2] = 0.0f;
fQ[0] = 0.0f;
fQ[1] = 0.0f;
fQ[2] = 0.0f;
fQ[3] = 1.0f;
fV[0] = 0.0f;
fV[1] = 0.0f;
fV[2] = 0.0f;
fOmega[0] = 0.0f;
fOmega[1] = 0.0f;
fOmega[2] = 0.0f;
}
inline void
TrbState::setZero()
{
fX[0] = 0.0f;
fX[1] = 0.0f;
fX[2] = 0.0f;
fQ[0] = 0.0f;
fQ[1] = 0.0f;
fQ[2] = 0.0f;
fQ[3] = 0.0f;
fV[0] = 0.0f;
fV[1] = 0.0f;
fV[2] = 0.0f;
fOmega[0] = 0.0f;
fOmega[1] = 0.0f;
fOmega[2] = 0.0f;
}
inline void
TrbState::setAuxils(const vmVector3 &centerLocal,const vmVector3 &halfLocal)
{
vmVector3 centerW = getPosition() + rotate(getOrientation(),centerLocal);
vmVector3 halfW = absPerElem(vmMatrix3(getOrientation())) * halfLocal;
center[0] = centerW[0];
center[1] = centerW[1];
center[2] = centerW[2];
half[0] = halfW[0];
half[1] = halfW[1];
half[2] = halfW[2];
}
inline void
TrbState::setAuxilsCcd(const vmVector3 &centerLocal,const vmVector3 &halfLocal,float timeStep)
{
vmVector3 centerW = getPosition() + rotate(getOrientation(),centerLocal);
vmVector3 halfW = absPerElem(vmMatrix3(getOrientation())) * halfLocal;
vmVector3 diffvec = getLinearVelocity()*timeStep;
vmVector3 newCenter = centerW + diffvec;
vmVector3 aabbMin = minPerElem(newCenter - halfW,centerW - halfW);
vmVector3 aabbMax = maxPerElem(newCenter + halfW,centerW + halfW);
centerW = 0.5f * (aabbMin + aabbMax);
halfW =0.5f * (aabbMax - aabbMin);
center[0] = centerW[0];
center[1] = centerW[1];
center[2] = centerW[2];
half[0] = halfW[0];
half[1] = halfW[1];
half[2] = halfW[2];
}
inline
void TrbState::reset()
{
#if 0
mSleepCount = 0;
mMotionType = PfxMotionTypeActive;
mDeleted = 0;
mSleeping = 0;
mUseSleep = 1;
mUseCcd = 0;
mUseContactCallback = 0;
mUseSleepCallback = 0;
mRigidBodyId = 0;
mContactFilterSelf = 0xffffffff;
mContactFilterTarget = 0xffffffff;
mLinearDamping = 1.0f;
mAngularDamping = 0.99f;
mPosition = vmVector3(0.0f);
mOrientation = vmQuat::identity();
mLinearVelocity = vmVector3(0.0f);
mAngularVelocity = vmVector3(0.0f);
#endif
setMotionType(PfxMotionTypeActive);
contactFilterSelf=contactFilterTarget=0xffffffff;
deleted = 0;
mSleeping = 0;
useSleep = 1;
trbBodyIdx=0;
mSleepCount=0;
useCcd = 0;
useContactCallback = 0;
useSleepCallback = 0;
linearDamping = 1.0f;
angularDamping = 0.99f;
}
#endif /* __TRBSTATEVEC_H__ */

View file

@ -0,0 +1,138 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "LinearMath/btScalar.h"
#include "PlatformDefinitions.h"
#ifdef USE_WIN32_THREADING //platform specific defines are defined in PlatformDefinitions.h
#ifndef WIN32_THREAD_SUPPORT_H
#define WIN32_THREAD_SUPPORT_H
#include "LinearMath/btAlignedObjectArray.h"
#include "btThreadSupportInterface.h"
typedef void (*Win32ThreadFunc)(void* userPtr,void* lsMemory);
typedef void* (*Win32lsMemorySetupFunc)();
///Win32ThreadSupport helps to initialize/shutdown libspe2, start/stop SPU tasks and communication
class Win32ThreadSupport : public btThreadSupportInterface
{
public:
///placeholder, until libspe2 support is there
struct btSpuStatus
{
uint32_t m_taskId;
uint32_t m_commandId;
uint32_t m_status;
Win32ThreadFunc m_userThreadFunc;
void* m_userPtr; //for taskDesc etc
void* m_lsMemory; //initialized using Win32LocalStoreMemorySetupFunc
void* m_threadHandle; //this one is calling 'Win32ThreadFunc'
void* m_eventStartHandle;
char m_eventStartHandleName[32];
void* m_eventCompletetHandle;
char m_eventCompletetHandleName[32];
};
private:
btAlignedObjectArray<btSpuStatus> m_activeSpuStatus;
btAlignedObjectArray<void*> m_completeHandles;
int m_maxNumTasks;
public:
///Setup and initialize SPU/CELL/Libspe2
struct Win32ThreadConstructionInfo
{
Win32ThreadConstructionInfo(char* uniqueName,
Win32ThreadFunc userThreadFunc,
Win32lsMemorySetupFunc lsMemoryFunc,
int numThreads=1,
int threadStackSize=65535
)
:m_uniqueName(uniqueName),
m_userThreadFunc(userThreadFunc),
m_lsMemoryFunc(lsMemoryFunc),
m_numThreads(numThreads),
m_threadStackSize(threadStackSize)
{
}
char* m_uniqueName;
Win32ThreadFunc m_userThreadFunc;
Win32lsMemorySetupFunc m_lsMemoryFunc;
int m_numThreads;
int m_threadStackSize;
};
Win32ThreadSupport(const Win32ThreadConstructionInfo& threadConstructionInfo);
///cleanup/shutdown Libspe2
virtual ~Win32ThreadSupport();
void startThreads(const Win32ThreadConstructionInfo& threadInfo);
///send messages to SPUs
virtual void sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t uiArgument1);
///check for messages from SPUs
virtual void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1);
virtual bool isTaskCompleted(unsigned int *puiArgument0, unsigned int *puiArgument1, int timeOutInMilliseconds);
///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded)
virtual void startSPU();
///tell the task scheduler we are done with the SPU tasks
virtual void stopSPU();
virtual void setNumTasks(int numTasks)
{
m_maxNumTasks = numTasks;
}
virtual int getNumTasks() const
{
return m_maxNumTasks;
}
virtual void* getThreadLocalMemory(int taskId)
{
return m_activeSpuStatus[taskId].m_lsMemory;
}
virtual btBarrier* createBarrier();
virtual btCriticalSection* createCriticalSection();
};
#endif //WIN32_THREAD_SUPPORT_H
#endif //USE_WIN32_THREADING

View file

@ -0,0 +1,138 @@
/*
Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
Copyright (C) 2006, 2009 Sony Computer Entertainment 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.
*/
//----------------------------------------------------------------------------------------
#ifndef BTGPU3DGRIDBROADPHASE_H
#define BTGPU3DGRIDBROADPHASE_H
//----------------------------------------------------------------------------------------
#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
#include "btGpu3DGridBroadphaseSharedTypes.h"
//----------------------------------------------------------------------------------------
///The btGpu3DGridBroadphase uses GPU-style code compiled for CPU to compute overlapping pairs
class btGpu3DGridBroadphase : public btSimpleBroadphase
{
protected:
bool m_bInitialized;
unsigned int m_numBodies;
unsigned int m_numCells;
unsigned int m_maxPairsPerBody;
btScalar m_cellFactorAABB;
unsigned int m_maxBodiesPerCell;
bt3DGridBroadphaseParams m_params;
btScalar m_maxRadius;
// CPU data
unsigned int* m_hBodiesHash;
unsigned int* m_hCellStart;
unsigned int* m_hPairBuffStartCurr;
bt3DGrid3F1U* m_hAABB;
unsigned int* m_hPairBuff;
unsigned int* m_hPairScan;
unsigned int* m_hPairOut;
// large proxies
int m_numLargeHandles;
int m_maxLargeHandles;
int m_LastLargeHandleIndex;
btSimpleBroadphaseProxy* m_pLargeHandles;
void* m_pLargeHandlesRawPtr;
int m_firstFreeLargeHandle;
int allocLargeHandle()
{
btAssert(m_numLargeHandles < m_maxLargeHandles);
int freeLargeHandle = m_firstFreeLargeHandle;
m_firstFreeLargeHandle = m_pLargeHandles[freeLargeHandle].GetNextFree();
m_numLargeHandles++;
if(freeLargeHandle > m_LastLargeHandleIndex)
{
m_LastLargeHandleIndex = freeLargeHandle;
}
return freeLargeHandle;
}
void freeLargeHandle(btSimpleBroadphaseProxy* proxy)
{
int handle = int(proxy - m_pLargeHandles);
btAssert((handle >= 0) && (handle < m_maxHandles));
if(handle == m_LastLargeHandleIndex)
{
m_LastLargeHandleIndex--;
}
proxy->SetNextFree(m_firstFreeLargeHandle);
m_firstFreeLargeHandle = handle;
proxy->m_clientObject = 0;
m_numLargeHandles--;
}
bool isLargeProxy(const btVector3& aabbMin, const btVector3& aabbMax);
bool isLargeProxy(btBroadphaseProxy* proxy);
// debug
unsigned int m_numPairsAdded;
unsigned int m_numPairsRemoved;
unsigned int m_numOverflows;
//
public:
btGpu3DGridBroadphase(const btVector3& worldAabbMin,const btVector3& worldAabbMax,
int gridSizeX, int gridSizeY, int gridSizeZ,
int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody,
int maxBodiesPerCell = 8,
btScalar cellFactorAABB = btScalar(1.0f));
btGpu3DGridBroadphase( btOverlappingPairCache* overlappingPairCache,
const btVector3& worldAabbMin,const btVector3& worldAabbMax,
int gridSizeX, int gridSizeY, int gridSizeZ,
int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody,
int maxBodiesPerCell = 8,
btScalar cellFactorAABB = btScalar(1.0f));
virtual ~btGpu3DGridBroadphase();
virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
virtual btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy);
virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback);
virtual void resetPool(btDispatcher* dispatcher);
protected:
void _initialize( const btVector3& worldAabbMin,const btVector3& worldAabbMax,
int gridSizeX, int gridSizeY, int gridSizeZ,
int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody,
int maxBodiesPerCell = 8,
btScalar cellFactorAABB = btScalar(1.0f));
void _finalize();
void addPairsToCache(btDispatcher* dispatcher);
void addLarge2LargePairsToCache(btDispatcher* dispatcher);
// overrides for CPU version
virtual void setParameters(bt3DGridBroadphaseParams* hostParams);
virtual void prepareAABB();
virtual void calcHashAABB();
virtual void sortHash();
virtual void findCellStart();
virtual void findOverlappingPairs();
virtual void findPairsLarge();
virtual void computePairCacheChanges();
virtual void scanOverlappingPairBuff();
virtual void squeezeOverlappingPairBuff();
};
//----------------------------------------------------------------------------------------
#endif //BTGPU3DGRIDBROADPHASE_H
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------

View file

@ -0,0 +1,430 @@
/*
Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
Copyright (C) 2006, 2009 Sony Computer Entertainment 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.
*/
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
// K E R N E L F U N C T I O N S
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
// calculate position in uniform grid
BT_GPU___device__ int3 bt3DGrid_calcGridPos(float4 p)
{
int3 gridPos;
gridPos.x = (int)floor((p.x - BT_GPU_params.m_worldOriginX) / BT_GPU_params.m_cellSizeX);
gridPos.y = (int)floor((p.y - BT_GPU_params.m_worldOriginY) / BT_GPU_params.m_cellSizeY);
gridPos.z = (int)floor((p.z - BT_GPU_params.m_worldOriginZ) / BT_GPU_params.m_cellSizeZ);
return gridPos;
} // bt3DGrid_calcGridPos()
//----------------------------------------------------------------------------------------
// calculate address in grid from position (clamping to edges)
BT_GPU___device__ uint bt3DGrid_calcGridHash(int3 gridPos)
{
gridPos.x = BT_GPU_max(0, BT_GPU_min(gridPos.x, (int)BT_GPU_params.m_gridSizeX - 1));
gridPos.y = BT_GPU_max(0, BT_GPU_min(gridPos.y, (int)BT_GPU_params.m_gridSizeY - 1));
gridPos.z = BT_GPU_max(0, BT_GPU_min(gridPos.z, (int)BT_GPU_params.m_gridSizeZ - 1));
return BT_GPU___mul24(BT_GPU___mul24(gridPos.z, BT_GPU_params.m_gridSizeY), BT_GPU_params.m_gridSizeX) + BT_GPU___mul24(gridPos.y, BT_GPU_params.m_gridSizeX) + gridPos.x;
} // bt3DGrid_calcGridHash()
//----------------------------------------------------------------------------------------
// calculate grid hash value for each body using its AABB
BT_GPU___global__ void calcHashAABBD(bt3DGrid3F1U* pAABB, uint2* pHash, uint numBodies)
{
int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x;
if(index >= (int)numBodies)
{
return;
}
bt3DGrid3F1U bbMin = pAABB[index*2];
bt3DGrid3F1U bbMax = pAABB[index*2 + 1];
float4 pos;
pos.x = (bbMin.fx + bbMax.fx) * 0.5f;
pos.y = (bbMin.fy + bbMax.fy) * 0.5f;
pos.z = (bbMin.fz + bbMax.fz) * 0.5f;
// get address in grid
int3 gridPos = bt3DGrid_calcGridPos(pos);
uint gridHash = bt3DGrid_calcGridHash(gridPos);
// store grid hash and body index
pHash[index] = BT_GPU_make_uint2(gridHash, index);
} // calcHashAABBD()
//----------------------------------------------------------------------------------------
BT_GPU___global__ void findCellStartD(uint2* pHash, uint* cellStart, uint numBodies)
{
int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x;
if(index >= (int)numBodies)
{
return;
}
uint2 sortedData = pHash[index];
// Load hash data into shared memory so that we can look
// at neighboring body's hash value without loading
// two hash values per thread
BT_GPU___shared__ uint sharedHash[257];
sharedHash[BT_GPU_threadIdx.x+1] = sortedData.x;
if((index > 0) && (BT_GPU_threadIdx.x == 0))
{
// first thread in block must load neighbor body hash
volatile uint2 prevData = pHash[index-1];
sharedHash[0] = prevData.x;
}
BT_GPU___syncthreads();
if((index == 0) || (sortedData.x != sharedHash[BT_GPU_threadIdx.x]))
{
cellStart[sortedData.x] = index;
}
} // findCellStartD()
//----------------------------------------------------------------------------------------
BT_GPU___device__ uint cudaTestAABBOverlap(bt3DGrid3F1U min0, bt3DGrid3F1U max0, bt3DGrid3F1U min1, bt3DGrid3F1U max1)
{
return (min0.fx <= max1.fx)&& (min1.fx <= max0.fx) &&
(min0.fy <= max1.fy)&& (min1.fy <= max0.fy) &&
(min0.fz <= max1.fz)&& (min1.fz <= max0.fz);
} // cudaTestAABBOverlap()
//----------------------------------------------------------------------------------------
BT_GPU___device__ void findPairsInCell( int3 gridPos,
uint index,
uint2* pHash,
uint* pCellStart,
bt3DGrid3F1U* pAABB,
uint* pPairBuff,
uint2* pPairBuffStartCurr,
uint numBodies)
{
if ( (gridPos.x < 0) || (gridPos.x > (int)BT_GPU_params.m_gridSizeX - 1)
|| (gridPos.y < 0) || (gridPos.y > (int)BT_GPU_params.m_gridSizeY - 1)
|| (gridPos.z < 0) || (gridPos.z > (int)BT_GPU_params.m_gridSizeZ - 1))
{
return;
}
uint gridHash = bt3DGrid_calcGridHash(gridPos);
// get start of bucket for this cell
uint bucketStart = pCellStart[gridHash];
if (bucketStart == 0xffffffff)
{
return; // cell empty
}
// iterate over bodies in this cell
uint2 sortedData = pHash[index];
uint unsorted_indx = sortedData.y;
bt3DGrid3F1U min0 = BT_GPU_FETCH(pAABB, unsorted_indx*2);
bt3DGrid3F1U max0 = BT_GPU_FETCH(pAABB, unsorted_indx*2 + 1);
uint handleIndex = min0.uw;
uint2 start_curr = pPairBuffStartCurr[handleIndex];
uint start = start_curr.x;
uint curr = start_curr.y;
uint2 start_curr_next = pPairBuffStartCurr[handleIndex+1];
uint curr_max = start_curr_next.x - start - 1;
uint bucketEnd = bucketStart + BT_GPU_params.m_maxBodiesPerCell;
bucketEnd = (bucketEnd > numBodies) ? numBodies : bucketEnd;
for(uint index2 = bucketStart; index2 < bucketEnd; index2++)
{
uint2 cellData = pHash[index2];
if (cellData.x != gridHash)
{
break; // no longer in same bucket
}
uint unsorted_indx2 = cellData.y;
if (unsorted_indx2 < unsorted_indx) // check not colliding with self
{
bt3DGrid3F1U min1 = BT_GPU_FETCH(pAABB, unsorted_indx2*2);
bt3DGrid3F1U max1 = BT_GPU_FETCH(pAABB, unsorted_indx2*2 + 1);
if(cudaTestAABBOverlap(min0, max0, min1, max1))
{
uint handleIndex2 = min1.uw;
uint k;
for(k = 0; k < curr; k++)
{
uint old_pair = pPairBuff[start+k] & (~BT_3DGRID_PAIR_ANY_FLG);
if(old_pair == handleIndex2)
{
pPairBuff[start+k] |= BT_3DGRID_PAIR_FOUND_FLG;
break;
}
}
if(k == curr)
{
if(curr >= curr_max)
{ // not a good solution, but let's avoid crash
break;
}
pPairBuff[start+curr] = handleIndex2 | BT_3DGRID_PAIR_NEW_FLG;
curr++;
}
}
}
}
pPairBuffStartCurr[handleIndex] = BT_GPU_make_uint2(start, curr);
return;
} // findPairsInCell()
//----------------------------------------------------------------------------------------
BT_GPU___global__ void findOverlappingPairsD( bt3DGrid3F1U* pAABB, uint2* pHash, uint* pCellStart,
uint* pPairBuff, uint2* pPairBuffStartCurr, uint numBodies)
{
int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x;
if(index >= (int)numBodies)
{
return;
}
uint2 sortedData = pHash[index];
uint unsorted_indx = sortedData.y;
bt3DGrid3F1U bbMin = BT_GPU_FETCH(pAABB, unsorted_indx*2);
bt3DGrid3F1U bbMax = BT_GPU_FETCH(pAABB, unsorted_indx*2 + 1);
float4 pos;
pos.x = (bbMin.fx + bbMax.fx) * 0.5f;
pos.y = (bbMin.fy + bbMax.fy) * 0.5f;
pos.z = (bbMin.fz + bbMax.fz) * 0.5f;
// get address in grid
int3 gridPos = bt3DGrid_calcGridPos(pos);
// examine only neighbouring cells
for(int z=-1; z<=1; z++) {
for(int y=-1; y<=1; y++) {
for(int x=-1; x<=1; x++) {
findPairsInCell(gridPos + BT_GPU_make_int3(x, y, z), index, pHash, pCellStart, pAABB, pPairBuff, pPairBuffStartCurr, numBodies);
}
}
}
} // findOverlappingPairsD()
//----------------------------------------------------------------------------------------
BT_GPU___global__ void findPairsLargeD( bt3DGrid3F1U* pAABB, uint2* pHash, uint* pCellStart, uint* pPairBuff,
uint2* pPairBuffStartCurr, uint numBodies, uint numLarge)
{
int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x;
if(index >= (int)numBodies)
{
return;
}
uint2 sortedData = pHash[index];
uint unsorted_indx = sortedData.y;
bt3DGrid3F1U min0 = BT_GPU_FETCH(pAABB, unsorted_indx*2);
bt3DGrid3F1U max0 = BT_GPU_FETCH(pAABB, unsorted_indx*2 + 1);
uint handleIndex = min0.uw;
uint2 start_curr = pPairBuffStartCurr[handleIndex];
uint start = start_curr.x;
uint curr = start_curr.y;
uint2 start_curr_next = pPairBuffStartCurr[handleIndex+1];
uint curr_max = start_curr_next.x - start - 1;
for(uint i = 0; i < numLarge; i++)
{
uint indx2 = numBodies + i;
bt3DGrid3F1U min1 = BT_GPU_FETCH(pAABB, indx2*2);
bt3DGrid3F1U max1 = BT_GPU_FETCH(pAABB, indx2*2 + 1);
if(cudaTestAABBOverlap(min0, max0, min1, max1))
{
uint k;
uint handleIndex2 = min1.uw;
for(k = 0; k < curr; k++)
{
uint old_pair = pPairBuff[start+k] & (~BT_3DGRID_PAIR_ANY_FLG);
if(old_pair == handleIndex2)
{
pPairBuff[start+k] |= BT_3DGRID_PAIR_FOUND_FLG;
break;
}
}
if(k == curr)
{
pPairBuff[start+curr] = handleIndex2 | BT_3DGRID_PAIR_NEW_FLG;
if(curr >= curr_max)
{ // not a good solution, but let's avoid crash
break;
}
curr++;
}
}
}
pPairBuffStartCurr[handleIndex] = BT_GPU_make_uint2(start, curr);
return;
} // findPairsLargeD()
//----------------------------------------------------------------------------------------
BT_GPU___global__ void computePairCacheChangesD(uint* pPairBuff, uint2* pPairBuffStartCurr,
uint* pPairScan, bt3DGrid3F1U* pAABB, uint numBodies)
{
int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x;
if(index >= (int)numBodies)
{
return;
}
bt3DGrid3F1U bbMin = pAABB[index * 2];
uint handleIndex = bbMin.uw;
uint2 start_curr = pPairBuffStartCurr[handleIndex];
uint start = start_curr.x;
uint curr = start_curr.y;
uint *pInp = pPairBuff + start;
uint num_changes = 0;
for(uint k = 0; k < curr; k++, pInp++)
{
if(!((*pInp) & BT_3DGRID_PAIR_FOUND_FLG))
{
num_changes++;
}
}
pPairScan[index+1] = num_changes;
} // computePairCacheChangesD()
//----------------------------------------------------------------------------------------
BT_GPU___global__ void squeezeOverlappingPairBuffD(uint* pPairBuff, uint2* pPairBuffStartCurr, uint* pPairScan,
uint* pPairOut, bt3DGrid3F1U* pAABB, uint numBodies)
{
int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x;
if(index >= (int)numBodies)
{
return;
}
bt3DGrid3F1U bbMin = pAABB[index * 2];
uint handleIndex = bbMin.uw;
uint2 start_curr = pPairBuffStartCurr[handleIndex];
uint start = start_curr.x;
uint curr = start_curr.y;
uint* pInp = pPairBuff + start;
uint* pOut = pPairOut + pPairScan[index];
uint* pOut2 = pInp;
uint num = 0;
for(uint k = 0; k < curr; k++, pInp++)
{
if(!((*pInp) & BT_3DGRID_PAIR_FOUND_FLG))
{
*pOut = *pInp;
pOut++;
}
if((*pInp) & BT_3DGRID_PAIR_ANY_FLG)
{
*pOut2 = (*pInp) & (~BT_3DGRID_PAIR_ANY_FLG);
pOut2++;
num++;
}
}
pPairBuffStartCurr[handleIndex] = BT_GPU_make_uint2(start, num);
} // squeezeOverlappingPairBuffD()
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
// E N D O F K E R N E L F U N C T I O N S
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
extern "C"
{
//----------------------------------------------------------------------------------------
void BT_GPU_PREF(calcHashAABB)(bt3DGrid3F1U* pAABB, unsigned int* hash, unsigned int numBodies)
{
int numThreads, numBlocks;
BT_GPU_PREF(computeGridSize)(numBodies, 256, numBlocks, numThreads);
// execute the kernel
BT_GPU_EXECKERNEL(numBlocks, numThreads, calcHashAABBD, (pAABB, (uint2*)hash, numBodies));
// check if kernel invocation generated an error
BT_GPU_CHECK_ERROR("calcHashAABBD kernel execution failed");
} // calcHashAABB()
//----------------------------------------------------------------------------------------
void BT_GPU_PREF(findCellStart(unsigned int* hash, unsigned int* cellStart, unsigned int numBodies, unsigned int numCells))
{
int numThreads, numBlocks;
BT_GPU_PREF(computeGridSize)(numBodies, 256, numBlocks, numThreads);
BT_GPU_SAFE_CALL(BT_GPU_Memset(cellStart, 0xffffffff, numCells*sizeof(uint)));
BT_GPU_EXECKERNEL(numBlocks, numThreads, findCellStartD, ((uint2*)hash, (uint*)cellStart, numBodies));
BT_GPU_CHECK_ERROR("Kernel execution failed: findCellStartD");
} // findCellStart()
//----------------------------------------------------------------------------------------
void BT_GPU_PREF(findOverlappingPairs(bt3DGrid3F1U* pAABB, unsigned int* pHash, unsigned int* pCellStart, unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int numBodies))
{
#if B_CUDA_USE_TEX
BT_GPU_SAFE_CALL(cudaBindTexture(0, pAABBTex, pAABB, numBodies * 2 * sizeof(bt3DGrid3F1U)));
#endif
int numThreads, numBlocks;
BT_GPU_PREF(computeGridSize)(numBodies, 64, numBlocks, numThreads);
BT_GPU_EXECKERNEL(numBlocks, numThreads, findOverlappingPairsD, (pAABB,(uint2*)pHash,(uint*)pCellStart,(uint*)pPairBuff,(uint2*)pPairBuffStartCurr,numBodies));
BT_GPU_CHECK_ERROR("Kernel execution failed: bt_CudaFindOverlappingPairsD");
#if B_CUDA_USE_TEX
BT_GPU_SAFE_CALL(cudaUnbindTexture(pAABBTex));
#endif
} // findOverlappingPairs()
//----------------------------------------------------------------------------------------
void BT_GPU_PREF(findPairsLarge(bt3DGrid3F1U* pAABB, unsigned int* pHash, unsigned int* pCellStart, unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int numBodies, unsigned int numLarge))
{
#if B_CUDA_USE_TEX
BT_GPU_SAFE_CALL(cudaBindTexture(0, pAABBTex, pAABB, (numBodies+numLarge) * 2 * sizeof(bt3DGrid3F1U)));
#endif
int numThreads, numBlocks;
BT_GPU_PREF(computeGridSize)(numBodies, 64, numBlocks, numThreads);
BT_GPU_EXECKERNEL(numBlocks, numThreads, findPairsLargeD, (pAABB,(uint2*)pHash,(uint*)pCellStart,(uint*)pPairBuff,(uint2*)pPairBuffStartCurr,numBodies,numLarge));
BT_GPU_CHECK_ERROR("Kernel execution failed: btCuda_findPairsLargeD");
#if B_CUDA_USE_TEX
BT_GPU_SAFE_CALL(cudaUnbindTexture(pAABBTex));
#endif
} // findPairsLarge()
//----------------------------------------------------------------------------------------
void BT_GPU_PREF(computePairCacheChanges(unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int* pPairScan, bt3DGrid3F1U* pAABB, unsigned int numBodies))
{
int numThreads, numBlocks;
BT_GPU_PREF(computeGridSize)(numBodies, 256, numBlocks, numThreads);
BT_GPU_EXECKERNEL(numBlocks, numThreads, computePairCacheChangesD, ((uint*)pPairBuff,(uint2*)pPairBuffStartCurr,(uint*)pPairScan,pAABB,numBodies));
BT_GPU_CHECK_ERROR("Kernel execution failed: btCudaComputePairCacheChangesD");
} // computePairCacheChanges()
//----------------------------------------------------------------------------------------
void BT_GPU_PREF(squeezeOverlappingPairBuff(unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int* pPairScan, unsigned int* pPairOut, bt3DGrid3F1U* pAABB, unsigned int numBodies))
{
int numThreads, numBlocks;
BT_GPU_PREF(computeGridSize)(numBodies, 256, numBlocks, numThreads);
BT_GPU_EXECKERNEL(numBlocks, numThreads, squeezeOverlappingPairBuffD, ((uint*)pPairBuff,(uint2*)pPairBuffStartCurr,(uint*)pPairScan,(uint*)pPairOut,pAABB,numBodies));
BT_GPU_CHECK_ERROR("Kernel execution failed: btCudaSqueezeOverlappingPairBuffD");
} // btCuda_squeezeOverlappingPairBuff()
//------------------------------------------------------------------------------------------------
} // extern "C"
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,61 @@
/*
Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
Copyright (C) 2006, 2009 Sony Computer Entertainment 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.
*/
//----------------------------------------------------------------------------------------
// Shared definitions for GPU-based 3D Grid collision detection broadphase
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Keep this file free from Bullet headers
// it is included into both CUDA and CPU code
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//----------------------------------------------------------------------------------------
#ifndef BTGPU3DGRIDBROADPHASESHAREDDEFS_H
#define BTGPU3DGRIDBROADPHASESHAREDDEFS_H
//----------------------------------------------------------------------------------------
#include "btGpu3DGridBroadphaseSharedTypes.h"
//----------------------------------------------------------------------------------------
extern "C"
{
//----------------------------------------------------------------------------------------
void BT_GPU_PREF(calcHashAABB)(bt3DGrid3F1U* pAABB, unsigned int* hash, unsigned int numBodies);
void BT_GPU_PREF(findCellStart)(unsigned int* hash, unsigned int* cellStart, unsigned int numBodies, unsigned int numCells);
void BT_GPU_PREF(findOverlappingPairs)(bt3DGrid3F1U* pAABB, unsigned int* pHash, unsigned int* pCellStart, unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int numBodies);
void BT_GPU_PREF(findPairsLarge)(bt3DGrid3F1U* pAABB, unsigned int* pHash, unsigned int* pCellStart, unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int numBodies, unsigned int numLarge);
void BT_GPU_PREF(computePairCacheChanges)(unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int* pPairScan, bt3DGrid3F1U* pAABB, unsigned int numBodies);
void BT_GPU_PREF(squeezeOverlappingPairBuff)(unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int* pPairScan, unsigned int* pPairOut, bt3DGrid3F1U* pAABB, unsigned int numBodies);
//----------------------------------------------------------------------------------------
} // extern "C"
//----------------------------------------------------------------------------------------
#endif // BTGPU3DGRIDBROADPHASESHAREDDEFS_H

View file

@ -0,0 +1,67 @@
/*
Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
Copyright (C) 2006, 2009 Sony Computer Entertainment 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.
*/
//----------------------------------------------------------------------------------------
// Shared definitions for GPU-based 3D Grid collision detection broadphase
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Keep this file free from Bullet headers
// it is included into both CUDA and CPU code
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//----------------------------------------------------------------------------------------
#ifndef BTGPU3DGRIDBROADPHASESHAREDTYPES_H
#define BTGPU3DGRIDBROADPHASESHAREDTYPES_H
//----------------------------------------------------------------------------------------
#define BT_3DGRID_PAIR_FOUND_FLG (0x40000000)
#define BT_3DGRID_PAIR_NEW_FLG (0x20000000)
#define BT_3DGRID_PAIR_ANY_FLG (BT_3DGRID_PAIR_FOUND_FLG | BT_3DGRID_PAIR_NEW_FLG)
//----------------------------------------------------------------------------------------
struct bt3DGridBroadphaseParams
{
unsigned int m_gridSizeX;
unsigned int m_gridSizeY;
unsigned int m_gridSizeZ;
unsigned int m_numCells;
float m_worldOriginX;
float m_worldOriginY;
float m_worldOriginZ;
float m_cellSizeX;
float m_cellSizeY;
float m_cellSizeZ;
unsigned int m_numBodies;
unsigned int m_maxBodiesPerCell;
};
//----------------------------------------------------------------------------------------
struct bt3DGrid3F1U
{
float fx;
float fy;
float fz;
unsigned int uw;
};
//----------------------------------------------------------------------------------------
#endif // BTGPU3DGRIDBROADPHASESHAREDTYPES_H

View file

@ -0,0 +1,211 @@
/*
Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
Copyright (C) 2006, 2009 Sony Computer Entertainment 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.
*/
// definitions for "GPU on CPU" code
#ifndef BT_GPU_DEFINES_H
#define BT_GPU_DEFINES_H
typedef unsigned int uint;
struct int2
{
int x, y;
};
struct uint2
{
unsigned int x, y;
};
struct int3
{
int x, y, z;
};
struct uint3
{
unsigned int x, y, z;
};
struct float4
{
float x, y, z, w;
};
struct float3
{
float x, y, z;
};
#define BT_GPU___device__ inline
#define BT_GPU___devdata__
#define BT_GPU___constant__
#define BT_GPU_max(a, b) ((a) > (b) ? (a) : (b))
#define BT_GPU_min(a, b) ((a) < (b) ? (a) : (b))
#define BT_GPU_params s3DGridBroadphaseParams
#define BT_GPU___mul24(a, b) ((a)*(b))
#define BT_GPU___global__ inline
#define BT_GPU___shared__ static
#define BT_GPU___syncthreads()
#define CUDART_PI_F SIMD_PI
static inline uint2 bt3dGrid_make_uint2(unsigned int x, unsigned int y)
{
uint2 t; t.x = x; t.y = y; return t;
}
#define BT_GPU_make_uint2(x, y) bt3dGrid_make_uint2(x, y)
static inline int3 bt3dGrid_make_int3(int x, int y, int z)
{
int3 t; t.x = x; t.y = y; t.z = z; return t;
}
#define BT_GPU_make_int3(x, y, z) bt3dGrid_make_int3(x, y, z)
static inline float3 bt3dGrid_make_float3(float x, float y, float z)
{
float3 t; t.x = x; t.y = y; t.z = z; return t;
}
#define BT_GPU_make_float3(x, y, z) bt3dGrid_make_float3(x, y, z)
static inline float3 bt3dGrid_make_float34(float4 f)
{
float3 t; t.x = f.x; t.y = f.y; t.z = f.z; return t;
}
#define BT_GPU_make_float34(f) bt3dGrid_make_float34(f)
static inline float3 bt3dGrid_make_float31(float f)
{
float3 t; t.x = t.y = t.z = f; return t;
}
#define BT_GPU_make_float31(x) bt3dGrid_make_float31(x)
static inline float4 bt3dGrid_make_float42(float3 v, float f)
{
float4 t; t.x = v.x; t.y = v.y; t.z = v.z; t.w = f; return t;
}
#define BT_GPU_make_float42(a, b) bt3dGrid_make_float42(a, b)
static inline float4 bt3dGrid_make_float44(float a, float b, float c, float d)
{
float4 t; t.x = a; t.y = b; t.z = c; t.w = d; return t;
}
#define BT_GPU_make_float44(a, b, c, d) bt3dGrid_make_float44(a, b, c, d)
inline int3 operator+(int3 a, int3 b)
{
return bt3dGrid_make_int3(a.x + b.x, a.y + b.y, a.z + b.z);
}
inline float4 operator+(const float4& a, const float4& b)
{
float4 r; r.x = a.x+b.x; r.y = a.y+b.y; r.z = a.z+b.z; r.w = a.w+b.w; return r;
}
inline float4 operator*(const float4& a, float fact)
{
float4 r; r.x = a.x*fact; r.y = a.y*fact; r.z = a.z*fact; r.w = a.w*fact; return r;
}
inline float4 operator*(float fact, float4& a)
{
return (a * fact);
}
inline float4& operator*=(float4& a, float fact)
{
a = fact * a;
return a;
}
inline float4& operator+=(float4& a, const float4& b)
{
a = a + b;
return a;
}
inline float3 operator+(const float3& a, const float3& b)
{
float3 r; r.x = a.x+b.x; r.y = a.y+b.y; r.z = a.z+b.z; return r;
}
inline float3 operator-(const float3& a, const float3& b)
{
float3 r; r.x = a.x-b.x; r.y = a.y-b.y; r.z = a.z-b.z; return r;
}
static inline float bt3dGrid_dot(float3& a, float3& b)
{
return a.x*b.x+a.y*b.y+a.z*b.z;
}
#define BT_GPU_dot(a,b) bt3dGrid_dot(a,b)
static inline float bt3dGrid_dot4(float4& a, float4& b)
{
return a.x*b.x+a.y*b.y+a.z*b.z+a.w*b.w;
}
#define BT_GPU_dot4(a,b) bt3dGrid_dot4(a,b)
static inline float3 bt3dGrid_cross(const float3& a, const float3& b)
{
float3 r; r.x = a.y*b.z-a.z*b.y; r.y = -a.x*b.z+a.z*b.x; r.z = a.x*b.y-a.y*b.x; return r;
}
#define BT_GPU_cross(a,b) bt3dGrid_cross(a,b)
inline float3 operator*(const float3& a, float fact)
{
float3 r; r.x = a.x*fact; r.y = a.y*fact; r.z = a.z*fact; return r;
}
inline float3& operator+=(float3& a, const float3& b)
{
a = a + b;
return a;
}
inline float3& operator-=(float3& a, const float3& b)
{
a = a - b;
return a;
}
inline float3& operator*=(float3& a, float fact)
{
a = a * fact;
return a;
}
inline float3 operator-(const float3& v)
{
float3 r; r.x = -v.x; r.y = -v.y; r.z = -v.z; return r;
}
#define BT_GPU_FETCH(a, b) a[b]
#define BT_GPU_FETCH4(a, b) a[b]
#define BT_GPU_PREF(func) btGpu_##func
#define BT_GPU_SAFE_CALL(func) func
#define BT_GPU_Memset memset
#define BT_GPU_MemcpyToSymbol(a, b, c) memcpy(&a, b, c)
#define BT_GPU_BindTexture(a, b, c, d)
#define BT_GPU_UnbindTexture(a)
static uint2 s_blockIdx, s_blockDim, s_threadIdx;
#define BT_GPU_blockIdx s_blockIdx
#define BT_GPU_blockDim s_blockDim
#define BT_GPU_threadIdx s_threadIdx
#define BT_GPU_EXECKERNEL(numb, numt, kfunc, args) {s_blockDim.x=numt;for(int nb=0;nb<numb;nb++){s_blockIdx.x=nb;for(int nt=0;nt<numt;nt++){s_threadIdx.x=nt;kfunc args;}}}
#define BT_GPU_CHECK_ERROR(s)
#endif //BT_GPU_DEFINES_H

View file

@ -0,0 +1,55 @@
/*
Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
Copyright (C) 2006, 2009 Sony Computer Entertainment 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.
*/
//----------------------------------------------------------------------------------------
// Shared code for GPU-based utilities
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Keep this file free from Bullet headers
// will be compiled by both CPU and CUDA compilers
// file with definitions of BT_GPU_xxx should be included first
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//----------------------------------------------------------------------------------------
#include "btGpuUtilsSharedDefs.h"
//----------------------------------------------------------------------------------------
extern "C"
{
//----------------------------------------------------------------------------------------
//Round a / b to nearest higher integer value
int BT_GPU_PREF(iDivUp)(int a, int b)
{
return (a % b != 0) ? (a / b + 1) : (a / b);
} // iDivUp()
//----------------------------------------------------------------------------------------
// compute grid and thread block size for a given number of elements
void BT_GPU_PREF(computeGridSize)(int n, int blockSize, int &numBlocks, int &numThreads)
{
numThreads = BT_GPU_min(blockSize, n);
numBlocks = BT_GPU_PREF(iDivUp)(n, numThreads);
} // computeGridSize()
//----------------------------------------------------------------------------------------
} // extern "C"

View file

@ -0,0 +1,52 @@
/*
Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
Copyright (C) 2006, 2007 Sony Computer Entertainment 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.
*/
// Shared definitions for GPU-based utilities
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Keep this file free from Bullet headers
// it is included into both CUDA and CPU code
// file with definitions of BT_GPU_xxx should be included first
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#ifndef BTGPUUTILSDHAREDDEFS_H
#define BTGPUUTILSDHAREDDEFS_H
extern "C"
{
//Round a / b to nearest higher integer value
int BT_GPU_PREF(iDivUp)(int a, int b);
// compute grid and thread block size for a given number of elements
void BT_GPU_PREF(computeGridSize)(int n, int blockSize, int &numBlocks, int &numThreads);
void BT_GPU_PREF(allocateArray)(void** devPtr, unsigned int size);
void BT_GPU_PREF(freeArray)(void* devPtr);
void BT_GPU_PREF(copyArrayFromDevice)(void* host, const void* device, unsigned int size);
void BT_GPU_PREF(copyArrayToDevice)(void* device, const void* host, unsigned int size);
void BT_GPU_PREF(registerGLBufferObject(unsigned int vbo));
void* BT_GPU_PREF(mapGLBufferObject(unsigned int vbo));
void BT_GPU_PREF(unmapGLBufferObject(unsigned int vbo));
} // extern "C"
#endif // BTGPUUTILSDHAREDDEFS_H

View file

@ -0,0 +1,283 @@
/*
Copyright (C) 2010 Sony Computer Entertainment Inc.
All rights reserved.
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef __BT_PARALLEL_CONSTRAINT_SOLVER_H
#define __BT_PARALLEL_CONSTRAINT_SOLVER_H
#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
#include "LinearMath/btScalar.h"
#include "PlatformDefinitions.h"
#define PFX_MAX_SOLVER_PHASES 64
#define PFX_MAX_SOLVER_BATCHES 16
#define PFX_MAX_SOLVER_PAIRS 128
#define PFX_MIN_SOLVER_PAIRS 16
#ifdef __CELLOS_LV2__
ATTRIBUTE_ALIGNED128(struct) PfxParallelBatch {
#else
ATTRIBUTE_ALIGNED16(struct) PfxParallelBatch {
#endif
uint16_t pairIndices[PFX_MAX_SOLVER_PAIRS];
};
#ifdef __CELLOS_LV2__
ATTRIBUTE_ALIGNED128(struct) PfxParallelGroup {
#else
ATTRIBUTE_ALIGNED16(struct) PfxParallelGroup {
#endif
uint16_t numPhases;
uint16_t numBatches[PFX_MAX_SOLVER_PHASES];
uint16_t numPairs[PFX_MAX_SOLVER_PHASES*PFX_MAX_SOLVER_BATCHES];
};
ATTRIBUTE_ALIGNED16(struct) PfxSortData16 {
union {
uint8_t i8data[16];
uint16_t i16data[8];
uint32_t i32data[4];
#ifdef __SPU__
vec_uint4 vdata;
#endif
};
#ifdef __SPU__
void set8(int elem,uint8_t data) {vdata=(vec_uint4)spu_insert(data,(vec_uchar16)vdata,elem);}
void set16(int elem,uint16_t data) {vdata=(vec_uint4)spu_insert(data,(vec_ushort8)vdata,elem);}
void set32(int elem,uint32_t data) {vdata=(vec_uint4)spu_insert(data,(vec_uint4)vdata,elem);}
uint8_t get8(int elem) const {return spu_extract((vec_uchar16)vdata,elem);}
uint16_t get16(int elem) const {return spu_extract((vec_ushort8)vdata,elem);}
uint32_t get32(int elem) const {return spu_extract((vec_uint4)vdata,elem);}
#else
void set8(int elem,uint8_t data) {i8data[elem] = data;}
void set16(int elem,uint16_t data) {i16data[elem] = data;}
void set32(int elem,uint32_t data) {i32data[elem] = data;}
uint8_t get8(int elem) const {return i8data[elem];}
uint16_t get16(int elem) const {return i16data[elem];}
uint32_t get32(int elem) const {return i32data[elem];}
#endif
};
typedef PfxSortData16 PfxConstraintPair;
//J PfxBroadphasePairƤÊ
SIMD_FORCE_INLINE void pfxSetConstraintId(PfxConstraintPair &pair,uint32_t i) {pair.set32(2,i);}
SIMD_FORCE_INLINE void pfxSetNumConstraints(PfxConstraintPair &pair,uint8_t n) {pair.set8(7,n);}
SIMD_FORCE_INLINE uint32_t pfxGetConstraintId1(const PfxConstraintPair &pair) {return pair.get32(2);}
SIMD_FORCE_INLINE uint8_t pfxGetNumConstraints(const PfxConstraintPair &pair) {return pair.get8(7);}
typedef PfxSortData16 PfxBroadphasePair;
SIMD_FORCE_INLINE void pfxSetRigidBodyIdA(PfxBroadphasePair &pair,uint16_t i) {pair.set16(0,i);}
SIMD_FORCE_INLINE void pfxSetRigidBodyIdB(PfxBroadphasePair &pair,uint16_t i) {pair.set16(1,i);}
SIMD_FORCE_INLINE void pfxSetMotionMaskA(PfxBroadphasePair &pair,uint8_t i) {pair.set8(4,i);}
SIMD_FORCE_INLINE void pfxSetMotionMaskB(PfxBroadphasePair &pair,uint8_t i) {pair.set8(5,i);}
SIMD_FORCE_INLINE void pfxSetBroadphaseFlag(PfxBroadphasePair &pair,uint8_t f) {pair.set8(6,(pair.get8(6)&0xf0)|(f&0x0f));}
SIMD_FORCE_INLINE void pfxSetActive(PfxBroadphasePair &pair,bool b) {pair.set8(6,(pair.get8(6)&0x0f)|((b?1:0)<<4));}
SIMD_FORCE_INLINE void pfxSetContactId(PfxBroadphasePair &pair,uint32_t i) {pair.set32(2,i);}
SIMD_FORCE_INLINE uint16_t pfxGetRigidBodyIdA(const PfxBroadphasePair &pair) {return pair.get16(0);}
SIMD_FORCE_INLINE uint16_t pfxGetRigidBodyIdB(const PfxBroadphasePair &pair) {return pair.get16(1);}
SIMD_FORCE_INLINE uint8_t pfxGetMotionMaskA(const PfxBroadphasePair &pair) {return pair.get8(4);}
SIMD_FORCE_INLINE uint8_t pfxGetMotionMaskB(const PfxBroadphasePair &pair) {return pair.get8(5);}
SIMD_FORCE_INLINE uint8_t pfxGetBroadphaseFlag(const PfxBroadphasePair &pair) {return pair.get8(6)&0x0f;}
SIMD_FORCE_INLINE bool pfxGetActive(const PfxBroadphasePair &pair) {return (pair.get8(6)>>4)!=0;}
SIMD_FORCE_INLINE uint32_t pfxGetContactId1(const PfxBroadphasePair &pair) {return pair.get32(2);}
#if defined(__PPU__) || defined (__SPU__)
ATTRIBUTE_ALIGNED128(struct) PfxSolverBody {
#else
ATTRIBUTE_ALIGNED16(struct) PfxSolverBody {
#endif
vmVector3 mDeltaLinearVelocity;
vmVector3 mDeltaAngularVelocity;
vmMatrix3 mInertiaInv;
vmQuat mOrientation;
float mMassInv;
float friction;
float restitution;
float unused;
float unused2;
float unused3;
float unused4;
float unused5;
};
#ifdef __PPU__
#include "SpuDispatch/BulletPE2ConstraintSolverSpursSupport.h"
#endif
static SIMD_FORCE_INLINE vmVector3 btReadVector3(const double* p)
{
float tmp[3] = {float(p[0]),float(p[1]),float(p[2])};
vmVector3 v;
loadXYZ(v, tmp);
return v;
}
static SIMD_FORCE_INLINE vmQuat btReadQuat(const double* p)
{
float tmp[4] = {float(p[0]),float(p[1]),float(p[2]),float(p[4])};
vmQuat vq;
loadXYZW(vq, tmp);
return vq;
}
static SIMD_FORCE_INLINE void btStoreVector3(const vmVector3 &src, double* p)
{
float tmp[3];
vmVector3 v = src;
storeXYZ(v, tmp);
p[0] = tmp[0];
p[1] = tmp[1];
p[2] = tmp[2];
}
static SIMD_FORCE_INLINE vmVector3 btReadVector3(const float* p)
{
vmVector3 v;
loadXYZ(v, p);
return v;
}
static SIMD_FORCE_INLINE vmQuat btReadQuat(const float* p)
{
vmQuat vq;
loadXYZW(vq, p);
return vq;
}
static SIMD_FORCE_INLINE void btStoreVector3(const vmVector3 &src, float* p)
{
vmVector3 v = src;
storeXYZ(v, p);
}
class btPersistentManifold;
enum {
PFX_CONSTRAINT_SOLVER_CMD_SETUP_SOLVER_BODIES,
PFX_CONSTRAINT_SOLVER_CMD_SETUP_CONTACT_CONSTRAINTS,
PFX_CONSTRAINT_SOLVER_CMD_SETUP_JOINT_CONSTRAINTS,
PFX_CONSTRAINT_SOLVER_CMD_SOLVE_CONSTRAINTS,
PFX_CONSTRAINT_SOLVER_CMD_POST_SOLVER
};
struct PfxSetupContactConstraintsIO {
PfxConstraintPair *offsetContactPairs;
uint32_t numContactPairs1;
class TrbState *offsetRigStates;
struct PfxSolverBody *offsetSolverBodies;
uint32_t numRigidBodies;
float separateBias;
float timeStep;
class btCriticalSection* criticalSection;
};
struct PfxSolveConstraintsIO {
PfxParallelGroup *contactParallelGroup;
PfxParallelBatch *contactParallelBatches;
PfxConstraintPair *contactPairs;
uint32_t numContactPairs;
btPersistentManifold *offsetContactManifolds;
PfxParallelGroup *jointParallelGroup;
PfxParallelBatch *jointParallelBatches;
PfxConstraintPair *jointPairs;
uint32_t numJointPairs;
TrbState *offsetRigStates;
PfxSolverBody *offsetSolverBodies;
uint32_t numRigidBodies;
uint32_t iteration;
uint32_t taskId;
class btBarrier* barrier;
};
struct PfxPostSolverIO {
TrbState *states;
PfxSolverBody *solverBodies;
uint32_t numRigidBodies;
};
ATTRIBUTE_ALIGNED16(struct) btConstraintSolverIO {
uint8_t cmd;
union {
PfxSetupContactConstraintsIO setupContactConstraints;
PfxSolveConstraintsIO solveConstraints;
PfxPostSolverIO postSolver;
};
//SPU only
uint32_t barrierAddr2;
uint32_t criticalsectionAddr2;
uint32_t maxTasks1;
};
void SolverThreadFunc(void* userPtr,void* lsMemory);
void* SolverlsMemoryFunc();
///The btParallelConstraintSolver performs computations on constraint rows in parallel
///Using the cross-platform threading it supports Windows, Linux, Mac OSX and PlayStation 3 Cell SPUs
class btParallelConstraintSolver : public btSequentialImpulseConstraintSolver
{
protected:
struct btParallelSolverMemoryCache* m_memoryCache;
class btThreadSupportInterface* m_solverThreadSupport;
struct btConstraintSolverIO* m_solverIO;
class btBarrier* m_barrier;
class btCriticalSection* m_criticalSection;
public:
btParallelConstraintSolver(class btThreadSupportInterface* solverThreadSupport);
virtual ~btParallelConstraintSolver();
virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher);
};
#endif //__BT_PARALLEL_CONSTRAINT_SOLVER_H

View file

@ -0,0 +1,85 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef THREAD_SUPPORT_INTERFACE_H
#define THREAD_SUPPORT_INTERFACE_H
#include <LinearMath/btScalar.h> //for ATTRIBUTE_ALIGNED16
#include "PlatformDefinitions.h"
#include "PpuAddressSpace.h"
class btBarrier {
public:
btBarrier() {}
virtual ~btBarrier() {}
virtual void sync() = 0;
virtual void setMaxCount(int n) = 0;
virtual int getMaxCount() = 0;
};
class btCriticalSection {
public:
btCriticalSection() {}
virtual ~btCriticalSection() {}
ATTRIBUTE_ALIGNED16(unsigned int mCommonBuff[32]);
virtual unsigned int getSharedParam(int i) = 0;
virtual void setSharedParam(int i,unsigned int p) = 0;
virtual void lock() = 0;
virtual void unlock() = 0;
};
class btThreadSupportInterface
{
public:
virtual ~btThreadSupportInterface();
///send messages to SPUs
virtual void sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t uiArgument1) =0;
///check for messages from SPUs
virtual void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1) =0;
///non-blocking test if a task is completed. First implement all versions, and then enable this API
///virtual bool isTaskCompleted(unsigned int *puiArgument0, unsigned int *puiArgument1, int timeOutInMilliseconds)=0;
///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded)
virtual void startSPU() =0;
///tell the task scheduler we are done with the SPU tasks
virtual void stopSPU()=0;
///tell the task scheduler to use no more than numTasks tasks
virtual void setNumTasks(int numTasks)=0;
virtual int getNumTasks() const = 0;
virtual btBarrier* createBarrier() = 0;
virtual btCriticalSection* createCriticalSection() = 0;
virtual void* getThreadLocalMemory(int taskId) { return 0; }
};
#endif //THREAD_SUPPORT_INTERFACE_H

View file

@ -0,0 +1,74 @@
/*
Copyright (C) 2006, 2007 Sony Computer Entertainment Inc.
All rights reserved.
Redistribution and use in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Sony Computer Entertainment Inc nor the names
of its contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef AOS_VECTORMATH_BULLET_CONVERT_H
#define AOS_VECTORMATH_BULLET_CONVERT_H
#include "vectormath/vmInclude.h"
#include "LinearMath/btVector3.h"
#include "LinearMath/btQuaternion.h"
#include "LinearMath/btMatrix3x3.h"
inline Vectormath::Aos::Vector3 getVmVector3(const btVector3& bulletVec)
{
return Vectormath::Aos::Vector3(bulletVec.getX(),bulletVec.getY(),bulletVec.getZ());
}
inline btVector3 getBtVector3(const Vectormath::Aos::Vector3& vmVec)
{
return btVector3(vmVec.getX(),vmVec.getY(),vmVec.getZ());
}
inline btVector3 getBtVector3(const Vectormath::Aos::Point3& vmVec)
{
return btVector3(vmVec.getX(),vmVec.getY(),vmVec.getZ());
}
inline Vectormath::Aos::Quat getVmQuat(const btQuaternion& bulletQuat)
{
Vectormath::Aos::Quat vmQuat(bulletQuat.getX(),bulletQuat.getY(),bulletQuat.getZ(),bulletQuat.getW());
return vmQuat;
}
inline btQuaternion getBtQuat(const Vectormath::Aos::Quat& vmQuat)
{
return btQuaternion (vmQuat.getX(),vmQuat.getY(),vmQuat.getZ(),vmQuat.getW());
}
inline Vectormath::Aos::Matrix3 getVmMatrix3(const btMatrix3x3& btMat)
{
Vectormath::Aos::Matrix3 mat(
getVmVector3(btMat.getColumn(0)),
getVmVector3(btMat.getColumn(1)),
getVmVector3(btMat.getColumn(2)));
return mat;
}
#endif //AOS_VECTORMATH_BULLET_CONVERT_H