From 0c171bfc8d9ec3979d283dad8e0077f7b009115b Mon Sep 17 00:00:00 2001 From: Ben Krajancic Date: Tue, 6 Feb 2018 11:04:00 +1100 Subject: [PATCH] Better rescue (#3106) * Half of the rescue animation is now placing the kart back down * Bit of cleaning * Single Camera Cut * Update rescue_animation.hpp * Update rescue_animation.cpp * progress to fixes * potential fix * broken implementation * Latest attempt * Instant camera snap when placing the kart down * style cleanups * Fix BACKSLASH HYEH --- src/graphics/camera_normal.cpp | 47 +++++++++------ src/graphics/camera_normal.hpp | 6 +- src/karts/rescue_animation.cpp | 106 ++++++++++++++++++++------------- src/karts/rescue_animation.hpp | 7 +++ 4 files changed, 106 insertions(+), 60 deletions(-) diff --git a/src/graphics/camera_normal.cpp b/src/graphics/camera_normal.cpp index 2e4c12bc2..7f962a474 100644 --- a/src/graphics/camera_normal.cpp +++ b/src/graphics/camera_normal.cpp @@ -68,10 +68,10 @@ CameraNormal::CameraNormal(Camera::CameraType type, int camera_index, //----------------------------------------------------------------------------- /** Moves the camera smoothly from the current camera position (and target) * to the new position and target. - * \param wanted_position The position the camera wanted to reach. - * \param wanted_target The point the camera wants to point to. + * \param dt Delta time, + * \param if false, the camera instantly moves to the endpoint, or else it smoothly moves */ -void CameraNormal::smoothMoveCamera(float dt) +void CameraNormal::moveCamera(float dt, bool smooth) { if(!m_kart) return; @@ -112,20 +112,24 @@ void CameraNormal::smoothMoveCamera(float dt) //m_smooth_dt = 0.3f * dt + 0.7f * m_smooth_dt; - float delta = (dt*5.0f); - if (delta < 0.0f) - delta = 0.0f; - else if (delta > 1.0f) - delta = 1.0f; - + float delta = 1; + float delta2 = 1; + if (smooth) + { + delta = (dt*5.0f); + if (delta < 0.0f) + delta = 0.0f; + else if (delta > 1.0f) + delta = 1.0f; + + delta2 = dt * 8.0f; + if (delta2 < 0) + delta2 = 0; + else if (delta2 > 1) + delta2 = 1; + } m_camera_offset += (wanted_camera_offset - m_camera_offset) * delta; - float delta2 = dt * 8.0f; - if (delta2 < 0) - delta2 = 0; - else if (delta2 > 1) - delta2 = 1; - btTransform btt = m_kart->getTrans(); m_kart_position = btt.getOrigin(); btQuaternion q1, q2; @@ -133,6 +137,7 @@ void CameraNormal::smoothMoveCamera(float dt) q2 = btt.getRotation().normalized(); if (dot(q1, q2) < 0.0f) q2 = -q2; + m_kart_rotation = q1.slerp(q2, delta2); btt.setOrigin(m_kart_position); @@ -159,8 +164,11 @@ void CameraNormal::smoothMoveCamera(float dt) assert(!std::isnan(m_camera->getPosition().Y)); assert(!std::isnan(m_camera->getPosition().Z)); -} // smoothMoveCamera - +} // MoveCamera +void CameraNormal::snapToPosition() +{ + moveCamera(1, false); +} //----------------------------------------------------------------------------- /** Determine the camera settings for the current frame. * \param above_kart How far above the camera should aim at. @@ -257,7 +265,7 @@ void CameraNormal::update(float dt) + core::vector3df(0, above_kart, 0)); m_camera->setTarget(current_target); } - else // no kart animation + else // no kart animation { float above_kart, cam_angle, side_way, distance; bool smoothing; @@ -266,6 +274,7 @@ void CameraNormal::update(float dt) } } // update + // ---------------------------------------------------------------------------- /** Actually sets the camera based on the given parameter. * \param above_kart How far above the camera should aim at. @@ -296,7 +305,7 @@ void CameraNormal::positionCamera(float dt, float above_kart, float cam_angle, if (smoothing) { - smoothMoveCamera(dt); + moveCamera(dt, true); } else { diff --git a/src/graphics/camera_normal.hpp b/src/graphics/camera_normal.hpp index f80a01626..80853de5b 100644 --- a/src/graphics/camera_normal.hpp +++ b/src/graphics/camera_normal.hpp @@ -51,11 +51,12 @@ private: Vec3 m_camera_offset; - void smoothMoveCamera(float dt); + void moveCamera(float dt, bool smooth); void handleEndCamera(float dt); void getCameraSettings(float *above_kart, float *cam_angle, float *side_way, float *distance, bool *smoothing); + void positionCamera(float dt, float above_kart, float cam_angle, float side_way, float distance, float smoothing); @@ -70,6 +71,9 @@ private: AbstractKart* kart); virtual ~CameraNormal() {} public: + + void snapToPosition(); + // ------------------------------------------------------------------------ bool isDebug() { return false; } // ------------------------------------------------------------------------ bool isFPS() { return false; } diff --git a/src/karts/rescue_animation.cpp b/src/karts/rescue_animation.cpp index 1dfa20ce5..49f6a2a63 100644 --- a/src/karts/rescue_animation.cpp +++ b/src/karts/rescue_animation.cpp @@ -37,6 +37,7 @@ #include +#include "graphics/camera_normal.hpp" /** The constructor stores a pointer to the kart this object is animating, * and initialised the timer. * \param kart Pointer to the kart which is animated. @@ -54,20 +55,8 @@ RescueAnimation::RescueAnimation(AbstractKart *kart, bool is_auto_rescue) // Determine maximum rescue height with up-raycast float max_height = m_kart->getKartProperties()->getRescueHeight(); - float hit_dest = 9999999.9f; - Vec3 hit; - const Material* m = NULL; - Vec3 to = m_up_vector * 10000.0f; - const TriangleMesh &tm = Track::getCurrentTrack()->getTriangleMesh(); - if (tm.castRay(m_xyz, to, &hit, &m, NULL/*normal*/, /*interpolate*/true)) - { - hit_dest = (hit - m_xyz).length(); - hit_dest -= Referee::getHeight(); - if (hit_dest < 1.0f) - { - hit_dest = 1.0f; - } - } + float hit_dest = maximumHeight(); + max_height = std::min(hit_dest, max_height); m_velocity = max_height / m_timer; @@ -91,7 +80,7 @@ RescueAnimation::RescueAnimation(AbstractKart *kart, bool is_auto_rescue) { m_des_rotation = m_orig_rotation; } - + // Add a hit unless it was auto-rescue if (race_manager->getMinorMode()==RaceManager::MINOR_MODE_3_STRIKES && !is_auto_rescue) @@ -101,50 +90,87 @@ RescueAnimation::RescueAnimation(AbstractKart *kart, bool is_auto_rescue) if (UserConfigParams::m_arena_ai_stats) world->increaseRescueCount(); } + }; // RescueAnimation + //----------------------------------------------------------------------------- /** This object is automatically destroyed when the timer expires. */ RescueAnimation::~RescueAnimation() { - // If m_timer >=0, this object is deleted because the kart - // is deleted (at the end of a race), which means that - // world is in the process of being deleted. In this case - // we can't call removeKartAfterRescue() or getPhysics anymore. - if(m_timer < 0) - World::getWorld()->moveKartAfterRescue(m_kart); + m_kart->getBody()->setLinearVelocity(btVector3(0, 0, 0)); + m_kart->getBody()->setAngularVelocity(btVector3(0, 0, 0)); m_kart->getNode()->removeChild(m_referee->getSceneNode()); delete m_referee; m_referee = NULL; - if(m_timer < 0) - { - m_kart->getBody()->setLinearVelocity(btVector3(0,0,0)); - m_kart->getBody()->setAngularVelocity(btVector3(0,0,0)); - Physics::getInstance()->addKart(m_kart); - for(unsigned int i=0; igetKart()==m_kart && - camera->getType() != Camera::CM_TYPE_END) - camera->setMode(Camera::CM_NORMAL); - } - } } // ~RescueAnimation +// Determine maximum rescue height with up-raycast +float RescueAnimation::maximumHeight() +{ + float hit_dest = 9999999.9f; + + Vec3 hit; + const Material* m = NULL; + Vec3 to = m_up_vector * 10000.0f; + const TriangleMesh &tm = Track::getCurrentTrack()->getTriangleMesh(); + if (tm.castRay(m_xyz, to, &hit, &m, NULL/*normal*/, /*interpolate*/true)) + { + hit_dest = (hit - m_xyz).length(); + hit_dest -= Referee::getHeight(); + if (hit_dest < 1.0f) + { + hit_dest = 1.0f; + } + } + return hit_dest; +} // ---------------------------------------------------------------------------- + /** Updates the kart animation. * \param dt Time step size. * \return True if the explosion is still shown, false if it has finished. */ void RescueAnimation::update(float dt) { - m_xyz += dt * m_velocity * m_up_vector; - m_kart->setXYZ(m_xyz); - btQuaternion result = m_des_rotation.slerp(m_orig_rotation, - m_timer / m_kart->getKartProperties()->getRescueDuration()); - result.normalize(); - m_kart->setRotation(result); + + if (m_timer <= (m_kart->getKartProperties()->getRescueDuration() * rescue_moment)) + { + if (kart_on_track == false) + { + kart_on_track = true; + + World::getWorld()->moveKartAfterRescue(m_kart); + + for (unsigned int i = 0; i < Camera::getNumCameras(); i++) + { + CameraNormal* camera = dynamic_cast(Camera::getCamera(i)); + if (camera && camera->getKart() == m_kart && + dynamic_cast(camera)) + { + camera->setMode(Camera::CM_NORMAL); + camera->snapToPosition(); + } + } + + m_up_vector = m_kart->getTrans().getBasis().getColumn(1); + m_xyz = m_kart->getXYZ(); + + float hit_dest = maximumHeight(); + float max_height = std::min(hit_dest, m_kart->getKartProperties()->getRescueHeight()) * rescue_moment; + m_xyz += max_height * m_up_vector; + } + + m_xyz -= dt * m_velocity * m_up_vector; + m_kart->setXYZ(m_xyz); + } + else + { + m_xyz += dt * m_velocity * m_up_vector; + m_kart->setXYZ(m_xyz); + } + AbstractKartAnimation::update(dt); } // update diff --git a/src/karts/rescue_animation.hpp b/src/karts/rescue_animation.hpp index 211a0062b..2d278652a 100644 --- a/src/karts/rescue_animation.hpp +++ b/src/karts/rescue_animation.hpp @@ -46,11 +46,18 @@ protected: /** The velocity with which the kart is moved. */ float m_velocity; + /* At what percent of the animation should the kart be on the track*/ + /*0.75 means that for 3 quaters of the animation it'll be on track*/ + const float rescue_moment = 0.6F; + /* Has the kart been moved onto the track */ + bool kart_on_track = false; + /** The referee during a rescue operation. */ Referee *m_referee; public: RescueAnimation(AbstractKart *kart, bool is_auto_rescue=false); + float maximumHeight(); virtual ~RescueAnimation(); virtual void update(float dt); }; // RescueAnimation