Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/branches/updater: derivation now works too for the UPointCurve

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