Logo Search packages:      
Sourcecode: kcometen4 version File versions  Download package

curvecomet.cpp

/***************************************************************************
 *   Copyright (C) 2005 by Peter Müller                                    *
 *   pmueller@cs.tu-berlin.de                                              *
 *   Copyright (C) 2008 by John Stamp <jstamp@users.sourceforge.net>       *
 *                                                                         *
 *   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 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
 ***************************************************************************/
#include "curvecomet.h"

CurveComet::CurveComet(CometenScene * scene, double time, double _lifeTime, 
                       const Vec3f& start, const Vec4f & _acolor, 
                       const Vec4f & _ecolor)
:
Comet(scene, 1.0),
startTime(time),
lifeTime(_lifeTime),
acolor(_acolor),
ecolor(_ecolor)
{
      GLuint tex = scene->textures[T_PARTICLE];

      psystem = new ParticleSystem(time, tex, start, start, 800, 0, 1.5, 2.0,  
                                   true, 400, 0, 5, false, 
                                   4, acolor, ecolor);
      
      decal = new Decal(tex, start, 12.0, 
                        true, Vec3f::UNIT_X, acolor);
      
      createCurve(start);
      numChildren = rand(25, 30);
      destroyed = false;
}

CurveComet::~CurveComet() {
      delete psystem;
      delete decal;
      delete curve;
}

void CurveComet::process(double time, double /*unused*/) {
      position = curve->position((time - startTime) / lifeTime);
      
      if (!destroyed) {
            if (time - startTime > lifeTime) 
                  destroy(time);
      }
      
      decal->setPosition(position);
      psystem->setEmitterPos1(psystem->getEmitterPos2());
      psystem->setEmitterPos2(position);
      psystem->process(time);
      
      if (destroyed) {
            psystem->stop();
      }
}

void CurveComet::render(const Vec3f& campos) {
      if (!destroyed) {
            decal->render(campos);
      }
      psystem->render(campos);
}

void CurveComet::createCurve(const Vec3f& start) {
      Vec3f points[15];
      double bw = scene->getBoxWidth() / 2;
      double bh = scene->getBoxHeight() / 2;
      int n = 15;
      
      points[0] = start;
      for (int k = 1; k < n; k++) {
            points[k] = Vec3f(frand(-bw,bw),frand(-bh,bh),frand(-bw,bw));
      }
      
      Vec3f diff = points[n-1] - points[n-2];
      double l = diff.normalize();
      
      if (l > 200) {
            points[n-1] = points[n-2] + diff * 200;
      }
      
      curve = new Bezier3(points, n);
}

void CurveComet::destroyEffect1(double time, const Vec3f& pos, const Vec3f& vel) {
      Comet* newc;
      Vec3f points[4];
      Vec3f dir, dir2, dir3;
      Vec3f b, c;
      double bw = scene->getBoxWidth()/2;
      double bh = scene->getBoxHeight()/2;
      
      dir = vel;
      dir.normalize();
      Vec3f::generateOrthonormalBasis(dir, b, c);
      points[0] = pos;
      for (int i = 0; i < numChildren; i++) {
            dir2 = Vec3f::Vec3f::randomUnitOnPlane(b,c);
            dir3 = dir.cross(dir2);
            
            points[1] = points[0] + dir2 * 50;
            points[1][0] = clamp<float>(points[1][0], -bw, bw);
            points[1][1] = clamp<float>(points[1][1], -bh, bh);
            points[1][2] = clamp<float>(points[1][2], -bw, bw);
            points[2] = points[0] + dir3 * 50;
            points[2][0] = clamp<float>(points[2][0], -bw, bw);
            points[2][1] = clamp<float>(points[2][1], -bh, bh);
            points[2][2] = clamp<float>(points[2][2], -bw, bw);
            points[3] = points[0] + dir3 * frand(0,5);
            points[3][0] = clamp<float>(points[3][0], -bw, bw);
            points[3][1] = clamp<float>(points[3][1], -bh, bh);
            points[3][2] = clamp<float>(points[3][2], -bw, bw);
            
            newc = new SmallCurveComet(scene, time, frand(2.75, 3.25),  
                                       points, 4, acolor, ecolor);
            scene->addComet(newc);
      }
}

void CurveComet::destroyEffect2(double time, const Vec3f& pos, const Vec3f& /*unused*/) {
      Comet* newc;
      Vec3f points[4];
      Vec3f dir, dir2, dir3;
      double bw = scene->getBoxWidth()/2;
      double bh = scene->getBoxHeight()/2;
      
      points[0] = pos;
      for (int i = 0; i < numChildren; i++) {
            dir = Vec3f::Vec3f::randomUnit();
            Vec3f::generateOrthonormalBasis(dir, dir2, dir3);
            points[1] = points[0] + dir * 10 
                  + Vec3f::randomUnitOnPlane(dir2, dir3) * 35;
            points[1][0] = clamp<float>(points[1][0], -bw, bw);
            points[1][1] = clamp<float>(points[1][1], -bh, bh);
            points[1][2] = clamp<float>(points[1][2], -bw, bw);
            points[2] = points[0]+ dir * 20 
                  + Vec3f::randomUnitOnPlane(dir2, dir3) * 35;
            points[2][0] = clamp<float>(points[2][0], -bw, bw);
            points[2][1] = clamp<float>(points[2][1], -bh, bh);
            points[2][2] = clamp<float>(points[2][2], -bw, bw);
            points[3] = points[0]+ dir * 30 
                  + Vec3f::randomUnitOnPlane(dir2, dir3) * 35;
            points[3][0] = clamp<float>(points[3][0], -bw, bw);
            points[3][1] = clamp<float>(points[3][1], -bh, bh);
            points[3][2] = clamp<float>(points[3][2], -bw, bw);
            
            newc = new SmallCurveComet(scene, time, frand(1.0, 1.25),  
                                       points, 4, acolor, ecolor);
            scene->addComet(newc);
      }
}

void CurveComet::destroyEffect3(double time, const Vec3f& pos, const Vec3f& /*unused*/) {
      Comet* newc;
      Vec3f points[4];
      Vec3f dir, dir2, dir3;
      double bw = scene->getBoxWidth()/2;
      double bh = scene->getBoxHeight()/2;
      
      points[0] = pos;
      for (int i = 0; i < numChildren; i++) {
            dir = Vec3f::Vec3f::randomUnit();
            Vec3f::generateOrthonormalBasis(dir, dir2, dir3);
            dir2 = Vec3f::randomUnitOnPlane(dir2, dir3);
            
            points[1] = points[0] + dir * 50;
            points[1][0] = clamp<float>(points[1][0], -bw, bw);
            points[1][1] = clamp<float>(points[1][1], -bh, bh);
            points[1][2] = clamp<float>(points[1][2], -bw, bw);
            points[2] = points[1] + dir2 * 50;
            points[2][0] = clamp<float>(points[2][0], -bw, bw);
            points[2][1] = clamp<float>(points[2][1], -bh, bh);
            points[2][2] = clamp<float>(points[2][2], -bw, bw);
            points[3] = points[0] + dir2 * 2.5;
            points[3][0] = clamp<float>(points[3][0], -bw, bw);
            points[3][1] = clamp<float>(points[3][1], -bh, bh);
            points[3][2] = clamp<float>(points[3][2], -bw, bw);

            newc = new SmallCurveComet(scene, time, frand(1.75, 1.99),  
                                       points, 4, acolor, ecolor);
            scene->addComet(newc);
      }
}

void CurveComet::destroy(double time) {
      Vec3f pos;
      Vec3f vel;
      Comet* newc;
      
      if (destroyed)
            return;
      
      pos = curve->position((time - startTime) / lifeTime);
      vel = curve->firstDerivate((time - startTime) / lifeTime);
      switch (rand() % 3) {
      case 0:
            destroyEffect1(time, pos, vel);
            break;
      case 1:
            destroyEffect2(time, pos, vel);
            break;
      case 2:
      default:
            destroyEffect3(time, pos, vel);
            break;
      }
      
      newc = new Explosion(scene, time, 1.0, pos, 25*size, 300, acolor, ecolor);
      scene->addComet(newc);
      
      psystem->stop();
      destroyed = true;
}


bool CurveComet::isDestroyed() {
      return destroyed;
}

bool CurveComet::isDone() {
      return destroyed && psystem->done();
}


/*
 *  SmallCurveComet
 */

SmallCurveComet::SmallCurveComet(CometenScene * scene, double time, 
      double _lifeTime, const Vec3f *points, int numPoints, 
    const Vec4f & _acolor, const Vec4f & _ecolor)
:
Comet(scene, 0.25),
startTime(time),
lifeTime(_lifeTime),
acolor(_acolor),
ecolor(_ecolor)
{
      GLuint tex = scene->textures[T_PARTICLE];
      
      assert(points && numPoints >= 2);
      
      position = points[0];
      psystem = new ParticleSystem(time, tex, points[0], points[0], 300, 0, 
                                   1.5, 2.0,  true, 150, 0.0, 2.0, false, 
                                   1.75, acolor, ecolor);
      
      decal = new Decal(tex, points[0], 3.0, 
                        true, Vec3f::UNIT_X, acolor);
      
      curve = new Bezier3(points, numPoints);
      destroyed = false;
}

SmallCurveComet::~SmallCurveComet() {
      delete psystem;
      delete decal;
      delete curve;
}

void SmallCurveComet::process(double time, double /*unused*/) {
      position = curve->position((time - startTime) / lifeTime);
      
      decal->setPosition(position);
      psystem->setEmitterPos1(psystem->getEmitterPos2());
      psystem->setEmitterPos2(position);
      psystem->process(time);
      
      if (!destroyed) {
            if (time - startTime > lifeTime) 
                  destroy(time);
      }
}

void SmallCurveComet::render(const Vec3f& campos) {
      if (!destroyed) {
            decal->render(campos);
      }
      psystem->render(campos);
}

void SmallCurveComet::destroy(double time) {
      Vec3f pos;
      Comet* newc;
      
      if (destroyed)
            return;
      
      pos = curve->position((time - startTime) / lifeTime);
      newc = new Explosion(scene, time, 1.0, pos, 25*size, 150, acolor, ecolor);
      scene->addComet(newc);
      
      psystem->stop();
      destroyed = true;
}


bool SmallCurveComet::isDestroyed() {
      return destroyed;
}

bool SmallCurveComet::isDone() {
      return destroyed && psystem->done();
}


Generated by  Doxygen 1.6.0   Back to index