Main Page Namespace List Class Hierarchy Alphabetical List Compound List File List Namespace Members Compound Members File Members Related Pages

# OgreSimpleSpline.cpp

Go to the documentation of this file.

    00001 /*
    00002 -----------------------------------------------------------------------------
    00003 This source file is part of OGRE
    00004     (Object-oriented Graphics Rendering Engine)
    00005 For the latest info, see http://www.ogre3d.org/
    00006
    00007 Copyright © 2000-2002 The OGRE Team
    00008 Also see acknowledgements in Readme.html
    00009
    00010 This program is free software; you can redistribute it and/or modify it under
    00011 the terms of the GNU Lesser General Public License as published by the Free Software
    00012 Foundation; either version 2 of the License, or (at your option) any later
    00013 version.
    00014
    00015 This program is distributed in the hope that it will be useful, but WITHOUT
    00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
    00018
    00019 You should have received a copy of the GNU Lesser General Public License along with
    00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
    00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
    00022 http://www.gnu.org/copyleft/lesser.txt.
    00023 -----------------------------------------------------------------------------
    00024 */
    00025 #include "OgreStableHeaders.h"
    00026 #include "OgreSimpleSpline.h"
    00027 #include "OgreVector4.h"
    00028 #include "OgreMatrix4.h"
    00029
    00030
    00031
    00032 namespace Ogre {
    00033
    00034     //---------------------------------------------------------------------
    00035     SimpleSpline::SimpleSpline()
    00036     {
    00037         // Set up matrix
    00038         // Hermite polynomial
    00039         mCoeffs[0][0] = 2;
    00040         mCoeffs[0][1] = -2;
    00041         mCoeffs[0][2] = 1;
    00042         mCoeffs[0][3] = 1;
    00043         mCoeffs[1][0] = -3;
    00044         mCoeffs[1][1] = 3;
    00045         mCoeffs[1][2] = -2;
    00046         mCoeffs[1][3] = -1;
    00047         mCoeffs[2][0] = 0;
    00048         mCoeffs[2][1] = 0;
    00049         mCoeffs[2][2] = 1;
    00050         mCoeffs[2][3] = 0;
    00051         mCoeffs[3][0] = 1;
    00052         mCoeffs[3][1] = 0;
    00053         mCoeffs[3][2] = 0;
    00054         mCoeffs[3][3] = 0;
    00055
    00056         mAutoCalc = true;
    00057     }
    00058     //---------------------------------------------------------------------
    00059     SimpleSpline::~SimpleSpline()
    00060     {
    00061     }
    00062     //---------------------------------------------------------------------
    00063     void SimpleSpline::addPoint(const Vector3& p)
    00064     {
    00065         mPoints.push_back(p);
    00066         if (mAutoCalc)
    00067         {
    00068             recalcTangents();
    00069         }
    00070     }
    00071     //---------------------------------------------------------------------
    00072     Vector3 SimpleSpline::interpolate(Real t)
    00073     {
    00074         // Currently assumes points are evenly spaced, will cause velocity
    00075         // change where this is not the case
    00076         // TODO: base on arclength?
    00077
    00078
    00079         // Work out which segment this is in
    00080         Real fSeg = t * mPoints.size();
    00081         unsigned int segIdx = (unsigned int)fSeg;
    00082         // Apportion t
    00083         t = fSeg - segIdx;
    00084
    00085         return interpolate(segIdx, t);
    00086
    00087     }
    00088     //---------------------------------------------------------------------
    00089     Vector3 SimpleSpline::interpolate(unsigned int fromIndex, Real t)
    00090     {
    00091         // Bounds check
    00092         assert (fromIndex >= 0 && fromIndex < mPoints.size() &&
    00093             "fromIndex out of bounds");
    00094
    00095         if ((fromIndex + 1) == mPoints.size())
    00096         {
    00097             // Duff request, cannot blend to nothing
    00098             // Just return source
    00099             return mPoints[fromIndex];
    00100
    00101         }
    00102
    00103         // Fast special cases
    00104         if (t == 0.0f)
    00105         {
    00106             return mPoints[fromIndex];
    00107         }
    00108         else if(t == 1.0f)
    00109         {
    00110             return mPoints[fromIndex + 1];
    00111         }
    00112
    00113         // Real interpolation
    00114         // Form a vector of powers of t
    00115         Real t2, t3;
    00116         t2 = t * t;
    00117         t3 = t2 * t;
    00118         Vector4 powers(t3, t2, t, 1);
    00119
    00120
    00121         // Algorithm is ret = powers * mCoeffs * Matrix4(point1, point2, tangent1, tangent2)
    00122         Vector3& point1 = mPoints[fromIndex];
    00123         Vector3& point2 = mPoints[fromIndex+1];
    00124         Vector3& tan1 = mTangents[fromIndex];
    00125         Vector3& tan2 = mTangents[fromIndex+1];
    00126         Matrix4 pt;
    00127
    00128         pt[0][0] = point1.x;
    00129         pt[0][1] = point1.y;
    00130         pt[0][2] = point1.z;
    00131         pt[0][3] = 1.0f;
    00132         pt[1][0] = point2.x;
    00133         pt[1][1] = point2.y;
    00134         pt[1][2] = point2.z;
    00135         pt[1][3] = 1.0f;
    00136         pt[2][0] = tan1.x;
    00137         pt[2][1] = tan1.y;
    00138         pt[2][2] = tan1.z;
    00139         pt[2][3] = 1.0f;
    00140         pt[3][0] = tan2.x;
    00141         pt[3][1] = tan2.y;
    00142         pt[3][2] = tan2.z;
    00143         pt[3][3] = 1.0f;
    00144
    00145         Vector4 ret = powers * mCoeffs * pt;
    00146
    00147
    00148         return Vector3(ret.x, ret.y, ret.z);
    00149
    00150
    00151
    00152
    00153     }
    00154     //---------------------------------------------------------------------
    00155     void SimpleSpline::recalcTangents(void)
    00156     {
    00157         // Catmull-Rom approach
    00158         //
    00159         // tangent[i] = 0.5 * (point[i+1] - point[i-1])
    00160         //
    00161         // Assume endpoint tangents are parallel with line with neighbour
    00162
    00163         size_t i, numPoints;
    00164         bool isClosed;
    00165
    00166         numPoints = mPoints.size();
    00167         if (numPoints < 2)
    00168         {
    00169             // Can't do anything yet
    00170             return;
    00171         }
    00172
    00173         // Closed or open?
    00174         if (mPoints[0] == mPoints[numPoints-1])
    00175         {
    00176             isClosed = true;
    00177         }
    00178         else
    00179         {
    00180             isClosed = false;
    00181         }
    00182
    00183         mTangents.resize(numPoints);
    00184
    00185
    00186
    00187         for(i = 0; i < numPoints; ++i)
    00188         {
    00189             if (i ==0)
    00190             {
    00191                 // Special case start
    00192                 if (isClosed)
    00193                 {
    00194                     // Use numPoints-2 since numPoints-1 is the last point and == [0]
    00195                     mTangents[i] = 0.5 * (mPoints[1] - mPoints[numPoints-2]);
    00196                 }
    00197                 else
    00198                 {
    00199                     mTangents[i] = 0.5 * (mPoints[1] - mPoints[0]);
    00200                 }
    00201             }
    00202             else if (i == numPoints-1)
    00203             {
    00204                 // Special case end
    00205                 if (isClosed)
    00206                 {
    00207                     // Use same tangent as already calculated for [0]
    00208                     mTangents[i] = mTangents[0];
    00209                 }
    00210                 else
    00211                 {
    00212                     mTangents[i] = 0.5 * (mPoints[i] - mPoints[i-1]);
    00213                 }
    00214             }
    00215             else
    00216             {
    00217                 mTangents[i] = 0.5 * (mPoints[i+1] - mPoints[i-1]);
    00218             }
    00219
    00220         }
    00221
    00222
    00223
    00224     }
    00225     //---------------------------------------------------------------------
    00226     const Vector3& SimpleSpline::getPoint(unsigned short index) const
    00227     {
    00228         assert (index < mPoints.size() && "Point index is out of bounds!!");
    00229
    00230         return mPoints[index];
    00231     }
    00232     //---------------------------------------------------------------------
    00233     unsigned short SimpleSpline::getNumPoints(void) const
    00234     {
    00235         return (unsigned short)mPoints.size();
    00236     }
    00237     //---------------------------------------------------------------------
    00238     void SimpleSpline::clear(void)
    00239     {
    00240         mPoints.clear();
    00241         mTangents.clear();
    00242     }
    00243     //---------------------------------------------------------------------
    00244     void SimpleSpline::updatePoint(unsigned short index, const Vector3& value)
    00245     {
    00246         assert (index < mPoints.size() && "Point index is out of bounds!!");
    00247
    00248         mPoints[index] = value;
    00249         if (mAutoCalc)
    00250         {
    00251             recalcTangents();
    00252         }
    00253     }
    00254     //---------------------------------------------------------------------
    00255     void SimpleSpline::setAutoCalculate(bool autoCalc)
    00256     {
    00257         mAutoCalc = autoCalc;
    00258     }
    00259
    00260
    00261
    00262
    00263 }
    00264
    00265
    00266
    00267

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:46 2004