Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/branches/parenting: :TrackManager: forking works.

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