Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/playability.old/src/lib/math/curve.cc @ 10581

Last change on this file since 10581 was 10335, checked in by bknecht, 18 years ago

track now works pretty good. I'm really pleased. Check it out, it doesn't crash anymore

File size: 7.0 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Benjamin Grauer
13   co-programmer: Patrick Boenzli
14
15   ADD: Patrick Boenzli           B-Spline
16
17
18   TODO:
19     local-Time implementation
20     NURBS
21     !!tList implementation!!
22
23*/
24
25#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_MATH
26
27#include "curve.h"
28
29#include "debug.h"
30
31#include <cmath>
32#include <stdio.h>
33
34
35/**
36  *  default constructor for a Curve
37*/
38Curve::Curve()
39{
40  this->nodeCount = 0;
41  this->localTime = 0;
42  this->derivation = 0;
43  this->dirCurve = NULL;
44  this->firstNode = new PathNode();
45  this->currentNode = firstNode;
46
47  this->firstNode->position = Vector (.0, .0, .0);
48  this->firstNode->number = 0;
49  this->firstNode->next = 0; // not sure if this really points to NULL!!
50}
51
52
53Curve::~Curve()
54{
55  PathNode* pn = this->firstNode;
56  PathNode* unusedPN;
57  while( pn != NULL)
58  {
59    unusedPN = pn;
60    pn = pn->next;
61    delete unusedPN;
62  }
63
64  if (dirCurve)
65    delete dirCurve;
66}
67
68
69/**
70 *  adds a new Node to the bezier Curve
71 * @param newNode a Vector to the position of the new node
72*/
73void Curve::addNode(const Vector& newNode)
74{
75  if (nodeCount != 0 )
76    {
77      currentNode = currentNode->next = new PathNode;
78    }
79  currentNode->position = newNode;
80  currentNode->next = 0;
81  currentNode->number = (++nodeCount);
82  this->rebuild();
83  return;
84}
85
86/**
87 *  adds a new Node to the bezier Curve
88 * @param newNode a Vector to the position of the new node
89 * @param insertPosition after the n-th node the new node will be inserted
90*/
91void Curve::addNode(const Vector& newNode, unsigned int insertPosition)
92{
93  if (this->nodeCount == 0 || insertPosition > this->nodeCount)
94    return addNode(newNode);
95
96  if (insertPosition == 0)
97    insertPosition = 1;
98
99  PathNode* insNode = new PathNode;
100
101  // relinking
102  PathNode* tmpNode = this->firstNode;
103  if (insertPosition > 1)
104    {
105      while (tmpNode->next->number != insertPosition)
106        tmpNode= tmpNode->next;
107      insNode->next = tmpNode->next;
108      tmpNode->next = insNode;
109    }
110  else
111    {
112      insNode->next = this->firstNode;
113      this->firstNode = insNode;
114    }
115  // renumbering
116  insNode->number = insertPosition;
117  tmpNode = insNode->next;
118  while (tmpNode)
119    {
120      tmpNode->number++;
121      tmpNode = tmpNode->next;
122    }
123
124    // finished
125  insNode->position = newNode;
126  ++nodeCount;
127  this->rebuild();
128  return;
129}
130
131/**
132 *  Finds a Node by its Number, and returns its Position
133 * @param nodeToFind the n'th node in the List of nodes
134 * @returns A Vector to the Position of the Node.
135*/
136Vector Curve::getNode(unsigned int nodeToFind)
137{
138  if (nodeToFind > this->nodeCount || nodeToFind < 0)
139    return Vector(0,0,0);
140  PathNode* tmpNode = this->firstNode;
141  for (int i = 1; i < nodeToFind; i++)
142    tmpNode = tmpNode->next;
143  return tmpNode->position;
144}
145
146/**
147 * This function returns an approximation of the length of the curve
148 *
149*/
150float Curve::getLength()
151{
152      float length = 0;
153      PathNode* tmpNode = this->firstNode;
154      for(int i = 1; i < this->nodeCount; i++)
155      {
156              length += Vector(tmpNode->next->position - tmpNode->position).len();
157      }
158      return length;
159}
160
161/**
162 *  Outputs information about the state of this Curve
163*/
164void Curve::debug()
165{
166  printf("<<-------------------------------\n");
167  printf("Curve Information:\n");
168  printf("NodeCount: %d\n", this->nodeCount);
169  PathNode* tmpNode = this->firstNode;
170  while (tmpNode)
171    {
172      printf("node #%d: %f, %f, %f\n", tmpNode->number, tmpNode->position.x, tmpNode->position.y, tmpNode->position.z);
173      tmpNode = tmpNode->next;
174    }
175  printf("------------------------------->>\n");
176}
177
178
179///////////////////////////////////
180/// Bezier Curve //////////////////
181///////////////////////////////////
182
183/**
184 *  Creates a new BezierCurve
185*/
186BezierCurve::BezierCurve ()
187{
188  this->derivation = 0;
189  dirCurve = new BezierCurve(1);
190}
191
192/**
193 *  Creates a new BezierCurve-Derivation-Curve
194*/
195BezierCurve::BezierCurve (int derivation)
196{
197  this->derivation = derivation;
198  dirCurve=NULL;
199}
200
201/**
202 *  Deletes a BezierCurve.
203
204   It does this by freeing all the space taken over from the nodes
205*/
206BezierCurve::~BezierCurve()
207{
208
209}
210
211/**
212 *  Rebuilds a Curve
213*/
214void BezierCurve::rebuild()
215{
216  PathNode* tmpNode = firstNode;
217
218  // rebuilding the Curve itself
219  float k = 0;
220  float n = nodeCount -1;
221  float binCoef = 1;
222  while( tmpNode)
223    {
224      tmpNode->factor = binCoef;
225      if( tmpNode = tmpNode->next)
226        {
227          binCoef *= (n-k) / (k+1);
228          ++k;
229        }
230    }
231
232  // rebuilding the Derivation curve
233  if( this->derivation <= 1)
234    {
235      tmpNode = firstNode;
236      delete dirCurve;
237      dirCurve = new BezierCurve(1);
238      while( tmpNode->next)
239        {
240          Vector tmpVector = (tmpNode->next->position) - (tmpNode->position);
241          tmpVector.x*=(float)nodeCount;
242          tmpVector.y*=(float)nodeCount;
243          tmpVector.z*=(float)nodeCount;
244          tmpVector.normalize();
245          this->dirCurve->addNode(tmpVector);
246          tmpNode = tmpNode->next;
247        }
248    }
249}
250
251/**
252 *  calculates the Position on the curve
253 * @param t The position on the Curve (0<=t<=1)
254 * @return the Position on the Path
255*/
256Vector BezierCurve::calcPos(float t)
257{
258  Vector ret = Vector(0.0,0.0,0.0);
259  if (this->nodeCount >= 3)
260    {
261      PathNode* tmpNode = this->firstNode;
262      double factor = pow(1.0-t,nodeCount-1);
263      while(tmpNode)
264        {
265          ret.x += tmpNode->factor * factor * tmpNode->position.x;
266          ret.y += tmpNode->factor * factor * tmpNode->position.y;
267          ret.z += tmpNode->factor * factor * tmpNode->position.z;
268          factor *= t/(1.0-t); // same as pow but much faster.
269
270          tmpNode = tmpNode->next;
271        }
272    }
273  else if (nodeCount == 2)
274    {
275      ret = this->firstNode->position *(1.0-t);
276      ret = ret + this->firstNode->next->position * t;
277    }
278  else if (nodeCount == 1)
279    ret = this->firstNode->position;
280  return ret;
281}
282
283/**
284 *  Calulates the direction of the Curve at time t.
285 * @param t The time at which to evaluate the curve.
286 * @returns The valuated Vector.
287*/
288Vector BezierCurve::calcDir (float t)
289{
290  return this->calcPos(t + 0.01) - this->calcPos(t);
291  //return this->dirCurve->calcPos(t);
292}
293
294/**
295 *  Calulates the acceleration (second derivate) of the Curve at time t.
296 * @param t The time at which to evaluate the curve.
297 * @returns The valuated Vector.
298*/
299Vector BezierCurve::calcAcc (float t)
300{
301  return this->dirCurve->getDirCurve()->calcPos(t);
302}
303
304/**
305 *  Calculates the Quaternion needed for our rotations
306 * @param t The time at which to evaluate the cuve.
307 * @returns The evaluated Quaternion.
308*/
309Quaternion BezierCurve::calcQuat (float t)
310{
311  return Quaternion (calcDir(t), Vector(0,0,1));
312}
313
314
315/**
316  \brief returns the Position of the point calculated on the Curve
317  \return a Vector to the calculated position
318*/
319Vector BezierCurve::getPos() const
320{
321  return curvePoint;
322}
Note: See TracBrowser for help on using the repository browser.