mirror of
https://github.com/bulletphysics/bullet3
synced 2025-01-18 21:10:05 +00:00
move ExplititEuler cloth solver to its own file, so it can be replaced by PDB, implicit euler etc
add wireframe toggle ('w' key) add --paused command-line option to start simulation in paused mode render cloth using drawPoints method
This commit is contained in:
parent
d0faea90f9
commit
8faac34801
@ -14,6 +14,8 @@
|
|||||||
#include "stb_image/stb_image.h"
|
#include "stb_image/stb_image.h"
|
||||||
#include "CpuSoftClothDemoInternalData.h"
|
#include "CpuSoftClothDemoInternalData.h"
|
||||||
|
|
||||||
|
#include "ExplicitEuler.h"
|
||||||
|
|
||||||
static b3KeyboardCallback oldCallback = 0;
|
static b3KeyboardCallback oldCallback = 0;
|
||||||
extern bool gReset;
|
extern bool gReset;
|
||||||
|
|
||||||
@ -107,94 +109,26 @@ struct GraphicsVertex
|
|||||||
float texcoord[2];
|
float texcoord[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
void CpuSoftClothDemo::computeForces()
|
|
||||||
{
|
|
||||||
B3_PROFILE("computeForces");
|
|
||||||
|
|
||||||
b3Vector3 gravityAcceleration = b3MakeVector3(0,-9.8,0);
|
|
||||||
//f=m*a
|
|
||||||
for (int i=0;i<numPoints;i++)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
float particleMass = m_clothData->m_particleMasses[i];
|
|
||||||
|
|
||||||
b3Vector3 particleMassVec = b3MakeVector3(particleMass,particleMass,particleMass,0);
|
|
||||||
m_clothData->m_forces[i] = gravityAcceleration*particleMass;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GraphicsVertex* cpu_buffer = (GraphicsVertex*)m_data->m_clothVertices;
|
|
||||||
|
|
||||||
|
|
||||||
//add spring forces
|
|
||||||
for(int i=0;i<m_clothData->m_springs.size();i++)
|
|
||||||
{
|
|
||||||
|
|
||||||
int indexA = m_clothData->m_springs[i].m_particleIndexA;
|
|
||||||
int indexB = m_clothData->m_springs[i].m_particleIndexB;
|
|
||||||
float restLength = m_clothData->m_springs[i].m_restLength;
|
|
||||||
const ClothMaterial& mat = m_clothData->m_materials[m_clothData->m_springs[i].m_material];
|
|
||||||
|
|
||||||
const b3Vector3& posA = (const b3Vector3&)cpu_buffer[indexA].pos;
|
|
||||||
const b3Vector3& posB = (const b3Vector3&)cpu_buffer[indexB].pos;
|
|
||||||
const b3Vector3& velA = m_clothData->m_velocities[indexA];
|
|
||||||
const b3Vector3& velB = m_clothData->m_velocities[indexB];
|
|
||||||
|
|
||||||
b3Vector3 deltaP = posA-posB;
|
|
||||||
b3Vector3 deltaV = velA-velB;
|
|
||||||
float dist = deltaP.length();
|
|
||||||
b3Vector3 deltaPNormalized = deltaP/dist;
|
|
||||||
|
|
||||||
float spring = -mat.m_stiffness * (dist-restLength)*100000;
|
|
||||||
float damper = mat.m_damping * b3Dot(deltaV,deltaPNormalized)*100;
|
|
||||||
|
|
||||||
b3Vector3 springForce = (spring+damper)*deltaPNormalized;
|
|
||||||
float particleMassA = m_clothData->m_particleMasses[indexA];
|
|
||||||
float particleMassB = m_clothData->m_particleMasses[indexB];
|
|
||||||
|
|
||||||
//if (springForce.length())
|
|
||||||
{
|
|
||||||
if (particleMassA)
|
|
||||||
{
|
|
||||||
m_clothData->m_forces[indexA] += springForce*particleMassA;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (particleMassB)
|
|
||||||
{
|
|
||||||
m_clothData->m_forces[indexB] -= springForce*particleMassB;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CpuSoftClothDemo::integrateEuler(float deltaTime)
|
|
||||||
{
|
|
||||||
B3_PROFILE("integrateEuler");
|
|
||||||
b3Vector3 deltaTimeVec = b3MakeVector3(deltaTime,deltaTime,deltaTime,0);
|
|
||||||
|
|
||||||
GraphicsVertex* cpu_buffer = (GraphicsVertex*)m_data->m_clothVertices;
|
|
||||||
|
|
||||||
for (int i=0;i<numPoints;i++)
|
|
||||||
{
|
|
||||||
float mass = m_clothData->m_particleMasses[i];
|
|
||||||
if (mass)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
b3Vector3 dv = (m_clothData->m_forces[i]/mass)*deltaTimeVec;
|
|
||||||
m_clothData->m_velocities[i]+= dv;
|
|
||||||
m_clothData->m_velocities[i]*=0.999;
|
|
||||||
|
|
||||||
b3Vector3& pos = (b3Vector3&) cpu_buffer[i].pos;
|
|
||||||
pos += m_clothData->m_velocities[i]*deltaTimeVec;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CpuSoftClothDemo::renderScene()
|
void CpuSoftClothDemo::renderScene()
|
||||||
{
|
{
|
||||||
m_instancingRenderer->renderScene();
|
//wireframe
|
||||||
|
bool wireframe=true;
|
||||||
|
if (wireframe)
|
||||||
|
{
|
||||||
|
m_instancingRenderer->init();
|
||||||
|
m_instancingRenderer->updateCamera();
|
||||||
|
m_instancingRenderer->drawLine(b3MakeVector3(0,0,0),b3MakeVector3(1,0,0),b3MakeVector3(1,0,0,1),1);
|
||||||
|
m_instancingRenderer->drawLine(b3MakeVector3(0,0,0),b3MakeVector3(0,1,0),b3MakeVector3(0,1,0,1),1);
|
||||||
|
m_instancingRenderer->drawLine(b3MakeVector3(0,0,0),b3MakeVector3(0,0,1),b3MakeVector3(0,0,1,1),1);
|
||||||
|
|
||||||
|
float color[4]={1,0,0,1};
|
||||||
|
m_instancingRenderer->drawPoints(m_data->m_clothVertices,color,numPoints,sizeof(GraphicsVertex),2);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
m_instancingRenderer->renderScene();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
void CpuSoftBodyDemo::renderScene()
|
void CpuSoftBodyDemo::renderScene()
|
||||||
@ -219,12 +153,15 @@ void CpuSoftClothDemo::clientMoveAndDisplay()
|
|||||||
|
|
||||||
float deltaTime = 1./1000.;//1./60.f;
|
float deltaTime = 1./1000.;//1./60.f;
|
||||||
//float deltaTime = 1./60.f;
|
//float deltaTime = 1./60.f;
|
||||||
for (int i=0;i<10;i++)
|
|
||||||
{
|
|
||||||
computeForces();
|
|
||||||
integrateEuler(deltaTime);
|
|
||||||
|
|
||||||
}
|
//write positions
|
||||||
|
int vertexStride =sizeof(GraphicsVertex);//9 * sizeof(float);
|
||||||
|
|
||||||
|
ExplicitEuler::solveConstraints(m_clothData, (char*)m_data->m_clothVertices, vertexStride, deltaTime);
|
||||||
|
|
||||||
|
|
||||||
|
//read positions
|
||||||
|
|
||||||
m_instancingRenderer->updateShape(m_data->m_clothShapeIndex,m_data->m_clothVertices);
|
m_instancingRenderer->updateShape(m_data->m_clothShapeIndex,m_data->m_clothVertices);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -290,6 +227,21 @@ void CpuSoftClothDemo::setupScene(const ConstructionInfo& ci)
|
|||||||
GLint err = glGetError();
|
GLint err = glGetError();
|
||||||
b3Assert(err==GL_NO_ERROR);
|
b3Assert(err==GL_NO_ERROR);
|
||||||
|
|
||||||
|
if (0)
|
||||||
|
{
|
||||||
|
//draw a fixed ground box
|
||||||
|
int strideInBytes = 9*sizeof(float);
|
||||||
|
int numVertices = sizeof(cube_vertices)/strideInBytes;
|
||||||
|
int numIndices = sizeof(cube_indices)/sizeof(int);
|
||||||
|
int shapeId = ci.m_instancingRenderer->registerShape(&cube_vertices[0],numVertices,cube_indices,numIndices);
|
||||||
|
b3Vector3 position = b3MakeVector3(0,-50,0);//((j+1)&1)+i*2.2,1+j*2.,((j+1)&1)+k*2.2);
|
||||||
|
b3Quaternion orn(0,0,0,1);
|
||||||
|
b3Vector4 scaling=b3MakeVector4(100,1,100,1);
|
||||||
|
float color[4]={0.8,0.8,0.8,1};
|
||||||
|
|
||||||
|
int id = ci.m_instancingRenderer->registerGraphicsInstance(shapeId,position,orn,color,scaling);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
GraphicsVertex* cpu_buffer = new GraphicsVertex[width*height];
|
GraphicsVertex* cpu_buffer = new GraphicsVertex[width*height];
|
||||||
|
@ -64,9 +64,7 @@ public:
|
|||||||
return "CpuSoftCloth";
|
return "CpuSoftCloth";
|
||||||
}
|
}
|
||||||
|
|
||||||
void computeForces();
|
|
||||||
void integrateEuler(float deltaTime);
|
|
||||||
|
|
||||||
virtual void clientMoveAndDisplay();
|
virtual void clientMoveAndDisplay();
|
||||||
|
|
||||||
static CpuDemo* MyCreateFunc()
|
static CpuDemo* MyCreateFunc()
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define CPU_SOFTCLOTH_INTERNAL_DATA_H
|
#define CPU_SOFTCLOTH_INTERNAL_DATA_H
|
||||||
|
|
||||||
#include "Bullet3Common/b3AlignedObjectArray.h"
|
#include "Bullet3Common/b3AlignedObjectArray.h"
|
||||||
|
#include "Bullet3Common/b3Vector3.h"
|
||||||
|
|
||||||
struct ClothSpring
|
struct ClothSpring
|
||||||
{
|
{
|
||||||
@ -20,11 +21,10 @@ struct ClothMaterial
|
|||||||
struct CpuSoftClothDemoInternalData
|
struct CpuSoftClothDemoInternalData
|
||||||
{
|
{
|
||||||
b3AlignedObjectArray<ClothSpring> m_springs;
|
b3AlignedObjectArray<ClothSpring> m_springs;
|
||||||
b3AlignedObjectArray<ClothMaterial> m_materials;
|
b3AlignedObjectArray<ClothMaterial> m_materials;
|
||||||
b3AlignedObjectArray<b3Vector3> m_velocities;
|
b3AlignedObjectArray<b3Vector3> m_velocities;
|
||||||
b3AlignedObjectArray<b3Vector3> m_forces;
|
b3AlignedObjectArray<b3Vector3> m_forces;
|
||||||
b3AlignedObjectArray<float> m_particleMasses;
|
b3AlignedObjectArray<float> m_particleMasses;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //CPU_SOFTCLOTH_INTERNAL_DATA_H
|
#endif //CPU_SOFTCLOTH_INTERNAL_DATA_H
|
||||||
|
106
Demos3/CpuDemos/deformable/ExplicitEuler.cpp
Normal file
106
Demos3/CpuDemos/deformable/ExplicitEuler.cpp
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
#include "ExplicitEuler.h"
|
||||||
|
|
||||||
|
#include "CpuSoftClothDemoInternalData.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ExplicitEuler::computeForces(struct CpuSoftClothDemoInternalData* clothData, char* vertexPositions, int vertexStride, float dt)
|
||||||
|
{
|
||||||
|
|
||||||
|
B3_PROFILE("computeForces");
|
||||||
|
int numPoints = clothData->m_particleMasses.size();
|
||||||
|
|
||||||
|
b3Vector3 gravityAcceleration = b3MakeVector3(0,-9.8,0);
|
||||||
|
//f=m*a
|
||||||
|
for (int i=0;i<numPoints;i++)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
float particleMass = clothData->m_particleMasses[i];
|
||||||
|
|
||||||
|
b3Vector3 particleMassVec = b3MakeVector3(particleMass,particleMass,particleMass,0);
|
||||||
|
clothData->m_forces[i] = gravityAcceleration*particleMass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//add spring forces
|
||||||
|
for(int i=0;i<clothData->m_springs.size();i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
int indexA = clothData->m_springs[i].m_particleIndexA;
|
||||||
|
int indexB = clothData->m_springs[i].m_particleIndexB;
|
||||||
|
float restLength = clothData->m_springs[i].m_restLength;
|
||||||
|
const ClothMaterial& mat = clothData->m_materials[clothData->m_springs[i].m_material];
|
||||||
|
|
||||||
|
const b3Vector3& posA = (const b3Vector3&)vertexPositions[indexA*vertexStride];
|
||||||
|
const b3Vector3& posB = (const b3Vector3&)vertexPositions[indexB*vertexStride];
|
||||||
|
const b3Vector3& velA = clothData->m_velocities[indexA];
|
||||||
|
const b3Vector3& velB = clothData->m_velocities[indexB];
|
||||||
|
|
||||||
|
b3Vector3 deltaP = posA-posB;
|
||||||
|
b3Vector3 deltaV = velA-velB;
|
||||||
|
float dist = deltaP.length();
|
||||||
|
b3Vector3 deltaPNormalized = deltaP/dist;
|
||||||
|
|
||||||
|
float spring = -mat.m_stiffness * (dist-restLength)*100000;
|
||||||
|
float damper = mat.m_damping * b3Dot(deltaV,deltaPNormalized)*100;
|
||||||
|
|
||||||
|
b3Vector3 springForce = (spring+damper)*deltaPNormalized;
|
||||||
|
float particleMassA = clothData->m_particleMasses[indexA];
|
||||||
|
float particleMassB = clothData->m_particleMasses[indexB];
|
||||||
|
|
||||||
|
//if (springForce.length())
|
||||||
|
{
|
||||||
|
if (particleMassA)
|
||||||
|
{
|
||||||
|
clothData->m_forces[indexA] += springForce*particleMassA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (particleMassB)
|
||||||
|
{
|
||||||
|
clothData->m_forces[indexB] -= springForce*particleMassB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExplicitEuler::integrateExplicitEuler(struct CpuSoftClothDemoInternalData* clothData, char* vertexPositions, int vertexStride,float deltaTime)
|
||||||
|
{
|
||||||
|
B3_PROFILE("integrateEuler");
|
||||||
|
b3Vector3 deltaTimeVec = b3MakeVector3(deltaTime,deltaTime,deltaTime,0);
|
||||||
|
|
||||||
|
int numPoints = clothData->m_particleMasses.size();
|
||||||
|
|
||||||
|
for (int i=0;i<numPoints;i++)
|
||||||
|
{
|
||||||
|
float mass = clothData->m_particleMasses[i];
|
||||||
|
if (mass)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
b3Vector3 dv = (clothData->m_forces[i]/mass)*deltaTimeVec;
|
||||||
|
clothData->m_velocities[i]+= dv;
|
||||||
|
clothData->m_velocities[i]*=0.999;
|
||||||
|
|
||||||
|
b3Vector3& pos = (b3Vector3&)vertexPositions[i*vertexStride];
|
||||||
|
|
||||||
|
pos += clothData->m_velocities[i]*deltaTimeVec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExplicitEuler::solveConstraints(struct CpuSoftClothDemoInternalData* data, char* vertexPositions, int vertexStride,float deltaTime)
|
||||||
|
{
|
||||||
|
computeForces(data,vertexPositions,vertexStride,deltaTime);
|
||||||
|
|
||||||
|
integrateExplicitEuler(data,vertexPositions,vertexStride,deltaTime);
|
||||||
|
}
|
15
Demos3/CpuDemos/deformable/ExplicitEuler.h
Normal file
15
Demos3/CpuDemos/deformable/ExplicitEuler.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
#ifndef EXPLICIT_EULER_H
|
||||||
|
#define EXPLICIT_EULER_H
|
||||||
|
|
||||||
|
struct ExplicitEuler
|
||||||
|
{
|
||||||
|
static void computeForces(struct CpuSoftClothDemoInternalData* data, char* vtx, int vertexStride, float dt);
|
||||||
|
|
||||||
|
static void integrateExplicitEuler(struct CpuSoftClothDemoInternalData* data, char* vtx, int vertexStride,float dt);
|
||||||
|
|
||||||
|
static void solveConstraints(struct CpuSoftClothDemoInternalData* data, char* vtx, int vertexStride,float dt);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //EXPLICIT_EULER_H
|
@ -192,9 +192,22 @@ static void MyMouseButtonCallback(int button, int state, float x, float y)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern bool useShadowMap;
|
extern bool useShadowMap;
|
||||||
|
bool useWireFrame = false;
|
||||||
|
|
||||||
void MyKeyboardCallback(int key, int state)
|
void MyKeyboardCallback(int key, int state)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (key=='w' && state)
|
||||||
|
{
|
||||||
|
useWireFrame = !useWireFrame;
|
||||||
|
if (useWireFrame)
|
||||||
|
{
|
||||||
|
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
|
||||||
|
}
|
||||||
|
}
|
||||||
if (key=='s' && state)
|
if (key=='s' && state)
|
||||||
{
|
{
|
||||||
useShadowMap=!useShadowMap;
|
useShadowMap=!useShadowMap;
|
||||||
|
@ -607,6 +607,8 @@ int main(int argc, char* argv[])
|
|||||||
args.GetCmdLineArgument("y_gap", ci.gapY);
|
args.GetCmdLineArgument("y_gap", ci.gapY);
|
||||||
args.GetCmdLineArgument("z_gap", ci.gapZ);
|
args.GetCmdLineArgument("z_gap", ci.gapZ);
|
||||||
|
|
||||||
|
gPause = args.CheckCmdLineFlag("paused");
|
||||||
|
|
||||||
gDebugForceLoadingFromSource = args.CheckCmdLineFlag("load_cl_kernels_from_disk");
|
gDebugForceLoadingFromSource = args.CheckCmdLineFlag("load_cl_kernels_from_disk");
|
||||||
gDebugSkipLoadingBinary = args.CheckCmdLineFlag("disable_cached_cl_kernels");
|
gDebugSkipLoadingBinary = args.CheckCmdLineFlag("disable_cached_cl_kernels");
|
||||||
#ifndef B3_NO_PROFILE
|
#ifndef B3_NO_PROFILE
|
||||||
@ -726,7 +728,7 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
if (benchmark)
|
if (benchmark)
|
||||||
{
|
{
|
||||||
gPause = false;
|
|
||||||
char prefixFileName[1024];
|
char prefixFileName[1024];
|
||||||
char csvFileName[1024];
|
char csvFileName[1024];
|
||||||
char detailsFileName[1024];
|
char detailsFileName[1024];
|
||||||
|
@ -1318,8 +1318,8 @@ void GLInstancingRenderer::drawPoints(const float* positions, const float color[
|
|||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, lineVertexBufferObject);
|
glBindBuffer(GL_ARRAY_BUFFER, lineVertexBufferObject);
|
||||||
glEnableVertexAttribArray(0);
|
glEnableVertexAttribArray(0);
|
||||||
int numFloats = pointStrideInBytes/sizeof(float);
|
int numFloats = 3;//pointStrideInBytes/sizeof(float);
|
||||||
glVertexAttribPointer(0, numFloats, GL_FLOAT, GL_FALSE, 0, 0);
|
glVertexAttribPointer(0, numFloats, GL_FLOAT, GL_FALSE, pointStrideInBytes, 0);
|
||||||
glDrawArrays(GL_POINTS, 0, numPoints);
|
glDrawArrays(GL_POINTS, 0, numPoints);
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
glPointSize(1);
|
glPointSize(1);
|
||||||
|
Loading…
Reference in New Issue
Block a user