Make cannon smoother.

This commit is contained in:
hiker
2017-02-20 07:41:33 +11:00
parent 30cff00757
commit a17b537699
7 changed files with 95 additions and 24 deletions

View File

@@ -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

View File

@@ -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; }

View File

@@ -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);

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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();