Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 10672 was 10368, checked in by patrick, 18 years ago

merged the branche playability into the trunk

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