/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2006 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: This is anohter installment of the infamous track system. It serves for temporary use only and is mainly a slimmed version of the old track. The track is used to steer the spaceship. In this case the track will have to control a PNode. The spaceship will be able to fly around this node. The camera will always be focused on that point. As we do this we have exactly the verticalscroller feeling we want. main-programmer: Benjamin Knecht */ #include "util/loading/load_param.h" #include "track/track.h" #include "p_node.h" #include "stdincl.h" #include "debug.h" ObjectListDefinition(Track); // CREATE_FACTORY(Track); /** * standard constructor */ Track::Track() { this->init(); } /** * this is a constructor for use with the xml loading file * @param root xml root element for this object */ Track::Track(const TiXmlElement* root) { this->init(); if (root != NULL) this->loadParams(root); } /** * initializes this class */ void Track::init() { this->curveType = CURVE_BEZIER; // this->startingTime = 0; this->duration = 20; this->endTime = 20; this->width = 10; this->curve = new BezierCurve(); this->trackNode = new PNode(PNode::getNullParent(), PNODE_ALL); this->nodeCount = 0; this->localTime = 0; this->pause = false; } /** * standard destructor */ Track::~Track() { } void Track::loadParams(const TiXmlElement* root) { LOAD_PARAM_START_CYCLE(root, element); { LoadParam_CYCLE(element, "addPoint", this, Track, addPoint) .describe("Adds a new Point to the currently selected TrackElement"); LoadParam_CYCLE(element, "speed", this, Track, setSpeed) .describe("Sets speed of traveling"); LoadParam_CYCLE(element, "mode", this, Track, setMode) .describe("Sets mode of track behavior"); } LOAD_PARAM_END_CYCLE(element); } /** * This function adds a point with its coordinates to the track * @param x * @param y * @param z */ void Track::addPoint(float x, float y, float z) { this->addPointV(Vector (x,y,z)); } /** * This function adds a point to the track as a vector * @param newPoint */ void Track::addPointV(Vector newPoint) { this->curve->addNode(newPoint); if( this->nodeCount == 0) this->trackNode->setAbsCoor(newPoint); this->nodeCount++; // PRINTF(0)("Point added to curve\n"); } /** * This function sets the speed of the trackNode by altering the duration * of the time the trackNode travels on the whole track. This is bad because * the speed depends on the length of the curve. (by getting the curve's length * this function will make a lot more sense) */ void Track::setSpeed(float speed) { this->duration = this->duration/speed; this->speed = speed; } /** * Sets the mode of the track. 0 means wait at the end. 1 means rerun track */ void Track::setMode(int newMode) { this->mode = newMode; } /** * Sets the bool if the track runs (false) or not (true) */ void Track::pauseTrack(bool stop) { this->pause = stop; } /** * We probably doesn't even need this */ //void Track::finalize() //{ // for (int i = 1; i<= trackElemCount ;i++) // { // TrackElement* tmpElem = this->firstTrackElem->findByID(i); // if( tmpElem->childCount > 0) // { // tIterator* iterator = tmpElem->children->getIterator(); // TrackElement* enumElem = iterator->firstElement(); // //TrackElement* enumElem = tmpElem->children->enumerate(); // while (enumElem) // { // // // c1-continuity // enumElem->curve->addNode(enumElem->curve->getNode(0) + // ((enumElem->curve->getNode(0) - // tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-1)) // ),2); // enumElem->nodeCount++; // // c2-continuity // enumElem->curve->addNode((tmpElem->curve->getNode(tmpElem->curve->getNodeCount())- // tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-1)) * 4 + // tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-2), 3); // enumElem->nodeCount++; // PRINTF(5)("accelerations: %d-in: count: %d, %f, %f, %f\n %d-out: count: %d %f, %f, %f\n", // tmpElem->ID, tmpElem->nodeCount, // tmpElem->curve->calcAcc(0.999).x, tmpElem->curve->calcAcc(0.999).y, tmpElem->curve->calcAcc(0.999).z, // enumElem->ID, enumElem->nodeCount, // enumElem->curve->calcAcc(0).x, enumElem->curve->calcAcc(0).y, enumElem->curve->calcAcc(0).z); // // enumElem = iterator->nextElement(); // } // delete iterator; // } // } /*for (int i = 1; i <= trackElemCount;i++) if (this->firstTrackElem->findByID(i)->endTime > this->maxTime) this->maxTime = this->firstTrackElem->findByID(i)->endTime; // very bad implemented :/ */ //} Vector Track::calcPos() const { return this->curve->calcPos(this->localTime/this->duration); } Vector Track::calcDir() const { return this->curve->calcDir(this->localTime/this->duration); } void Track::tick(float dt) { // PRINTF(4)("CurrentTrackID: %d, LocalTime is: %f, timestep is: %f\n", this->currentTrackElem->ID, this->localTime, dt); // if (this->localTime <= this->firstTrackElem->duration) // this->jumpTo(this->localTime); // if (this->localTime <= this->maxTime) // if (this->localTime > this->currentTrackElem->endTime // && this->currentTrackElem->children) // { // if (this->currentTrackElem->jumpTime != 0.0) // this->jumpTo(this->localTime + this->currentTrackElem->jumpTime); // // jump to the next TrackElement and also set the history of the new Element to the old one. // TrackElement* tmpHistoryElem = this->currentTrackElem; // this->currentTrackElem = this->currentTrackElem->getChild(this->choosePath(this->currentTrackElem)); // this->currentTrackElem->history = tmpHistoryElem; // if (this->currentTrackElem->getName()) // { // this->trackText->setText(this->currentTrackElem->getName()); // this->textAnimation->replay(); // } // } if (this->trackNode) { // tmp save float oldTime = this->localTime; if(this->mode == 0) { if(this->localTime < this->duration) this->localTime += dt; } else { this->localTime += dt; if(this->localTime >= this->duration) this->localTime = 0; } Vector tmp = this->calcPos(); Vector dV = tmp - this->trackNode->getAbsCoor(); float dx = speed * dt; float ratio = dx / dV.len(); if( dt > 0.0f) { float newDt = dt * ratio; if(this->pause) newDt = 0; this->localTime = oldTime += newDt; } tmp = this->calcPos(); Vector v(0.0, 1.0, 0.0); Quaternion quat = Quaternion(this->calcDir(), v); Quaternion q(-PI/2, v); quat = quat * q; // move trackNode of the track this->trackNode->shiftCoor(tmp - this->trackNode->getAbsCoor()); // set direction and roll angle of trackNode this->trackNode->setAbsDir(quat); } } /** * @returns the main TrackNode */ PNode* Track::getTrackNode() { return this->trackNode; } /** * Imports a model of the Graph into the OpenGL-environment. * @param dt The Iterator used in seconds for Painting the Graph. This is for testing facility only. Do this if you want to see the Path inside the Level. eventually this will all be packed into a gl-list. */ void Track::drawGraph(float dt) const { glMatrixMode(GL_MODELVIEW); glPushMatrix(); glPushAttrib(GL_ENABLE_BIT); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); glLineWidth(2.0); PNode* node = PNode::getNullParent(); glTranslatef (node->getAbsCoor ().x, node->getAbsCoor ().y, node->getAbsCoor ().z); Vector tmpRot = node->getAbsDir().getSpacialAxis(); glRotatef (node->getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z ); glBegin(GL_LINE_STRIP); glColor3f(1.0, 1.0, 0.6); Vector tmpVector; for(float f = 0.0; f < 1.0; f+=dt) { //PRINTF(0)("drawing",this->calcPos().x, this->calcPos().y, this->calcPos().z); tmpVector = this->curve->calcPos(f); glVertex3f(tmpVector.x, tmpVector.y, tmpVector.z); } glEnd(); glPopAttrib(); glPopMatrix(); }