Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 10114 was 9110, checked in by bensch, 18 years ago

orxonox/trunk: merged the Presentation back

File size: 6.7 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/**
[4836]147 *  Outputs information about the state of this Curve
[3433]148*/
[4746]149void Curve::debug()
[3433]150{
151  printf("<<-------------------------------\n");
152  printf("Curve Information:\n");
153  printf("NodeCount: %d\n", this->nodeCount);
154  PathNode* tmpNode = this->firstNode;
155  while (tmpNode)
156    {
157      printf("node #%d: %f, %f, %f\n", tmpNode->number, tmpNode->position.x, tmpNode->position.y, tmpNode->position.z);
158      tmpNode = tmpNode->next;
159    }
160  printf("------------------------------->>\n");
161}
162
163
[3365]164///////////////////////////////////
165/// Bezier Curve //////////////////
166///////////////////////////////////
167
[3019]168/**
[4836]169 *  Creates a new BezierCurve
[3018]170*/
[4746]171BezierCurve::BezierCurve ()
[3018]172{
[3365]173  this->derivation = 0;
174  dirCurve = new BezierCurve(1);
175}
176
177/**
[4836]178 *  Creates a new BezierCurve-Derivation-Curve
[3365]179*/
180BezierCurve::BezierCurve (int derivation)
181{
182  this->derivation = derivation;
183  dirCurve=NULL;
184}
185
186/**
[4836]187 *  Deletes a BezierCurve.
[3365]188
189   It does this by freeing all the space taken over from the nodes
190*/
[4746]191BezierCurve::~BezierCurve()
[3365]192{
[5231]193
[3365]194}
195
196/**
[4836]197 *  Rebuilds a Curve
[3365]198*/
[4746]199void BezierCurve::rebuild()
[3365]200{
201  PathNode* tmpNode = firstNode;
[3217]202
[3365]203  // rebuilding the Curve itself
[5232]204  float k = 0;
[3365]205  float n = nodeCount -1;
206  float binCoef = 1;
[5232]207  while( tmpNode)
[3365]208    {
209      tmpNode->factor = binCoef;
[5232]210      if( tmpNode = tmpNode->next)
[5211]211        {
[5232]212          binCoef *= (n-k) / (k+1);
[5211]213          ++k;
214        }
[3365]215    }
216
217  // rebuilding the Derivation curve
[5232]218  if( this->derivation <= 1)
[3365]219    {
220      tmpNode = firstNode;
221      delete dirCurve;
222      dirCurve = new BezierCurve(1);
[5232]223      while( tmpNode->next)
[5211]224        {
[5232]225          Vector tmpVector = (tmpNode->next->position) - (tmpNode->position);
[5211]226          tmpVector.x*=(float)nodeCount;
227          tmpVector.y*=(float)nodeCount;
228          tmpVector.z*=(float)nodeCount;
229          tmpVector.normalize();
230          this->dirCurve->addNode(tmpVector);
231          tmpNode = tmpNode->next;
232        }
[3365]233    }
234}
235
236/**
[4836]237 *  calculates the Position on the curve
238 * @param t The position on the Curve (0<=t<=1)
239 * @return the Position on the Path
[3365]240*/
[5211]241Vector BezierCurve::calcPos(float t)
[3365]242{
243  Vector ret = Vector(0.0,0.0,0.0);
244  if (this->nodeCount >= 3)
245    {
246      PathNode* tmpNode = this->firstNode;
247      double factor = pow(1.0-t,nodeCount-1);
248      while(tmpNode)
[5211]249        {
250          ret.x += tmpNode->factor * factor * tmpNode->position.x;
251          ret.y += tmpNode->factor * factor * tmpNode->position.y;
252          ret.z += tmpNode->factor * factor * tmpNode->position.z;
253          factor *= t/(1.0-t); // same as pow but much faster.
254
255          tmpNode = tmpNode->next;
256        }
[3365]257    }
258  else if (nodeCount == 2)
259    {
260      ret = this->firstNode->position *(1.0-t);
261      ret = ret + this->firstNode->next->position * t;
262    }
263  else if (nodeCount == 1)
264    ret = this->firstNode->position;
265  return ret;
266}
267
268/**
[4836]269 *  Calulates the direction of the Curve at time t.
270 * @param t The time at which to evaluate the curve.
271 * @returns The valuated Vector.
[3365]272*/
273Vector BezierCurve::calcDir (float t)
274{
[4472]275  return this->dirCurve->calcPos(t);
[3365]276}
277
[4472]278/**
[4836]279 *  Calulates the acceleration (second derivate) of the Curve at time t.
280 * @param t The time at which to evaluate the curve.
281 * @returns The valuated Vector.
[4472]282*/
[3433]283Vector BezierCurve::calcAcc (float t)
284{
[4472]285  return this->dirCurve->getDirCurve()->calcPos(t);
[3433]286}
287
[3365]288/**
[4836]289 *  Calculates the Quaternion needed for our rotations
290 * @param t The time at which to evaluate the cuve.
291 * @returns The evaluated Quaternion.
[3365]292*/
293Quaternion BezierCurve::calcQuat (float t)
294{
295  return Quaternion (calcDir(t), Vector(0,0,1));
296}
297
298
299/**
300  \brief returns the Position of the point calculated on the Curve
301  \return a Vector to the calculated position
302*/
[4746]303Vector BezierCurve::getPos() const
[3365]304{
305  return curvePoint;
306}
Note: See TracBrowser for help on using the repository browser.