/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Benjamin Grauer co-programmer: Patrick Boenzli ADD: Patrick Boenzli B-Spline TODO: local-Time implementation NURBS */ #include "curve.h" #include #include /** \brief adds a new Node to the bezier Curve \param newNode a Vector to the position of the new node */ void Curve::addNode(const Vector& newNode) { if (nodeCount != 0 ) { currentNode = currentNode->next = new PathNode; } currentNode->position = newNode; currentNode->next = 0; // not sure if this really points to NULL!! currentNode->number = (++nodeCount); this->rebuild(); return; } /** \brief Creates a new BezierCurve */ BezierCurve::BezierCurve (void) { this->derivation = 0; dirCurve = new BezierCurve(1); this->init(); } /** \brief Creates a new BezierCurve-Derivation-Curve */ BezierCurve::BezierCurve (int derivation) { this->derivation = derivation; dirCurve=NULL; this->init(); } /** \brief Deletes a BezierCurve. It does this by freeing all the space taken over from the nodes */ BezierCurve::~BezierCurve (void) { PathNode* tmpNode; currentNode = firstNode; while (tmpNode != 0) { tmpNode = currentNode; currentNode = currentNode->next; delete tmpNode; } if (dirCurve) delete dirCurve; } /** \brief Initializes a BezierCurve */ void BezierCurve::init(void) { nodeCount = 0; firstNode = new PathNode; currentNode = firstNode; firstNode->position = Vector (.0, .0, .0); firstNode->number = 0; firstNode->next = 0; // not sure if this really points to NULL!! return; } /** \brief Rebuilds a Curve */ void BezierCurve::rebuild(void) { PathNode* tmpNode = firstNode; // rebuilding the Curve itself int k=0; int binCoef = 1; while(tmpNode) { if (k+1 < nodeCount-k) binCoef *=(nodeCount-k)/(k+1); else binCoef /= (k+1)/(nodeCount-k); ++k; tmpNode->factor = binCoef; tmpNode = tmpNode->next; } // rebuilding the Derivation curve if(this->derivation == 0) { tmpNode = firstNode; delete dirCurve; dirCurve = new BezierCurve(1); while(tmpNode->next) { Vector tmpVector = (tmpNode->next->position)- (tmpNode->position); tmpVector.x*=(float)nodeCount; tmpVector.y*=(float)nodeCount; tmpVector.z*=(float)nodeCount; tmpVector.normalize(); this->dirCurve->addNode(tmpVector); tmpNode = tmpNode->next; } } } /** \brief calculates the Position on the curve \param t The position on the Curve (0<=t<=1) \return the Position on the Path */ Vector BezierCurve::calcPos(float t) { if (nodeCount <=4) { // if (verbose >= 1) // printf ("Please define at least 4 nodes, until now you have only defined %i.\n", nodeCount); return Vector(0,0,0); } PathNode* tmpNode = firstNode; Vector ret = Vector(0.0,0.0,0.0); float factor = 1.0*pow(1.0-t,nodeCount); while(tmpNode) { factor *= t/(1.0-t); // same as pow but much faster. ret.x += tmpNode->factor * factor * tmpNode->position.x; ret.y += tmpNode->factor * factor * tmpNode->position.y; ret.z += tmpNode->factor * factor * tmpNode->position.z; tmpNode = tmpNode->next; } return ret; } /** \brief Calulates the direction of the Curve at time t. \param The time at which to evaluate the curve. \returns The vvaluated Vector. */ Vector BezierCurve::calcDir (float t) { return dirCurve->calcPos(t); } /** \brief Calculates the Quaternion needed for our rotations \param t The time at which to evaluate the cuve. \returns The evaluated Quaternion. */ Quaternion BezierCurve::calcQuat (float t) { return Quaternion (calcDir(t), Vector(0,0,1)); } /** \brief returns the Position of the point calculated on the Curve \return a Vector to the calculated position */ Vector BezierCurve::getPos(void) const { return curvePoint; }