Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: valgrind mem-leak-recovered

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