Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/branches/parenting: fixed major flaw in BezierCurve-calculation. before all BezierCurves started in the Origin. Now they are realy bezier-curves.

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