Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/trackManager/src/lib/math/curve.cc @ 3517

Last change on this file since 3517 was 3517, checked in by bensch, 19 years ago

orxonox/branches/trackManager: some doxygen-tags.

File size: 10.4 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     
22*/
23
24#include "curve.h"
25#include "matrix.h"
26#include "debug.h"
27
28#include <math.h>
29#include <stdio.h>
30
31/**
32   \brief adds a new Node to the bezier Curve
33   \param newNode a Vector to the position of the new node
34*/
35void Curve::addNode(const Vector& newNode)
36{
37  if (nodeCount != 0 )
38    {
39      currentNode = currentNode->next = new PathNode;
40    }
41  currentNode->position = newNode;
42  currentNode->next = 0;
43  currentNode->number = (++nodeCount);
44  this->rebuild();
45  return;
46}
47
48/**
49   \brief adds a new Node to the bezier Curve ath Position insertPosition
50   \param insertPosition The Position on the Path to insert the node.
51   \param newNode a Vector to the position of the new node
52*/
53void Curve::addNode(const Vector& newNode, unsigned int insertPosition)
54{
55
56  if (this->nodeCount == 0 || insertPosition > this->nodeCount)
57    return addNode(newNode);
58
59  if (insertPosition == 0)
60    insertPosition = 1;
61
62  PathNode* insNode = new PathNode;
63
64  // relinking
65  PathNode* tmpNode = this->firstNode;
66  if (insertPosition > 1)
67    {
68      while (tmpNode->next->number != insertPosition)
69        tmpNode= tmpNode->next;
70      insNode->next = tmpNode->next;
71      tmpNode->next = insNode;
72    }
73  else
74    {
75      insNode->next = this->firstNode;
76      this->firstNode = insNode;
77    }
78  // renumbering
79  insNode->number = insertPosition;
80  tmpNode = insNode->next;
81  while (tmpNode)
82    {
83      tmpNode->number++;
84      tmpNode = tmpNode->next;
85    }
86
87    // finished
88  insNode->position = newNode;
89  ++nodeCount;
90  this->rebuild();
91  return;
92}
93
94/**
95   \brief Finds a Node by its Number, and returns its Position
96   \param nodeToFind the n'th node in the List of nodes
97   \returns A Vector to the Position of the Node.
98*/
99Vector Curve::getNode(unsigned int nodeToFind)
100{
101  if (nodeToFind > this->nodeCount || nodeToFind < 0)
102    return Vector(0,0,0);
103  PathNode* tmpNode = this->firstNode;
104  for (int i = 1; i < nodeToFind; i++)
105    tmpNode = tmpNode->next;
106  return tmpNode->position;
107}
108
109/**
110   \brief Outputs information about the state of this Curve
111*/
112void Curve::debug(void)
113{
114  printf("<<-------------------------------\n");
115  printf("Curve Information:\n");
116  printf("NodeCount: %d\n", this->nodeCount);
117  PathNode* tmpNode = this->firstNode;
118  while (tmpNode)
119    {
120      printf("node #%d: %f, %f, %f\n", tmpNode->number, tmpNode->position.x, tmpNode->position.y, tmpNode->position.z);
121      tmpNode = tmpNode->next;
122    }
123  printf("------------------------------->>\n");
124}
125
126
127///////////////////////////////////
128/// Bezier Curve //////////////////
129///////////////////////////////////
130
131/**
132   \brief Creates a new BezierCurve
133*/
134BezierCurve::BezierCurve (void)
135{
136  this->derivation = 0;
137  dirCurve = new BezierCurve(1);
138  this->init();
139}
140
141/**
142   \brief Creates a new BezierCurve-Derivation-Curve
143*/
144BezierCurve::BezierCurve (int derivation)
145{
146  this->derivation = derivation;
147  dirCurve=NULL;
148  this->init();
149}
150
151/**
152   \brief Deletes a BezierCurve.
153
154   It does this by freeing all the space taken over from the nodes
155*/
156BezierCurve::~BezierCurve(void)
157{
158  PathNode* tmpNode;
159  currentNode = firstNode;
160  while (tmpNode != 0)
161    {
162      tmpNode = currentNode;
163      currentNode = currentNode->next;
164      delete tmpNode;
165    }
166  if (dirCurve)
167    delete dirCurve;
168}
169
170/**
171   \brief Initializes a BezierCurve
172*/
173void BezierCurve::init(void)
174{
175  nodeCount = 0;
176  firstNode = new PathNode;
177  currentNode = firstNode;
178
179  firstNode->position = Vector (.0, .0, .0);
180  firstNode->number = 0;
181  firstNode->next = 0; // not sure if this really points to NULL!!
182
183  return;
184}
185
186/**
187   \brief Rebuilds a Curve
188*/
189void BezierCurve::rebuild(void)
190{
191  PathNode* tmpNode = firstNode;
192
193  // rebuilding the Curve itself
194  float k=0;
195  float n = nodeCount -1;
196  float binCoef = 1;
197  while(tmpNode)
198    {
199      tmpNode->factor = binCoef;
200      if (tmpNode =tmpNode->next)
201        {
202          binCoef *=(n-k)/(k+1);
203          ++k;
204        }
205    }
206
207  // rebuilding the Derivation curve
208  if(this->derivation <= 1)
209    {
210      tmpNode = firstNode;
211      delete dirCurve;
212      dirCurve = new BezierCurve(1);
213      while(tmpNode->next)
214        {
215          Vector tmpVector = (tmpNode->next->position)- (tmpNode->position);
216          tmpVector.x*=(float)nodeCount;
217          tmpVector.y*=(float)nodeCount;
218          tmpVector.z*=(float)nodeCount;
219          tmpVector.normalize();
220          this->dirCurve->addNode(tmpVector);
221          tmpNode = tmpNode->next;
222        }
223    }
224}
225
226/**
227   \brief calculates the Position on the curve
228   \param t The position on the Curve (0<=t<=1)
229   \return the Position on the Path
230*/
231Vector BezierCurve::calcPos(float t) 
232{
233  Vector ret = Vector(0.0,0.0,0.0);
234  if (this->nodeCount >= 3)
235    {
236      PathNode* tmpNode = this->firstNode;
237      double factor = pow(1.0-t,nodeCount-1);
238      while(tmpNode)
239        {
240          ret.x += tmpNode->factor * factor * tmpNode->position.x;
241          ret.y += tmpNode->factor * factor * tmpNode->position.y;
242          ret.z += tmpNode->factor * factor * tmpNode->position.z;
243          factor *= t/(1.0-t); // same as pow but much faster.
244         
245          tmpNode = tmpNode->next;
246        }
247    }
248  else if (nodeCount == 2)
249    {
250      ret = this->firstNode->position *(1.0-t);
251      ret = ret + this->firstNode->next->position * t;
252    }
253  else if (nodeCount == 1)
254    ret = this->firstNode->position;
255  return ret;
256}
257
258/**
259   \brief Calulates the direction of the Curve at time t.
260   \param t The time at which to evaluate the curve.
261   \returns The Directional Vector.
262*/
263Vector BezierCurve::calcDir (float t)
264{
265  return dirCurve->calcPos(t);
266}
267
268/**
269   \brief Calulates the acceleration of the Curve at time t.
270   \param t The time at which to evaluate the curve.
271   \returns The acceleration-Vector.
272*/
273Vector BezierCurve::calcAcc (float t)
274{
275  return dirCurve->dirCurve->calcPos(t);
276}
277
278/**
279   \brief Calculates the Quaternion needed for our rotations
280   \param t The time at which to evaluate the cuve.
281   \returns The evaluated Quaternion.
282*/
283Quaternion BezierCurve::calcQuat (float t)
284{
285  return Quaternion (calcDir(t), Vector(0,0,1));
286}
287
288
289/**
290  \brief returns the Position of the point calculated on the Curve
291  \return a Vector to the calculated position
292*/
293Vector BezierCurve::getPos(void) const
294{
295  return curvePoint;
296}
297
298
299
300///////////////////////////////////
301//// Uniform Point curve  /////////
302///////////////////////////////////
303/**
304   \brief Creates a new UPointCurve
305*/
306UPointCurve::UPointCurve (void)
307{
308  this->derivation = 0;
309  this->init();
310}
311
312/**
313   \brief Creates a new UPointCurve-Derivation-Curve of deriavation'th degree
314*/
315UPointCurve::UPointCurve (int derivation)
316{
317  this->derivation = derivation;
318  dirCurve=NULL;
319  this->init();
320}
321
322/**
323   \brief Deletes a UPointCurve.
324
325   It does this by freeing all the space taken over from the nodes
326*/
327UPointCurve::~UPointCurve(void)
328{
329  PathNode* tmpNode;
330  currentNode = firstNode;
331  while (tmpNode != 0)
332    {
333      tmpNode = currentNode;
334      currentNode = currentNode->next;
335      delete tmpNode;
336    }
337  if (dirCurve)
338    delete dirCurve;
339}
340
341/**
342   \brief Initializes a UPointCurve
343*/
344void UPointCurve::init(void)
345{
346  nodeCount = 0;
347  firstNode = new PathNode;
348  currentNode = firstNode;
349
350  firstNode->position = Vector (.0, .0, .0);
351  firstNode->number = 0;
352  firstNode->next = 0; // not sure if this really points to NULL!!
353
354  return;
355}
356
357/**
358   \brief Rebuilds a UPointCurve
359   
360   \todo very bad algorithm
361*/
362void UPointCurve::rebuild(void)
363{
364  // rebuilding the Curve itself
365  PathNode* tmpNode = this->firstNode;
366  int i=0;
367  Matrix xTmpMat = Matrix(this->nodeCount, this->nodeCount);
368  Matrix yTmpMat = Matrix(this->nodeCount, this->nodeCount);
369  Matrix zTmpMat = Matrix(this->nodeCount, this->nodeCount);
370  Matrix xValMat = Matrix(this->nodeCount, 3);
371  Matrix yValMat = Matrix(this->nodeCount, 3);
372  Matrix zValMat = Matrix(this->nodeCount, 3);
373  while(tmpNode)
374    {
375      Vector fac = Vector(1,1,1);
376      for (int j = 0; j < this->nodeCount; j++)
377        {
378          xTmpMat(i,j) = fac.x; fac.x *= (float)i/(float)this->nodeCount;//tmpNode->position.x;
379          yTmpMat(i,j) = fac.y; fac.y *= (float)i/(float)this->nodeCount;//tmpNode->position.y;
380          zTmpMat(i,j) = fac.z; fac.z *= (float)i/(float)this->nodeCount;//tmpNode->position.z;
381        }
382      xValMat(i,0) = tmpNode->position.x;
383      yValMat(i,0) = tmpNode->position.y;
384      zValMat(i,0) = tmpNode->position.z;
385      ++i;
386      tmpNode = tmpNode->next;
387    }
388  tmpNode = this->firstNode;
389  xValMat = xTmpMat.Inv() *= xValMat;
390  yValMat = yTmpMat.Inv() *= yValMat;
391  zValMat = zTmpMat.Inv() *= zValMat;
392  i = 0;
393  while(tmpNode)
394    {
395      tmpNode->vFactor.x = xValMat(i,0);
396      tmpNode->vFactor.y = yValMat(i,0);
397      tmpNode->vFactor.z = zValMat(i,0);
398
399      i++;
400      tmpNode = tmpNode->next;
401    }
402}
403
404/**
405   \brief calculates the Position on the curve
406   \param t The position on the Curve (0<=t<=1)
407   \return the Position on the Path
408*/
409Vector UPointCurve::calcPos(float t) 
410{
411  PathNode* tmpNode = firstNode;
412  Vector ret = Vector(0.0,0.0,0.0);
413  float factor = 1.0;
414  while(tmpNode)
415    {
416      ret.x += tmpNode->vFactor.x * factor;
417      ret.y += tmpNode->vFactor.y * factor;
418      ret.z += tmpNode->vFactor.z * factor;
419      factor *= t;
420
421      tmpNode = tmpNode->next;
422    }
423  return ret;
424}
425
426/**
427   \brief Calulates the direction of the Curve at time t.
428   \param t The time at which to evaluate the curve.
429   \returns The vvaluated Vector.
430*/
431Vector UPointCurve::calcDir (float t)
432{
433  PathNode* tmpNode = firstNode;
434  Vector ret = Vector(0.0,0.0,0.0);
435  float factor = 1.0/t;
436  int k=0;
437  while(tmpNode)
438    {
439      ret.x += tmpNode->vFactor.x * factor *k;
440      ret.y += tmpNode->vFactor.y * factor *k;
441      ret.z += tmpNode->vFactor.z * factor *k;
442      factor *= t;
443      k++;
444      tmpNode = tmpNode->next;
445    }
446  ret.normalize();
447  return ret;
448}
449
450Vector UPointCurve::calcAcc (float t)
451{
452}
453
454/**
455   \brief Calculates the Quaternion needed for our rotations
456   \param t The time at which to evaluate the cuve.
457   \returns The evaluated Quaternion.
458*/
459Quaternion UPointCurve::calcQuat (float t)
460{
461  return Quaternion (calcDir(t), Vector(0,0,1));
462}
463
464
465/**
466  \brief returns the Position of the point calculated on the Curve
467  \return a Vector to the calculated position
468*/
469Vector UPointCurve::getPos(void) const
470{
471  return curvePoint;
472}
Note: See TracBrowser for help on using the repository browser.