/* 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: Trail system for engine output trails. uses a catmull rom spline to interpolate the curve which is subdivided into sections parts. main-programmer: Marc Schaerer */ #include "trail.h" #include "util/loading/load_param.h" #include "util/loading/factory.h" #include "quaternion.h" #include "vector.h" #include "graphics_engine.h" #include "material.h" #include "glincl.h" #include "state.h" #include "debug.h" #include "class_id_DEPRECATED.h" ObjectListDefinition(Trail); CREATE_FACTORY(Trail); /** * standart constructor * @param maxLength maximum length of the trail. You will later need to set the actual length used. * @param sections number of sections into which the trail polygon shall be splited. Higher number for more smooth curves * @param radius radius of the trail cross. * */ Trail::Trail (float maxLength, int sections, float radius) { this->maxLength = maxLength; this->length = 1.0; this->sections = sections; this->radius = radius; this->nodeList = new Vector[sections]; this->init(); } Trail::Trail (const TiXmlElement* root) { this->init(); if( root) this->loadParams(root); } /** * destroys a Trail */ Trail::~Trail () { if (this->material) delete this->material; delete this->nodeList; } /** * initializes the Trail */ void Trail::init() { this->registerObject(this, Trail::_objectList); this->setName("Trail"); this->material = new Material(); this->material->setIllum(3); this->material->setDiffuse(1.0,1.0,1.0); this->material->setSpecular(0.0,0.0,0.0); this->material->setAmbient(1.0, 1.0, 1.0); this->setAbsCoor(0, 0, 0); this->setVisibiliy(true); this->nodeList[0] = (this->getAbsCoor()); //PRINTF(0)("Trail data: N%i (%f,%f,%f)",0,this->getAbsCoor().x,this->getAbsCoor().y,this->getAbsCoor().z); for( int i = 1; i < sections; i++) { this->nodeList[i] = (this->getAbsCoor() - ((Vector(1,0,0) * (i * this->maxLength / sections)))); //PRINTF(0)(" N%i (%f,%f,%f)",i,this->nodeList[i].x,this->nodeList[i].y,this->nodeList[i].z); } //PRINTF(0)("\n"); } /** * load params * @param root TiXmlElement object */ void Trail::loadParams(const TiXmlElement* root) { WorldEntity::loadParams( root); } /** * sets the material to load * @param textureFile The texture-file to load */ void Trail::setTexture(const std::string& textureFile) { this->material->setDiffuseMap(textureFile); } /** * ticks the Trail * @param dt the time to ticks */ void Trail::tick(float dt) { // Update node positions float secLen = this->maxLength / this->sections; this->nodeList[0] = (this->getAbsCoor()); for(int i = 1; i < this->sections; i++) { this->nodeList[i] = this->nodeList[i-1] - (this->nodeList[i-1] - this->nodeList[i]).getNormalized()*secLen; } /* this->length = this->maxLength / (this->getAbsCoor() - this->nodeList[this->sections-1]).len(); if (!likely(this->length == 1.0)) for(int i = 1; i < this->sections; i++) this->nodeList[i] = this->getAbsCoor()- (this->getAbsCoor() - this->nodeList[i])*this->length; */ /*PRINTF(0)("TRAIL POS "); for( int i=0; i < this->sections; i++) { PRINTF(0)("N%i (%f,%f,%f)",i,this->nodeList[i].x,this->nodeList[i].y,this->nodeList[i].z); } PRINTF(0)("\n");*/ } /** * draws the trail * the trail has a cone shape */ void Trail::draw() const { if(!this->isVisible()) return; Vector* Q = new Vector[4]; Vector targ; Vector now, later; float fact = 1.0/this->sections; float rad0, rad1; //glPushAttrib(GL_ENABLE_BIT); glPushMatrix(); //glMatrixMode(GL_MODELVIEW); //glLoadIdentity(); glTranslatef(-this->getAbsCoor().x,-this->getAbsCoor().y,-this->getAbsCoor().z); glScalef(1,1,1); this->material->select(); /* glBegin(GL_TRIANGLESTRIP); for( int i = 0; i < this->sections-1; i++) { rad1 = this->radius * (1.0-i*fact); rad0 = this->radius * (1.0-(i+1)*fact); now = this->nodeList[i]; later = this->nodeList[i+1]; if( i == 0) targ = this->getAbsDir().apply(Vector(1,0,0)).getNormalized(); else targ = (this->getAbsCoor() - now).getNormalized(); // vertical polygon Q[0] = now + Vector(0,rad1,0) ; Q[1] = later + Vector(0,rad0,0) ; Q[2] = later + Vector(0,-rad0,0) ; Q[3] = now + Vector(0,-rad1,0) ; //PRINTF(0)("Debug output: Q0 (%f,%f,%f) :: Q1 (%f,%f,%f) :: Q2 (%f,%f,%f) :: Q3 (%f,%f,%f)\n",Q[0].x,Q[0].y,Q[0].z,Q[1].x,Q[1].y,Q[1].z,Q[2].x,Q[2].y,Q[2].z,Q[3].x,Q[3].y,Q[3].z); glTexCoord2f(0.0f, 0.0f); glVertex3f(Q[0].x,Q[0].y,Q[0].z); glTexCoord2f(0.0f, 1.0f); glVertex3f(Q[1].x,Q[1].y,Q[1].z); glTexCoord2f(1.0f, 1.0f); glVertex3f(Q[2].x,Q[2].y,Q[2].z); glTexCoord2f(1.0f, 0.0f); glVertex3f(Q[3].x,Q[3].y,Q[3].z); } glEnd(); glBegin(GL_TRIANGLESTRIP); for( int i = 0; i < this->sections-1; i++) { rad1 = this->radius * (1.0-i*fact); rad0 = this->radius * (1.0-(i+1)*fact); now = this->nodeList[i]; later = this->nodeList[i+1]; if( i == 0) targ = this->getAbsDir().apply(Vector(1,0,0)).getNormalized(); else targ = (this->getAbsCoor() - now).getNormalized(); // vertical polygon Q[0] = now + Vector(0,rad1,0) ; Q[1] = later + Vector(0,rad0,0) ; Q[2] = later + Vector(0,-rad0,0) ; Q[3] = now + Vector(0,-rad1,0) ; //PRINTF(0)("Debug output: Q0 (%f,%f,%f) :: Q1 (%f,%f,%f) :: Q2 (%f,%f,%f) :: Q3 (%f,%f,%f)\n",Q[0].x,Q[0].y,Q[0].z,Q[1].x,Q[1].y,Q[1].z,Q[2].x,Q[2].y,Q[2].z,Q[3].x,Q[3].y,Q[3].z); glTexCoord2f(0.0f, 0.0f); glVertex3f(Q[0].x,Q[0].y,Q[0].z); glTexCoord2f(1.0f, 1.0f); glVertex3f(Q[2].x,Q[2].y,Q[2].z); glTexCoord2f(0.0f, 1.0f); glVertex3f(Q[1].x,Q[1].y,Q[1].z); glTexCoord2f(1.0f, 0.0f); glVertex3f(Q[3].x,Q[3].y,Q[3].z); } glEnd();*/ glBegin(GL_TRIANGLE_STRIP); for( int i = 1; i < this->sections-1; i++) { rad1 = this->radius * (1.0-i*fact); rad0 = this->radius * (1.0-(i+1)*fact); now = this->nodeList[i]; later = this->nodeList[i+1]; if( i == 0) targ = this->getAbsDir().apply(Vector(1,0,0)).getNormalized(); else targ = (this->getAbsCoor() - now).getNormalized(); // horizontal polygon Q[0] = now + Vector(0,rad1,0) ; Q[3] = now + Vector(0,-rad1,0) ; glTexCoord2f(0.0f, 0.0f); glVertex3f(Q[0].x,Q[0].y,Q[0].z); glTexCoord2f(1.0f, 0.0f); glVertex3f(Q[3].x,Q[3].y,Q[3].z); if( i == this->sections - 1) { Q[1] = later + Vector(0,rad0,0) ; Q[2] = later + Vector(0,-rad0,0) ; glTexCoord2f(0.0f, 1.0f); glVertex3f(Q[1].x,Q[1].y,Q[1].z); glTexCoord2f(1.0f, 1.0f); glVertex3f(Q[2].x,Q[2].y,Q[2].z); } } glEnd(); glBegin(GL_TRIANGLE_STRIP); for( int i = this->sections-1; i > 0; i--) { rad1 = this->radius * (1.0-i*fact); rad0 = this->radius * (1.0-(i-1)*fact); now = this->nodeList[i]; later = this->nodeList[i-1]; if( i == 0) targ = this->getAbsDir().apply(Vector(1,0,0)).getNormalized(); else targ = (this->getAbsCoor() - now).getNormalized(); // horizontal polygon Q[0] = now + Vector(0,rad1,0) ; Q[3] = now + Vector(0,-rad1,0) ; glTexCoord2f(1.0f, 0.0f); glVertex3f(Q[3].x,Q[3].y,Q[3].z); glTexCoord2f(0.0f, 0.0f); glVertex3f(Q[0].x,Q[0].y,Q[0].z); if( i == 1) { Q[1] = later + Vector(0,rad0,0) ; Q[2] = later + Vector(0,-rad0,0) ; glTexCoord2f(1.0f, 1.0f); glVertex3f(Q[2].x,Q[2].y,Q[2].z); glTexCoord2f(0.0f, 1.0f); glVertex3f(Q[1].x,Q[1].y,Q[1].z); } } glEnd(); glBegin(GL_TRIANGLE_STRIP); for( int i = 1; i < this->sections-1; i++) { rad1 = this->radius * (1.0-i*fact); rad0 = this->radius * (1.0-(i+1)*fact); now = this->nodeList[i]; later = this->nodeList[i+1]; if( i == 0) targ = this->getAbsDir().apply(Vector(1,0,0)).getNormalized(); else targ = (this->getAbsCoor() - now).getNormalized(); // horizontal polygon Q[0] = now + targ.cross(Vector(0,rad1,0)) ; Q[3] = now + targ.cross(Vector(0,-rad1,0)) ; glTexCoord2f(0.0f, 0.0f); glVertex3f(Q[0].x,Q[0].y,Q[0].z); glTexCoord2f(1.0f, 0.0f); glVertex3f(Q[3].x,Q[3].y,Q[3].z); if( i == this->sections-1) { Q[1] = later + targ.cross(Vector(0,rad0,0)) ; Q[2] = later + targ.cross(Vector(0,-rad0,0)) ; glTexCoord2f(0.0f, 1.0f); glVertex3f(Q[1].x,Q[1].y,Q[1].z); glTexCoord2f(1.0f, 1.0f); glVertex3f(Q[2].x,Q[2].y,Q[2].z); } } glEnd(); glBegin(GL_TRIANGLE_STRIP); for( int i = this->sections-1; i > 0; i--) { rad1 = this->radius * (1.0-i*fact); rad0 = this->radius * (1.0-(i-1)*fact); now = this->nodeList[i]; later = this->nodeList[i-1]; if( i == 0) targ = this->getAbsDir().apply(Vector(1,0,0)).getNormalized(); else targ = (this->getAbsCoor() - now).getNormalized(); // horizontal polygon Q[0] = now + targ.cross(Vector(0,rad1,0)) ; Q[3] = now + targ.cross(Vector(0,-rad1,0)) ; glTexCoord2f(0.0f, 0.0f); glVertex3f(Q[0].x,Q[0].y,Q[0].z); glTexCoord2f(1.0f, 0.0f); glVertex3f(Q[3].x,Q[3].y,Q[3].z); if( i == 1) { Q[1] = later + targ.cross(Vector(0,rad0,0)) ; Q[2] = later + targ.cross(Vector(0,-rad0,0)) ; glTexCoord2f(0.0f, 1.0f); glVertex3f(Q[1].x,Q[1].y,Q[1].z); glTexCoord2f(1.0f, 1.0f); glVertex3f(Q[2].x,Q[2].y,Q[2].z); } } glEnd(); this->material->unselect(); glPopMatrix(); //glPopAttrib(); /* //glTranslatef(this->getAbsCoor().x, this->getAbsCoor().y, this->getAbsCoor().z); //glTranslatef(0,0,0); const PNode* camera = State::getCameraNode(); //!< @todo MUST be different Vector cameraPos = camera->getAbsCoor(); Vector cameraTargetPos = State::getCameraTargetNode()->getAbsCoor(); Vector view = cameraTargetPos - cameraPos; Vector up = Vector(0, 1, 0); up = camera->getAbsDir().apply(up); Vector h = up.cross(view); Vector v = h.cross(view); h.normalize(); v.normalize(); v *= sizeX; h *= sizeY; //v += this->getAbsCoor(); //PRINTF(0)("sizeX: %f sizeY: %f\n", sizeX, sizeY); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(this->getAbsCoor().x - h.x - v.x, this->getAbsCoor().y - h.y - v.y, this->getAbsCoor().z - h.z - v.z); glTexCoord2f(1.0f, 0.0f); glVertex3f( this->getAbsCoor().x + h.x - v.x, this->getAbsCoor().y + h.y - v.y, this->getAbsCoor().z + h.z - v.z); glTexCoord2f(1.0f, 1.0f); glVertex3f(this->getAbsCoor().x + h.x + v.x, this->getAbsCoor().y + h.y + v.y, this->getAbsCoor().z + h.z + v.z); glTexCoord2f(0.0f, 1.0f); glVertex3f(this->getAbsCoor().x - h.x + v.x, this->getAbsCoor().y - h.y + v.y, this->getAbsCoor().z - h.z + v.z); glEnd(); glPopMatrix(); glPopAttrib();*/ }