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
cont_terrain.cpp
Go to the documentation of this file.
1 #include "cont_terrain.h"
2 #include "universe.h"
3 #include "star_system.h"
4 #include "gfx/matrix.h"
5 #include "vegastrike.h"
6 #include "gfx/mesh.h"
7 #include "unit_generic.h"
8 #include "collide2/Stdafx.h"
11 #include "collide2/basecollider.h"
12 
13 #include "unit_collide.h"
14 #include "vs_globals.h"
15 #include "config_xml.h"
16 ContinuousTerrain::ContinuousTerrain( const char *filename, const Vector &Scales, const float mass )
17 {
18  float tmass;
19  FILE *fp = VSFileSystem::vs_open( filename, "r" );
20  if (fp) {
21  VSFileSystem::vs_fscanf( fp, "%d %f\n<%f %f %f>", &width, &tmass, &this->Scales.i, &this->Scales.j, &this->Scales.k );
22  if (mass)
23  tmass = mass;
24  if (Scales.i && Scales.j && Scales.k) {
25  this->Scales.i *= Scales.i;
26  this->Scales.j *= Scales.j;
27  this->Scales.k *= Scales.k;
28  }
29  numcontterr = width*width;
30  data = new Terrain*[numcontterr];
31  md = new MeshDat[numcontterr];
32  std::string *filenames = new std::string[numcontterr];
33  int i;
34  for (i = 0; i < numcontterr; i++) {
35  data[i] = NULL;
36  md[i].mesh = NULL;
37  md[i].collider = NULL;
38  char tmp[512];
39  VSFileSystem::vs_fscanf( fp, "%511s", tmp );
40  tmp[511] = '\0';
41  for (int k = 0; k < 512; k++) {
42  if (tmp[k] == '^') {
43  tmp[k] = '\0';
44 
45  vector< mesh_polygon >polies;
46  md[i].mesh = Mesh::LoadMesh( tmp, Vector( 1, 1, 1 ), 0, NULL );
47  sscanf( tmp+i+1, "%f,%f", &sizeX, &sizeZ );
48  md[i].mesh->GetPolys( polies );
49  sizeX = md[i].mesh->corner_max().i-md[i].mesh->corner_min().i;
50  sizeZ = md[i].mesh->corner_max().k-md[i].mesh->corner_min().k;
51  md[i].collider = new csOPCODECollider( polies );
52  }
53  if (tmp[k] == '\0')
54  break;
55  }
56  filenames[i] = tmp;
57  }
59  for (i = 0; i < width; i++)
60  for (int j = 0; j < width; j++) {
62  if (i%2 && j%2)
63  up = &sideupparityodd;
64  else if (j%2)
65  up = &sideparityodd;
66  else if (i%2)
67  up = &upparityodd;
68  if (md[i*width+j].mesh == NULL)
69  data[i*width+j] = new Terrain( filenames[i*width+j].c_str(), this->Scales, tmass, 0, up );
70  }
71  location = new QVector[numcontterr];
72  dirty = new bool[numcontterr];
73  delete[] filenames;
74  if (data[0]) {
75  sizeX = data[0]->getSizeX();
76  sizeZ = data[0]->getSizeZ();
77  }
78  for (i = 0; i < numcontterr; i++)
79  if (data[i]) {
80  if ( sizeX != data[i]->getSizeX() || sizeZ != data[i]->getSizeZ() )
82  "Warning: Sizes of terrain do not match...expect gaps in continuous terrain\n" );
83  data[i]->SetTotalSize( sizeX*width, sizeZ*width );
84  }
85  for (i = 0; i < width; i++)
86  for (int j = 0; j < width; j++) {
87  int nj = j-1 < 0 ? width-1 : j-1;
88  int ni = i-1 < 0 ? width-1 : i-1;
89  if (data[j+width*i] && data[(j+1)%width+width*i] && data[j+width*( (i+1)%width )] && data[nj+width*i]
90  && data[j+width*ni]) {
91  data[j+width*i]->SetNeighbors( data[(j+1)%width+width*i],
92  data[j+width*( (i+1)%width )],
93  data[nj+width*i],
94  data[j+width*ni] );
95  data[j+width*i]->StaticCullData( 25 );
96  }
97  location[j+width*i].Set( 0+sizeX*j, 0, 0-sizeZ*i );
98  }
99  Matrix tmpmat;
100  Identity( tmpmat );
101  SetTransformation( tmpmat );
102  } else {
103  numcontterr = 0;
104  width = 0;
105  dirty = NULL;
106  location = NULL;
107  data = NULL;
108  md = NULL;
109  }
110 }
111 
113 {
114  for (int i = 0; i < numcontterr; i++) {
115  if (data[i])
116  delete data[i];
117  if (md[i].mesh)
118  delete md[i].mesh;
119  if (md[i].collider)
120  delete md[i].collider;
121  }
122  if (dirty)
123  delete[] dirty;
124  if (location)
125  delete[] location;
126  if (data)
127  delete[] data;
128  if (md)
129  delete[] md;
130 }
132 {
133  for (int i = 0; i < numcontterr; i++) {
134  if (data[i])
135  data[i]->Collide();
136  //FIXME
137  else
138  assert( 0 );
139  }
140 }
142 {
143  bool datacol = false;
144  for (int i = 0; i < numcontterr; i++) {
145  if (data[i])
146  data[i]->Collide( un );
147  else
148  datacol = true;
149  }
150  if (datacol)
151  Collide( un, transformation );
152 }
154 {
155  Matrix ident;
156  Identity( ident );
157  ShipPos.i /= Scales.i;
158  ShipPos.j /= Scales.j;
159  ShipPos.k /= Scales.k;
160  for (int i = 0; i < numcontterr; i++) {
161  QVector tmploc = ShipPos-location[i]+QVector( (data[i])->getminX()+.5*(data[i])->getSizeX(), 0,
162  (data[i])->getminZ()+.5*(data[i])->getSizeZ() );
163  if ( data[i]->GetGroundPos( tmploc, norm, ident, sizeX*width, sizeZ*width ) ) {
164  tmploc += location[i]-QVector( (data[i])->getminX()+.5*(data[i])->getSizeX(), 0,
165  (data[i])->getminZ()+.5*(data[i])->getSizeZ() );
166 
167  tmploc.i *= Scales.i;
168  tmploc.j *= Scales.j;
169  tmploc.k *= Scales.k;
170  return tmploc;
171  }
172  }
173  VSFileSystem::vs_fprintf( stderr, "Can't find %f,%f,%f\n", ShipPos.i, ShipPos.j, ShipPos.k );
174  ShipPos.i *= Scales.i;
175  ShipPos.j *= Scales.j;
176  ShipPos.k *= Scales.k;
177  return ShipPos;
178 }
180 {
181  for (int i = 0; i < numcontterr; i++)
182  if ( data[i]->GetGroundPos( ShipPos, norm, sizeX*width, sizeZ*width ) )
183  return ShipPos;
184  return ShipPos;
185 }
187 {
188  for (int i = 0; i < numcontterr; i++)
189  if (data[i])
190  data[i]->DisableDraw();
191 }
193 {
194  for (int i = 0; i < numcontterr; i++)
195  if (data[i])
196  data[i]->DisableUpdate();
197 }
199 {
200  for (int i = 0; i < numcontterr; i++)
201  if (data[i])
202  data[i]->EnableDraw();
203 }
205 {
206  for (int i = 0; i < numcontterr; i++)
207  if (data[i])
208  data[i]->EnableUpdate();
209 }
210 
212 {
213  for (int i = 0; i < numcontterr; i++) {
214  if (data[i]) {
215  data[i]->Render();
216  } else if (md[i].mesh) {
217  Vector TransformedPosition = Transform( md[i].mat,
218  md[i].mesh->Position() );
219  float d = GFXSphereInFrustum( TransformedPosition,
220  md[i].mesh->rSize()
221  );
222  if (d)
223  md[i].mesh->Draw( 1000, md[i].mat, d, -1, (_Universe->AccessCamera()->GetNebula() != NULL) ? -1 : 0 );
224  }
225  }
226 }
227 void ContinuousTerrain::SetTransformation( const Matrix &transformation )
228 {
229  CopyMatrix( this->transformation, transformation );
230  ScaleMatrix( this->transformation, Scales );
231  for (int i = 0; i < numcontterr; i++)
232  dirty[i] = true;
233 }
234 
235 bool ContinuousTerrain::checkInvScale( double &pos, double campos, float size )
236 {
237  bool retval = false;
238  size *= width;
239  float tmp = pos-campos;
240  while ( fabs( tmp-size ) < fabs( tmp ) ) {
241  tmp -= size;
242  retval = true;
243  }
244  while ( fabs( tmp+size ) < fabs( tmp ) ) {
245  tmp += size;
246  retval = true;
247  }
248  if (retval)
249  pos = tmp+campos;
250  return retval;
251 }
253 {
254  Matrix transform;
255  if (un->isUnit() == BUILDINGPTR)
256  return;
257  ScaleMatrix( t, Scales );
258  CopyMatrix( transform, t );
259  for (int i = 0; i < numcontterr; i++) {
260  QVector tmp( Transform( t, location[i]-QVector(
261  (data[i] ? (data[i])->getminX() : md[i].mesh->corner_min().i)+.5
262  *( data[i] ? (data[i])->getSizeX() : (md[i].mesh->corner_max().i
263  -md[i].mesh->corner_min().i) ),
264  0,
265  (data[i] ? (data[i])->getminZ() : md[i].mesh->corner_min().k)
266  +( .5
267  *( data[i] ? (data[i])->getSizeZ() : (md[i].mesh->corner_max().i-md[i].mesh->corner_min(
268  )
269  .i) ) ) ) ) );
270 
271  transform.p = tmp;
272  if (data[i]) {
273  data[i]->Collide( un, transform );
274  } else {
275  bool autocol = false;
276  QVector diff = InvScaleTransform( t, un->Position() );
277  if (diff.j < 0) autocol = true;
278  diff.i = fmod( (double) diff.i, (double) sizeX*width );
279  if (diff.i < 0)
280  diff.i += sizeX*width;
281  diff.k = fmod( (double) diff.k, (double) sizeZ*width );
282  if (diff.k < 0)
283  diff.k += sizeZ*width;
284  if ( !(rand()%10) )
285  VSFileSystem::vs_fprintf( stderr, "unit in out sapce %f %f %f\n", diff.i, diff.j, diff.k );
286  diff = Transform( t, diff );
287  const csReversibleTransform bigtransform( transform );
288  Matrix smallmat = ( un->GetTransformation() );
289 
290  smallmat.p = diff;
291  const csReversibleTransform smalltransform( smallmat );
292 #if 0
293  Matrix transform;
294  AdjustTerrain( transform, t, un->Position(), i );
295  const csReversibleTransform bigtransform( transform );
296 
297  const csReversibleTransform smalltransform( un->GetTransformation() );
298 #endif
299  QVector smallpos, bigpos;
300  Vector smallNormal, bigNormal;
301  if (autocol) {
302  smallpos = un->Position();
303  bigpos = un->Position()-QVector( 0, un->rSize(), 0 );
304  smallNormal = Vector( 0, -1, 0 );
305  bigNormal = Vector( 0, 1, 0 );
306  autocol = true;
307  }
308  if (md[i].collider) {
309  if (un->colTrees) {
310  if ( un->colTrees->colTree( un, Vector( 0, 0, 0 ) ) ) {
311  if ( un->colTrees->colTree( un, Vector( 0, 0, 0 ) )->Collide( *md[i].collider,
312  &smalltransform,
313  &bigtransform ) ) {
315  unsigned int numHits = csOPCODECollider::GetCollisionPairCount();
316  if (numHits) {
317  smallpos.Set( (mycollide[0].a1.x+mycollide[0].b1.x+mycollide[0].c1.x)/3,
318  (mycollide[0].a1.y+mycollide[0].b1.y+mycollide[0].c1.y)/3,
319  (mycollide[0].a1.z+mycollide[0].b1.z+mycollide[0].c1.z)/3 );
320  smallpos = Transform( un->cumulative_transformation_matrix, smallpos );
321  bigpos.Set( (mycollide[0].a2.x+mycollide[0].b2.x+mycollide[0].c2.x)/3,
322  (mycollide[0].a2.y+mycollide[0].b2.y+mycollide[0].c2.y)/3,
323  (mycollide[0].a2.z+mycollide[0].b2.z+mycollide[0].c2.z)/3 );
324  bigpos = Transform( transform, bigpos );
325  csVector3 sn, bn;
326  sn.Cross( mycollide[0].b1-mycollide[0].a1, mycollide[0].c1-mycollide[0].a1 );
327  bn.Cross( mycollide[0].b2-mycollide[0].a2, mycollide[0].c2-mycollide[0].a2 );
328  sn.Normalize();
329  bn.Normalize();
330  smallNormal.Set( sn.x, sn.y, sn.z );
331  bigNormal.Set( bn.x, bn.y, bn.z );
332  smallNormal = TransformNormal( un->cumulative_transformation_matrix, smallNormal );
333  bigNormal = TransformNormal( transform, bigNormal );
334  autocol = true;
335  }
336  }
337  }
338  }
339  }
340  if (autocol) {
341  static float mass = 1000;
342  un->ApplyForce( bigNormal*.4*un->GetMass()*fabs( bigNormal.Dot( (un->GetVelocity()/SIMULATION_ATOM) ) ) );
343  un->ApplyDamage( un->Position().Cast()-bigNormal*un->rSize(), -bigNormal, .5
344  *fabs( bigNormal.Dot( un->GetVelocity() ) )*mass*SIMULATION_ATOM, un, GFXColor( 1,
345  1,
346  1,
347  1 ), NULL );
348  }
349  }
350  }
351 }
352 
353 void ContinuousTerrain::AdjustTerrain( Matrix &transform, const Matrix &transformation, const QVector &campos, int i )
354 {
355  dirty[i] |= checkInvScale( location[i].i, campos.i, sizeX );
356  dirty[i] |= checkInvScale( location[i].k, campos.k, sizeZ );
357  CopyMatrix( transform, transformation );
358  QVector tmp( Transform( transformation, location[i]-QVector(
359  (data[i] ? (data[i])->getminX() : md[i].mesh->corner_min().i)+.5
360  *( data[i] ? (data[i])->getSizeX() : (md[i].mesh->corner_max().i-md[i].mesh->corner_min().i) ),
361  0,
362  (data[i] ? (data[i])->getminZ() : md[i].mesh->corner_min().k)
363  +( .5
364  *( data[i] ? (data[i])->getSizeZ() : (md[i].mesh->corner_max().i-md[i].mesh->corner_min().i) ) ) ) ) );
365  transform.p = tmp;
366 }
368 {
369  Matrix transform;
370 
371  QVector campos = InvScaleTransform( transformation, _Universe->AccessCamera()->GetPosition() );
372  for (int i = 0; i < numcontterr; i++)
373  if (1 || dirty[i]) {
374  AdjustTerrain( transform, transformation, campos, i );
375  if (data[i])
376  (data[i])->SetTransformation( transform );
377  else
378  md[i].mat = transform;
379  dirty[i] = false;
380  }
381 }
382 
384 {
385  return (data[0])
386  ? data[0]->GetUpVector( pos )
387  : Vector( transformation.getQ() );
388 }
389 
391 {
392  ct->DisableDraw();
393 }
394