Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/trackManager/src/curve.cc @ 3374

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

orxonox/branches/trackManager: deleted old track-system

File size: 8.8 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  while(tmpNode)
134    {
135      tmpNode->factor = binCoef;
136      if (tmpNode =tmpNode->next)
137        {
138          binCoef *=(n-k)/(k+1);
139          ++k;
140        }
141    }
142
143  // rebuilding the Derivation curve
144  if(this->derivation <= 1)
145    {
146      tmpNode = firstNode;
147      delete dirCurve;
148      dirCurve = new BezierCurve(1);
149      while(tmpNode->next)
150        {
151          Vector tmpVector = (tmpNode->next->position)- (tmpNode->position);
152          tmpVector.x*=(float)nodeCount;
153          tmpVector.y*=(float)nodeCount;
154          tmpVector.z*=(float)nodeCount;
155          tmpVector.normalize();
156          this->dirCurve->addNode(tmpVector);
157          tmpNode = tmpNode->next;
158        }
159    }
160}
161
162/**
163   \brief calculates the Position on the curve
164   \param t The position on the Curve (0<=t<=1)
165   \return the Position on the Path
166*/
167Vector BezierCurve::calcPos(float t) 
168{
169  Vector ret = Vector(0.0,0.0,0.0);
170  if (this->nodeCount >= 3)
171    {
172      PathNode* tmpNode = this->firstNode;
173      double factor = pow(1.0-t,nodeCount-1);
174      while(tmpNode)
175        {
176          ret.x += tmpNode->factor * factor * tmpNode->position.x;
177          ret.y += tmpNode->factor * factor * tmpNode->position.y;
178          ret.z += tmpNode->factor * factor * tmpNode->position.z;
179          factor *= t/(1.0-t); // same as pow but much faster.
180         
181          tmpNode = tmpNode->next;
182        }
183    }
184  else if (nodeCount == 2)
185    {
186      ret = this->firstNode->position *(1.0-t);
187      ret = ret + this->firstNode->next->position * t;
188    }
189  else if (nodeCount == 1)
190    ret = this->firstNode->position;
191  return ret;
192}
193
194/**
195   \brief Calulates the direction of the Curve at time t.
196   \param The time at which to evaluate the curve.
197   \returns The vvaluated Vector.
198*/
199Vector BezierCurve::calcDir (float t)
200{
201  return dirCurve->calcPos(t);
202}
203
204Vector BezierCurve::calcAcc (float t)
205{
206  return dirCurve->dirCurve->calcPos(t);
207}
208
209/**
210   \brief Calculates the Quaternion needed for our rotations
211   \param t The time at which to evaluate the cuve.
212   \returns The evaluated Quaternion.
213*/
214Quaternion BezierCurve::calcQuat (float t)
215{
216  return Quaternion (calcDir(t), Vector(0,0,1));
217}
218
219
220/**
221  \brief returns the Position of the point calculated on the Curve
222  \return a Vector to the calculated position
223*/
224Vector BezierCurve::getPos(void) const
225{
226  return curvePoint;
227}
228
229
230
231///////////////////////////////////
232//// Uniform Point curve  /////////
233///////////////////////////////////
234/**
235   \brief Creates a new UPointCurve
236*/
237UPointCurve::UPointCurve (void)
238{
239  this->derivation = 0;
240  this->init();
241}
242
243/**
244   \brief Creates a new UPointCurve-Derivation-Curve of deriavation'th degree
245*/
246UPointCurve::UPointCurve (int derivation)
247{
248  this->derivation = derivation;
249  dirCurve=NULL;
250  this->init();
251}
252
253/**
254   \brief Deletes a UPointCurve.
255
256   It does this by freeing all the space taken over from the nodes
257*/
258UPointCurve::~UPointCurve(void)
259{
260  PathNode* tmpNode;
261  currentNode = firstNode;
262  while (tmpNode != 0)
263    {
264      tmpNode = currentNode;
265      currentNode = currentNode->next;
266      delete tmpNode;
267    }
268  if (dirCurve)
269    delete dirCurve;
270}
271
272/**
273   \brief Initializes a UPointCurve
274*/
275void UPointCurve::init(void)
276{
277  nodeCount = 0;
278  firstNode = new PathNode;
279  currentNode = firstNode;
280
281  firstNode->position = Vector (.0, .0, .0);
282  firstNode->number = 0;
283  firstNode->next = 0; // not sure if this really points to NULL!!
284
285  return;
286}
287
288/**
289   \brief Rebuilds a UPointCurve
290   
291   \todo very bad algorithm
292*/
293void UPointCurve::rebuild(void)
294{
295  // rebuilding the Curve itself
296  PathNode* tmpNode = this->firstNode;
297  int i=0;
298  Matrix xTmpMat = Matrix(this->nodeCount, this->nodeCount);
299  Matrix yTmpMat = Matrix(this->nodeCount, this->nodeCount);
300  Matrix zTmpMat = Matrix(this->nodeCount, this->nodeCount);
301  Matrix xValMat = Matrix(this->nodeCount, 3);
302  Matrix yValMat = Matrix(this->nodeCount, 3);
303  Matrix zValMat = Matrix(this->nodeCount, 3);
304  while(tmpNode)
305    {
306      Vector fac = Vector(1,1,1);
307      for (int j = 0; j < this->nodeCount; j++)
308        {
309          xTmpMat(i,j) = fac.x; fac.x *= (float)i/(float)this->nodeCount;//tmpNode->position.x;
310          yTmpMat(i,j) = fac.y; fac.y *= (float)i/(float)this->nodeCount;//tmpNode->position.y;
311          zTmpMat(i,j) = fac.z; fac.z *= (float)i/(float)this->nodeCount;//tmpNode->position.z;
312        }
313      xValMat(i,0) = tmpNode->position.x;
314      yValMat(i,0) = tmpNode->position.y;
315      zValMat(i,0) = tmpNode->position.z;
316      ++i;
317      tmpNode = tmpNode->next;
318    }
319  tmpNode = this->firstNode;
320  xValMat = xTmpMat.Inv() *= xValMat;
321  yValMat = yTmpMat.Inv() *= yValMat;
322  zValMat = zTmpMat.Inv() *= zValMat;
323  i = 0;
324  while(tmpNode)
325    {
326      tmpNode->vFactor.x = xValMat(i,0);
327      tmpNode->vFactor.y = yValMat(i,0);
328      tmpNode->vFactor.z = zValMat(i,0);
329
330      i++;
331      tmpNode = tmpNode->next;
332    }
333}
334
335/**
336   \brief calculates the Position on the curve
337   \param t The position on the Curve (0<=t<=1)
338   \return the Position on the Path
339*/
340Vector UPointCurve::calcPos(float t) 
341{
342  PathNode* tmpNode = firstNode;
343  Vector ret = Vector(0.0,0.0,0.0);
344  float factor = 1.0;
345  while(tmpNode)
346    {
347      ret.x += tmpNode->vFactor.x * factor;
348      ret.y += tmpNode->vFactor.y * factor;
349      ret.z += tmpNode->vFactor.z * factor;
350      factor *= t;
351
352      tmpNode = tmpNode->next;
353    }
354  return ret;
355}
356
357/**
358   \brief Calulates the direction of the Curve at time t.
359   \param The time at which to evaluate the curve.
360   \returns The vvaluated Vector.
361*/
362Vector UPointCurve::calcDir (float t)
363{
364  PathNode* tmpNode = firstNode;
365  Vector ret = Vector(0.0,0.0,0.0);
366  float factor = 1.0/t;
367  int k=0;
368  while(tmpNode)
369    {
370      ret.x += tmpNode->vFactor.x * factor *k;
371      ret.y += tmpNode->vFactor.y * factor *k;
372      ret.z += tmpNode->vFactor.z * factor *k;
373      factor *= t;
374      k++;
375      tmpNode = tmpNode->next;
376    }
377  ret.normalize();
378  return ret;
379}
380
381Vector UPointCurve::calcAcc (float t)
382{
383}
384
385/**
386   \brief Calculates the Quaternion needed for our rotations
387   \param t The time at which to evaluate the cuve.
388   \returns The evaluated Quaternion.
389*/
390Quaternion UPointCurve::calcQuat (float t)
391{
392  return Quaternion (calcDir(t), Vector(0,0,1));
393}
394
395
396/**
397  \brief returns the Position of the point calculated on the Curve
398  \return a Vector to the calculated position
399*/
400Vector UPointCurve::getPos(void) const
401{
402  return curvePoint;
403}
Note: See TracBrowser for help on using the repository browser.