Make possible to apply force to bodies in the testbed application
This commit is contained in:
parent
594e948ae7
commit
e7c5432936
|
@ -139,6 +139,7 @@ void Gui::createSimulationPanel() {
|
|||
new Label(mSimulationPanel, "Scene","sans-bold");
|
||||
ComboBox* comboBoxScenes = new ComboBox(mSimulationPanel, scenesNames);
|
||||
comboBoxScenes->set_fixed_width(150);
|
||||
comboBoxScenes->popup()->child_at(0)->set_fixed_height(800);
|
||||
comboBoxScenes->set_callback([&, scenes](int index) {
|
||||
mApp->switchScene(scenes[index]);
|
||||
});
|
||||
|
|
|
@ -91,8 +91,7 @@ bool Scene::mapMouseCoordinatesToSphere(double xMouse, double yMouse,
|
|||
}
|
||||
|
||||
// Called when a mouse button event occurs
|
||||
bool Scene::mouseButtonEvent(int button, bool down, int mods,
|
||||
double mousePosX, double mousePosY) {
|
||||
bool Scene::mouseButtonEvent(int button, bool down, int mods, double mousePosX, double mousePosY) {
|
||||
|
||||
// If the mouse button is pressed
|
||||
if (down) {
|
||||
|
|
|
@ -199,8 +199,7 @@ class Scene : public rp3d::EventListener {
|
|||
virtual bool keyboardEvent(int key, int scancode, int action, int mods);
|
||||
|
||||
/// Called when a mouse button event occurs
|
||||
virtual bool mouseButtonEvent(int button, bool down, int mods,
|
||||
double mousePosX, double mousePosY);
|
||||
virtual bool mouseButtonEvent(int button, bool down, int mods, double mousePosX, double mousePosY);
|
||||
|
||||
/// Called when a mouse motion event occurs
|
||||
virtual bool mouseMotionEvent(double xMouse, double yMouse, int leftButtonState,
|
||||
|
|
|
@ -47,7 +47,8 @@ SceneDemo::SceneDemo(const std::string& name, EngineSettings& settings, bool isP
|
|||
mColorShader("shaders/color.vert", "shaders/color.frag"),
|
||||
mQuadShader("shaders/quad.vert", "shaders/quad.frag"),
|
||||
mVBOQuad(GL_ARRAY_BUFFER), mDebugVBOLinesVertices(GL_ARRAY_BUFFER), mDebugVBOTrianglesVertices(GL_ARRAY_BUFFER),
|
||||
mMeshFolderPath("meshes/"), mPhysicsWorld(nullptr), mIsPhysicsWorldSimulated(isPhysicsWorldSimulated) {
|
||||
mMeshFolderPath("meshes/"), mPhysicsWorld(nullptr), mIsPhysicsWorldSimulated(isPhysicsWorldSimulated),
|
||||
mIsMovingBody(false), mMovingBody(nullptr) {
|
||||
|
||||
shadowMapTextureLevel++;
|
||||
|
||||
|
@ -612,6 +613,75 @@ void SceneDemo::removeAllVisualContactPoints() {
|
|||
mVisualContactPoints.clear();
|
||||
}
|
||||
|
||||
// Called when the user is moving a body with the mouse
|
||||
void SceneDemo::moveBodyWithMouse(double mousePosX, double mousePosY) {
|
||||
|
||||
if (!mIsMovingBody) {
|
||||
|
||||
// Find the body and the position of the mouse on that body (with raycasting)
|
||||
openglframework::Vector4 screenPoint1((mousePosX / mWindowWidth) * 2.0 - 1.0, ((mWindowHeight - mousePosY) / mWindowHeight) * 2.0 - 1.0, -1, 1);
|
||||
openglframework::Vector4 screenPoint2((mousePosX / mWindowWidth) * 2.0 - 1.0, ((mWindowHeight - mousePosY) / mWindowHeight) * 2.0 - 1.0, 1, 1);
|
||||
openglframework::Vector4 worldP1 = (mCamera.getTransformMatrix() * mCamera.getProjectionMatrix().getInverse()) * screenPoint1;
|
||||
openglframework::Vector4 worldP2 = (mCamera.getTransformMatrix() * mCamera.getProjectionMatrix().getInverse()) * screenPoint2;
|
||||
openglframework::Vector3 cameraPos = mCamera.getOrigin();
|
||||
rp3d::Vector3 worldPoint1(worldP1.x, worldP1.y, worldP1.z);
|
||||
rp3d::Vector3 worldPoint2(worldP2.x, worldP2.y, worldP2.z);
|
||||
rp3d::Ray ray(worldPoint1, worldPoint2);
|
||||
mPhysicsWorld->raycast(ray, this);
|
||||
}
|
||||
|
||||
if (mMovingBody != nullptr) {
|
||||
openglframework::Vector4 previousScreenPos(mLastMouseX / mWindowWidth, (mWindowHeight - mLastMouseY) / mWindowHeight, 0, 0);
|
||||
openglframework::Vector4 currentScreenPos(mousePosX / mWindowWidth, (mWindowHeight - mousePosY) / mWindowHeight, 0, 0);
|
||||
openglframework::Vector4 forceScreen = currentScreenPos - previousScreenPos;
|
||||
openglframework::Vector4 f = mCamera.getTransformMatrix() * forceScreen * MOUSE_MOVE_BODY_FORCE;
|
||||
rp3d::Vector3 force(f.x, f.y, f.z);
|
||||
mMovingBody->applyForceAtLocalPosition(force, mMovingBodyLocalPoint);
|
||||
}
|
||||
|
||||
mLastMouseX = mousePosX;
|
||||
mLastMouseY = mousePosY;
|
||||
mIsMovingBody = true;
|
||||
}
|
||||
|
||||
// Called when a mouse button event occurs
|
||||
bool SceneDemo::mouseButtonEvent(int button, bool down, int mods, double mousePosX, double mousePosY) {
|
||||
|
||||
// Left mouse click with CTRL key pressed on keyboard (moving a body)
|
||||
if (down && (mods & GLFW_MOD_CONTROL)) {
|
||||
|
||||
moveBodyWithMouse(mousePosX, mousePosY);
|
||||
return true;
|
||||
}
|
||||
|
||||
mIsMovingBody = false;
|
||||
mMovingBody = nullptr;
|
||||
|
||||
return Scene::mouseButtonEvent(button, down, mods, mousePosX, mousePosY);
|
||||
}
|
||||
|
||||
// Called when a mouse motion event occurs
|
||||
bool SceneDemo::mouseMotionEvent(double xMouse, double yMouse, int leftButtonState, int rightButtonState, int middleButtonState, int altKeyState) {
|
||||
|
||||
if (mIsMovingBody) {
|
||||
moveBodyWithMouse(xMouse, yMouse);
|
||||
return true;
|
||||
}
|
||||
|
||||
return Scene::mouseMotionEvent(xMouse, yMouse, leftButtonState, rightButtonState, middleButtonState, altKeyState);
|
||||
}
|
||||
|
||||
// Called when a raycast hit occurs (used to move a body with the mouse)
|
||||
rp3d::decimal SceneDemo::notifyRaycastHit(const rp3d::RaycastInfo& raycastInfo) {
|
||||
|
||||
rp3d::RigidBody* body = dynamic_cast<rp3d::RigidBody*>(raycastInfo.body);
|
||||
mMovingBody = body;
|
||||
const rp3d::Transform localToWorldTransform = raycastInfo.collider->getLocalToWorldTransform();
|
||||
mMovingBodyLocalPoint = localToWorldTransform.getInverse() * raycastInfo.worldPoint;
|
||||
|
||||
return raycastInfo.hitFraction;
|
||||
}
|
||||
|
||||
// Update the engine settings
|
||||
void SceneDemo::updateEngineSettings() {
|
||||
|
||||
|
|
|
@ -35,11 +35,12 @@
|
|||
// Constants
|
||||
const int SHADOWMAP_WIDTH = 2048;
|
||||
const int SHADOWMAP_HEIGHT = 2048;
|
||||
const float MOUSE_MOVE_BODY_FORCE = 100000.0f;
|
||||
|
||||
// Class SceneDemo
|
||||
// Abstract class that represents a 3D scene for the ReactPhysics3D examples.
|
||||
// This scene has a single light source with shadow mapping.
|
||||
class SceneDemo : public Scene {
|
||||
class SceneDemo : public Scene, rp3d::RaycastCallback {
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -121,6 +122,15 @@ class SceneDemo : public Scene {
|
|||
/// True if we need to step the physics simulation each frame
|
||||
bool mIsPhysicsWorldSimulated;
|
||||
|
||||
/// True if the user is currently moving a body with the mouse
|
||||
bool mIsMovingBody;
|
||||
|
||||
/// Local-space point on the body use to move it with the mouse
|
||||
rp3d::Vector3 mMovingBodyLocalPoint;
|
||||
|
||||
/// Pointer to the body that is currently moved with the mouse by the user
|
||||
rp3d::RigidBody* mMovingBody;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Create the Shadow map FBO and texture
|
||||
|
@ -150,6 +160,9 @@ class SceneDemo : public Scene {
|
|||
/// Remove all contact points
|
||||
void removeAllVisualContactPoints();
|
||||
|
||||
/// Called when the user is moving a body with the mouse
|
||||
void moveBodyWithMouse(double mousePosX, double mousePosY);
|
||||
|
||||
public:
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
@ -181,6 +194,16 @@ class SceneDemo : public Scene {
|
|||
|
||||
/// Enable/disable debug rendering
|
||||
virtual void setIsDebugRendererEnabled(bool isEnabled) override;
|
||||
|
||||
/// Called when a mouse button event occurs
|
||||
virtual bool mouseButtonEvent(int button, bool down, int mods, double mousePosX, double mousePosY) override;
|
||||
|
||||
/// Called when a mouse motion event occurs
|
||||
virtual bool mouseMotionEvent(double xMouse, double yMouse, int leftButtonState,
|
||||
int rightButtonState, int middleButtonState, int altKeyState) override;
|
||||
|
||||
/// Called when a raycast hit occurs (used to move a body with the mouse)
|
||||
virtual rp3d::decimal notifyRaycastHit(const rp3d::RaycastInfo& raycastInfo) override;
|
||||
};
|
||||
|
||||
// Enabled/Disable the shadow mapping
|
||||
|
|
|
@ -110,7 +110,7 @@ void TestbedApplication::createScenes() {
|
|||
mScenes.push_back(cubeStackScene);
|
||||
|
||||
// Joints scene
|
||||
JointsScene* jointsScene = new JointsScene("Joints", mEngineSettings);
|
||||
JointsScene* jointsScene = new JointsScene("HingeJoint - Bridge", mEngineSettings);
|
||||
mScenes.push_back(jointsScene);
|
||||
|
||||
// Collision shapes scene
|
||||
|
@ -356,6 +356,19 @@ bool TestbedApplication::keyboard_event(int key, int scancode, int action, int m
|
|||
return true;
|
||||
}
|
||||
|
||||
// Close application on escape key
|
||||
if (key == GLFW_KEY_P && action == GLFW_PRESS) {
|
||||
|
||||
if (mTimer.isRunning()) {
|
||||
pauseSimulation();
|
||||
}
|
||||
else {
|
||||
playSimulation();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return mCurrentScene->keyboardEvent(key, scancode, action, modifiers);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user