Make cannon smoother.
This commit is contained in:
@@ -363,6 +363,38 @@ float Ipo::IpoData::getCubicBezier(float t, float p0, float p1,
|
||||
return ((a*t+b)*t+c)*t+p0;
|
||||
} // bezier
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Determines the rotation between the start and end of this curve.
|
||||
*/
|
||||
btQuaternion Ipo::IpoData::getOverallRotation()
|
||||
{
|
||||
// Vectors at start and end of curve
|
||||
Vec3 start, end;
|
||||
|
||||
if (m_interpolation == IP_BEZIER)
|
||||
{
|
||||
// In case of Bezier use the handles to get initial and final
|
||||
// orientation
|
||||
start = m_handle2[0] - m_handle1[0];
|
||||
end = *m_handle2.back() - *m_handle1.back();
|
||||
}
|
||||
else // Const or linear
|
||||
{
|
||||
// In this case determine the start vector by selecting using the
|
||||
// beginning and a second point a bit further on the curve
|
||||
start.setX(get(m_start_time + 0.1f, 0, 0) - m_points[0].getX());
|
||||
start.setY(get(m_start_time + 0.1f, 1, 0) - m_points[0].getY());
|
||||
start.setZ(get(m_start_time + 0.1f, 2, 0) - m_points[0].getZ());
|
||||
int n = m_points.size() - 2;
|
||||
end. setX(get(m_end_time - 0.1f, 0, n) - m_points[n].getX());
|
||||
end. setY(get(m_end_time - 0.1f, 1, n) - m_points[n].getY());
|
||||
end. setZ(get(m_end_time - 0.1f, 2, n) - m_points[n].getZ());
|
||||
}
|
||||
|
||||
btQuaternion q = shortestArcQuatNormalize2(start, end);
|
||||
return q;
|
||||
} // IpData::getOverallRoation
|
||||
|
||||
// ============================================================================
|
||||
/** The Ipo constructor. Ipos can share the actual data to interpolate, which
|
||||
* is stored in a separate IpoData object, see Ipo(const Ipo *ipo)
|
||||
@@ -499,3 +531,19 @@ float Ipo::get(float time, unsigned int index) const
|
||||
assert(!std::isnan(rval));
|
||||
return rval;
|
||||
} // get
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Return the quaternion that rotates an object form the start of the IPO
|
||||
* to the end.
|
||||
*/
|
||||
btQuaternion Ipo::getOverallRotation()
|
||||
{
|
||||
// In case of a single point only:
|
||||
if (m_next_n == 0)
|
||||
{
|
||||
// Return a unit quaternion
|
||||
btQuaternion q(0, 0, 0, 1);
|
||||
return q;
|
||||
}
|
||||
return m_ipo_data->getOverallRotation();
|
||||
} // getOverallRoation
|
||||
@@ -81,10 +81,10 @@ private:
|
||||
private:
|
||||
float getCubicBezier(float t, float p0, float p1,
|
||||
float p2, float p3) const;
|
||||
void approximateBezier(float t0, float t1,
|
||||
const Vec3 &p0, const Vec3 &p1,
|
||||
const Vec3 &h0, const Vec3 &h2,
|
||||
unsigned int rec_level = 0);
|
||||
void approximateBezier(float t0, float t1,
|
||||
const Vec3 &p0, const Vec3 &p1,
|
||||
const Vec3 &h0, const Vec3 &h2,
|
||||
unsigned int rec_level = 0);
|
||||
public:
|
||||
IpoData(const XMLNode &curve, float fps, bool reverse);
|
||||
void readCurve(const XMLNode &node, bool reverse);
|
||||
@@ -94,6 +94,7 @@ private:
|
||||
const Vec3 &h1, const Vec3 &h2);
|
||||
float adjustTime(float time);
|
||||
float get(float time, unsigned int index, unsigned int n);
|
||||
btQuaternion getOverallRotation();
|
||||
|
||||
}; // IpoData
|
||||
// ------------------------------------------------------------------------
|
||||
@@ -123,7 +124,7 @@ public:
|
||||
float get(float time, unsigned int index) const;
|
||||
void setInitialTransform(const Vec3 &xyz, const Vec3 &hpr);
|
||||
void reset();
|
||||
|
||||
btQuaternion getOverallRotation();
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the raw data points for this IPO. */
|
||||
const std::vector<Vec3>& getPoints() const { return m_ipo_data->m_points; }
|
||||
|
||||
@@ -27,8 +27,10 @@
|
||||
|
||||
#include "LinearMath/btTransform.h"
|
||||
|
||||
CannonAnimation::CannonAnimation(AbstractKart *kart, Ipo *ipo)
|
||||
: AbstractKartAnimation(kart, "CannonAnimation")
|
||||
CannonAnimation::CannonAnimation(AbstractKart *kart, Ipo *ipo,
|
||||
const Vec3 &start_left, const Vec3 &start_right,
|
||||
const Vec3 &end_left, const Vec3 &end_right )
|
||||
: AbstractKartAnimation(kart, "CannonAnimation")
|
||||
{
|
||||
m_curve = new AnimationBase(ipo);
|
||||
m_timer = ipo->getEndTime();
|
||||
@@ -39,6 +41,12 @@ CannonAnimation::CannonAnimation(AbstractKart *kart, Ipo *ipo)
|
||||
m_curve->update(0, &m_previous_orig_xyz);
|
||||
m_delta = kart->getXYZ() - m_previous_orig_xyz;
|
||||
|
||||
m_delta_rotation =
|
||||
shortestArcQuatNormalize2(start_left - start_right,
|
||||
end_left - end_right );
|
||||
|
||||
|
||||
|
||||
// Now the delta vector needs to be rotated back, so that it will point
|
||||
// in the right direction when it is (in update) rotated to be the same
|
||||
// as the kart's heading. To estimate the angle at the start, use the
|
||||
@@ -46,11 +54,6 @@ CannonAnimation::CannonAnimation(AbstractKart *kart, Ipo *ipo)
|
||||
const float dt = 0.1f;
|
||||
Vec3 xyz1;
|
||||
m_curve->update(dt, &xyz1);
|
||||
core::vector3df rot = (m_previous_orig_xyz-xyz1).toIrrVector()
|
||||
.getHorizontalAngle();
|
||||
btQuaternion q(Vec3(0,1,0),rot.Y*DEGREE_TO_RAD);
|
||||
btMatrix3x3 m(q);
|
||||
m_delta = m * m_delta;
|
||||
|
||||
// The previous call to m_curve->update will set the internal timer
|
||||
// of the curve to dt. Reset it to 0 to make sure the timer is in
|
||||
@@ -104,7 +107,11 @@ void CannonAnimation::update(float dt)
|
||||
}
|
||||
m_previous_orig_xyz = xyz;
|
||||
|
||||
Vec3 rotated_delta = m_kart->getTrans().getBasis()*m_delta;
|
||||
btQuaternion zero(0, 0, 0, 1);
|
||||
// The timer count backwards, so the fraction goes from 1 to 0
|
||||
float f = m_timer / m_curve->getAnimationDuration();
|
||||
btQuaternion current_rot = m_delta_rotation.slerp(zero, f);
|
||||
Vec3 rotated_delta = quatRotate(current_rot, m_delta);
|
||||
m_kart->setXYZ(xyz + rotated_delta);
|
||||
|
||||
AbstractKartAnimation::update(dt);
|
||||
|
||||
@@ -22,15 +22,18 @@
|
||||
#include "karts/abstract_kart_animation.hpp"
|
||||
#include "utils/vec3.hpp"
|
||||
|
||||
/** This animation shoots the kart to a specified point on the track.
|
||||
*
|
||||
* \ingroup karts
|
||||
*/
|
||||
#include "LinearMath/btQuaternion.h"
|
||||
|
||||
class AbstractKart;
|
||||
class AnimationBase;
|
||||
class Ipo;
|
||||
|
||||
|
||||
/** This animation shoots the kart to a specified point on the track.
|
||||
*
|
||||
* \ingroup karts
|
||||
*/
|
||||
|
||||
class CannonAnimation: public AbstractKartAnimation
|
||||
{
|
||||
protected:
|
||||
@@ -40,6 +43,10 @@ protected:
|
||||
* kart position (so the kart moves relative to the curve). */
|
||||
Vec3 m_delta;
|
||||
|
||||
/** The amount of rotation to be applied to m_delta so that it keeps
|
||||
* being on the 'right' side of the curve. */
|
||||
btQuaternion m_delta_rotation;
|
||||
|
||||
/** Stores the curve interpolation for the cannon. */
|
||||
AnimationBase *m_curve;
|
||||
|
||||
@@ -48,7 +55,9 @@ protected:
|
||||
Vec3 m_previous_orig_xyz;
|
||||
|
||||
public:
|
||||
CannonAnimation(AbstractKart *kart, Ipo *ipo);
|
||||
CannonAnimation(AbstractKart *kart, Ipo *ipo,
|
||||
const Vec3 &start_left, const Vec3 &start_right,
|
||||
const Vec3 &end_left, const Vec3 &end_right);
|
||||
virtual ~CannonAnimation();
|
||||
virtual void update(float dt);
|
||||
|
||||
|
||||
@@ -35,13 +35,14 @@
|
||||
CheckCannon::CheckCannon(const XMLNode &node, unsigned int index)
|
||||
: CheckLine(node, index)
|
||||
{
|
||||
core::vector3df p1, p2;
|
||||
if(!node.get("target-p1", &p1) || !node.get("target-p2", &p2))
|
||||
if( !node.get("target-p1", &m_target_left ) ||
|
||||
!node.get("target-p2", &m_target_right) )
|
||||
Log::fatal("CheckCannon", "No target line specified.");
|
||||
m_target.setLine(p1, p2);
|
||||
|
||||
m_curve = new Ipo(*(node.getNode("curve")),
|
||||
/*fps*/25,
|
||||
/*reverse*/race_manager->getReverseTrack());
|
||||
|
||||
#if defined(DEBUG) && !defined(SERVER_ONLY)
|
||||
if(UserConfigParams::m_track_debug)
|
||||
{
|
||||
@@ -73,9 +74,9 @@ CheckCannon::~CheckCannon()
|
||||
*/
|
||||
void CheckCannon::trigger(unsigned int kart_index)
|
||||
{
|
||||
Vec3 target(m_target.getMiddle());
|
||||
AbstractKart *kart = World::getWorld()->getKart(kart_index);
|
||||
if(kart->getKartAnimation()) return;
|
||||
|
||||
new CannonAnimation(kart, m_curve->clone());
|
||||
new CannonAnimation(kart, m_curve->clone(), getLeftPoint(), getRightPoint(),
|
||||
m_target_left, m_target_right);
|
||||
} // CheckCannon
|
||||
|
||||
@@ -37,7 +37,8 @@ class CheckCannon : public CheckLine
|
||||
{
|
||||
private:
|
||||
/** The target point the kart will fly to. */
|
||||
core::line3df m_target;
|
||||
Vec3 m_target_left;
|
||||
Vec3 m_target_right;
|
||||
|
||||
/** Stores the cannon curve data. */
|
||||
Ipo *m_curve;
|
||||
|
||||
@@ -71,6 +71,10 @@ private:
|
||||
/** How much a kart is allowed to be over the minimum height of a
|
||||
* quad and still considered to be able to cross it. */
|
||||
static const int m_over_min_height = 4;
|
||||
protected:
|
||||
const Vec3 &getLeftPoint() const { return m_left_point; }
|
||||
const Vec3 &getRightPoint() const { return m_right_point; }
|
||||
|
||||
public:
|
||||
CheckLine(const XMLNode &node, unsigned int index);
|
||||
virtual ~CheckLine();
|
||||
|
||||
Reference in New Issue
Block a user