Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: hunted a valgrind error msg in the curve class, restructured the code to delete only local variables not external

File size: 6.6 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/**
71 *  adds a new Node to the bezier Curve
72 * @param newNode a Vector to the position of the new node
73*/
74void Curve::addNode(const Vector& newNode)
75{
76  if (nodeCount != 0 )
77    {
78      currentNode = currentNode->next = new PathNode;
79    }
80  currentNode->position = newNode;
81  currentNode->next = 0;
82  currentNode->number = (++nodeCount);
83  this->rebuild();
84  return;
85}
86
87/**
88 *  adds a new Node to the bezier Curve
89 * @param newNode a Vector to the position of the new node
90 * @param insertPosition after the n-th node the new node will be inserted
91*/
92void Curve::addNode(const Vector& newNode, unsigned int insertPosition)
93{
94  if (this->nodeCount == 0 || insertPosition > this->nodeCount)
95    return addNode(newNode);
96
97  if (insertPosition == 0)
98    insertPosition = 1;
99
100  PathNode* insNode = new PathNode;
101
102  // relinking
103  PathNode* tmpNode = this->firstNode;
104  if (insertPosition > 1)
105    {
106      while (tmpNode->next->number != insertPosition)
107        tmpNode= tmpNode->next;
108      insNode->next = tmpNode->next;
109      tmpNode->next = insNode;
110    }
111  else
112    {
113      insNode->next = this->firstNode;
114      this->firstNode = insNode;
115    }
116  // renumbering
117  insNode->number = insertPosition;
118  tmpNode = insNode->next;
119  while (tmpNode)
120    {
121      tmpNode->number++;
122      tmpNode = tmpNode->next;
123    }
124
125    // finished
126  insNode->position = newNode;
127  ++nodeCount;
128  this->rebuild();
129  return;
130}
131
132/**
133 *  Finds a Node by its Number, and returns its Position
134 * @param nodeToFind the n'th node in the List of nodes
135 * @returns A Vector to the Position of the Node.
136*/
137Vector Curve::getNode(unsigned int nodeToFind)
138{
139  if (nodeToFind > this->nodeCount || nodeToFind < 0)
140    return Vector(0,0,0);
141  PathNode* tmpNode = this->firstNode;
142  for (int i = 1; i < nodeToFind; i++)
143    tmpNode = tmpNode->next;
144  return tmpNode->position;
145}
146
147/**
148 *  Outputs information about the state of this Curve
149*/
150void Curve::debug()
151{
152  printf("<<-------------------------------\n");
153  printf("Curve Information:\n");
154  printf("NodeCount: %d\n", this->nodeCount);
155  PathNode* tmpNode = this->firstNode;
156  while (tmpNode)
157    {
158      printf("node #%d: %f, %f, %f\n", tmpNode->number, tmpNode->position.x, tmpNode->position.y, tmpNode->position.z);
159      tmpNode = tmpNode->next;
160    }
161  printf("------------------------------->>\n");
162}
163
164
165///////////////////////////////////
166/// Bezier Curve //////////////////
167///////////////////////////////////
168
169/**
170 *  Creates a new BezierCurve
171*/
172BezierCurve::BezierCurve ()
173{
174  this->derivation = 0;
175  dirCurve = new BezierCurve(1);
176}
177
178/**
179 *  Creates a new BezierCurve-Derivation-Curve
180*/
181BezierCurve::BezierCurve (int derivation)
182{
183  this->derivation = derivation;
184  dirCurve=NULL;
185}
186
187/**
188 *  Deletes a BezierCurve.
189
190   It does this by freeing all the space taken over from the nodes
191*/
192BezierCurve::~BezierCurve()
193{
194
195}
196
197/**
198 *  Rebuilds a Curve
199*/
200void BezierCurve::rebuild()
201{
202  PathNode* tmpNode = firstNode;
203
204  // rebuilding the Curve itself
205  float k=0;
206  float n = nodeCount -1;
207  float binCoef = 1;
208  while(tmpNode)
209    {
210      tmpNode->factor = binCoef;
211      if (tmpNode =tmpNode->next)
212        {
213          binCoef *=(n-k)/(k+1);
214          ++k;
215        }
216    }
217
218  // rebuilding the Derivation curve
219  if(this->derivation <= 1)
220    {
221      tmpNode = firstNode;
222      delete dirCurve;
223      dirCurve = new BezierCurve(1);
224      while(tmpNode->next)
225        {
226          Vector tmpVector = (tmpNode->next->position)- (tmpNode->position);
227          tmpVector.x*=(float)nodeCount;
228          tmpVector.y*=(float)nodeCount;
229          tmpVector.z*=(float)nodeCount;
230          tmpVector.normalize();
231          this->dirCurve->addNode(tmpVector);
232          tmpNode = tmpNode->next;
233        }
234    }
235}
236
237/**
238 *  calculates the Position on the curve
239 * @param t The position on the Curve (0<=t<=1)
240 * @return the Position on the Path
241*/
242Vector BezierCurve::calcPos(float t)
243{
244  Vector ret = Vector(0.0,0.0,0.0);
245  if (this->nodeCount >= 3)
246    {
247      PathNode* tmpNode = this->firstNode;
248      double factor = pow(1.0-t,nodeCount-1);
249      while(tmpNode)
250        {
251          ret.x += tmpNode->factor * factor * tmpNode->position.x;
252          ret.y += tmpNode->factor * factor * tmpNode->position.y;
253          ret.z += tmpNode->factor * factor * tmpNode->position.z;
254          factor *= t/(1.0-t); // same as pow but much faster.
255
256          tmpNode = tmpNode->next;
257        }
258    }
259  else if (nodeCount == 2)
260    {
261      ret = this->firstNode->position *(1.0-t);
262      ret = ret + this->firstNode->next->position * t;
263    }
264  else if (nodeCount == 1)
265    ret = this->firstNode->position;
266  return ret;
267}
268
269/**
270 *  Calulates the direction of the Curve at time t.
271 * @param t The time at which to evaluate the curve.
272 * @returns The valuated Vector.
273*/
274Vector BezierCurve::calcDir (float t)
275{
276  return this->dirCurve->calcPos(t);
277}
278
279/**
280 *  Calulates the acceleration (second derivate) of the Curve at time t.
281 * @param t The time at which to evaluate the curve.
282 * @returns The valuated Vector.
283*/
284Vector BezierCurve::calcAcc (float t)
285{
286  return this->dirCurve->getDirCurve()->calcPos(t);
287}
288
289/**
290 *  Calculates the Quaternion needed for our rotations
291 * @param t The time at which to evaluate the cuve.
292 * @returns The evaluated Quaternion.
293*/
294Quaternion BezierCurve::calcQuat (float t)
295{
296  return Quaternion (calcDir(t), Vector(0,0,1));
297}
298
299
300/**
301  \brief returns the Position of the point calculated on the Curve
302  \return a Vector to the calculated position
303*/
304Vector BezierCurve::getPos() const
305{
306  return curvePoint;
307}
Note: See TracBrowser for help on using the repository browser.