doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
DeclParticle.cpp
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 #include "../idlib/precompiled.h"
30 #pragma hdrstop
31 
33  const char *name;
34  int count;
35  const char *desc;
36 };
37 
39  { "rect", 3, "" },
40  { "cylinder", 4, "" },
41  { "sphere", 3, "" }
42 };
43 
45  { "cone", 1, "" },
46  { "outward", 1, "" },
47 };
48 
50  { "view", 0, "" },
51  { "aimed", 2, "" },
52  { "x", 0, "" },
53  { "y", 0, "" },
54  { "z", 0, "" }
55 };
56 
58  { "standard", 0, "Standard" },
59  { "helix", 5, "sizeX Y Z radialSpeed axialSpeed" },
60  { "flies", 3, "radialSpeed axialSpeed size" },
61  { "orbit", 2, "radius speed"},
62  { "drip", 2, "something something" }
63 };
64 
65 const int CustomParticleCount = sizeof( ParticleCustomDesc ) / sizeof( const ParticleParmDesc );
66 
67 /*
68 =================
69 idDeclParticle::Size
70 =================
71 */
72 size_t idDeclParticle::Size( void ) const {
73  return sizeof( idDeclParticle );
74 }
75 
76 /*
77 =====================
78 idDeclParticle::GetStageBounds
79 =====================
80 */
82 
83  stage->bounds.Clear();
84 
85  // this isn't absolutely guaranteed, but it should be close
86 
88 
89  renderEntity_t renderEntity;
90  memset( &renderEntity, 0, sizeof( renderEntity ) );
91  renderEntity.axis = mat3_identity;
92 
93  renderView_t renderView;
94  memset( &renderView, 0, sizeof( renderView ) );
95  renderView.viewaxis = mat3_identity;
96 
97  g.renderEnt = &renderEntity;
98  g.renderView = &renderView;
99  g.origin.Zero();
100  g.axis = mat3_identity;
101 
102  idRandom steppingRandom;
103  steppingRandom.SetSeed( 0 );
104 
105  // just step through a lot of possible particles as a representative sampling
106  for ( int i = 0 ; i < 1000 ; i++ ) {
107  g.random = g.originalRandom = steppingRandom;
108 
109  int maxMsec = stage->particleLife * 1000;
110  for ( int inCycleTime = 0 ; inCycleTime < maxMsec ; inCycleTime += 16 ) {
111 
112  // make sure we get the very last tic, which may make up an extreme edge
113  if ( inCycleTime + 16 > maxMsec ) {
114  inCycleTime = maxMsec - 1;
115  }
116 
117  g.frac = (float)inCycleTime / ( stage->particleLife * 1000 );
118  g.age = inCycleTime * 0.001f;
119 
120  // if the particle doesn't get drawn because it is faded out or beyond a kill region,
121  // don't increment the verts
122 
123  idVec3 origin;
124  stage->ParticleOrigin( &g, origin );
125  stage->bounds.AddPoint( origin );
126  }
127  }
128 
129  // find the max size
130  float maxSize = 0;
131 
132  for ( float f = 0; f <= 1.0f; f += 1.0f / 64 ) {
133  float size = stage->size.Eval( f, steppingRandom );
134  float aspect = stage->aspect.Eval( f, steppingRandom );
135  if ( aspect > 1 ) {
136  size *= aspect;
137  }
138  if ( size > maxSize ) {
139  maxSize = size;
140  }
141  }
142 
143  maxSize += 8; // just for good measure
144  // users can specify a per-stage bounds expansion to handle odd cases
145  stage->bounds.ExpandSelf( maxSize + stage->boundsExpansion );
146 }
147 
148 /*
149 ================
150 idDeclParticle::ParseParms
151 
152 Parses a variable length list of parms on one line
153 ================
154 */
155 void idDeclParticle::ParseParms( idLexer &src, float *parms, int maxParms ) {
156  idToken token;
157 
158  memset( parms, 0, maxParms * sizeof( *parms ) );
159  int count = 0;
160  while( 1 ) {
161  if ( !src.ReadTokenOnLine( &token ) ) {
162  return;
163  }
164  if ( count == maxParms ) {
165  src.Error( "too many parms on line" );
166  return;
167  }
168  token.StripQuotes();
169  parms[count] = atof( token );
170  count++;
171  }
172 }
173 
174 /*
175 ================
176 idDeclParticle::ParseParametric
177 ================
178 */
180  idToken token;
181 
182  parm->table = NULL;
183  parm->from = parm->to = 0.0f;
184 
185  if ( !src.ReadToken( &token ) ) {
186  src.Error( "not enough parameters" );
187  return;
188  }
189 
190  if ( token.IsNumeric() ) {
191  // can have a to + 2nd parm
192  parm->from = parm->to = atof( token );
193  if ( src.ReadToken( &token ) ) {
194  if ( !token.Icmp( "to" ) ) {
195  if ( !src.ReadToken( &token ) ) {
196  src.Error( "missing second parameter" );
197  return;
198  }
199  parm->to = atof( token );
200  } else {
201  src.UnreadToken( &token );
202  }
203  }
204  } else {
205  // table
206  parm->table = static_cast<const idDeclTable *>( declManager->FindType( DECL_TABLE, token, false ) );
207  }
208 
209 }
210 
211 /*
212 ================
213 idDeclParticle::ParseParticleStage
214 ================
215 */
217  idToken token;
218 
219  idParticleStage *stage = new idParticleStage;
220  stage->Default();
221 
222  while (1) {
223  if ( src.HadError() ) {
224  break;
225  }
226  if ( !src.ReadToken( &token ) ) {
227  break;
228  }
229  if ( !token.Icmp( "}" ) ) {
230  break;
231  }
232  if ( !token.Icmp( "material" ) ) {
233  src.ReadToken( &token );
234  stage->material = declManager->FindMaterial( token.c_str() );
235  continue;
236  }
237  if ( !token.Icmp( "count" ) ) {
238  stage->totalParticles = src.ParseInt();
239  continue;
240  }
241  if ( !token.Icmp( "time" ) ) {
242  stage->particleLife = src.ParseFloat();
243  continue;
244  }
245  if ( !token.Icmp( "cycles" ) ) {
246  stage->cycles = src.ParseFloat();
247  continue;
248  }
249  if ( !token.Icmp( "timeOffset" ) ) {
250  stage->timeOffset = src.ParseFloat();
251  continue;
252  }
253  if ( !token.Icmp( "deadTime" ) ) {
254  stage->deadTime = src.ParseFloat();
255  continue;
256  }
257  if ( !token.Icmp( "randomDistribution" ) ) {
258  stage->randomDistribution = src.ParseBool();
259  continue;
260  }
261  if ( !token.Icmp( "bunching" ) ) {
262  stage->spawnBunching = src.ParseFloat();
263  continue;
264  }
265 
266  if ( !token.Icmp( "distribution" ) ) {
267  src.ReadToken( &token );
268  if ( !token.Icmp( "rect" ) ) {
269  stage->distributionType = PDIST_RECT;
270  } else if ( !token.Icmp( "cylinder" ) ) {
272  } else if ( !token.Icmp( "sphere" ) ) {
274  } else {
275  src.Error( "bad distribution type: %s\n", token.c_str() );
276  }
277  ParseParms( src, stage->distributionParms, sizeof( stage->distributionParms ) / sizeof( stage->distributionParms[0] ) );
278  continue;
279  }
280 
281  if ( !token.Icmp( "direction" ) ) {
282  src.ReadToken( &token );
283  if ( !token.Icmp( "cone" ) ) {
284  stage->directionType = PDIR_CONE;
285  } else if ( !token.Icmp( "outward" ) ) {
286  stage->directionType = PDIR_OUTWARD;
287  } else {
288  src.Error( "bad direction type: %s\n", token.c_str() );
289  }
290  ParseParms( src, stage->directionParms, sizeof( stage->directionParms ) / sizeof( stage->directionParms[0] ) );
291  continue;
292  }
293 
294  if ( !token.Icmp( "orientation" ) ) {
295  src.ReadToken( &token );
296  if ( !token.Icmp( "view" ) ) {
297  stage->orientation = POR_VIEW;
298  } else if ( !token.Icmp( "aimed" ) ) {
299  stage->orientation = POR_AIMED;
300  } else if ( !token.Icmp( "x" ) ) {
301  stage->orientation = POR_X;
302  } else if ( !token.Icmp( "y" ) ) {
303  stage->orientation = POR_Y;
304  } else if ( !token.Icmp( "z" ) ) {
305  stage->orientation = POR_Z;
306  } else {
307  src.Error( "bad orientation type: %s\n", token.c_str() );
308  }
309  ParseParms( src, stage->orientationParms, sizeof( stage->orientationParms ) / sizeof( stage->orientationParms[0] ) );
310  continue;
311  }
312 
313  if ( !token.Icmp( "customPath" ) ) {
314  src.ReadToken( &token );
315  if ( !token.Icmp( "standard" ) ) {
317  } else if ( !token.Icmp( "helix" ) ) {
318  stage->customPathType = PPATH_HELIX;
319  } else if ( !token.Icmp( "flies" ) ) {
320  stage->customPathType = PPATH_FLIES;
321  } else if ( !token.Icmp( "spherical" ) ) {
322  stage->customPathType = PPATH_ORBIT;
323  } else {
324  src.Error( "bad path type: %s\n", token.c_str() );
325  }
326  ParseParms( src, stage->customPathParms, sizeof( stage->customPathParms ) / sizeof( stage->customPathParms[0] ) );
327  continue;
328  }
329 
330  if ( !token.Icmp( "speed" ) ) {
331  ParseParametric( src, &stage->speed );
332  continue;
333  }
334  if ( !token.Icmp( "rotation" ) ) {
335  ParseParametric( src, &stage->rotationSpeed );
336  continue;
337  }
338  if ( !token.Icmp( "angle" ) ) {
339  stage->initialAngle = src.ParseFloat();
340  continue;
341  }
342  if ( !token.Icmp( "entityColor" ) ) {
343  stage->entityColor = src.ParseBool();
344  continue;
345  }
346  if ( !token.Icmp( "size" ) ) {
347  ParseParametric( src, &stage->size );
348  continue;
349  }
350  if ( !token.Icmp( "aspect" ) ) {
351  ParseParametric( src, &stage->aspect );
352  continue;
353  }
354  if ( !token.Icmp( "fadeIn" ) ) {
355  stage->fadeInFraction = src.ParseFloat();
356  continue;
357  }
358  if ( !token.Icmp( "fadeOut" ) ) {
359  stage->fadeOutFraction = src.ParseFloat();
360  continue;
361  }
362  if ( !token.Icmp( "fadeIndex" ) ) {
363  stage->fadeIndexFraction = src.ParseFloat();
364  continue;
365  }
366  if ( !token.Icmp( "color" ) ) {
367  stage->color[0] = src.ParseFloat();
368  stage->color[1] = src.ParseFloat();
369  stage->color[2] = src.ParseFloat();
370  stage->color[3] = src.ParseFloat();
371  continue;
372  }
373  if ( !token.Icmp( "fadeColor" ) ) {
374  stage->fadeColor[0] = src.ParseFloat();
375  stage->fadeColor[1] = src.ParseFloat();
376  stage->fadeColor[2] = src.ParseFloat();
377  stage->fadeColor[3] = src.ParseFloat();
378  continue;
379  }
380  if ( !token.Icmp("offset" ) ) {
381  stage->offset[0] = src.ParseFloat();
382  stage->offset[1] = src.ParseFloat();
383  stage->offset[2] = src.ParseFloat();
384  continue;
385  }
386  if ( !token.Icmp( "animationFrames" ) ) {
387  stage->animationFrames = src.ParseInt();
388  continue;
389  }
390  if ( !token.Icmp( "animationRate" ) ) {
391  stage->animationRate = src.ParseFloat();
392  continue;
393  }
394  if ( !token.Icmp( "boundsExpansion" ) ) {
395  stage->boundsExpansion = src.ParseFloat();
396  continue;
397  }
398  if ( !token.Icmp( "gravity" ) ) {
399  src.ReadToken( &token );
400  if ( !token.Icmp( "world" ) ) {
401  stage->worldGravity = true;
402  } else {
403  src.UnreadToken( &token );
404  }
405  stage->gravity = src.ParseFloat();
406  continue;
407  }
408 
409  src.Error( "unknown token %s\n", token.c_str() );
410  }
411 
412  // derive values
413  stage->cycleMsec = ( stage->particleLife + stage->deadTime ) * 1000;
414 
415  return stage;
416 }
417 
418 /*
419 ================
420 idDeclParticle::Parse
421 ================
422 */
423 bool idDeclParticle::Parse( const char *text, const int textLength ) {
424  idLexer src;
425  idToken token;
426 
427  src.LoadMemory( text, textLength, GetFileName(), GetLineNum() );
428  src.SetFlags( DECL_LEXER_FLAGS );
429  src.SkipUntilString( "{" );
430 
431  depthHack = 0.0f;
432 
433  while (1) {
434  if ( !src.ReadToken( &token ) ) {
435  break;
436  }
437 
438  if ( !token.Icmp( "}" ) ) {
439  break;
440  }
441 
442  if ( !token.Icmp( "{" ) ) {
443  idParticleStage *stage = ParseParticleStage( src );
444  if ( !stage ) {
445  src.Warning( "Particle stage parse failed" );
446  MakeDefault();
447  return false;
448  }
449  stages.Append( stage );
450  continue;
451  }
452 
453  if ( !token.Icmp( "depthHack" ) ) {
454  depthHack = src.ParseFloat();
455  continue;
456  }
457 
458  src.Warning( "bad token %s", token.c_str() );
459  MakeDefault();
460  return false;
461  }
462 
463  //
464  // calculate the bounds
465  //
466  bounds.Clear();
467  for( int i = 0; i < stages.Num(); i++ ) {
468  GetStageBounds( stages[i] );
469  bounds.AddBounds( stages[i]->bounds );
470  }
471 
472  if ( bounds.GetVolume() <= 0.1f ) {
473  bounds = idBounds( vec3_origin ).Expand( 8.0f );
474  }
475 
476  return true;
477 }
478 
479 /*
480 ================
481 idDeclParticle::FreeData
482 ================
483 */
485  stages.DeleteContents( true );
486 }
487 
488 /*
489 ================
490 idDeclParticle::DefaultDefinition
491 ================
492 */
493 const char *idDeclParticle::DefaultDefinition( void ) const {
494  return
495  "{\n"
496  "\t" "{\n"
497  "\t\t" "material\t_default\n"
498  "\t\t" "count\t20\n"
499  "\t\t" "time\t\t1.0\n"
500  "\t" "}\n"
501  "}";
502 }
503 
504 /*
505 ================
506 idDeclParticle::WriteParticleParm
507 ================
508 */
510 
511  f->WriteFloatString( "\t\t%s\t\t\t\t ", name );
512  if ( parm->table ) {
513  f->WriteFloatString( "%s\n", parm->table->GetName() );
514  } else {
515  f->WriteFloatString( "\"%.3f\" ", parm->from );
516  if ( parm->from == parm->to ) {
517  f->WriteFloatString( "\n" );
518  } else {
519  f->WriteFloatString( " to \"%.3f\"\n", parm->to );
520  }
521  }
522 }
523 
524 /*
525 ================
526 idDeclParticle::WriteStage
527 ================
528 */
530 
531  int i;
532 
533  f->WriteFloatString( "\t{\n" );
534  f->WriteFloatString( "\t\tcount\t\t\t\t%i\n", stage->totalParticles );
535  f->WriteFloatString( "\t\tmaterial\t\t\t%s\n", stage->material->GetName() );
536  if ( stage->animationFrames ) {
537  f->WriteFloatString( "\t\tanimationFrames \t%i\n", stage->animationFrames );
538  }
539  if ( stage->animationRate ) {
540  f->WriteFloatString( "\t\tanimationRate \t\t%.3f\n", stage->animationRate );
541  }
542  f->WriteFloatString( "\t\ttime\t\t\t\t%.3f\n", stage->particleLife );
543  f->WriteFloatString( "\t\tcycles\t\t\t\t%.3f\n", stage->cycles );
544  if ( stage->timeOffset ) {
545  f->WriteFloatString( "\t\ttimeOffset\t\t\t%.3f\n", stage->timeOffset );
546  }
547  if ( stage->deadTime ) {
548  f->WriteFloatString( "\t\tdeadTime\t\t\t%.3f\n", stage->deadTime );
549  }
550  f->WriteFloatString( "\t\tbunching\t\t\t%.3f\n", stage->spawnBunching );
551 
552  f->WriteFloatString( "\t\tdistribution\t\t%s ", ParticleDistributionDesc[stage->distributionType].name );
553  for ( i = 0; i < ParticleDistributionDesc[stage->distributionType].count; i++ ) {
554  f->WriteFloatString( "%.3f ", stage->distributionParms[i] );
555  }
556  f->WriteFloatString( "\n" );
557 
558  f->WriteFloatString( "\t\tdirection\t\t\t%s ", ParticleDirectionDesc[stage->directionType].name );
559  for ( i = 0; i < ParticleDirectionDesc[stage->directionType].count; i++ ) {
560  f->WriteFloatString( "\"%.3f\" ", stage->directionParms[i] );
561  }
562  f->WriteFloatString( "\n" );
563 
564  f->WriteFloatString( "\t\torientation\t\t\t%s ", ParticleOrientationDesc[stage->orientation].name );
565  for ( i = 0; i < ParticleOrientationDesc[stage->orientation].count; i++ ) {
566  f->WriteFloatString( "%.3f ", stage->orientationParms[i] );
567  }
568  f->WriteFloatString( "\n" );
569 
570  if ( stage->customPathType != PPATH_STANDARD ) {
571  f->WriteFloatString( "\t\tcustomPath %s ", ParticleCustomDesc[stage->customPathType].name );
572  for ( i = 0; i < ParticleCustomDesc[stage->customPathType].count; i++ ) {
573  f->WriteFloatString( "%.3f ", stage->customPathParms[i] );
574  }
575  f->WriteFloatString( "\n" );
576  }
577 
578  if ( stage->entityColor ) {
579  f->WriteFloatString( "\t\tentityColor\t\t\t1\n" );
580  }
581 
582  WriteParticleParm( f, &stage->speed, "speed" );
583  WriteParticleParm( f, &stage->size, "size" );
584  WriteParticleParm( f, &stage->aspect, "aspect" );
585 
586  if ( stage->rotationSpeed.from ) {
587  WriteParticleParm( f, &stage->rotationSpeed, "rotation" );
588  }
589 
590  if ( stage->initialAngle ) {
591  f->WriteFloatString( "\t\tangle\t\t\t\t%.3f\n", stage->initialAngle );
592  }
593 
594  f->WriteFloatString( "\t\trandomDistribution\t\t\t\t%i\n", static_cast<int>( stage->randomDistribution ) );
595  f->WriteFloatString( "\t\tboundsExpansion\t\t\t\t%.3f\n", stage->boundsExpansion );
596 
597 
598  f->WriteFloatString( "\t\tfadeIn\t\t\t\t%.3f\n", stage->fadeInFraction );
599  f->WriteFloatString( "\t\tfadeOut\t\t\t\t%.3f\n", stage->fadeOutFraction );
600  f->WriteFloatString( "\t\tfadeIndex\t\t\t\t%.3f\n", stage->fadeIndexFraction );
601 
602  f->WriteFloatString( "\t\tcolor \t\t\t\t%.3f %.3f %.3f %.3f\n", stage->color.x, stage->color.y, stage->color.z, stage->color.w );
603  f->WriteFloatString( "\t\tfadeColor \t\t\t%.3f %.3f %.3f %.3f\n", stage->fadeColor.x, stage->fadeColor.y, stage->fadeColor.z, stage->fadeColor.w );
604 
605  f->WriteFloatString( "\t\toffset \t\t\t\t%.3f %.3f %.3f\n", stage->offset.x, stage->offset.y, stage->offset.z );
606  f->WriteFloatString( "\t\tgravity \t\t\t" );
607  if ( stage->worldGravity ) {
608  f->WriteFloatString( "world " );
609  }
610  f->WriteFloatString( "%.3f\n", stage->gravity );
611  f->WriteFloatString( "\t}\n" );
612 }
613 
614 /*
615 ================
616 idDeclParticle::RebuildTextSource
617 ================
618 */
621 
622  f.WriteFloatString("\n\n/*\n"
623  "\tGenerated by the Particle Editor.\n"
624  "\tTo use the particle editor, launch the game and type 'editParticles' on the console.\n"
625  "*/\n" );
626 
627  f.WriteFloatString( "particle %s {\n", GetName() );
628 
629  if ( depthHack ) {
630  f.WriteFloatString( "\tdepthHack\t%f\n", depthHack );
631  }
632 
633  for ( int i = 0; i < stages.Num(); i++ ) {
634  WriteStage( &f, stages[i] );
635  }
636 
637  f.WriteFloatString( "}" );
638 
639  SetText( f.GetDataPtr() );
640 
641  return true;
642 }
643 
644 /*
645 ================
646 idDeclParticle::Save
647 ================
648 */
649 bool idDeclParticle::Save( const char *fileName ) {
651  if ( fileName ) {
653  }
655  return true;
656 }
657 
658 /*
659 ====================================================================================
660 
661 idParticleParm
662 
663 ====================================================================================
664 */
665 
666 float idParticleParm::Eval( float frac, idRandom &rand ) const {
667  if ( table ) {
668  return table->TableLookup( frac );
669  }
670  return from + frac * ( to - from );
671 }
672 
673 float idParticleParm::Integrate( float frac, idRandom &rand ) const {
674  if ( table ) {
675  common->Printf( "idParticleParm::Integrate: can't integrate tables\n" );
676  return 0;
677  }
678  return ( from + frac * ( to - from ) * 0.5f ) * frac;
679 }
680 
681 /*
682 ====================================================================================
683 
684 idParticleStage
685 
686 ====================================================================================
687 */
688 
689 /*
690 ================
691 idParticleStage::idParticleStage
692 ================
693 */
695  material = NULL;
696  totalParticles = 0;
697  cycles = 0.0f;
698  cycleMsec = 0;
699  spawnBunching = 0.0f;
700  particleLife = 0.0f;
701  timeOffset = 0.0f;
702  deadTime = 0.0f;
707  // idParticleParm speed;
708  gravity = 0.0f;
709  worldGravity = false;
713  offset.Zero();
714  animationFrames = 0;
715  animationRate = 0.0f;
716  randomDistribution = true;
717  entityColor = false;
718  initialAngle = 0.0f;
719  // idParticleParm rotationSpeed;
722  // idParticleParm size
723  // idParticleParm aspect
724  color.Zero();
725  fadeColor.Zero();
726  fadeInFraction = 0.0f;
727  fadeOutFraction = 0.0f;
728  fadeIndexFraction = 0.0f;
729  hidden = false;
730  boundsExpansion = 0.0f;
731  bounds.Clear();
732 }
733 
734 /*
735 ================
736 idParticleStage::Default
737 
738 Sets the stage to a default state
739 ================
740 */
742  material = declManager->FindMaterial( "_default" );
743  totalParticles = 100;
744  spawnBunching = 1.0f;
745  particleLife = 1.5f;
746  timeOffset = 0.0f;
747  deadTime = 0.0f;
749  distributionParms[0] = 8.0f;
750  distributionParms[1] = 8.0f;
751  distributionParms[2] = 8.0f;
752  distributionParms[3] = 0.0f;
754  directionParms[0] = 90.0f;
755  directionParms[1] = 0.0f;
756  directionParms[2] = 0.0f;
757  directionParms[3] = 0.0f;
759  orientationParms[0] = 0.0f;
760  orientationParms[1] = 0.0f;
761  orientationParms[2] = 0.0f;
762  orientationParms[3] = 0.0f;
763  speed.from = 150.0f;
764  speed.to = 150.0f;
765  speed.table = NULL;
766  gravity = 1.0f;
767  worldGravity = false;
769  customPathParms[0] = 0.0f;
770  customPathParms[1] = 0.0f;
771  customPathParms[2] = 0.0f;
772  customPathParms[3] = 0.0f;
773  customPathParms[4] = 0.0f;
774  customPathParms[5] = 0.0f;
775  customPathParms[6] = 0.0f;
776  customPathParms[7] = 0.0f;
777  offset.Zero();
778  animationFrames = 0;
779  animationRate = 0.0f;
780  initialAngle = 0.0f;
781  rotationSpeed.from = 0.0f;
782  rotationSpeed.to = 0.0f;
784  size.from = 4.0f;
785  size.to = 4.0f;
786  size.table = NULL;
787  aspect.from = 1.0f;
788  aspect.to = 1.0f;
789  aspect.table = NULL;
790  color.x = 1.0f;
791  color.y = 1.0f;
792  color.z = 1.0f;
793  color.w = 1.0f;
794  fadeColor.x = 0.0f;
795  fadeColor.y = 0.0f;
796  fadeColor.z = 0.0f;
797  fadeColor.w = 0.0f;
798  fadeInFraction = 0.1f;
799  fadeOutFraction = 0.25f;
800  fadeIndexFraction = 0.0f;
801  boundsExpansion = 0.0f;
802  randomDistribution = true;
803  entityColor = false;
804  cycleMsec = ( particleLife + deadTime ) * 1000;
805 }
806 
807 /*
808 ================
809 idParticleStage::NumQuadsPerParticle
810 
811 includes trails and cross faded animations
812 ================
813 */
815  int count = 1;
816 
817  if ( orientation == POR_AIMED ) {
818  int trails = idMath::Ftoi( orientationParms[0] );
819  // each trail stage will add an extra quad
820  count *= ( 1 + trails );
821  }
822 
823  // if we are doing strip-animation, we need to double the number and cross fade them
824  if ( animationFrames > 1 ) {
825  count *= 2;
826  }
827 
828  return count;
829 }
830 
831 /*
832 ===============
833 idParticleStage::ParticleOrigin
834 ===============
835 */
837  if ( customPathType == PPATH_STANDARD ) {
838  //
839  // find intial origin distribution
840  //
841  float radiusSqr, angle1, angle2;
842 
843  switch( distributionType ) {
844  case PDIST_RECT: { // ( sizeX sizeY sizeZ )
845  origin[0] = ( ( randomDistribution ) ? g->random.CRandomFloat() : 1.0f ) * distributionParms[0];
846  origin[1] = ( ( randomDistribution ) ? g->random.CRandomFloat() : 1.0f ) * distributionParms[1];
847  origin[2] = ( ( randomDistribution ) ? g->random.CRandomFloat() : 1.0f ) * distributionParms[2];
848  break;
849  }
850  case PDIST_CYLINDER: { // ( sizeX sizeY sizeZ ringFraction )
851  angle1 = ( ( randomDistribution ) ? g->random.CRandomFloat() : 1.0f ) * idMath::TWO_PI;
852 
853  idMath::SinCos16( angle1, origin[0], origin[1] );
854  origin[2] = ( ( randomDistribution ) ? g->random.CRandomFloat() : 1.0f );
855 
856  // reproject points that are inside the ringFraction to the outer band
857  if ( distributionParms[3] > 0.0f ) {
858  radiusSqr = origin[0] * origin[0] + origin[1] * origin[1];
859  if ( radiusSqr < distributionParms[3] * distributionParms[3] ) {
860  // if we are inside the inner reject zone, rescale to put it out into the good zone
861  float f = sqrt( radiusSqr ) / distributionParms[3];
862  float invf = 1.0f / f;
863  float newRadius = distributionParms[3] + f * ( 1.0f - distributionParms[3] );
864  float rescale = invf * newRadius;
865 
866  origin[0] *= rescale;
867  origin[1] *= rescale;
868  }
869  }
870  origin[0] *= distributionParms[0];
871  origin[1] *= distributionParms[1];
872  origin[2] *= distributionParms[2];
873  break;
874  }
875  case PDIST_SPHERE: { // ( sizeX sizeY sizeZ ringFraction )
876  // iterating with rejection is the only way to get an even distribution over a sphere
877  if ( randomDistribution ) {
878  do {
879  origin[0] = g->random.CRandomFloat();
880  origin[1] = g->random.CRandomFloat();
881  origin[2] = g->random.CRandomFloat();
882  radiusSqr = origin[0] * origin[0] + origin[1] * origin[1] + origin[2] * origin[2];
883  } while( radiusSqr > 1.0f );
884  } else {
885  origin.Set( 1.0f, 1.0f, 1.0f );
886  radiusSqr = 3.0f;
887  }
888 
889  if ( distributionParms[3] > 0.0f ) {
890  // we could iterate until we got something that also satisfied ringFraction,
891  // but for narrow rings that could be a lot of work, so reproject inside points instead
892  if ( radiusSqr < distributionParms[3] * distributionParms[3] ) {
893  // if we are inside the inner reject zone, rescale to put it out into the good zone
894  float f = sqrt( radiusSqr ) / distributionParms[3];
895  float invf = 1.0f / f;
896  float newRadius = distributionParms[3] + f * ( 1.0f - distributionParms[3] );
897  float rescale = invf * newRadius;
898 
899  origin[0] *= rescale;
900  origin[1] *= rescale;
901  origin[2] *= rescale;
902  }
903  }
904  origin[0] *= distributionParms[0];
905  origin[1] *= distributionParms[1];
906  origin[2] *= distributionParms[2];
907  break;
908  }
909  }
910 
911  // offset will effect all particle origin types
912  // add this before the velocity and gravity additions
913  origin += offset;
914 
915  //
916  // add the velocity over time
917  //
918  idVec3 dir;
919 
920  switch( directionType ) {
921  case PDIR_CONE: {
922  // angle is the full angle, so 360 degrees is any spherical direction
924  angle2 = g->random.CRandomFloat() * idMath::PI;
925 
926  float s1, c1, s2, c2;
927  idMath::SinCos16( angle1, s1, c1 );
928  idMath::SinCos16( angle2, s2, c2 );
929 
930  dir[0] = s1 * c2;
931  dir[1] = s1 * s2;
932  dir[2] = c1;
933  break;
934  }
935  case PDIR_OUTWARD: {
936  dir = origin;
937  dir.Normalize();
938  dir[2] += directionParms[0];
939  break;
940  }
941  }
942 
943  // add speed
944  float iSpeed = speed.Integrate( g->frac, g->random );
945  origin += dir * iSpeed * particleLife;
946 
947  } else {
948  //
949  // custom paths completely override both the origin and velocity calculations, but still
950  // use the standard gravity
951  //
952  float angle1, angle2, speed1, speed2;
953  switch( customPathType ) {
954  case PPATH_HELIX: { // ( sizeX sizeY sizeZ radialSpeed axialSpeed )
955  speed1 = g->random.CRandomFloat();
956  speed2 = g->random.CRandomFloat();
957  angle1 = g->random.RandomFloat() * idMath::TWO_PI + customPathParms[3] * speed1 * g->age;
958 
959  float s1, c1;
960  idMath::SinCos16( angle1, s1, c1 );
961 
962  origin[0] = c1 * customPathParms[0];
963  origin[1] = s1 * customPathParms[1];
964  origin[2] = g->random.RandomFloat() * customPathParms[2] + customPathParms[4] * speed2 * g->age;
965  break;
966  }
967  case PPATH_FLIES: { // ( radialSpeed axialSpeed size )
968  speed1 = idMath::ClampFloat( 0.4f, 1.0f, g->random.CRandomFloat() );
969  speed2 = idMath::ClampFloat( 0.4f, 1.0f, g->random.CRandomFloat() );
970  angle1 = g->random.RandomFloat() * idMath::PI * 2 + customPathParms[0] * speed1 * g->age;
971  angle2 = g->random.RandomFloat() * idMath::PI * 2 + customPathParms[1] * speed1 * g->age;
972 
973  float s1, c1, s2, c2;
974  idMath::SinCos16( angle1, s1, c1 );
975  idMath::SinCos16( angle2, s2, c2 );
976 
977  origin[0] = c1 * c2;
978  origin[1] = s1 * c2;
979  origin[2] = -s2;
980  origin *= customPathParms[2];
981  break;
982  }
983  case PPATH_ORBIT: { // ( radius speed axis )
984  angle1 = g->random.RandomFloat() * idMath::TWO_PI + customPathParms[1] * g->age;
985 
986  float s1, c1;
987  idMath::SinCos16( angle1, s1, c1 );
988 
989  origin[0] = c1 * customPathParms[0];
990  origin[1] = s1 * customPathParms[0];
991  origin.ProjectSelfOntoSphere( customPathParms[0] );
992  break;
993  }
994  case PPATH_DRIP: { // ( speed )
995  origin[0] = 0.0f;
996  origin[1] = 0.0f;
997  origin[2] = -( g->age * customPathParms[0] );
998  break;
999  }
1000  default: {
1001  common->Error( "idParticleStage::ParticleOrigin: bad customPathType" );
1002  }
1003  }
1004 
1005  origin += offset;
1006  }
1007 
1008  // adjust for the per-particle smoke offset
1009  origin *= g->axis;
1010  origin += g->origin;
1011 
1012  // add gravity after adjusting for axis
1013  if ( worldGravity ) {
1014  idVec3 gra( 0, 0, -gravity );
1015  gra *= g->renderEnt->axis.Transpose();
1016  origin += gra * g->age * g->age;
1017  } else {
1018  origin[2] -= gravity * g->age * g->age;
1019  }
1020 }
1021 
1022 /*
1023 ==================
1024 idParticleStage::ParticleVerts
1025 ==================
1026 */
1028  float psize = size.Eval( g->frac, g->random );
1029  float paspect = aspect.Eval( g->frac, g->random );
1030 
1031  float width = psize;
1032  float height = psize * paspect;
1033 
1034  idVec3 left, up;
1035 
1036  if ( orientation == POR_AIMED ) {
1037  // reset the values to an earlier time to get a previous origin
1038  idRandom currentRandom = g->random;
1039  float currentAge = g->age;
1040  float currentFrac = g->frac;
1041  idDrawVert *verts_p = verts;
1042  idVec3 stepOrigin = origin;
1043  idVec3 stepLeft;
1044  int numTrails = idMath::Ftoi( orientationParms[0] );
1045  float trailTime = orientationParms[1];
1046 
1047  if ( trailTime == 0 ) {
1048  trailTime = 0.5f;
1049  }
1050 
1051  float height = 1.0f / ( 1 + numTrails );
1052  float t = 0;
1053 
1054  for ( int i = 0 ; i <= numTrails ; i++ ) {
1055  g->random = g->originalRandom;
1056  g->age = currentAge - ( i + 1 ) * trailTime / ( numTrails + 1 ); // time to back up
1057  g->frac = g->age / particleLife;
1058 
1059  idVec3 oldOrigin;
1060  ParticleOrigin( g, oldOrigin );
1061 
1062  up = stepOrigin - oldOrigin; // along the direction of travel
1063 
1064  idVec3 forwardDir;
1065  g->renderEnt->axis.ProjectVector( g->renderView->viewaxis[0], forwardDir );
1066 
1067  up -= ( up * forwardDir ) * forwardDir;
1068 
1069  up.Normalize();
1070 
1071 
1072  left = up.Cross( forwardDir );
1073  left *= psize;
1074 
1075  verts_p[0] = verts[0];
1076  verts_p[1] = verts[1];
1077  verts_p[2] = verts[2];
1078  verts_p[3] = verts[3];
1079 
1080  if ( i == 0 ) {
1081  verts_p[0].xyz = stepOrigin - left;
1082  verts_p[1].xyz = stepOrigin + left;
1083  } else {
1084  verts_p[0].xyz = stepOrigin - stepLeft;
1085  verts_p[1].xyz = stepOrigin + stepLeft;
1086  }
1087  verts_p[2].xyz = oldOrigin - left;
1088  verts_p[3].xyz = oldOrigin + left;
1089 
1090  // modify texcoords
1091  verts_p[0].st[0] = verts[0].st[0];
1092  verts_p[0].st[1] = t;
1093 
1094  verts_p[1].st[0] = verts[1].st[0];
1095  verts_p[1].st[1] = t;
1096 
1097  verts_p[2].st[0] = verts[2].st[0];
1098  verts_p[2].st[1] = t+height;
1099 
1100  verts_p[3].st[0] = verts[3].st[0];
1101  verts_p[3].st[1] = t+height;
1102 
1103  t += height;
1104 
1105  verts_p += 4;
1106 
1107  stepOrigin = oldOrigin;
1108  stepLeft = left;
1109  }
1110 
1111  g->random = currentRandom;
1112  g->age = currentAge;
1113  g->frac = currentFrac;
1114 
1115  return 4 * (numTrails+1);
1116  }
1117 
1118  //
1119  // constant rotation
1120  //
1121  float angle;
1122 
1123  angle = ( initialAngle ) ? initialAngle : 360 * g->random.RandomFloat();
1124 
1125  float angleMove = rotationSpeed.Integrate( g->frac, g->random ) * particleLife;
1126  // have hald the particles rotate each way
1127  if ( g->index & 1 ) {
1128  angle += angleMove;
1129  } else {
1130  angle -= angleMove;
1131  }
1132 
1133  angle = angle / 180 * idMath::PI;
1134  float c = idMath::Cos16( angle );
1135  float s = idMath::Sin16( angle );
1136 
1137  if ( orientation == POR_Z ) {
1138  // oriented in entity space
1139  left[0] = s;
1140  left[1] = c;
1141  left[2] = 0;
1142  up[0] = c;
1143  up[1] = -s;
1144  up[2] = 0;
1145  } else if ( orientation == POR_X ) {
1146  // oriented in entity space
1147  left[0] = 0;
1148  left[1] = c;
1149  left[2] = s;
1150  up[0] = 0;
1151  up[1] = -s;
1152  up[2] = c;
1153  } else if ( orientation == POR_Y ) {
1154  // oriented in entity space
1155  left[0] = c;
1156  left[1] = 0;
1157  left[2] = s;
1158  up[0] = -s;
1159  up[1] = 0;
1160  up[2] = c;
1161  } else {
1162  // oriented in viewer space
1163  idVec3 entityLeft, entityUp;
1164 
1165  g->renderEnt->axis.ProjectVector( g->renderView->viewaxis[1], entityLeft );
1166  g->renderEnt->axis.ProjectVector( g->renderView->viewaxis[2], entityUp );
1167 
1168  left = entityLeft * c + entityUp * s;
1169  up = entityUp * c - entityLeft * s;
1170  }
1171 
1172  left *= width;
1173  up *= height;
1174 
1175  verts[0].xyz = origin - left + up;
1176  verts[1].xyz = origin + left + up;
1177  verts[2].xyz = origin - left - up;
1178  verts[3].xyz = origin + left - up;
1179 
1180  return 4;
1181 }
1182 
1183 /*
1184 ==================
1185 idParticleStage::ParticleTexCoords
1186 ==================
1187 */
1189  float s, width;
1190  float t, height;
1191 
1192  if ( animationFrames > 1 ) {
1193  width = 1.0f / animationFrames;
1194  float floatFrame;
1195  if ( animationRate ) {
1196  // explicit, cycling animation
1197  floatFrame = g->age * animationRate;
1198  } else {
1199  // single animation cycle over the life of the particle
1200  floatFrame = g->frac * animationFrames;
1201  }
1202  int intFrame = (int)floatFrame;
1203  g->animationFrameFrac = floatFrame - intFrame;
1204  s = width * intFrame;
1205  } else {
1206  s = 0.0f;
1207  width = 1.0f;
1208  }
1209 
1210  t = 0.0f;
1211  height = 1.0f;
1212 
1213  verts[0].st[0] = s;
1214  verts[0].st[1] = t;
1215 
1216  verts[1].st[0] = s+width;
1217  verts[1].st[1] = t;
1218 
1219  verts[2].st[0] = s;
1220  verts[2].st[1] = t+height;
1221 
1222  verts[3].st[0] = s+width;
1223  verts[3].st[1] = t+height;
1224 }
1225 
1226 /*
1227 ==================
1228 idParticleStage::ParticleColors
1229 ==================
1230 */
1232  float fadeFraction = 1.0f;
1233 
1234  // most particles fade in at the beginning and fade out at the end
1235  if ( g->frac < fadeInFraction ) {
1236  fadeFraction *= ( g->frac / fadeInFraction );
1237  }
1238  if ( 1.0f - g->frac < fadeOutFraction ) {
1239  fadeFraction *= ( ( 1.0f - g->frac ) / fadeOutFraction );
1240  }
1241 
1242  // individual gun smoke particles get more and more faded as the
1243  // cycle goes on (note that totalParticles won't be correct for a surface-particle deform)
1244  if ( fadeIndexFraction ) {
1245  float indexFrac = ( totalParticles - g->index ) / (float)totalParticles;
1246  if ( indexFrac < fadeIndexFraction ) {
1247  fadeFraction *= indexFrac / fadeIndexFraction;
1248  }
1249  }
1250 
1251  for ( int i = 0 ; i < 4 ; i++ ) {
1252  float fcolor = ( ( entityColor ) ? g->renderEnt->shaderParms[i] : color[i] ) * fadeFraction + fadeColor[i] * ( 1.0f - fadeFraction );
1253  int icolor = idMath::FtoiFast( fcolor * 255.0f );
1254  if ( icolor < 0 ) {
1255  icolor = 0;
1256  } else if ( icolor > 255 ) {
1257  icolor = 255;
1258  }
1259  verts[0].color[i] =
1260  verts[1].color[i] =
1261  verts[2].color[i] =
1262  verts[3].color[i] = icolor;
1263  }
1264 }
1265 
1266 /*
1267 ================
1268 idParticleStage::CreateParticle
1269 
1270 Returns 0 if no particle is created because it is completely faded out
1271 Returns 4 if a normal quad is created
1272 Returns 8 if two cross faded quads are created
1273 
1274 Vertex order is:
1275 
1276 0 1
1277 2 3
1278 ================
1279 */
1281  idVec3 origin;
1282 
1283  verts[0].Clear();
1284  verts[1].Clear();
1285  verts[2].Clear();
1286  verts[3].Clear();
1287 
1288  ParticleColors( g, verts );
1289 
1290  // if we are completely faded out, kill the particle
1291  if ( verts[0].color[0] == 0 && verts[0].color[1] == 0 && verts[0].color[2] == 0 && verts[0].color[3] == 0 ) {
1292  return 0;
1293  }
1294 
1295  ParticleOrigin( g, origin );
1296 
1297  ParticleTexCoords( g, verts );
1298 
1299  int numVerts = ParticleVerts( g, origin, verts );
1300 
1301  if ( animationFrames <= 1 ) {
1302  return numVerts;
1303  }
1304 
1305  // if we are doing strip-animation, we need to double the quad and cross fade it
1306  float width = 1.0f / animationFrames;
1307  float frac = g->animationFrameFrac;
1308  float iFrac = 1.0f - frac;
1309  for ( int i = 0 ; i < numVerts ; i++ ) {
1310  verts[numVerts + i] = verts[i];
1311 
1312  verts[numVerts + i].st[0] += width;
1313 
1314  verts[numVerts + i].color[0] *= frac;
1315  verts[numVerts + i].color[1] *= frac;
1316  verts[numVerts + i].color[2] *= frac;
1317  verts[numVerts + i].color[3] *= frac;
1318 
1319  verts[i].color[0] *= iFrac;
1320  verts[i].color[1] *= iFrac;
1321  verts[i].color[2] *= iFrac;
1322  verts[i].color[3] *= iFrac;
1323  }
1324 
1325  return numVerts * 2;
1326 }
1327 
1328 /*
1329 ==================
1330 idParticleStage::GetCustomPathName
1331 ==================
1332 */
1335  return ParticleCustomDesc[index].name;
1336 }
1337 
1338 /*
1339 ==================
1340 idParticleStage::GetCustomPathDesc
1341 ==================
1342 */
1345  return ParticleCustomDesc[index].desc;
1346 }
1347 
1348 /*
1349 ==================
1350 idParticleStage::NumCustomPathParms
1351 ==================
1352 */
1355  return ParticleCustomDesc[index].count;
1356 }
1357 
1358 /*
1359 ==================
1360 idParticleStage::SetCustomPathType
1361 ==================
1362 */
1365  for ( int i = 0; i < CustomParticleCount; i ++ ) {
1366  if ( idStr::Icmp( p, ParticleCustomDesc[i].name ) == 0 ) {
1367  customPathType = static_cast<prtCustomPth_t>( i );
1368  break;
1369  }
1370  }
1371 }
1372 
1373 /*
1374 ==================
1375 idParticleStage::operator=
1376 ==================
1377 */
1379  material = src.material;
1381  cycles = src.cycles;
1382  cycleMsec = src.cycleMsec;
1384  particleLife = src.particleLife;
1385  timeOffset = src.timeOffset;
1386  deadTime = src.deadTime;
1393  directionParms[0] = src.directionParms[0];
1394  directionParms[1] = src.directionParms[1];
1395  directionParms[2] = src.directionParms[2];
1396  directionParms[3] = src.directionParms[3];
1397  speed = src.speed;
1398  gravity = src.gravity;
1399  worldGravity = src.worldGravity;
1401  entityColor = src.entityColor;
1403  customPathParms[0] = src.customPathParms[0];
1404  customPathParms[1] = src.customPathParms[1];
1405  customPathParms[2] = src.customPathParms[2];
1406  customPathParms[3] = src.customPathParms[3];
1407  customPathParms[4] = src.customPathParms[4];
1408  customPathParms[5] = src.customPathParms[5];
1409  customPathParms[6] = src.customPathParms[6];
1410  customPathParms[7] = src.customPathParms[7];
1411  offset = src.offset;
1414  initialAngle = src.initialAngle;
1416  orientation = src.orientation;
1417  orientationParms[0] = src.orientationParms[0];
1418  orientationParms[1] = src.orientationParms[1];
1419  orientationParms[2] = src.orientationParms[2];
1420  orientationParms[3] = src.orientationParms[3];
1421  size = src.size;
1422  aspect = src.aspect;
1423  color = src.color;
1424  fadeColor = src.fadeColor;
1428  hidden = src.hidden;
1430  bounds = src.bounds;
1431 }
int GetLineNum(void) const
Definition: DeclManager.h:168
GLubyte g
Definition: glext.h:4662
float Eval(float frac, idRandom &rand) const
idParticleStage * ParseParticleStage(idLexer &src)
prtCustomPth_t
Definition: DeclParticle.h:66
bool AddBounds(const idBounds &a)
Definition: Bounds.h:255
float Integrate(float frac, idRandom &rand) const
void ParseParametric(idLexer &src, idParticleParm *parm)
float Normalize(void)
Definition: Vector.h:646
bool ReplaceSourceFileText(void)
Definition: DeclManager.h:184
idMat3 mat3_identity(idVec3(1, 0, 0), idVec3(0, 1, 0), idVec3(0, 0, 1))
void Clear(void)
Definition: DrawVert.h:73
void void bool HadError(void) const
Definition: Lexer.cpp:1794
const char * GetFileName(void) const
Definition: DeclManager.h:171
const int DECL_LEXER_FLAGS
Definition: DeclManager.h:93
float y
Definition: Vector.h:811
const int CustomParticleCount
idStr & StripQuotes(void)
Definition: Str.cpp:665
idMat3 Transpose(void) const
Definition: Matrix.h:677
void Set(const float x, const float y, const float z)
Definition: Vector.h:409
idVec3 xyz
Definition: DrawVert.h:42
static const float PI
Definition: Math.h:205
float fadeIndexFraction
Definition: DeclParticle.h:180
float z
Definition: Vector.h:812
float z
Definition: Vector.h:320
case const int
Definition: Callbacks.cpp:52
void Zero(void)
Definition: Vector.h:880
GLenum GLsizei GLenum GLenum const GLvoid * table
Definition: glext.h:2846
static float ClampFloat(float min, float max, float value)
Definition: Math.h:893
bool ParseBool(void)
Definition: Lexer.cpp:1249
const char * GetName(void) const
Definition: DeclManager.h:140
Definition: Vector.h:316
case const float
Definition: Callbacks.cpp:62
virtual idDecl * CreateNewDecl(declType_t type, const char *name, const char *fileName)=0
const renderEntity_t * renderEnt
Definition: DeclParticle.h:86
virtual size_t Size(void) const
bool Save(const char *fileName=NULL)
static const float M_DEG2RAD
Definition: Math.h:214
void Clear(void)
Definition: Bounds.h:201
Definition: Token.h:71
void SetFlags(int flags)
Definition: Lexer.h:298
virtual const idMaterial * FindMaterial(const char *name, bool makeDefault=true)=0
float GetVolume(void) const
Definition: Bounds.h:215
float ParseFloat(bool *errorFlag=NULL)
Definition: Lexer.cpp:1264
GLdouble s
Definition: glext.h:2935
const char * name
GLuint src
Definition: glext.h:5390
idVec3 Cross(const idVec3 &a) const
Definition: Vector.h:619
virtual bool Parse(const char *text, const int textLength)
int ReadTokenOnLine(idToken *token)
Definition: Lexer.cpp:1172
float x
Definition: Vector.h:318
void ParticleOrigin(particleGen_t *g, idVec3 &origin) const
int i
Definition: process.py:33
GLintptr offset
Definition: glext.h:3113
int ParseInt(void)
Definition: Lexer.cpp:1227
int Icmp(const char *text) const
Definition: Str.h:667
static int Ftoi(float f)
Definition: Math.h:797
static float Cos16(float a)
Definition: Math.h:350
void GetStageBounds(idParticleStage *stage)
idParticleParm aspect
Definition: DeclParticle.h:174
idParticleParm rotationSpeed
Definition: DeclParticle.h:168
idRandom originalRandom
Definition: DeclParticle.h:96
static float Sin16(float a)
Definition: Math.h:314
void ParticleColors(particleGen_t *g, idDrawVert *verts) const
const ParticleParmDesc ParticleDistributionDesc[]
Definition: File.h:50
bool AddPoint(const idVec3 &v)
Definition: Bounds.h:226
idVec2 st
Definition: DrawVert.h:43
Definition: Lexer.h:137
void Error(const char *str,...) id_attribute((format(printf
Definition: Lexer.cpp:215
GLuint GLuint GLsizei count
Definition: glext.h:2845
void ParticleTexCoords(particleGen_t *g, idDrawVert *verts) const
void SetSeed(int seed)
Definition: Random.h:62
void SetCustomPathType(const char *p)
GLuint index
Definition: glext.h:3476
const GLubyte * c
Definition: glext.h:4677
float RandomFloat(void)
Definition: Random.h:82
static int FtoiFast(float f)
Definition: Math.h:801
idVec3 vec3_origin(0.0f, 0.0f, 0.0f)
const char * GetDataPtr(void) const
Definition: File.h:144
float animationFrameFrac
Definition: DeclParticle.h:97
idCommon * common
Definition: Common.cpp:206
#define NULL
Definition: Lib.h:88
virtual int CreateParticle(particleGen_t *g, idDrawVert *verts) const
virtual const idDecl * FindType(declType_t type, const char *name, bool makeDefault=true)=0
const renderView_t * renderView
Definition: DeclParticle.h:87
float y
Definition: Vector.h:319
prtDirection_t directionType
Definition: DeclParticle.h:146
float w
Definition: Vector.h:813
prtDistribution_t distributionType
Definition: DeclParticle.h:143
const char * GetCustomPathName()
const idMaterial * material
Definition: DeclParticle.h:128
void DeleteContents(bool clear)
Definition: List.h:207
void operator=(const idParticleStage &src)
virtual int WriteFloatString(const char *fmt,...) id_attribute((format(printf
Definition: File.cpp:294
GLenum GLsizei width
Definition: glext.h:2846
void UnreadToken(const idToken *token)
Definition: Lexer.cpp:1159
virtual void Printf(const char *fmt,...) id_attribute((format(printf
float orientationParms[4]
Definition: DeclParticle.h:171
idList< idParticleStage * > stages
Definition: DeclParticle.h:204
static void SinCos16(float a, float &s, float &c)
Definition: Math.h:406
int LoadMemory(const char *ptr, int length, const char *name, int startLine=1)
Definition: Lexer.cpp:1646
idBounds Expand(const float d) const
Definition: Bounds.h:317
idBounds bounds
Definition: DeclParticle.h:205
const char * GetCustomPathDesc()
GLenum GLsizei GLsizei height
Definition: glext.h:2856
prtCustomPth_t customPathType
Definition: DeclParticle.h:157
void SetText(const char *text)
Definition: DeclManager.h:180
void ProjectVector(const idVec3 &src, idVec3 &dst) const
Definition: Matrix.h:628
idDeclManager * declManager
idRandom random
Definition: DeclParticle.h:90
static const float TWO_PI
Definition: Math.h:206
bool IsNumeric(void) const
Definition: Str.h:833
int ParticleVerts(particleGen_t *g, const idVec3 origin, idDrawVert *verts) const
int Append(const type &obj)
Definition: List.h:646
void void Warning(const char *str,...) id_attribute((format(printf
Definition: Lexer.cpp:241
idParticleParm speed
Definition: DeclParticle.h:149
void ProjectSelfOntoSphere(const float radius)
Definition: Vector.cpp:284
void ParseParms(idLexer &src, float *parms, int maxParms)
tuple f
Definition: idal.py:89
virtual void FreeData(void)
int Num(void) const
Definition: List.h:265
const GLcharARB * name
Definition: glext.h:3629
const char * desc
GLsizeiptr size
Definition: glext.h:3112
const idDeclTable * table
Definition: DeclParticle.h:44
virtual const char * DefaultDefinition(void) const
float distributionParms[4]
Definition: DeclParticle.h:144
void WriteStage(idFile *f, idParticleStage *stage)
byte color[4]
Definition: DrawVert.h:46
const char * c_str(void) const
Definition: Str.h:487
int SkipUntilString(const char *string)
Definition: Lexer.cpp:1097
idBounds & ExpandSelf(const float d)
Definition: Bounds.h:322
float directionParms[4]
Definition: DeclParticle.h:147
void MakeDefault(void)
Definition: DeclManager.h:190
prtOrientation_t orientation
Definition: DeclParticle.h:170
virtual void Error(const char *fmt,...) id_attribute((format(printf
GLfloat GLfloat p
Definition: glext.h:4674
idMat3 viewaxis
Definition: RenderWorld.h:216
bool RebuildTextSource(void)
float x
Definition: Vector.h:810
void Zero(void)
Definition: Vector.h:415
const ParticleParmDesc ParticleCustomDesc[]
float shaderParms[MAX_ENTITY_SHADER_PARMS]
Definition: RenderWorld.h:127
const ParticleParmDesc ParticleOrientationDesc[]
int ReadToken(idToken *token)
Definition: Lexer.cpp:820
const ParticleParmDesc ParticleDirectionDesc[]
float CRandomFloat(void)
Definition: Random.h:86
float customPathParms[8]
Definition: DeclParticle.h:158
void WriteParticleParm(idFile *f, idParticleParm *parm, const char *name)
virtual int NumQuadsPerParticle() const
idParticleParm size
Definition: DeclParticle.h:173
GLdouble GLdouble t
Definition: glext.h:2943