Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/parenting/src/curve.cc @ 3349

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

orxonox/branches/parenting: :TrackManager: curves are now being added in a C1-static maner (at least for bezier).

File size: 8.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     
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; // not sure if this really points to NULL!!
43  currentNode->number = (++nodeCount);
44  this->rebuild();
45  return;
46}
47
48/**
49   \brief Finds a Node by its Number, and returns its Position
50   \param nodeToFind the n'th node in the List of nodes
51   \returns A Vector to the Position of the Node.
52*/
53Vector Curve::getNode(unsigned int nodeToFind)
54{
55  if (nodeToFind > this->nodeCount)
56    return Vector(0,0,0);
57  PathNode* tmpNode = this->firstNode;
58  for (int i = 1; i < nodeToFind; i++)
59    tmpNode = tmpNode->next;
60  return tmpNode->position;
61}
62
63///////////////////////////////////
64/// Bezier Curve //////////////////
65///////////////////////////////////
66
67/**
68   \brief Creates a new BezierCurve
69*/
70BezierCurve::BezierCurve (void)
71{
72  this->derivation = 0;
73  dirCurve = new BezierCurve(1);
74  this->init();
75}
76
77/**
78   \brief Creates a new BezierCurve-Derivation-Curve
79*/
80BezierCurve::BezierCurve (int derivation)
81{
82  this->derivation = derivation;
83  dirCurve=NULL;
84  this->init();
85}
86
87/**
88   \brief Deletes a BezierCurve.
89
90   It does this by freeing all the space taken over from the nodes
91*/
92BezierCurve::~BezierCurve(void)
93{
94  PathNode* tmpNode;
95  currentNode = firstNode;
96  while (tmpNode != 0)
97    {
98      tmpNode = currentNode;
99      currentNode = currentNode->next;
100      delete tmpNode;
101    }
102  if (dirCurve)
103    delete dirCurve;
104}
105
106/**
107   \brief Initializes a BezierCurve
108*/
109void BezierCurve::init(void)
110{
111  nodeCount = 0;
112  firstNode = new PathNode;
113  currentNode = firstNode;
114
115  firstNode->position = Vector (.0, .0, .0);
116  firstNode->number = 0;
117  firstNode->next = 0; // not sure if this really points to NULL!!
118
119  return;
120}
121
122/**
123   \brief Rebuilds a Curve
124*/
125void BezierCurve::rebuild(void)
126{
127  PathNode* tmpNode = firstNode;
128
129  // rebuilding the Curve itself
130  float k=0;
131  float n = nodeCount -1;
132  float binCoef = 1;
133  printf("n=%f\n", n);
134  while(tmpNode)
135    {
136      tmpNode->factor = binCoef;
137      printf("bincoef: %f\n", binCoef);
138      if (tmpNode =tmpNode->next)
139        {
140          binCoef *=(n-k)/(k+1);
141          ++k;
142        }
143    }
144
145  // rebuilding the Derivation curve
146  if(this->derivation == 0)
147    {
148      tmpNode = firstNode;
149      delete dirCurve;
150      dirCurve = new BezierCurve(1);
151      while(tmpNode->next)
152        {
153          Vector tmpVector = (tmpNode->next->position)- (tmpNode->position);
154          tmpVector.x*=(float)nodeCount;
155          tmpVector.y*=(float)nodeCount;
156          tmpVector.z*=(float)nodeCount;
157          tmpVector.normalize();
158          this->dirCurve->addNode(tmpVector);
159          tmpNode = tmpNode->next;
160        }
161    }
162}
163
164/**
165   \brief calculates the Position on the curve
166   \param t The position on the Curve (0<=t<=1)
167   \return the Position on the Path
168   \todo implement nodeCount 0,1,2,3
169*/
170Vector BezierCurve::calcPos(float t) 
171{
172  if (nodeCount < 4)
173    {
174      //    if (verbose >= 1)
175      //      printf ("Please define at least 4 nodes, until now you have only defined %i.\n", nodeCount);
176      return Vector(0,0,0);
177    }
178  PathNode* tmpNode = firstNode;
179  Vector ret = Vector(0.0,0.0,0.0);
180  double factor = pow(1.0-t,nodeCount-1);
181  while(tmpNode)
182    {
183      ret.x += tmpNode->factor * factor * tmpNode->position.x;
184      ret.y += tmpNode->factor * factor * tmpNode->position.y;
185      ret.z += tmpNode->factor * factor * tmpNode->position.z;
186      factor *= t/(1.0-t); // same as pow but much faster.
187
188      tmpNode = tmpNode->next;
189    }
190  return ret;
191}
192
193/**
194   \brief Calulates the direction of the Curve at time t.
195   \param The time at which to evaluate the curve.
196   \returns The vvaluated Vector.
197*/
198Vector BezierCurve::calcDir (float t)
199{
200  return dirCurve->calcPos(t);
201}
202
203/**
204   \brief Calculates the Quaternion needed for our rotations
205   \param t The time at which to evaluate the cuve.
206   \returns The evaluated Quaternion.
207*/
208Quaternion BezierCurve::calcQuat (float t)
209{
210  return Quaternion (calcDir(t), Vector(0,0,1));
211}
212
213
214/**
215  \brief returns the Position of the point calculated on the Curve
216  \return a Vector to the calculated position
217*/
218Vector BezierCurve::getPos(void) const
219{
220  return curvePoint;
221}
222
223
224
225///////////////////////////////////
226//// Uniform Point curve  /////////
227///////////////////////////////////
228/**
229   \brief Creates a new UPointCurve
230*/
231UPointCurve::UPointCurve (void)
232{
233  this->derivation = 0;
234  this->init();
235}
236
237/**
238   \brief Creates a new UPointCurve-Derivation-Curve of deriavation'th degree
239*/
240UPointCurve::UPointCurve (int derivation)
241{
242  this->derivation = derivation;
243  dirCurve=NULL;
244  this->init();
245}
246
247/**
248   \brief Deletes a UPointCurve.
249
250   It does this by freeing all the space taken over from the nodes
251*/
252UPointCurve::~UPointCurve(void)
253{
254  PathNode* tmpNode;
255  currentNode = firstNode;
256  while (tmpNode != 0)
257    {
258      tmpNode = currentNode;
259      currentNode = currentNode->next;
260      delete tmpNode;
261    }
262  if (dirCurve)
263    delete dirCurve;
264}
265
266/**
267   \brief Initializes a UPointCurve
268*/
269void UPointCurve::init(void)
270{
271  nodeCount = 0;
272  firstNode = new PathNode;
273  currentNode = firstNode;
274
275  firstNode->position = Vector (.0, .0, .0);
276  firstNode->number = 0;
277  firstNode->next = 0; // not sure if this really points to NULL!!
278
279  return;
280}
281
282/**
283   \brief Rebuilds a UPointCurve
284   
285   \todo very bad algorithm
286*/
287void UPointCurve::rebuild(void)
288{
289  // rebuilding the Curve itself
290  PathNode* tmpNode = this->firstNode;
291  int i=0;
292  Matrix xTmpMat = Matrix(this->nodeCount, this->nodeCount);
293  Matrix yTmpMat = Matrix(this->nodeCount, this->nodeCount);
294  Matrix zTmpMat = Matrix(this->nodeCount, this->nodeCount);
295  Matrix xValMat = Matrix(this->nodeCount, 3);
296  Matrix yValMat = Matrix(this->nodeCount, 3);
297  Matrix zValMat = Matrix(this->nodeCount, 3);
298  while(tmpNode)
299    {
300      Vector fac = Vector(1,1,1);
301      for (int j = 0; j < this->nodeCount; j++)
302        {
303          xTmpMat(i,j) = fac.x; fac.x *= (float)i/(float)this->nodeCount;//tmpNode->position.x;
304          yTmpMat(i,j) = fac.y; fac.y *= (float)i/(float)this->nodeCount;//tmpNode->position.y;
305          zTmpMat(i,j) = fac.z; fac.z *= (float)i/(float)this->nodeCount;//tmpNode->position.z;
306        }
307      xValMat(i,0) = tmpNode->position.x;
308      yValMat(i,0) = tmpNode->position.y;
309      zValMat(i,0) = tmpNode->position.z;
310      ++i;
311      tmpNode = tmpNode->next;
312    }
313  tmpNode = this->firstNode;
314  xValMat = xTmpMat.Inv() *= xValMat;
315  yValMat = yTmpMat.Inv() *= yValMat;
316  zValMat = zTmpMat.Inv() *= zValMat;
317  i = 0;
318  while(tmpNode)
319    {
320      tmpNode->vFactor.x = xValMat(i,0);
321      tmpNode->vFactor.y = yValMat(i,0);
322      tmpNode->vFactor.z = zValMat(i,0);
323
324      i++;
325      tmpNode = tmpNode->next;
326    }
327}
328
329/**
330   \brief calculates the Position on the curve
331   \param t The position on the Curve (0<=t<=1)
332   \return the Position on the Path
333*/
334Vector UPointCurve::calcPos(float t) 
335{
336  PathNode* tmpNode = firstNode;
337  Vector ret = Vector(0.0,0.0,0.0);
338  float factor = 1.0;
339  while(tmpNode)
340    {
341      ret.x += tmpNode->vFactor.x * factor;
342      ret.y += tmpNode->vFactor.y * factor;
343      ret.z += tmpNode->vFactor.z * factor;
344      factor *= t;
345
346      tmpNode = tmpNode->next;
347    }
348  return ret;
349}
350
351/**
352   \brief Calulates the direction of the Curve at time t.
353   \param The time at which to evaluate the curve.
354   \returns The vvaluated Vector.
355*/
356Vector UPointCurve::calcDir (float t)
357{
358  PathNode* tmpNode = firstNode;
359  Vector ret = Vector(0.0,0.0,0.0);
360  float factor = 1.0/t;
361  int k=0;
362  while(tmpNode)
363    {
364      ret.x += tmpNode->vFactor.x * factor *k;
365      ret.y += tmpNode->vFactor.y * factor *k;
366      ret.z += tmpNode->vFactor.z * factor *k;
367      factor *= t;
368      k++;
369      tmpNode = tmpNode->next;
370    }
371  ret.normalize();
372  return ret;
373}
374
375/**
376   \brief Calculates the Quaternion needed for our rotations
377   \param t The time at which to evaluate the cuve.
378   \returns The evaluated Quaternion.
379*/
380Quaternion UPointCurve::calcQuat (float t)
381{
382  return Quaternion (calcDir(t), Vector(0,0,1));
383}
384
385
386/**
387  \brief returns the Position of the point calculated on the Curve
388  \return a Vector to the calculated position
389*/
390Vector UPointCurve::getPos(void) const
391{
392  return curvePoint;
393}
Note: See TracBrowser for help on using the repository browser.