Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
halo_system.cpp
Go to the documentation of this file.
1 #include <vector>
2 #include <string>
3 #include "vec.h"
4 #include "matrix.h"
5 #include "cmd/unit_generic.h"
6 #include "halo_system.h"
7 #include "universe.h"
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include "vegastrike.h"
11 #include "mesh.h"
12 #include "vs_globals.h"
13 #include "xml_support.h"
14 #include "config_xml.h"
15 #include "gfx/particle.h"
16 #include "lin_time.h"
17 #include "animation.h"
18 #include "car_assist.h"
20 
21 #include "cmd/unit_collide.h"
22 
23 #define HALO_SMOOTHING_UP_FACTOR (0.02)
24 #define HALO_SMOOTHING_DOWN_FACTOR (0.01)
25 #define HALO_STEERING_UP_FACTOR (0.00)
26 #define HALO_STEERING_DOWN_FACTOR (0.01)
27 #define HALO_STABILIZATION_RANGE (0.25)
28 
29 static float ffmax( float a, float b )
30 {
31  return a > b ? a : b;
32 }
33 void DoParticles( QVector pos, float percent, const Vector &velocity, float radial_size, float particle_size, int faction )
34 {
35  percent = 1-percent;
36  int i = rand();
37  static float scale = XMLSupport::parse_float( vs_config->getVariable( "graphics", "sparklescale", "8" ) );
38  static float sspeed = XMLSupport::parse_float( vs_config->getVariable( "graphics", "sparklespeed", ".5" ) );
39  static float flare = XMLSupport::parse_float( vs_config->getVariable( "graphics", "sparkleflare", ".15" ) );
40  static float spread = XMLSupport::parse_float( vs_config->getVariable( "graphics", "sparklespread", ".04" ) );
41  static float absspeed = XMLSupport::parse_float( vs_config->getVariable( "graphics", "sparkleabsolutespeed", ".02" ) );
42  static bool fixed_size = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "sparklefixedsize", "0" ) );
43  if (i < RAND_MAX*percent*scale) {
44  ParticlePoint pp;
45  float r1 = rand()/( (float) RAND_MAX*.5 )-1;
46  float r2 = rand()/( (float) RAND_MAX*.5 )-1;
47  float r3 = rand()/( (float) RAND_MAX*.5 )-1;
48  QVector rand( r1, r2, r3 );
49  pp.loc = pos+rand*radial_size*flare;
50  const float *col = FactionUtil::GetSparkColor( faction );
51  pp.col.r = col[0];
52  pp.col.g = col[1];
53  pp.col.b = col[2];
54  pp.col.a = 1.0f;
55  static float sciz = XMLSupport::parse_float( vs_config->getVariable( "graphics", "sparklesizeenginerelative", ".125" ) );
56  particleTrail.AddParticle( pp, rand*(ffmax(
57  velocity.Magnitude(),
58  absspeed )*spread+absspeed)+velocity*sspeed,
59  fixed_size ? sciz : (sqrt( particle_size )*sciz) );
60  }
61 }
62 
63 void LaunchOneParticle( const Matrix &mat, const Vector &vel, unsigned int seed, Unit *mush, float hull, int faction )
64 {
65  static float sciz =
66  XMLSupport::parse_float( vs_config->getVariable( "graphics", "sparkleenginesizerelativetoship", "0.1875" ) );
67  if (mush) {
68  bool done = false;
69  collideTrees *colTrees = mush->colTrees;
70  if (colTrees) {
71  if ( colTrees->usingColTree() ) {
72  csOPCODECollider *colTree = colTrees->rapidColliders[0];
73  unsigned int numvert = colTree->getNumVertex();
74  if (numvert) {
75  unsigned int whichvert = seed%numvert;
76  QVector v( colTree->getVertex( whichvert ).Cast() );
77  v = Transform( mat, v );
78  DoParticles( v, hull, vel, 0, mush->rSize()*sciz, faction );
79  done = true;
80  }
81  }
82  }
83  if (!done) {
84  // maybe ray collision?
85  }
86  if (!done) {
87  unsigned int siz = (unsigned int) ( 2*mush->rSize() );
88  if (siz != 0) {
89  QVector v( (seed%siz)-siz/2,
90  (seed%siz)-siz/2,
91  (seed%siz)-siz/2 );
92  DoParticles( v, hull, vel, 0, mush->rSize()*sciz, faction );
93  done = true;
94  }
95  }
96  }
97 }
98 
100 {
101  VSCONSTRUCT2( 'h' )
102  mesh = NULL;
103  activation = 0;
104  oscale = 0;
105  sparkle_accum = 0;
106 }
107 
109 {
110  this->loc = loc;
111  this->size = size;
112 }
113 
114 unsigned int HaloSystem::AddHalo( const char *filename,
115  const QVector &loc,
116  const Vector &size,
117  const GFXColor &col,
118  std::string type,
119  float activation_accel )
120 {
121 #ifdef CAR_SIM
122  ani.push_back( new Animation( "flare6.ani", 1, .1, MIPMAP, true, true, col ) );
123  ani.back()->SetDimensions( size.i, size.j );
124  ani.back()->SetPosition( loc );
125  halo_type.push_back( CAR::type_map.lookup( type ) ); //should default to headlights
126 #endif
127  if (mesh == NULL) {
129  mesh = Mesh::LoadMesh( ( string( filename ) ).c_str(), Vector( 1, 1, 1 ), neutralfac, NULL );
130  static float gs = XMLSupport::parse_float( vs_config->getVariable( "physics", "game_speed", "1" ) );
131  activation = activation_accel*gs;
132  }
133  static float engine_scale = XMLSupport::parse_float( vs_config->getVariable( "graphics", "engine_radii_scale", ".4" ) );
134  static float engine_length = XMLSupport::parse_float( vs_config->getVariable( "graphics", "engine_length_scale", "1.25" ) );
135 
136  halo.push_back( MyIndHalo( loc, Vector( size.i*engine_scale, size.j*engine_scale, size.k*engine_length ) ) );
137  return halo.size()-1;
138 }
139 using std::vector;
140 void HaloSystem::SetSize( unsigned int which, const Vector &size )
141 {
142  halo[which].size = size;
143 #ifdef CAR_SIM
144  ani[which]->SetDimensions( size.i, size.j );
145 #endif
146 }
147 void HaloSystem::SetPosition( unsigned int which, const QVector &loc )
148 {
149  halo[which].loc = loc;
150 #ifdef CAR_SIM
151  ani[which]->SetPosition( loc );
152 #endif
153 }
154 static float mymin( float a, float b )
155 {
156  return a > b ? b : a;
157 }
158 static float mymax( float a, float b )
159 {
160  return a > b ? a : b;
161 }
162 static float HaloAccelSmooth( float linaccel, float olinaccel, float maxlinaccel )
163 {
164  linaccel = mymax( 0, mymin( maxlinaccel, linaccel ) ); //Clamp input, somehow, sometimes it's not clamped
165  float phase = pow( ( (linaccel > olinaccel) ? HALO_SMOOTHING_UP_FACTOR : HALO_SMOOTHING_DOWN_FACTOR ), GetElapsedTime() );
166  float olinaccel2;
167  if (linaccel > olinaccel)
168  olinaccel2 = mymin( linaccel, olinaccel+maxlinaccel*HALO_STEERING_UP_FACTOR );
169 
170  else
171  olinaccel2 = mymax( linaccel, olinaccel-maxlinaccel*HALO_STEERING_DOWN_FACTOR );
172  linaccel = (1-phase)*linaccel+phase*olinaccel2;
173  linaccel = mymax( 0, mymin( maxlinaccel, linaccel ) );
174  return linaccel;
175 }
176 
177 bool HaloSystem::ShouldDraw( const Matrix &trans,
178  const Vector &velocity,
179  const Vector &accel,
180  float maxaccel,
181  float maxvelocity )
182 {
183  static bool halos_by_velocity = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "halos_by_velocity", "false" ) );
184  if (halo.size() == 0)
185  return false; //Any doubt?
186 
187  Vector thrustvector = trans.getR().Normalize();
188  if (halos_by_velocity) {
189  float linvel = velocity.Dot( thrustvector );
190  return linvel > activation;
191  } else {
192  if (maxaccel <= 0) maxaccel = 1;
193  if (maxvelocity <= 0) maxvelocity = 1;
194  float linaccel = HaloAccelSmooth( accel.Dot( thrustvector )/maxaccel, oscale, 1.0f );
195  return linaccel > activation*maxaccel;
196  }
197 }
198 void HaloSystem::Draw( const Matrix &trans,
199  const Vector &scale,
200  int halo_alpha,
201  float nebdist,
202  float hullpercent,
203  const Vector &velocity,
204  const Vector &accel,
205  float maxaccel,
206  float maxvelocity,
207  int faction )
208 {
209 #ifdef CAR_SIM
210  for (unsigned int i = 0; i < ani.size(); ++i) {
211  int bitwise = scale.j;
212  int typ = 0;
213 #ifdef CAR_SIM
214  typ = halo_type[i];
215 #endif
216  bool drawnow = (typ == CAR::RUNNINGLIGHTS);
217  if ( (typ == CAR::BRAKE && scale.k < .01 && scale.k > -.01) )
218  drawnow = true;
219  if ( (typ == CAR::REVERSE && scale.k <= -.01) )
220  drawnow = true;
221  if (typ == CAR::HEADLIGHTS)
222  if ( scale.j >= CAR::ON_NO_BLINKEN
223  || ( bitwise < CAR::ON_NO_BLINKEN && bitwise > 0 && (bitwise&CAR::FORWARD_BLINKEN) ) )
224  drawnow = true;
225  if (typ == CAR::SIREN)
226  if ( (bitwise > 0) && ( (bitwise >= CAR::ON_NO_BLINKEN) || (bitwise&CAR::SIREN_BLINKEN) ) )
227  drawnow = true;
228  float blink_prob = .8;
229  if (typ == CAR::RIGHTBLINK)
230  if ( (bitwise > 0) && (bitwise < CAR::ON_NO_BLINKEN) && (bitwise&CAR::RIGHT_BLINKEN) )
231  if (rand() < RAND_MAX*blink_prob)
232  drawnow = true;
233  if (typ == CAR::LEFTBLINK)
234  if ( (bitwise > 0) && (bitwise < CAR::ON_NO_BLINKEN) && (bitwise&CAR::LEFT_BLINKEN) )
235  if (rand() < RAND_MAX*blink_prob)
236  drawnow = true;
237  if (drawnow) {
238  ani[i]->SetPosition( Transform( trans, halo[i].loc ) );
239  ani[i]->SetDimensions( scale.i, scale.i );
240  ani[i]->Draw();
241  }
242  }
243 #else
244  if (halo_alpha >= 0) {
245  halo_alpha /= 2;
246  if ( (halo_alpha&0x1) == 0 )
247  halo_alpha += 1;
248  }
249  static bool halos_by_velocity = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "halos_by_velocity", "false" ) );
250 
251  Vector thrustvector = trans.getR().Normalize();
252  if (maxaccel <= 0) maxaccel = 1;
253  if (maxvelocity <= 0) maxvelocity = 1;
254  float value, maxvalue, minvalue;
255  if (halos_by_velocity) {
256  value = velocity.Dot( thrustvector );
257  maxvalue = sqrt( maxvelocity );
258  minvalue = activation;
259  } else {
260  oscale = HaloAccelSmooth( accel.Dot( thrustvector )/maxaccel, oscale, 1.0f );
261  value = oscale;
262  maxvalue = 1.0f;
263  minvalue = activation/maxaccel;
264  }
265  if ( (value > minvalue) && (scale.k > 0) ) {
266  vector< MyIndHalo >::iterator i = halo.begin();
267  for (; i != halo.end(); ++i) {
268  Matrix m = trans;
269  ScaleMatrix( m, Vector( scale.i*i->size.i, scale.j*i->size.j, scale.k*i->size.k*value/maxvalue ) );
270  m.p = Transform( trans, i->loc );
271  static float percentColorChange=XMLSupport::parse_float(vs_config->getVariable("graphics","percent_afterburner_color_change",".5"));
272  static float abRedness=XMLSupport::parse_float(vs_config->getVariable("graphics","afterburner_color_red","1.0"));
273  static float abGreenness=XMLSupport::parse_float(vs_config->getVariable("graphics","afterburner_color_green","0.0"));
274  static float abBlueness=XMLSupport::parse_float(vs_config->getVariable("graphics","afterburner_color_blue","0.0"));
275  static float percentRedness=XMLSupport::parse_float(vs_config->getVariable("graphics","engine_color_red","1.0"));
276  static float percentGreenness=XMLSupport::parse_float(vs_config->getVariable("graphics","engine_color_green","1.0"));
277  static float percentBlueness=XMLSupport::parse_float(vs_config->getVariable("graphics","engine_color_blue","1.0"));
278  GFXColor blend=GFXColor(percentRedness,percentGreenness,percentBlueness,1);
279 
280  if (value>maxvalue*percentColorChange) {
281  float test=value-maxvalue*percentColorChange;
282  test/=maxvalue*percentColorChange;
283  if (!(test<1.0)) test=1.0;
284  blend=GFXColor(abRedness*test+percentRedness*(1.0-test),abGreenness*test+percentGreenness*(1.0-test),abBlueness*test+percentBlueness*(1.0-test),1.0);
285 
286  }
287  MeshFX xtraFX=MeshFX(1.0,1.0,
288  true,
289  GFXColor(1,1,1,1),
290  GFXColor(1,1,1,1),
291  GFXColor(1,1,1,1),
292  blend);
293 
294  mesh->Draw( 50000000000000.0, m, 1, halo_alpha, nebdist, 0,false,&xtraFX );
295  if (hullpercent < .99) {
296  static float sparklerate = XMLSupport::parse_float( vs_config->getVariable( "graphics", "halosparklerate", "20" ) );
297  sparkle_accum += GetElapsedTime()*sparklerate;
298  int spawn = (int) (sparkle_accum);
299  sparkle_accum -= spawn;
300  while (spawn-- > 0)
301  DoParticles( m.p, hullpercent, velocity, mesh->rSize()*scale.i, mesh->rSize()*scale.i, faction );
302  }
303  }
304  }
305 #endif
306 }
308 {
309 #ifdef CAR_SIM
310  for (unsigned int i = 0; i < ani.size(); i++)
311  delete ani[i];
312  ani.clear();
313 #endif
315  if (mesh)
316  delete mesh;
317 }
318