Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3340 was 3330, checked in by bensch, 20 years ago

orxonox/branches/parenting: written the Headers for the class TrackManager: this will be a lot of work.

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