1
0
mirror of https://github.com/bulletphysics/bullet3 synced 2024-12-15 06:00:12 +00:00
bullet3/examples/Tutorial/Tutorial.cpp

246 lines
6.1 KiB
C++

#include "Tutorial.h"
#include "../CommonInterfaces/CommonGraphicsAppInterface.h"
#include "../CommonInterfaces/CommonRenderInterface.h"
#include "../CommonInterfaces/CommonExampleInterface.h"
#include "LinearMath/btTransform.h"
#include "../CommonInterfaces/CommonGUIHelperInterface.h"
#include "stb_image/stb_image.h"
struct LWPose
{
btVector3 m_worldPosition;
btQuaternion m_worldOrientation;
LWPose()
:m_worldPosition(0,0,0),
m_worldOrientation(0,0,0,1)
{
}
};
enum LWRIGIDBODY_FLAGS
{
LWFLAG_USE_QUATERNION_DERIVATIVE = 1,
};
struct LWRightBody
{
LWPose m_worldPose;
btVector3 m_linearVelocity;
btVector3 m_angularVelocity;
int m_graphicsIndex;
int m_flags;
LWRightBody()
:m_linearVelocity(0,0,0),
m_angularVelocity(0,0,0),
m_flags(LWFLAG_USE_QUATERNION_DERIVATIVE)
{
}
void integrateTransform(double deltaTime)
{
LWPose newPose;
newPose.m_worldPosition = m_worldPose.m_worldPosition + m_linearVelocity*deltaTime;
if (m_flags & LWFLAG_USE_QUATERNION_DERIVATIVE)
{
newPose.m_worldOrientation = m_worldPose.m_worldOrientation;
newPose.m_worldOrientation += (m_angularVelocity * newPose.m_worldOrientation) * (deltaTime * btScalar(0.5));
newPose.m_worldOrientation.normalize();
m_worldPose = newPose;
} else
{
//Exponential map
//google for "Practical Parameterization of Rotations Using the Exponential Map", F. Sebastian Grassia
//btQuaternion q_w = [ sin(|w|*dt/2) * w/|w| , cos(|w|*dt/2)]
//btQuaternion q_new = q_w * q_old;
btVector3 axis;
btScalar fAngle = m_angularVelocity.length();
//limit the angular motion
const btScalar angularMotionThreshold = btScalar(0.5)*SIMD_HALF_PI;
if (fAngle*deltaTime > angularMotionThreshold)
{
fAngle = angularMotionThreshold / deltaTime;
}
if ( fAngle < btScalar(0.001) )
{
// use Taylor's expansions of sync function
axis = m_angularVelocity*( btScalar(0.5)*deltaTime-(deltaTime*deltaTime*deltaTime)*(btScalar(0.020833333333))*fAngle*fAngle );
}
else
{
// sync(fAngle) = sin(c*fAngle)/t
axis = m_angularVelocity*( btSin(btScalar(0.5)*fAngle*deltaTime)/fAngle );
}
btQuaternion dorn (axis.x(),axis.y(),axis.z(),btCos( fAngle*deltaTime*btScalar(0.5) ));
btQuaternion orn0 = m_worldPose.m_worldOrientation;
btQuaternion predictedOrn = dorn * orn0;
predictedOrn.normalize();
m_worldPose.m_worldOrientation = predictedOrn;
}
}
void stepSimulation(double deltaTime)
{
integrateTransform(deltaTime);
}
};
class Tutorial : public CommonExampleInterface
{
CommonGraphicsApp* m_app;
int m_tutorialIndex;
LWRightBody* m_body;
public:
Tutorial(CommonGraphicsApp* app, int tutorialIndex)
:m_app(app),
m_tutorialIndex(tutorialIndex)
{
m_app->setUpAxis(2);
switch (m_tutorialIndex)
{
}
{
int boxId = m_app->registerCubeShape(100,100,1);
btVector3 pos(0,0,-1);
btQuaternion orn(0,0,0,1);
btVector4 color(1,1,1,1);
btVector3 scaling(1,1,1);
m_app->m_renderer->registerGraphicsInstance(boxId,pos,orn,color,scaling);
}
m_body = new LWRightBody();
m_body->m_worldPose.m_worldPosition.setValue(0,0,3);
{
int textureIndex = -1;
if (1)
{
int width,height,n;
const char* filename = "data/cube.png";
const unsigned char* image=0;
const char* prefix[]={"./","../","../../","../../../","../../../../"};
int numprefix = sizeof(prefix)/sizeof(const char*);
for (int i=0;!image && i<numprefix;i++)
{
char relativeFileName[1024];
sprintf(relativeFileName,"%s%s",prefix[i],filename);
image = stbi_load(relativeFileName, &width, &height, &n, 0);
}
b3Assert(image);
if (image)
{
textureIndex = m_app->m_renderer->registerTexture(image,width,height);
}
}
int boxId = m_app->registerCubeShape(1,1,1,textureIndex);//>registerGraphicsUnitSphereShape(SPHERE_LOD_HIGH, textureIndex);
btVector4 color(1,1,1,1);
btVector3 scaling(1,1,1);
m_body->m_graphicsIndex = m_app->m_renderer->registerGraphicsInstance(boxId,m_body->m_worldPose.m_worldPosition, m_body->m_worldPose.m_worldOrientation,color,scaling);
m_app->m_renderer->writeSingleInstanceTransformToCPU(m_body->m_worldPose.m_worldPosition, m_body->m_worldPose.m_worldOrientation, m_body->m_graphicsIndex);
}
m_app->m_renderer->writeTransforms();
}
virtual ~Tutorial()
{
m_app->m_renderer->enableBlend(false);
}
virtual void initPhysics()
{
}
virtual void exitPhysics()
{
}
virtual void stepSimulation(float deltaTime)
{
//m_body->m_linearVelocity=btVector3(0,0.1,0);
m_body->m_angularVelocity =btVector3(0,0.1,0);
m_body->integrateTransform(deltaTime);
m_app->m_renderer->writeSingleInstanceTransformToCPU(m_body->m_worldPose.m_worldPosition, m_body->m_worldPose.m_worldOrientation, m_body->m_graphicsIndex);
m_app->m_renderer->writeTransforms();
}
virtual void renderScene()
{
m_app->m_renderer->renderScene();
m_app->drawText3D("X",1,0,0,1);
m_app->drawText3D("Y",0,1,0,1);
m_app->drawText3D("Z",0,0,1,1);
}
virtual void physicsDebugDraw(int debugDrawFlags)
{
}
virtual bool mouseMoveCallback(float x,float y)
{
return false;
}
virtual bool mouseButtonCallback(int button, int state, float x, float y)
{
return false;
}
virtual bool keyboardCallback(int key, int state)
{
return false;
}
virtual void resetCamera()
{
float dist = 10.5;
float pitch = 136;
float yaw = 32;
float targetPos[3]={0,0,0};
if (m_app->m_renderer && m_app->m_renderer->getActiveCamera())
{
m_app->m_renderer->getActiveCamera()->setCameraDistance(dist);
m_app->m_renderer->getActiveCamera()->setCameraPitch(pitch);
m_app->m_renderer->getActiveCamera()->setCameraYaw(yaw);
m_app->m_renderer->getActiveCamera()->setCameraTargetPosition(targetPos[0],targetPos[1],targetPos[2]);
}
}
};
class CommonExampleInterface* TutorialCreateFunc(struct CommonExampleOptions& options)
{
return new Tutorial(options.m_guiHelper->getAppInterface(), options.m_option);
}