Frapper  1.0a
S3DGamePaths.h
Go to the documentation of this file.
1 /*
2 -----------------------------------------------------------------------------
3 This source file is part of FRAPPER
4 research.animationsinstitut.de
5 sourceforge.net/projects/frapper
6 
7 Copyright (c) 2008-2009 Filmakademie Baden-Wuerttemberg, Institute of Animation
8 
9 This program is free software; you can redistribute it and/or modify it under
10 the terms of the GNU Lesser General Public License as published by the Free Software
11 Foundation; version 2.1 of the License.
12 
13 This program is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16 
17 You should have received a copy of the GNU Lesser General Public License along with
18 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
20 http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
21 -----------------------------------------------------------------------------
22 */
23 
32 
33 #ifndef S3DGAMEPATHS_H
34 #define S3DGAMEPATHS_H
35 
36 #include "Helper.h"
37 
38 // shortcut definitions
39 typedef Ogre::Vector3 Vec3;
40 typedef Ogre::Quaternion Quat;
42 
43 namespace S3DGameNode {
44 using namespace Frapper;
45 
49 
50  // forward declaration;
51  class Path;
52  class SpherePath;
53  class StillPath;
54  class JumpPath;
55  class LinePath;
56  class SlingPath;
57  class FallPath;
58  class GameEvent;
59 
60  // Base path type.
61  // A path is used to move the character through the level.
62  // It needs to implement the GetOrientation() and GetPosition() functions
63  // for an alpha value between 0 and 1.
64  class Path
65  {
66  public:
67 
68  enum PathType { BASE, STILL, SPHERE, JUMP, LINE, SLING, FALL };
69 
70  Path() {};
71  Path( Vec3 position, Quat orientation )
72  : mPosition(position), mOrientation(orientation), mLength(1.0f) {};
73  Path( Vec3 startPosition, Vec3 endPosition )
74  : mPosition(startPosition), mStartPos(startPosition), mEndPos(endPosition) {};
75  Path( Vec3 startPosition, Vec3 endPosition, Quat orientation )
76  : mPosition(startPosition), mStartPos(startPosition), mEndPos(endPosition), mOrientation(orientation) {};
77  virtual ~Path() {};
78 
79  // virtual functions, to be overwriten in derived classes
80  virtual Quat GetOrientation( const float& alpha ) { return mOrientation;}
81  virtual Vec3 GetPosition( const float& alpha ) { return mPosition;}
82  virtual Vec3 GetStartPos() const { return mStartPos;}
83  virtual Vec3 GetEndPos() const { return mEndPos;}
84  virtual float GetNormalizedLength() { return mLength;}
85  virtual void SetNormalizedLength( float val) { mLength = val;}
86 
87  // The path type is used to distinguish between the different types of paths
88  virtual PathType GetPathType() { return BASE; }
89 
90  // Every path can have several events
91  QList<GameEvent*>& Events() { return mEvents; }
92 
93  // The name is only used for convenience
94  QString Name() const { return mName; }
95  void Name( QString val) { mName = val; }
96 
97  protected:
98 
99  Vec3 mPosition, mStartPos, mEndPos;
101  float mLength;
102  QString mName;
103  QList<GameEvent*> mEvents;
104  };
105 
106  //
107  // Simplest type of path. The character stands still on a fixed position with fixed orientation
108  //
109  class StillPath : public Path
110  {
111  public:
112 
113  StillPath( Vec3 position, Quat orientation)
114  : Path( position, orientation ) {}
115 
116  virtual PathType GetPathType() { return STILL;}
117  };
118 
119  //
120  // FallPath is like still path, but longer.
121  // Its used to play a fall animation while the camera is fixed at a certain position
122  //
123  class FallPath : public StillPath
124  {
125  public:
126  FallPath( Vec3 startPosition, Quat orientation )
127  : StillPath( startPosition, orientation )
128  { mLength = 20.0f; };
129 
130  virtual PathType GetPathType() { return FALL;}
131  };
132 
133  //
134  // SpherePath is the most used type of path in the game
135  // It describes the movement of the character over a sphere
136  //
137  class SpherePath : public Path
138  {
139  public:
140  SpherePath( Vec3 startPosition, Vec3 endPosition, Vec3 origin = Vec3(0,0,0) )
141  : Path( startPosition, endPosition ), mO(origin)
142  {
143  // translate positions into local coord system
144  mStartPos = startPosition - origin;
145  mEndPos = mEndPos - origin;
146 
147  mAngle = mStartPos.angleBetween( mEndPos );
148 
149  // Zero angles are _evil_!
150  Ogre::Radian epsAngle( std::numeric_limits<float>::epsilon());
151  CLAMP_LOWER( mAngle, epsAngle );
152 
153  mLength = mStartPos.length() * mAngle.valueRadians(); // b = r * a
154  mNormal = mStartPos.crossProduct(mEndPos).normalisedCopy();
155  };
156 
157  virtual Vec3 GetPosition( const float& alpha )
158  {
159  Quat rotation( alpha*mAngle, mNormal );
160  rotation.normalise();
161 
162  // rotate to new position according to alpha
163  Vec3 newPosition = rotation * mStartPos;
164  newPosition.normalise();
165 
166  // Linear interpolate height between start and end position
167  float height = LINEAR_INTERPOLATE( mStartPos.length(), mEndPos.length(), alpha);
168 
169  // scale normalized position according to current height
170  mPosition = height * newPosition;
171 
172  // Translate result back into global coord system
173  return mPosition+mO;
174  }
175 
176  virtual Quat GetOrientation( const float& alpha )
177  {
178  Quat orientation;
179 
180  // calculate PC up-vector, last calculated position
181  Vec3 up = mPosition;
182  up.normalise();
183 
185  Vec3 dir = Ogre::Plane(up, 0.0f).projectVector( mEndPos - mStartPos );
186  dir.normalise();
187 
188  // calculate right vector
189  Vec3 right = up.crossProduct(dir);
190  right.normalise();
191 
192  mOrientation = Quat(right, up, dir);
193  mOrientation.normalise();
194 
195  return mOrientation;
196  }
197  virtual PathType GetPathType() { return SPHERE;}
198 
199  protected:
200 
201  // Cartesian Coordinates
202  Ogre::Radian mAngle;
205  };
206 
207  //
208  // A JumpPath is created dynamically between two other paths
209  // Previously, the jump was done by adjusting the height of the character,
210  // while he moves along the path. In the current version,
211  // the height adjustment is baked into the character animation
212  //
213  class JumpPath : public SpherePath
214  {
215  public:
216  JumpPath( Vec3 startPosition, Quat startOrientation,
217  Vec3 endPosition, Quat endOrientation )
218  : SpherePath( startPosition, endPosition ),
219  mStartOrientation(startOrientation),
220  mEndOrientation(endOrientation)
221  {};
222 
223  //virtual Vec3 GetPosition( const float& alpha )
224  //{
225  // // get updated position on sphere path
226  // Vec3 direction = SpherePath::GetPosition(alpha);
227 
228  // // Add height for jump..
229  // direction.normalise();
230 
231  // // scale direction vector according to position [0..1] and arc length of path
232  // // the function for the scale factor is [http://www.wolframalpha.com/input/?i=-4(x(x-1))y,x=0to1,y=1to5]
233  // Vec3 heightVector = direction * -4.0f * (alpha*(alpha-1)) * 0.5f * mLength * mHeightScale;
234  //
235 
236  // return mPosition + heightVector;
237  //};
238 
239  //
240  // Use nlerp to get a smooth transition between the beginning and the ending orientation
241  //
242  virtual Quat GetOrientation( const float& alpha )
243  {
244  mOrientation = Quat::nlerp( alpha, mStartOrientation, mEndOrientation, true );
245  return mOrientation;
246  };
247 
248  virtual PathType GetPathType() { return JUMP;}
249 
250  void setLengthScale( float lengthScale ) { mLength *=lengthScale; }
251 
252  protected:
253  Quat mStartOrientation, mEndOrientation;
254  };
255 
256  //
257  // The LinePath describes straight movement on a line
258  // from starting to ending position
259  //
260  class LinePath : public Path
261  {
262  public:
263  LinePath( Vec3 startPosition, Vec3 endPosition )
264  : Path( startPosition, endPosition )
265  {
266  mLength = (mEndPos-mStartPos).length();
267 
268  while( mLength < 0.01f)
269  {
270  // if start ~~ end, scale end a litte bit
271  mEndPos *= 1.01f;
272  mLength = (mEndPos-mStartPos).length();
273  }
274 
275  // calculate orientation on line path
276  Vec3 up = mStartPos;
277  Vec3 dir = mEndPos - mStartPos;
278  Vec3 right = up.crossProduct(dir);
279  up.normalise();
280  dir.normalise();
281  right.normalise();
282 
283  mOrientation = Quat(right, up, dir);
284  mOrientation.normalise();
285  };
286 
287  virtual Vec3 GetPosition( const float& alpha ) { return LINEAR_INTERPOLATE( mStartPos, mEndPos, alpha);};
288  virtual PathType GetPathType() { return LINE;}
289 
290  protected:
291 
292  };
293 
294  class SlingPath : public Path
295  {
296  public:
297  SlingPath( Vec3 startPosition, Vec3 endPosition, Quat orientation )
298  : Path( startPosition, endPosition, orientation )
299  {};
300 
301  virtual Vec3 GetPosition( const float& alpha )
302  { return LINEAR_INTERPOLATE( mStartPos, mEndPos, alpha);};
303 
304  virtual PathType GetPathType()
305  { return SLING;}
306  };
307 
308 } // namespace S3DGameNode
309 #endif