diff --git a/src/animations/animation_base.hpp b/src/animations/animation_base.hpp index 8ed5dcad6..edc3f61d5 100644 --- a/src/animations/animation_base.hpp +++ b/src/animations/animation_base.hpp @@ -48,6 +48,11 @@ private: /** The current time in the cycle of a cyclic animation. */ float m_current_time; + /** The inital position of this object. */ + core::vector3df m_initial_xyz; + + /** The initial rotation of this object. */ + core::vector3df m_initial_hpr; protected: /** All IPOs for this animation. */ std::vector m_all_ipos; diff --git a/src/animations/ipo.cpp b/src/animations/ipo.cpp index a423b6915..66a572cfd 100644 --- a/src/animations/ipo.cpp +++ b/src/animations/ipo.cpp @@ -110,16 +110,16 @@ void Ipo::reset() void Ipo::update(float dt, core::vector3df *xyz, core::vector3df *hpr) { m_time += dt; - if(m_time>m_max_time) m_time = 0; + if(m_extend!=ET_CONST && m_time>m_max_time) m_time = 0; switch(m_channel) { case Ipo::IPO_LOCX : xyz->X = get(); break; case Ipo::IPO_LOCY : xyz->Y = get(); break; case Ipo::IPO_LOCZ : xyz->Z = get(); break; - case Ipo::IPO_ROTX : hpr->Y = get()*10.0f; break; - case Ipo::IPO_ROTY : hpr->Y = get()*10.0f; break; - case Ipo::IPO_ROTZ : hpr->Z = get()*10.0f; break; + case Ipo::IPO_ROTX : hpr->X = get(); break; + case Ipo::IPO_ROTY : hpr->Y = get(); break; + case Ipo::IPO_ROTZ : hpr->Z = get(); break; } // switch } // update @@ -156,9 +156,9 @@ float Ipo::get() const // FIXME: only const implemented atm. return m_points[n].Y; } - core::vector2df c = 3.0f*(m_handle2[n]-m_points[n]); - core::vector2df b = 3.0f*(m_handle1[n+1]-m_handle2[n])-c; - core::vector2df a = m_points[n+1] - m_points[n] - c - b; + core::vector2df c = 3.0f*(m_handle2[n]-m_points[n]); + core::vector2df b = 3.0f*(m_handle1[n+1]-m_handle2[n])-c; + core::vector2df a = m_points[n+1] - m_points[n] - c - b; float t = (m_time-m_points[n].X)/(m_points[n+1].X-m_points[n].X); core::vector2df r = ((a*t+b)*t+c)*t+m_points[n]; return r.Y; diff --git a/src/animations/three_d_animation.cpp b/src/animations/three_d_animation.cpp index c3c750aeb..408c617dd 100644 --- a/src/animations/three_d_animation.cpp +++ b/src/animations/three_d_animation.cpp @@ -23,9 +23,15 @@ #include "animations/ipo.hpp" #include "graphics/irr_driver.hpp" +#include "graphics/mesh_tools.hpp" #include "io/file_manager.hpp" #include "io/xml_node.hpp" +#include "modes/world.hpp" +#include "physics/physics.hpp" +#include "physics/kart_motion_state.hpp" +#include "race/race_manager.hpp" #include "tracks/bezier_curve.hpp" +#include "utils/constants.hpp" ThreeDAnimation::ThreeDAnimation(const std::string &track_name, const XMLNode &node, float fps) @@ -46,9 +52,69 @@ ThreeDAnimation::ThreeDAnimation(const std::string &track_name, core::vector3df xyz; node.get("xyz", &xyz); m_animated_node->setPosition(xyz); + core::vector3df hpr(0,0,0); + node.get("hpr", &hpr); + m_animated_node->setRotation(hpr); + /** Save the initial position and rotation in the base animation object. */ setInitialTransform(m_animated_node->getPosition(), m_animated_node->getRotation()); + + m_body = NULL; + m_motion_state = NULL; + m_collision_shape = NULL; + std::string shape; + node.get("shape", &shape); + if(shape!="") + { + createPhysicsBody(shape); + } } // ThreeDAnimation +// ---------------------------------------------------------------------------- +/** Creates a bullet rigid body for this animated model. */ +void ThreeDAnimation::createPhysicsBody(const std::string &shape) +{ + // 1. Determine size of the object + // ------------------------------- + Vec3 min, max; + MeshTools::minMax3D(m_mesh, &min, &max); + Vec3 extend = max-min; + if(shape=="box") + { + m_collision_shape = new btBoxShape(0.5*extend); + } + else if(shape=="cone") + { + float radius = 0.5f*std::max(extend.getX(), extend.getY()); + m_collision_shape = new btConeShapeZ(radius, extend.getZ()); + } + else + { + fprintf(stderr, "Shape '%s' is not supported, ignored.\n", shape.c_str()); + return; + } + const core::vector3df &hpr=m_animated_node->getRotation()*DEGREE_TO_RAD; + btQuaternion q(hpr.X, hpr.Y, hpr.Z); + const core::vector3df &xyz=m_animated_node->getPosition(); + Vec3 p(xyz); + btTransform trans(q,p); + m_motion_state = new KartMotionState(trans); + btRigidBody::btRigidBodyConstructionInfo info(0, m_motion_state, + m_collision_shape); + + m_body = new btRigidBody(info); + m_user_pointer.set(this); + m_body->setUserPointer(&m_user_pointer); + RaceManager::getWorld()->getPhysics()->addBody(m_body); + m_body->setCollisionFlags( m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + m_body->setActivationState(DISABLE_DEACTIVATION); +} // createPhysicsBody + +// ---------------------------------------------------------------------------- +/** Destructor. */ +ThreeDAnimation::~ThreeDAnimation() +{ +} // ~ThreeDAnimation + // ---------------------------------------------------------------------------- /** Updates position and rotation of this model. Called once per time step. * \param dt Time since last call. @@ -60,4 +126,14 @@ void ThreeDAnimation::update(float dt) AnimationBase::update(dt, &xyz, &hpr); //updates all IPOs m_animated_node->setPosition(xyz); m_animated_node->setRotation(hpr); + + // Now update the position of the bullet body if there is one: + if(m_body) + { + hpr = DEGREE_TO_RAD*hpr; + btQuaternion q(hpr.X, hpr.Y, hpr.Z); + Vec3 p(xyz); + btTransform trans(q,p); + m_motion_state->setWorldTransform(trans); + } } // update \ No newline at end of file diff --git a/src/animations/three_d_animation.hpp b/src/animations/three_d_animation.hpp index 12342a02f..e61383869 100644 --- a/src/animations/three_d_animation.hpp +++ b/src/animations/three_d_animation.hpp @@ -21,12 +21,14 @@ #define HEADER_THREE_D_ANIMATION_HPP #include -#include #include "irrlicht.h" using namespace irr; +#include "btBulletDynamicsCommon.h" + #include "animations/animation_base.hpp" +#include "physics/user_pointer.hpp" class XMLNode; class BezierCurve; @@ -40,10 +42,25 @@ private: /** The scene node for the model. */ scene::IAnimatedMeshSceneNode *m_animated_node; + + /** The bullet collision shape for the physics. */ + btCollisionShape *m_collision_shape; + + /** The bullet rigid body. */ + btRigidBody *m_body; + + /** Motion state of the physical object. */ + btMotionState *m_motion_state; + + /** A user pointer to connect a bullet body with this object. */ + UserPointer m_user_pointer; + + void createPhysicsBody(const std::string &shape); + public: ThreeDAnimation(const std::string &track_name, const XMLNode &node, float fps); - virtual ~ThreeDAnimation(){} + virtual ~ThreeDAnimation(); virtual void update(float dt); }; // ThreeDAnimation diff --git a/src/graphics/camera.cpp b/src/graphics/camera.cpp index 1bd722051..56f19d2a6 100644 --- a/src/graphics/camera.cpp +++ b/src/graphics/camera.cpp @@ -159,7 +159,7 @@ void Camera::update(float dt) steering = m_kart->getSteerPercent() * (1.0f + (m_kart->getSkidding() - 1.0f)/2.3f ); // dampen skidding effect dampened_steer = fabsf(steering) * steering; // quadratically to dampen small variations (but keep sign) m_angle_around = m_kart->getHPR().getX() + m_rotation_range * dampened_steer * 0.5f; - m_angle_up = m_kart->getHPR().getY() - DEGREE_TO_RAD(30.0f); + m_angle_up = m_kart->getHPR().getY() - 30.0f*DEGREE_TO_RAD; m_target = m_kart->getXYZ(); m_target.setZ(m_target.getZ()+0.75f); @@ -173,7 +173,7 @@ void Camera::update(float dt) break; case CM_REVERSE: // Same as CM_NORMAL except it looks backwards m_angle_around = m_kart->getHPR().getX() - m_rotation_range * m_kart->getSteerPercent() * m_kart->getSkidding(); - m_angle_up = m_kart->getHPR().getY() + DEGREE_TO_RAD(30.0f); + m_angle_up = m_kart->getHPR().getY() + 30.0f*DEGREE_TO_RAD; m_target = m_kart->getXYZ(); m_target.setZ(m_target.getZ()+0.75f); @@ -187,7 +187,7 @@ void Camera::update(float dt) break; case CM_CLOSEUP: // Lower to the ground and closer to the kart m_angle_around = m_kart->getHPR().getX() + m_rotation_range * m_kart->getSteerPercent() * m_kart->getSkidding(); - m_angle_up = m_kart->getHPR().getY() - DEGREE_TO_RAD(20.0f); + m_angle_up = m_kart->getHPR().getY() - 20.0f*DEGREE_TO_RAD; m_target = m_kart->getXYZ(); m_target.setZ(m_target.getZ()+0.75f); @@ -202,7 +202,7 @@ void Camera::update(float dt) case CM_LEADER_MODE: // Follows the leader kart, higher off of the ground, further from the kart, // and turns in the opposite direction from the kart for a nice effect. :) m_angle_around = RaceManager::getKart(0)->getHPR().getX(); - m_angle_up = RaceManager::getKart(0)->getHPR().getY() + DEGREE_TO_RAD(40.0f); + m_angle_up = RaceManager::getKart(0)->getHPR().getY() + 40.0f*DEGREE_TO_RAD; m_target = RaceManager::getKart(0)->getXYZ(); diff --git a/src/graphics/nitro.cpp b/src/graphics/nitro.cpp index a0f702768..9eb82fe51 100644 --- a/src/graphics/nitro.cpp +++ b/src/graphics/nitro.cpp @@ -72,9 +72,9 @@ void Nitro::update(float t) // There seems to be no way to randomise the velocity for particles, // so we have to do this manually, by changing the default velocity. // Irrlicht expects velocity (called 'direction') in m/ms!! - Vec3 dir(cos(DEGREE_TO_RAD(rand()%180))*0.001f, - sin(DEGREE_TO_RAD(rand()%180))*0.001f, - sin(DEGREE_TO_RAD(rand()%100))*0.001f); + Vec3 dir(cos(DEGREE_TO_RAD*(rand()%180))*0.001f, + sin(DEGREE_TO_RAD*(rand()%180))*0.001f, + sin(DEGREE_TO_RAD*(rand()%100))*0.001f); m_emitter->setDirection(dir.toIrrVector()); } // update diff --git a/src/graphics/smoke.cpp b/src/graphics/smoke.cpp index 07f66471f..eb3d9570c 100644 --- a/src/graphics/smoke.cpp +++ b/src/graphics/smoke.cpp @@ -84,9 +84,9 @@ void Smoke::update(float t) // There seems to be no way to randomise the velocity for particles, // so we have to do this manually, by changing the default velocity. // Irrlicht expects velocity (called 'direction') in m/ms!! - Vec3 dir(cos(DEGREE_TO_RAD(rand()%180))*0.002f, - sin(DEGREE_TO_RAD(rand()%180))*0.002f, - sin(DEGREE_TO_RAD(rand()%100))*0.002f); + Vec3 dir(cos(DEGREE_TO_RAD*(rand()%180))*0.002f, + sin(DEGREE_TO_RAD*(rand()%180))*0.002f, + sin(DEGREE_TO_RAD*(rand()%100))*0.002f); m_emitter->setDirection(dir.toIrrVector()); } // update diff --git a/src/graphics/water_splash.cpp b/src/graphics/water_splash.cpp index 9cea30ba6..9702120d5 100644 --- a/src/graphics/water_splash.cpp +++ b/src/graphics/water_splash.cpp @@ -97,8 +97,8 @@ void WaterSplash::update(float t) float f=m_kart->getSpeed(); if(f<1) return; // avoid problem with modulo 0 Vec3 dir((rand()%int(f))*(left?-1:1)*0.004f, - sin(DEGREE_TO_RAD(rand()%180))*0.004f, - sin(DEGREE_TO_RAD(rand()%100))*0.004f); + sin(DEGREE_TO_RAD*(rand()%180))*0.004f, + sin(DEGREE_TO_RAD*(rand()%100))*0.004f); m_emitter->setDirection(dir.toIrrVector()); } // update diff --git a/src/modes/linear_world.cpp b/src/modes/linear_world.cpp index 9fd65c2d1..f7e3e1719 100644 --- a/src/modes/linear_world.cpp +++ b/src/modes/linear_world.cpp @@ -616,8 +616,8 @@ void LinearWorld::checkForWrongDirection(unsigned int i) else if (angle_diff < -M_PI) angle_diff += 2*M_PI; // Display a warning message if the kart is going back way (unless // the kart has already finished the race). - if (( angle_diff > DEGREE_TO_RAD( 120.0f) || - angle_diff < DEGREE_TO_RAD(-120.0f)) && + if (( angle_diff > DEGREE_TO_RAD* 120.0f || + angle_diff < -DEGREE_TO_RAD*120.0f) && kart->getVelocityLC().getY() > 0.0f && !kart->hasFinishedRace() ) { diff --git a/src/physics/physics.cpp b/src/physics/physics.cpp index 089d98a53..4feeaaed7 100644 --- a/src/physics/physics.cpp +++ b/src/physics/physics.cpp @@ -144,7 +144,7 @@ void Physics::update(float dt) p->a->getPointerFlyable()->hit(p->b->getPointerKart()); } else // projectile hits projectile - { + { p->a->getPointerFlyable()->hit(NULL); p->b->getPointerFlyable()->hit(NULL); } diff --git a/src/physics/user_pointer.hpp b/src/physics/user_pointer.hpp index df4edf10c..c7c668a39 100644 --- a/src/physics/user_pointer.hpp +++ b/src/physics/user_pointer.hpp @@ -28,22 +28,29 @@ class Moveable; class Flyable; class Kart; class PhysicalObject; +class ThreeDAnimation; +/** A UserPointer is stored as a user pointer in all bullet bodies. This + * allows easily finding the appropriate STK object for a bullet body. + */ class UserPointer { public: + /** List of all possibles STK objects that are represented in the + * physics. */ enum UserPointerType {UP_UNDEF, UP_KART, UP_FLYABLE, UP_TRACK, - UP_PHYSICAL_OBJECT}; + UP_PHYSICAL_OBJECT, UP_ANIMATION}; private: void* m_pointer; UserPointerType m_user_pointer_type; public: - bool is(UserPointerType t) const {return m_user_pointer_type==t; } - TriangleMesh* getPointerTriangleMesh() const {return (TriangleMesh*)m_pointer; } - Moveable* getPointerMoveable() const {return (Moveable*)m_pointer; } - Flyable* getPointerFlyable() const {return (Flyable*)m_pointer; } - Kart* getPointerKart() const {return (Kart*)m_pointer; } - PhysicalObject *getPointerPhysicalObject() const {return (PhysicalObject*)m_pointer;} + bool is(UserPointerType t) const {return m_user_pointer_type==t; } + TriangleMesh* getPointerTriangleMesh() const {return (TriangleMesh*)m_pointer; } + Moveable* getPointerMoveable() const {return (Moveable*)m_pointer; } + Flyable* getPointerFlyable() const {return (Flyable*)m_pointer; } + Kart* getPointerKart() const {return (Kart*)m_pointer; } + PhysicalObject *getPointerPhysicalObject() const {return (PhysicalObject*)m_pointer; } + ThreeDAnimation*getPointerAnimation() const {return (ThreeDAnimation*)m_pointer;} void set(PhysicalObject* p) { m_user_pointer_type=UP_PHYSICAL_OBJECT; m_pointer =p; } void set(Kart* p) { m_user_pointer_type=UP_KART; @@ -52,6 +59,8 @@ public: m_pointer =p; } void set(TriangleMesh* p) { m_user_pointer_type=UP_TRACK; m_pointer =p; } + void set(ThreeDAnimation* p){ m_user_pointer_type=UP_ANIMATION; + m_pointer =p; } UserPointer() { zero(); } void zero() { m_user_pointer_type=UP_UNDEF; m_pointer = NULL; } diff --git a/src/robots/default_robot.cpp b/src/robots/default_robot.cpp index 80d1ac4d0..0cc1e8c13 100644 --- a/src/robots/default_robot.cpp +++ b/src/robots/default_robot.cpp @@ -302,7 +302,7 @@ void DefaultRobot::handleBraking() kart_ang_diff = normalizeAngle(kart_ang_diff); kart_ang_diff = fabsf(kart_ang_diff); - const float MIN_TRACK_ANGLE = DEGREE_TO_RAD(20.0f); + const float MIN_TRACK_ANGLE = DEGREE_TO_RAD*20.0f; const float CURVE_INSIDE_PERC = 0.25f; //Brake only if the road does not goes somewhat straight. @@ -314,7 +314,7 @@ void DefaultRobot::handleBraking() //out of the curve. if(!(m_world->getDistanceToCenterForKart(getWorldKartId()) > m_quad_graph->getNode(m_track_node).getPathWidth() * - -CURVE_INSIDE_PERC || m_curve_angle > RAD_TO_DEGREE(getMaxSteerAngle()))) + -CURVE_INSIDE_PERC || m_curve_angle > RAD_TO_DEGREE*getMaxSteerAngle())) { m_controls.m_brake = false; return; @@ -324,7 +324,7 @@ void DefaultRobot::handleBraking() { if(!(m_world->getDistanceToCenterForKart( getWorldKartId() ) < m_quad_graph->getNode(m_track_node).getPathWidth() * - CURVE_INSIDE_PERC || m_curve_angle < -RAD_TO_DEGREE(getMaxSteerAngle()))) + CURVE_INSIDE_PERC || m_curve_angle < -RAD_TO_DEGREE*getMaxSteerAngle())) { m_controls.m_brake = false; return; diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index 013c0cbde..13139925c 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -159,7 +159,7 @@ btTransform Track::getStartTransform(unsigned int pos) const start.setOrigin(orig); start.setRotation(btQuaternion(btVector3(0, 0, 1), pos