Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/lib/math/curve.cc @ 3588

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

orxonox/trunk: name-fix for TrackManager and minor fix in Curve.
There has also been a little fix in the light-class: light is a BaseObject not a World-Entity

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