Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/math/curve.cc @ 10611

Last change on this file since 10611 was 10368, checked in by patrick, 18 years ago

merged the branche playability into the trunk

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.