Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 8372 was 5232, checked in by patrick, 19 years ago

orxonox/trunk: solved a memory leak in the QuadtreeNode

File size: 6.7 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 <math.h>
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 *  Outputs information about the state of this Curve
148*/
149void Curve::debug()
150{
151  printf("<<-------------------------------\n");
152  printf("Curve Information:\n");
153  printf("NodeCount: %d\n", this->nodeCount);
154  PathNode* tmpNode = this->firstNode;
155  while (tmpNode)
156    {
157      printf("node #%d: %f, %f, %f\n", tmpNode->number, tmpNode->position.x, tmpNode->position.y, tmpNode->position.z);
158      tmpNode = tmpNode->next;
159    }
160  printf("------------------------------->>\n");
161}
162
163
164///////////////////////////////////
165/// Bezier Curve //////////////////
166///////////////////////////////////
167
168/**
169 *  Creates a new BezierCurve
170*/
171BezierCurve::BezierCurve ()
172{
173  this->derivation = 0;
174  dirCurve = new BezierCurve(1);
175}
176
177/**
178 *  Creates a new BezierCurve-Derivation-Curve
179*/
180BezierCurve::BezierCurve (int derivation)
181{
182  this->derivation = derivation;
183  dirCurve=NULL;
184}
185
186/**
187 *  Deletes a BezierCurve.
188
189   It does this by freeing all the space taken over from the nodes
190*/
191BezierCurve::~BezierCurve()
192{
193
194}
195
196/**
197 *  Rebuilds a Curve
198*/
199void BezierCurve::rebuild()
200{
201  PathNode* tmpNode = firstNode;
202
203  // rebuilding the Curve itself
204  float k = 0;
205  float n = nodeCount -1;
206  float binCoef = 1;
207  while( tmpNode)
208    {
209      tmpNode->factor = binCoef;
210      if( tmpNode = tmpNode->next)
211        {
212          binCoef *= (n-k) / (k+1);
213          ++k;
214        }
215    }
216
217  // rebuilding the Derivation curve
218  if( this->derivation <= 1)
219    {
220      tmpNode = firstNode;
221      delete dirCurve;
222      dirCurve = new BezierCurve(1);
223      while( tmpNode->next)
224        {
225          Vector tmpVector = (tmpNode->next->position) - (tmpNode->position);
226          tmpVector.x*=(float)nodeCount;
227          tmpVector.y*=(float)nodeCount;
228          tmpVector.z*=(float)nodeCount;
229          tmpVector.normalize();
230          this->dirCurve->addNode(tmpVector);
231          tmpNode = tmpNode->next;
232        }
233    }
234}
235
236/**
237 *  calculates the Position on the curve
238 * @param t The position on the Curve (0<=t<=1)
239 * @return the Position on the Path
240*/
241Vector BezierCurve::calcPos(float t)
242{
243  Vector ret = Vector(0.0,0.0,0.0);
244  if (this->nodeCount >= 3)
245    {
246      PathNode* tmpNode = this->firstNode;
247      double factor = pow(1.0-t,nodeCount-1);
248      while(tmpNode)
249        {
250          ret.x += tmpNode->factor * factor * tmpNode->position.x;
251          ret.y += tmpNode->factor * factor * tmpNode->position.y;
252          ret.z += tmpNode->factor * factor * tmpNode->position.z;
253          factor *= t/(1.0-t); // same as pow but much faster.
254
255          tmpNode = tmpNode->next;
256        }
257    }
258  else if (nodeCount == 2)
259    {
260      ret = this->firstNode->position *(1.0-t);
261      ret = ret + this->firstNode->next->position * t;
262    }
263  else if (nodeCount == 1)
264    ret = this->firstNode->position;
265  return ret;
266}
267
268/**
269 *  Calulates the direction of the Curve at time t.
270 * @param t The time at which to evaluate the curve.
271 * @returns The valuated Vector.
272*/
273Vector BezierCurve::calcDir (float t)
274{
275  return this->dirCurve->calcPos(t);
276}
277
278/**
279 *  Calulates the acceleration (second derivate) of the Curve at time t.
280 * @param t The time at which to evaluate the curve.
281 * @returns The valuated Vector.
282*/
283Vector BezierCurve::calcAcc (float t)
284{
285  return this->dirCurve->getDirCurve()->calcPos(t);
286}
287
288/**
289 *  Calculates the Quaternion needed for our rotations
290 * @param t The time at which to evaluate the cuve.
291 * @returns The evaluated Quaternion.
292*/
293Quaternion BezierCurve::calcQuat (float t)
294{
295  return Quaternion (calcDir(t), Vector(0,0,1));
296}
297
298
299/**
300  \brief returns the Position of the point calculated on the Curve
301  \return a Vector to the calculated position
302*/
303Vector BezierCurve::getPos() const
304{
305  return curvePoint;
306}
Note: See TracBrowser for help on using the repository browser.