Changeset 6621 in orxonox.OLD for trunk/src/lib/particles/sprite_particles.cc
- Timestamp:
- Jan 19, 2006, 11:46:28 PM (18 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/lib/particles/sprite_particles.cc
r6620 r6621 16 16 #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_GRAPHICS 17 17 18 #include "particle_system.h" 19 20 #include "particle_emitter.h" 21 22 #include "field.h" 23 #include "model.h" 18 #include "sprite_particles.h" 24 19 25 20 #include "load_param.h" … … 33 28 34 29 35 CREATE_FACTORY(ParticleSystem, CL_PARTICLE_SYSTEM); 36 SHELL_COMMAND(texture, ParticleSystem, setMaterialTexture) 30 CREATE_FACTORY(SpriteParticles, CL_SPRITE_PARTICLES); 31 32 SHELL_COMMAND(texture, SpriteParticles, setMaterialTexture) 37 33 ->defaultValues(1, "maps/evil-flower.png"); 38 34 … … 42 38 * standard constructor 43 39 * @param maxCount the Count of particles in the System 44 * @param type The Type of the ParticleSystem40 * @param type The Type of the SpriteParticles 45 41 */ 46 ParticleSystem::ParticleSystem (unsigned int maxCount, PARTICLE_TYPE type) 42 SpriteParticles::SpriteParticles (unsigned int maxCount) 43 : ParticleSystem(maxCount) 47 44 { 48 45 this->init(); 49 50 this->setMaxCount(maxCount);51 this->setType(type, 1);52 46 } 53 47 … … 56 50 * @param root: the XML-element to load from 57 51 */ 58 ParticleSystem::ParticleSystem(const TiXmlElement* root)52 SpriteParticles::SpriteParticles(const TiXmlElement* root) 59 53 { 60 54 this->init(); … … 66 60 * standard deconstructor 67 61 */ 68 ParticleSystem::~ParticleSystem()62 SpriteParticles::~SpriteParticles() 69 63 { 70 71 72 73 74 75 76 64 // deleting all the living Particles 65 while (this->particles) 66 { 67 Particle* tmpDelPart = this->particles; 68 this->particles = this->particles->next; 69 delete tmpDelPart; 70 } 77 71 78 // deleting all the dead particles 79 while (this->deadList) 80 { 81 Particle* tmpDelPart = this->deadList; 82 this->deadList = this->deadList->next; 83 delete tmpDelPart; 84 } 85 86 if (this->material) 87 delete this->material; 72 // deleting all the dead particles 73 while (this->deadList) 74 { 75 Particle* tmpDelPart = this->deadList; 76 this->deadList = this->deadList->next; 77 delete tmpDelPart; 78 } 88 79 } 89 80 90 81 /** 91 \brief initializes the ParticleSystemwith default values82 * @brief initializes the SpriteParticles with default values 92 83 */ 93 void ParticleSystem::init()84 void SpriteParticles::init() 94 85 { 95 this->setClassID(CL_ PARTICLE_SYSTEM, "ParticleSystem");86 this->setClassID(CL_SPRITE_PARTICLES, "SpriteParticles"); 96 87 97 88 this->material = NULL; 98 this->setMaxCount(PARTICLE_DEFAULT_MAX_COUNT);99 this->count = 0;100 this->particles = NULL;101 this->deadList = NULL;102 this->setConserve(1);103 this->setLifeSpan(1);104 this->glID = NULL;105 this->setType(PARTICLE_DEFAULT_TYPE, 1);106 107 this->toList(OM_ENVIRON);108 89 } 109 90 … … 113 94 * @param root the XML-element to load from. 114 95 */ 115 void ParticleSystem::loadParams(const TiXmlElement* root)96 void SpriteParticles::loadParams(const TiXmlElement* root) 116 97 { 117 WorldEntity::loadParams(root); 118 PhysicsInterface::loadParams(root); 98 SpriteParticles::loadParams(root); 119 99 120 LoadParam(root, "max-count", this, ParticleSystem, setMaxCount) 121 .describe("the maximal count of Particles, that can be emitted into this system"); 122 123 LoadParam(root, "life-span", this, ParticleSystem, setLifeSpan) 124 .describe("sets the life-span of the Particles."); 125 126 LoadParam(root, "conserve", this, ParticleSystem, setConserve) 127 .describe("sets the Conserve factor of the Particles (1.0: they keep all their energy, 0.0:they keep no energy)"); 128 129 LoadParam(root, "type", this, ParticleSystem, setType) 130 .describe("sets the type of the Particles, (dot, spark, sprite or model)"); 131 132 LoadParam(root, "texture", this, ParticleSystem, setMaterialTexture); 133 LoadParamXML(root, "emitter", this, ParticleSystem, addEmitterXML); 134 135 LOAD_PARAM_START_CYCLE(root, element); 136 { 137 element->ToText(); 138 // PER-PARTICLE-ATTRIBUTES: 139 LoadParam_CYCLE(element, "radius", this, ParticleSystem, setRadius) 140 .describe("The Radius of each particle over time (TimeIndex [0-1], radius at TimeIndex, randomRadius at TimeIndex)"); 141 142 LoadParam_CYCLE(element, "mass", this, ParticleSystem, setMass) 143 .describe("The Mass of each particle over time (TimeIndex: [0-1], mass at TimeIndex, randomMass at TimeIndex)"); 144 145 LoadParam_CYCLE(element, "color", this, ParticleSystem, setColor) 146 .describe("The Color of each particle over time (TimeIndex: [0-1], red: [0-1], green: [0-1], blue: [0-1], alpha: [0-1])"); 147 } 148 LOAD_PARAM_END_CYCLE(element); 149 } 150 151 /** 152 * @param maxCount the maximum count of particles that can be emitted 153 */ 154 void ParticleSystem::setMaxCount(int maxCount) 155 { 156 this->maxCount = maxCount; 157 } 158 159 160 /** 161 * @param particleType the type of particles in this System 162 * @param count how many particles (in PARTICLE_MULTI-mode) 163 @todo this will be different 164 */ 165 void ParticleSystem::setType(const char* particleType) 166 { 167 if (!strcmp(particleType, "dot")) 168 this->setType(PARTICLE_DOT); 169 else if(!strcmp(particleType, "spark")) 170 this->setType(PARTICLE_SPARK); 171 else if(!strcmp(particleType, "model")) 172 this->setType(PARTICLE_MODEL); 173 else // if (strcmp(particleType, "SPRITE")) 174 this->setType(PARTICLE_SPRITE); 175 } 176 177 /** 178 * @param particleType the type of particles in this System 179 * @param count how many particles (in PARTICLE_MULTI-mode) 180 @todo this MUST be different 181 */ 182 void ParticleSystem::setType(PARTICLE_TYPE particleType, int count) 183 { 184 this->particleType = particleType; 185 this->dialectCount = count; 186 // if (glID != NULL) 187 // delete glID; 188 189 // glID = new GLuint[count]; 190 // for (int i = 0; i< count; i++) 191 // glID[i] = 0; 192 193 // glID[0] = glGenLists(count); 194 if (this->material) 195 delete this->material; 196 this->material = NULL; 197 198 switch (this->particleType) 199 { 200 case PARTICLE_SPRITE: 201 this->material = new Material("transperencyMap"); 202 this->material->setDiffuseMap("maps/radialTransparency.png"); 203 // material->setTransparency(.5); 204 break; 205 } 100 LoadParam(root, "texture", this, SpriteParticles, setMaterialTexture); 206 101 } 207 102 208 103 // setting properties 209 104 /** 210 * sets the material to an external material105 * @brief sets the material to an external material 211 106 * @param material: the material to set this material to. 212 213 107 * 108 * !! important if the extern material gets deleted it MUST be unregistered here or segfault !! 214 109 */ 215 void ParticleSystem::setMaterial(Material* material)110 void SpriteParticles::setMaterial(Material* material) 216 111 { 217 this->material = material;112 this->material = *material; 218 113 } 219 114 220 void ParticleSystem::setMaterialTexture(const char* textureFile)115 void SpriteParticles::setMaterialTexture(const char* textureFile) 221 116 { 222 if (this->material != NULL) 223 this->material->setDiffuseMap(textureFile); 117 this->material.setDiffuseMap(textureFile); 224 118 } 225 119 226 120 /** 227 * Sets the lifespan of newly created particles 228 */ 229 void ParticleSystem::setLifeSpan(float lifeSpan, float randomLifeSpan) 230 { 231 this->lifeSpan = lifeSpan; 232 this->randomLifeSpan = randomLifeSpan; 233 } 234 235 /** 236 * sets the conserve Factor of newly created particles 237 */ 238 void ParticleSystem::setConserve(float conserve) 239 { 240 if (conserve > 1.0) 241 this->conserve = 1.0; 242 else if (conserve < 0.0) 243 this->conserve = 0.0; 244 else 245 this->conserve = conserve; 246 } 247 248 ///////////////////////////// 249 /* Per-Particle Attributes */ 250 ///////////////////////////// 251 /** 252 * sets a key in the radius-animation on a per-particle basis 253 * @param lifeCycleTime the time (partilceLifeTime/particleAge) [0-1] 254 * @param radius the radius at this position 255 * @param randRadius the randRadius at this position 256 */ 257 void ParticleSystem::setRadius(float lifeCycleTime, float radius, float randRadius) 258 { 259 this->radiusAnim.changeEntry(lifeCycleTime, radius); 260 this->randRadiusAnim.changeEntry(lifeCycleTime, randRadius); 261 } 262 263 /** 264 * sets a key in the mass-animation on a per-particle basis 265 * @param lifeCycleTime the time (partilceLifeTime/particleAge) [0-1] 266 * @param mass the mass at this position 267 * @param randMass the randomMass at this position 268 */ 269 void ParticleSystem::setMass(float lifeCycleTime, float mass, float randMass) 270 { 271 this->massAnim.changeEntry(lifeCycleTime, mass); 272 this->randMassAnim.changeEntry(lifeCycleTime, randMass); 273 } 274 275 /** 276 * sets a key in the color-animation on a per-particle basis 277 * @param lifeCycleTime: the time (partilceLifeTime/particleAge) [0-1] 278 * @param red: red 279 * @param green: green 280 * @param blue: blue 281 * @param alpha: alpha 282 */ 283 void ParticleSystem::setColor(float lifeCycleTime, float red, float green, float blue, float alpha) 284 { 285 this->colorAnim[0].changeEntry(lifeCycleTime, red); 286 this->colorAnim[1].changeEntry(lifeCycleTime, green); 287 this->colorAnim[2].changeEntry(lifeCycleTime, blue); 288 this->colorAnim[3].changeEntry(lifeCycleTime, alpha); 289 } 290 291 292 void ParticleSystem::addEmitter(ParticleEmitter* emitter) 293 { 294 assert (emitter != NULL); 295 if (emitter->getSystem() != NULL) 296 emitter->getSystem()->removeEmitter(emitter); 297 this->emitters.push_back(emitter); 298 } 299 300 void ParticleSystem::addEmitterXML(const TiXmlElement* emitterRoot) 301 { 302 ParticleEmitter* emitter = new ParticleEmitter(emitterRoot); 303 this->addEmitter(emitter); 304 } 305 306 307 void ParticleSystem::removeEmitter(ParticleEmitter* emitter) 308 { 309 std::list<ParticleEmitter*>::iterator it = std::find(this->emitters.begin(), this->emitters.end(), emitter); 310 if (it != this->emitters.end()) 311 this->emitters.erase(it); 312 } 313 314 /** 315 * ticks the system. 316 * @param dt the time to tick all the Particles of the System 317 318 this is used to get all the particles some motion 319 */ 320 void ParticleSystem::tick(float dt) 321 { 322 Particle* tickPart = particles; // the particle to Tick 323 Particle* prevPart = NULL; 324 while (likely(tickPart != NULL)) 325 { 326 // applying force to the System. 327 if (likely (tickPart->mass > 0.0)) 328 tickPart->velocity += tickPart->extForce / tickPart->mass * dt; 329 // rendering new position. 330 tickPart->position += tickPart->velocity * dt; 331 tickPart->orientation += tickPart->momentum *dt; 332 333 tickPart->radius = radiusAnim.getValue(tickPart->lifeCycle) 334 + randRadiusAnim.getValue(tickPart->lifeCycle) * tickPart->radiusRand; 335 336 tickPart->mass = massAnim.getValue(tickPart->lifeCycle) 337 + randMassAnim.getValue(tickPart->lifeCycle) * tickPart->massRand; 338 339 tickPart->extForce = Vector(0,0,0); 340 341 // applying Color 342 tickPart->color[0] = this->colorAnim[0].getValue(tickPart->lifeCycle); 343 tickPart->color[1] = this->colorAnim[1].getValue(tickPart->lifeCycle); 344 tickPart->color[2] = this->colorAnim[2].getValue(tickPart->lifeCycle); 345 tickPart->color[3] = this->colorAnim[3].getValue(tickPart->lifeCycle); 346 347 // many more to come 348 349 if (this->conserve < 1.0) 350 { 351 tickPart->velocity *= this->conserve; 352 tickPart->momentum *= this->conserve; 353 } 354 // find out if we have to delete tickPart 355 if (unlikely((tickPart->lifeCycle += dt/tickPart->lifeTime) >= 1.0)) 356 { 357 // remove the particle from the list 358 if (likely(prevPart != NULL)) 359 { 360 prevPart->next = tickPart->next; 361 tickPart->next = this->deadList; 362 this->deadList = tickPart; 363 tickPart = prevPart->next; 364 } 365 else 366 { 367 prevPart = NULL; 368 this->particles = tickPart->next; 369 tickPart->next = this->deadList; 370 this->deadList = tickPart; 371 tickPart = this->particles; 372 } 373 --this->count; 374 } 375 else 376 { 377 prevPart = tickPart; 378 tickPart = tickPart->next; 379 } 380 } 381 382 std::list<ParticleEmitter*>::iterator emitter; 383 for (emitter = this->emitters.begin(); emitter != this->emitters.end(); emitter++) 384 (*emitter)->tick(dt); 385 } 386 387 /** 388 * applies some force to a Particle. 389 * @param field the Field to apply. 121 * @brief draws all the Particles of this System 122 * 123 * The Cases in this Function all do the same: 124 * Drawing all the particles with the appropriate Type. 125 * This is just the fastest Way to do this, but will most likely be changed in the future. 390 126 */ 391 void ParticleSystem::applyField(Field* field) 392 { 393 Particle* tickPart = particles; 394 while (tickPart) 395 { 396 tickPart->extForce += field->calcForce(tickPart->position); 397 tickPart = tickPart->next; 398 } 399 } 400 401 402 /** 403 * @returns the count of Faces of this ParticleSystem 404 */ 405 unsigned int ParticleSystem::getFaceCount() const 406 { 407 switch (this->particleType) 408 { 409 case PARTICLE_SPRITE: 410 return this->count; 411 break; 412 case PARTICLE_MODEL: 413 if (this->getModel(0)) 414 return this->count * this->getModel()->getTriangleCount(); 415 break; 416 } 417 } 418 419 420 /** 421 * draws all the Particles of this System 422 423 The Cases in this Function all do the same: 424 Drawing all the particles with the appropriate Type. 425 This is just the fastest Way to do this, but will most likely be changed in the future. 426 */ 427 void ParticleSystem::draw() const 127 void SpriteParticles::draw() const 428 128 { 429 129 glPushAttrib(GL_ENABLE_BIT); … … 431 131 Particle* drawPart = particles; 432 132 433 switch (this->particleType) 434 { 435 default: 436 case PARTICLE_SPRITE: 437 glDisable(GL_LIGHTING); 438 glMatrixMode(GL_MODELVIEW); 439 glDepthMask(GL_FALSE); 133 glDisable(GL_LIGHTING); 134 glMatrixMode(GL_MODELVIEW); 135 glDepthMask(GL_FALSE); 440 136 441 material->select();442 137 material.select(); 138 glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA); 443 139 444 140 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_MODULATE); 445 141 446 142 447 448 449 450 143 while (likely(drawPart != NULL)) 144 { 145 glColor4fv(drawPart->color); 146 //! @todo implement a faster code for the look-at Camera algorithm. 451 147 452 453 454 455 456 457 458 459 460 461 462 463 148 const PNode* camera = State::getCamera(); //!< @todo MUST be different 149 Vector cameraPos = camera->getAbsCoor(); 150 Vector cameraTargetPos = State::getCameraTarget()->getAbsCoor(); 151 Vector view = cameraTargetPos - cameraPos; 152 Vector up = Vector(0, 1, 0); 153 up = camera->getAbsDir().apply(up); 154 Vector h = up.cross(view); 155 Vector v = h.cross(view); 156 h.normalize(); 157 v.normalize(); 158 v *= .5 * drawPart->radius; 159 h *= .5 * drawPart->radius; 464 160 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 161 glBegin(GL_TRIANGLE_STRIP); 162 glTexCoord2i(1, 1); 163 glVertex3f(drawPart->position.x - h.x - v.x, 164 drawPart->position.y - h.y - v.y, 165 drawPart->position.z - h.z - v.z); 166 glTexCoord2i(0, 1); 167 glVertex3f(drawPart->position.x - h.x + v.x, 168 drawPart->position.y - h.y + v.y, 169 drawPart->position.z - h.z + v.z); 170 glTexCoord2i(1, 0); 171 glVertex3f(drawPart->position.x + h.x - v.x, 172 drawPart->position.y + h.y - v.y, 173 drawPart->position.z + h.z - v.z); 174 glTexCoord2i(0, 0); 175 glVertex3f(drawPart->position.x + h.x + v.x, 176 drawPart->position.y + h.y + v.y, 177 drawPart->position.z + h.z + v.z); 482 178 483 179 glEnd(); 484 180 485 drawPart = drawPart->next; 486 } 487 glDepthMask(GL_TRUE); 488 break; 489 490 case PARTICLE_SPARK: 491 glDisable(GL_LIGHTING); 492 glDepthMask(GL_FALSE); 493 //glEnable(GL_LINE_SMOOTH); 494 glEnable(GL_BLEND); 495 496 glBegin(GL_LINES); 497 while (likely(drawPart != NULL)) 498 { 499 glColor4fv(drawPart->color); 500 glVertex3f(drawPart->position.x, drawPart->position.y, drawPart->position.z); 501 glVertex3f(drawPart->position.x - drawPart->velocity.x * drawPart->radius, 502 drawPart->position.y - drawPart->velocity.y * drawPart->radius, 503 drawPart->position.z - drawPart->velocity.z * drawPart->radius); 504 drawPart = drawPart->next; 505 } 506 glEnd(); 507 break; 508 509 case PARTICLE_MODEL: 510 { 511 GLfloat matrix[4][4]; 512 513 if (likely(this->getModel() != NULL)) 514 while (likely(drawPart != NULL)) 515 { 516 glPushMatrix(); 517 glMatrixMode(GL_MODELVIEW); 518 /* move */ 519 glTranslatef(drawPart->position.x, drawPart->position.y, drawPart->position.z); 520 /* scale */ 521 glScalef(drawPart->radius, drawPart->radius, drawPart->radius); 522 /* rotate */ 523 drawPart->orientation.matrix (matrix); 524 glMultMatrixf((float*)matrix); 525 526 this->getModel()->draw(); 527 528 glPopMatrix(); 529 drawPart = drawPart->next; 530 } 531 else 532 PRINTF(2)("no model loaded onto ParticleSystem-%s\n", this->getName()); 533 } 534 break; 535 536 case PARTICLE_DOT: 537 glDisable(GL_LIGHTING); 538 glBegin(GL_POINTS); 539 while (likely(drawPart != NULL)) 540 { 541 glColor4fv(drawPart->color); 542 543 glLineWidth(drawPart->radius); 544 545 glVertex3f(drawPart->position.x, drawPart->position.y, drawPart->position.z); 546 drawPart = drawPart->next; 547 } 548 glEnd(); 549 break; 181 drawPart = drawPart->next; 550 182 } 183 glDepthMask(GL_TRUE); 551 184 glPopAttrib(); 552 185 } 553 554 /**555 * adds a new Particle to the System556 * @param position the initial position, where the particle gets emitted.557 * @param velocity the initial velocity of the particle.558 * @param orientation the initial orientation of the Paritcle.559 * @param momentum the initial momentum of the Particle (the speed of its rotation).560 * @param data some more data given by the emitter561 */562 void ParticleSystem::addParticle(const Vector& position, const Vector& velocity, const Quaternion& orientation, const Quaternion& momentum, unsigned int data)563 {564 if (this->count <= this->maxCount)565 {566 // if it is the first Particle567 if (unlikely(particles == NULL))568 {569 if (likely(deadList != NULL))570 {571 this->particles = this->deadList;572 deadList = deadList->next;573 }574 else575 {576 PRINTF(5)("Generating new Particle\n");577 this->particles = new Particle;578 }579 this->particles->next = NULL;580 }581 // filling the List from the beginning582 else583 {584 Particle* tmpPart;585 if (likely(deadList != NULL))586 {587 tmpPart = this->deadList;588 deadList = deadList->next;589 }590 else591 {592 PRINTF(5)("Generating new Particle\n");593 tmpPart = new Particle;594 }595 tmpPart->next = this->particles;596 this->particles = tmpPart;597 }598 particles->lifeTime = this->lifeSpan + (float)(rand()/RAND_MAX)* this->randomLifeSpan;599 particles->lifeCycle = 0.0;600 particles->position = position;601 particles->velocity = velocity;602 603 particles->orientation = orientation;604 particles->momentum = momentum;605 606 // particle->rotation = ; //! @todo rotation is once again something to be done.607 particles->massRand = 2*(float)rand()/RAND_MAX -1;608 particles->radiusRand = 2* (float)rand()/RAND_MAX -1;609 particles->mass = this->massAnim.getValue(0.0) + this->randMassAnim.getValue(0.0)*particles->massRand;610 particles->radius = this->radiusAnim.getValue(0.0) + this->randRadiusAnim.getValue(0.0)*particles->radiusRand;611 612 ++this->count;613 }614 else615 PRINTF(5)("maximum count of particles reached not adding any more\n");616 }617 618 /**619 * outputs some nice debug information620 */621 void ParticleSystem::debug() const622 {623 PRINT(0)(" ParticleSystem %s, type: ", this->getName());624 {625 if (this->particleType == PARTICLE_MODEL)626 PRINT(0)("model");627 else if (this->particleType == PARTICLE_SPRITE)628 PRINT(0)("sprite");629 else if (this->particleType == PARTICLE_DOT)630 PRINT(0)("dot");631 else if (this->particleType == PARTICLE_SPARK)632 PRINT(0)("spark");633 634 PRINT(0)("\n");635 }636 637 PRINT(0)(" ParticleCount: %d, maximumCount: %d :: filled %d%%\n", this->count, this->maxCount, 100*this->count/this->maxCount);638 if (deadList)639 {640 PRINT(0)(" - ParticleDeadList is used: ");641 int i = 1;642 Particle* tmpPart = this->deadList;643 while (tmpPart = tmpPart->next) ++i;644 PRINT(0)("count: %d\n", i);645 }646 }
Note: See TracChangeset
for help on using the changeset viewer.