Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3923 was 3595, checked in by bensch, 20 years ago

orxonox/trunk: deleted the UPOINTCURVE was very bad.
also deleted matrix.cc because of some license problems, and we do not need all the functions (and it can't even work with the vector-class

File size: 6.1 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     tList implementation
22     
23*/
24
25#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_MATH
26
27#include "curve.h"
28
29#include "debug.h"
30
31#include <math.h>
32#include <stdio.h>
33
34
35/**
36    \brief default constructor for a Curve
37*/
38Curve::Curve(void)
39{
40  nodeCount = 0;
41  firstNode = new PathNode;
42  currentNode = firstNode;
43
44  firstNode->position = Vector (.0, .0, .0);
45  firstNode->number = 0;
46  firstNode->next = 0; // not sure if this really points to NULL!!
47}
48
49/**
50   \brief adds a new Node to the bezier Curve
51   \param newNode a Vector to the position of the new node
52*/
53void Curve::addNode(const Vector& newNode)
54{
55  if (nodeCount != 0 )
56    {
57      currentNode = currentNode->next = new PathNode;
58    }
59  currentNode->position = newNode;
60  currentNode->next = 0;
61  currentNode->number = (++nodeCount);
62  this->rebuild();
63  return;
64}
65
66void Curve::addNode(const Vector& newNode, unsigned int insertPosition)
67{
68
69  if (this->nodeCount == 0 || insertPosition > this->nodeCount)
70    return addNode(newNode);
71
72  if (insertPosition == 0)
73    insertPosition = 1;
74
75  PathNode* insNode = new PathNode;
76
77  // relinking
78  PathNode* tmpNode = this->firstNode;
79  if (insertPosition > 1)
80    {
81      while (tmpNode->next->number != insertPosition)
82        tmpNode= tmpNode->next;
83      insNode->next = tmpNode->next;
84      tmpNode->next = insNode;
85    }
86  else
87    {
88      insNode->next = this->firstNode;
89      this->firstNode = insNode;
90    }
91  // renumbering
92  insNode->number = insertPosition;
93  tmpNode = insNode->next;
94  while (tmpNode)
95    {
96      tmpNode->number++;
97      tmpNode = tmpNode->next;
98    }
99
100    // finished
101  insNode->position = newNode;
102  ++nodeCount;
103  this->rebuild();
104  return;
105}
106
107/**
108   \brief Finds a Node by its Number, and returns its Position
109   \param nodeToFind the n'th node in the List of nodes
110   \returns A Vector to the Position of the Node.
111*/
112Vector Curve::getNode(unsigned int nodeToFind)
113{
114  if (nodeToFind > this->nodeCount || nodeToFind < 0)
115    return Vector(0,0,0);
116  PathNode* tmpNode = this->firstNode;
117  for (int i = 1; i < nodeToFind; i++)
118    tmpNode = tmpNode->next;
119  return tmpNode->position;
120}
121
122/**
123   \brief Outputs information about the state of this Curve
124*/
125void Curve::debug(void)
126{
127  printf("<<-------------------------------\n");
128  printf("Curve Information:\n");
129  printf("NodeCount: %d\n", this->nodeCount);
130  PathNode* tmpNode = this->firstNode;
131  while (tmpNode)
132    {
133      printf("node #%d: %f, %f, %f\n", tmpNode->number, tmpNode->position.x, tmpNode->position.y, tmpNode->position.z);
134      tmpNode = tmpNode->next;
135    }
136  printf("------------------------------->>\n");
137}
138
139
140///////////////////////////////////
141/// Bezier Curve //////////////////
142///////////////////////////////////
143
144/**
145   \brief Creates a new BezierCurve
146*/
147BezierCurve::BezierCurve (void)
148{
149  this->derivation = 0;
150  dirCurve = new BezierCurve(1);
151}
152
153/**
154   \brief Creates a new BezierCurve-Derivation-Curve
155*/
156BezierCurve::BezierCurve (int derivation)
157{
158  this->derivation = derivation;
159  dirCurve=NULL;
160}
161
162/**
163   \brief Deletes a BezierCurve.
164
165   It does this by freeing all the space taken over from the nodes
166*/
167BezierCurve::~BezierCurve(void)
168{
169  PathNode* tmpNode;
170  currentNode = firstNode;
171  while (tmpNode != 0)
172    {
173      tmpNode = currentNode;
174      currentNode = currentNode->next;
175      delete tmpNode;
176    }
177  if (dirCurve)
178    delete dirCurve;
179}
180
181/**
182   \brief Rebuilds a Curve
183*/
184void BezierCurve::rebuild(void)
185{
186  PathNode* tmpNode = firstNode;
187
188  // rebuilding the Curve itself
189  float k=0;
190  float n = nodeCount -1;
191  float binCoef = 1;
192  while(tmpNode)
193    {
194      tmpNode->factor = binCoef;
195      if (tmpNode =tmpNode->next)
196        {
197          binCoef *=(n-k)/(k+1);
198          ++k;
199        }
200    }
201
202  // rebuilding the Derivation curve
203  if(this->derivation <= 1)
204    {
205      tmpNode = firstNode;
206      delete dirCurve;
207      dirCurve = new BezierCurve(1);
208      while(tmpNode->next)
209        {
210          Vector tmpVector = (tmpNode->next->position)- (tmpNode->position);
211          tmpVector.x*=(float)nodeCount;
212          tmpVector.y*=(float)nodeCount;
213          tmpVector.z*=(float)nodeCount;
214          tmpVector.normalize();
215          this->dirCurve->addNode(tmpVector);
216          tmpNode = tmpNode->next;
217        }
218    }
219}
220
221/**
222   \brief calculates the Position on the curve
223   \param t The position on the Curve (0<=t<=1)
224   \return the Position on the Path
225*/
226Vector BezierCurve::calcPos(float t) 
227{
228  Vector ret = Vector(0.0,0.0,0.0);
229  if (this->nodeCount >= 3)
230    {
231      PathNode* tmpNode = this->firstNode;
232      double factor = pow(1.0-t,nodeCount-1);
233      while(tmpNode)
234        {
235          ret.x += tmpNode->factor * factor * tmpNode->position.x;
236          ret.y += tmpNode->factor * factor * tmpNode->position.y;
237          ret.z += tmpNode->factor * factor * tmpNode->position.z;
238          factor *= t/(1.0-t); // same as pow but much faster.
239         
240          tmpNode = tmpNode->next;
241        }
242    }
243  else if (nodeCount == 2)
244    {
245      ret = this->firstNode->position *(1.0-t);
246      ret = ret + this->firstNode->next->position * t;
247    }
248  else if (nodeCount == 1)
249    ret = this->firstNode->position;
250  return ret;
251}
252
253/**
254   \brief Calulates the direction of the Curve at time t.
255   \param The time at which to evaluate the curve.
256   \returns The vvaluated Vector.
257*/
258Vector BezierCurve::calcDir (float t)
259{
260  return dirCurve->calcPos(t);
261}
262
263Vector BezierCurve::calcAcc (float t)
264{
265  return dirCurve->dirCurve->calcPos(t);
266}
267
268/**
269   \brief Calculates the Quaternion needed for our rotations
270   \param t The time at which to evaluate the cuve.
271   \returns The evaluated Quaternion.
272*/
273Quaternion BezierCurve::calcQuat (float t)
274{
275  return Quaternion (calcDir(t), Vector(0,0,1));
276}
277
278
279/**
280  \brief returns the Position of the point calculated on the Curve
281  \return a Vector to the calculated position
282*/
283Vector BezierCurve::getPos(void) const
284{
285  return curvePoint;
286}
Note: See TracBrowser for help on using the repository browser.