/* 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 "graphics_engine.h" #include "material.h" #include "glincl.h" #include "state.h" #include "debug.h" #define trailAlphaMax 1.0f #define trailAlphaMin 0.2f 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, PNode* parent) { this->maxLength = maxLength; this->length = 1.0; this->sections = sections; this->radius = radius; this->setParent( parent); 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->setVisibility(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());// - (((this->getParent()->getAbsDir().apply(Vector(1,1,1))).getNormalized() * (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 len = 0; float secLen = this->maxLength / this->sections; this->nodeList[0] = this->getAbsCoor(); this->nodeList[1] = this->getAbsCoor() - ((this->getParent()->getAbsDir().apply(Vector(1,0,0))).getNormalized() * this->maxLength / sections); for(int i = 2; i < this->sections; i++) { len = (this->nodeList[i-1] - this->nodeList[i]).len(); if( secLen < len) len = secLen; this->nodeList[i] = this->nodeList[i-1] - (this->nodeList[i-1] - this->nodeList[i]).getNormalized()*len; } } /** * 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 radzero, radone; glPushAttrib(GL_ENABLE_BIT); glPushMatrix(); //glMatrixMode(GL_MODELVIEW); //glLoadIdentity(); /* glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE); glDisable( GL_ALPHA_TEST);*/ glTranslatef(-this->getAbsCoor().x,-this->getAbsCoor().y,-this->getAbsCoor().z); glScalef(1,1,1); this->material->select(); //float alphaStep = 1.0 / this->sections; glBegin(GL_TRIANGLE_STRIP); // Alpha goes from 1.0 to 0.4 -> alphastep = .6 / this->sections for( int i = 1; i < this->sections-1; i++) { radone = this->radius * (1.0-i*fact + 0.2 * (float)rand()/(float)RAND_MAX); radzero = this->radius * (1.0-(i+1)*fact + 0.2 * (float)rand()/(float)RAND_MAX); 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,radone,0) ; Q[3] = now + Vector(0,-radone,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,radzero,0) ; Q[2] = later + Vector(0,-radzero,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--) { radone = this->radius * (1.0-i*fact + 0.2 * (float)rand()/(float)RAND_MAX); radzero = this->radius * (1.0-(i-1)*fact + 0.2 * (float)rand()/(float)RAND_MAX); 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,radone,0) ; Q[3] = now + Vector(0,-radone,0) ; glTexCoord2f(1.0f, 0.0f); glVertex3f(Q[3].x,Q[3].y,Q[3].z+0.01f); glTexCoord2f(0.0f, 0.0f); glVertex3f(Q[0].x,Q[0].y,Q[0].z+0.01f); if( i == 1) { Q[1] = later + Vector(0,radzero,0) ; Q[2] = later + Vector(0,-radzero,0) ; glTexCoord2f(1.0f, 1.0f); glVertex3f(Q[2].x,Q[2].y,Q[2].z+0.01f); glTexCoord2f(0.0f, 1.0f); glVertex3f(Q[1].x,Q[1].y,Q[1].z+0.01f); } } glEnd(); glBegin(GL_TRIANGLE_STRIP); for( int i = 1; i < this->sections-1; i++) { radone = this->radius * (1.0-i*fact + 0.2 * (float)rand()/(float)RAND_MAX); radzero = this->radius * (1.0-(i+1)*fact + 0.2 * (float)rand()/(float)RAND_MAX); 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,radone,0)) ; Q[3] = now + targ.cross(Vector(0,-radone,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,radzero,0)) ; Q[2] = later + targ.cross(Vector(0,-radzero,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--) { radone = this->radius * (1.0-i*fact + 0.2 * (float)rand()/(float)RAND_MAX); radzero = this->radius * (1.0-(i-1)*fact + 0.2 * (float)rand()/(float)RAND_MAX); 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,radone,0)) ; Q[3] = now + targ.cross(Vector(0,-radone,0)) ; glTexCoord2f(0.0f, 0.0f); glVertex3f(Q[0].x+0.01f,Q[0].y,Q[0].z); glTexCoord2f(1.0f, 0.0f); glVertex3f(Q[3].x+0.01f,Q[3].y,Q[3].z); if( i == 1) { Q[1] = later + targ.cross(Vector(0,radzero,0)) ; Q[2] = later + targ.cross(Vector(0,-radzero,0)) ; glTexCoord2f(0.0f, 1.0f); glVertex3f(Q[1].x+0.01f,Q[1].y,Q[1].z); glTexCoord2f(1.0f, 1.0f); glVertex3f(Q[2].x+0.01f,Q[2].y,Q[2].z); } } glEnd(); this->material->unselect(); glPopMatrix(); glPopAttrib(); }