From b829170121d3657369904ec62d8065606777a9ce Mon Sep 17 00:00:00 2001 From: Aki Date: Fri, 1 Oct 2021 18:54:04 +0200 Subject: Removed doxygen generated docs They can be rebuild anytime and are considered a build artifact/binary. --- Doc/doxygen/html/_terrain_patch_8cpp_source.html | 1230 ---------------------- 1 file changed, 1230 deletions(-) delete mode 100644 Doc/doxygen/html/_terrain_patch_8cpp_source.html (limited to 'Doc/doxygen/html/_terrain_patch_8cpp_source.html') diff --git a/Doc/doxygen/html/_terrain_patch_8cpp_source.html b/Doc/doxygen/html/_terrain_patch_8cpp_source.html deleted file mode 100644 index 7227aac..0000000 --- a/Doc/doxygen/html/_terrain_patch_8cpp_source.html +++ /dev/null @@ -1,1230 +0,0 @@ - - - - - -Starshatter_Open: D:/SRC/StarshatterSVN/Stars45/TerrainPatch.cpp Source File - - - - - - - - - - - - - -
-
- - - - - - -
-
Starshatter_Open -
-
Open source Starshatter engine
-
-
- - - - - -
-
- -
-
-
- -
- - - - -
- -
- -
-
-
TerrainPatch.cpp
-
-
-Go to the documentation of this file.
1 /* Project Starshatter 4.5
-
2  Destroyer Studios LLC
-
3  Copyright © 1997-2005. All Rights Reserved.
-
4 
-
5  SUBSYSTEM: Stars.exe
-
6  FILE: TerrainPatch.cpp
-
7  AUTHOR: John DiCamillo
-
8 
-
9 
-
10  OVERVIEW
-
11  ========
-
12 */
-
13 
-
14 #include "MemDebug.h"
-
15 #include "Terrain.h"
-
16 #include "TerrainLayer.h"
-
17 #include "TerrainPatch.h"
-
18 #include "TerrainRegion.h"
-
19 #include "Sim.h"
-
20 
-
21 #include "Light.h"
-
22 #include "CameraView.h"
-
23 #include "Projector.h"
-
24 #include "Bitmap.h"
-
25 #include "DataLoader.h"
-
26 #include "Game.h"
-
27 #include "Scene.h"
-
28 #include "Water.h"
-
29 
-
30 // +====================================================================+
-
31 
-
32 // #define DEBUG_DETAIL 1
-
33 
-
34 // +====================================================================+
-
35 
-
36 const int MAX_DETAIL = 4;
-
37 const int PATCH_SIZE = 17;
-
38 const int HALF_PATCH_SIZE = 8;
- -
40 
-
41 static bool illuminating = false;
-
42 
-
43 // +--------------------------------------------------------------------+
-
44 
-
45 TerrainPatch::TerrainPatch(Terrain* terr,const Bitmap* patch, const Rect& r,
-
46 const Point& p1, const Point& p2)
-
47 : ndetail(0), terrain(terr), rect(r), water(0), min_height(1e9), max_height(-1e9)
-
48 {
-
49  luminous = true; // we will do our own lighting
-
50  own_model = false; // manage the model lifetimes in this derived class
-
51 
- -
53  scale = fabs(p1.x - p2.x) / (PATCH_SIZE-1);
-
54  mtnscale = p2.y - p1.y;
-
55  base = p1.y;
-
56  size = p2.x - p1.x;
-
57 
-
58  ZeroMemory(detail_levels, sizeof(detail_levels));
-
59 
-
60  terrain_width = patch->Width();
-
61 
-
62  loc = (p1 + p2) * 0.5;
-
63  loc.y = base;
-
64 
-
65  radius = (float) (size * 0.75);
-
66  heights = new(__FILE__,__LINE__) float[MAX_VERTS];
-
67 
-
68  float* pHeight = heights;
-
69  int tscale = rect.w / (PATCH_SIZE-1);
-
70  int i, j;
-
71 
-
72  for (i = 0; i < PATCH_SIZE; i++) {
-
73  int ty = rect.y + i * tscale;
-
74 
-
75  if (ty < 0)
-
76  ty = 0;
-
77 
-
78  if (ty > patch->Height()-1)
-
79  ty = patch->Height()-1;
-
80 
-
81  for (j = 0; j < PATCH_SIZE; j++) {
-
82  int tx = rect.x + (PATCH_SIZE-1 - j) * tscale;
-
83 
-
84  if (tx < 0)
-
85  tx = 0;
-
86 
-
87  if (tx > patch->Width()-1)
-
88  tx = patch->Width()-1;
-
89 
-
90  int red = patch->GetColor(tx,ty).Red();
-
91  float alt = (float) (red * mtnscale);
-
92 
-
93  if (alt < min_height)
-
94  min_height = alt;
-
95  if (alt > max_height)
-
96  max_height = alt;
-
97 
-
98  if (terrain->WaterTexture() && red < 2)
-
99  alt = -5000.0f;
-
100 
-
101  *pHeight++ = alt;
-
102  }
-
103  }
-
104 
-
105  Material* mtl = new(__FILE__,__LINE__) Material;
-
106  mtl->Ka = ColorValue(0.5f, 0.5f, 0.5f);
-
107  mtl->Kd = ColorValue(0.3f, 0.6f, 0.2f);
-
108  mtl->Ks = Color::Black;
-
109 
-
110  mtl->tex_diffuse = terrain->Texture();
-
111 
-
112  materials.append(mtl);
-
113 
- -
115  for (i = 0; i < layers.size(); i++) {
-
116  Bitmap* tex0 = layers.at(i)->GetTileTexture();
-
117  Bitmap* tex1 = 0;
-
118  Bitmap* texd = layers.at(i)->GetDetailTexture();
-
119 
-
120  if (i < layers.size()-1)
-
121  tex1 = layers.at(i+1)->GetTileTexture();
-
122 
-
123  if (!texd)
-
124  texd = terrain->DetailTexture(0);
-
125 
-
126  mtl = new(__FILE__,__LINE__) Material;
-
127  mtl->Ka = ColorValue(0.5f, 0.5f, 0.5f);
-
128  mtl->Kd = ColorValue(0.3f, 0.6f, 0.2f);
-
129  mtl->Ks = Color::Black;
-
130 
-
131  if ((i & 1) != 0) {
-
132  mtl->tex_diffuse = tex1;
-
133  mtl->tex_alternate = tex0;
-
134  }
-
135  else {
-
136  mtl->tex_diffuse = tex0;
-
137  mtl->tex_alternate = tex1;
-
138  }
-
139 
-
140  mtl->tex_detail = texd;
-
141 
-
142  materials.append(mtl);
-
143  }
-
144 
-
145  for (i = 0; i <= max_detail; i++)
-
146  BuildDetailLevel(i);
-
147 
-
148  model = detail_levels[1];
-
149 }
-
150 
-
151 // +--------------------------------------------------------------------+
-
152 
- -
154 const Rect& r,
-
155 const Point& p1,
-
156 const Point& p2,
-
157 double sea_level)
-
158 : ndetail(0), terrain(terr), rect(r), water(0)
-
159 {
-
160  luminous = true; // water is lit by the graphics engine
-
161  own_model = false; // manage the model lifetimes in this derived class
-
162 
- -
164  scale = fabs(p1.x - p2.x) / (PATCH_SIZE-1);
-
165  mtnscale = 0;
-
166  base = sea_level;
-
167  size = p2.x - p1.x;
-
168 
-
169  ZeroMemory(detail_levels, sizeof(detail_levels));
-
170 
-
171  terrain_width = 0;
-
172 
-
173  loc = (p1 + p2) * 0.5;
-
174  loc.y = base;
-
175 
-
176  radius = (float) (size * 0.75);
-
177  heights = new(__FILE__,__LINE__) float[MAX_VERTS];
-
178 
-
179  float* pHeight = heights;
-
180  int i, j;
-
181 
-
182  for (i = 0; i < PATCH_SIZE; i++) {
-
183  for (j = 0; j < PATCH_SIZE; j++) {
-
184  *pHeight++ = (float) sea_level;
-
185  }
-
186  }
-
187 
-
188  Material* mtl = new(__FILE__,__LINE__) Material;
-
189  mtl->Ka = Color::Gray;
-
190  mtl->Kd = Color::White;
-
191  mtl->Ks = Color::White;
-
192  mtl->power = 30.0f;
-
193  mtl->shadow = false;
-
194  mtl->tex_diffuse = terrain->WaterTexture();
-
195  //strcpy_s(mtl->shader, "WaterReflections");
-
196  materials.append(mtl);
-
197 
-
198  water = terrain->GetWater(1);
-
199 
-
200  for (i = 0; i <= max_detail; i++)
-
201  BuildDetailLevel(i);
-
202 
-
203  model = detail_levels[1];
-
204 }
-
205 
-
206 // +--------------------------------------------------------------------+
-
207 
- -
209 {
-
210  delete [] heights;
-
211 
-
212  for (int i = 0; i < MAX_LOD; i++) {
-
213  Model* m = detail_levels[i];
-
214 
-
215  if (m) {
-
216  m->GetMaterials().clear();
-
217  delete m;
-
218  }
-
219  }
-
220 
-
221  materials.destroy();
-
222 }
-
223 
-
224 // +--------------------------------------------------------------------+
-
225 
-
226 void
-
227 TerrainPatch::SetScales(double s, double m, double b)
-
228 {
-
229  scale = s;
-
230  mtnscale = m;
-
231  base = b;
-
232 }
-
233 
-
234 // +--------------------------------------------------------------------+
-
235 
-
236 static int mcomp(const void* a, const void* b)
-
237 {
-
238  Poly* pa = (Poly*) a;
-
239  Poly* pb = (Poly*) b;
-
240 
-
241  if (pa->sortval == pb->sortval)
-
242  return 0;
-
243 
-
244  if (pa->sortval < pb->sortval)
-
245  return 1;
-
246 
-
247  return -1;
-
248 }
-
249 
-
250 
-
251 static void bisect(VertexSet* vset, int v[4])
-
252 {
-
253  double d1 = fabs(vset->loc[ v[0] ].y -
-
254  vset->loc[ v[3] ].y);
-
255 
-
256  double d2 = fabs(vset->loc[ v[1] ].y -
-
257  vset->loc[ v[2] ].y);
-
258 
-
259  if (d2 < 0.7*d1) {
-
260  int odd[4] = { v[1], v[3], v[0], v[2] };
-
261  for (int i = 0; i < 4; i++)
-
262  v[i] = odd[i];
-
263  }
-
264 }
-
265 
-
266 bool
- -
268 {
-
269  int i, j;
-
270 
-
271  int detail_size = 1 << level;
-
272  int ds1 = detail_size+1;
-
273 
-
274  if (detail_size > PATCH_SIZE)
-
275  return false;
-
276 
-
277  Model* model = new(__FILE__,__LINE__) Model;
-
278  detail_levels[level] = model;
-
279 
-
280  model->SetLuminous(luminous);
-
281  model->SetDynamic(true);
-
282 
-
283  const int NUM_STRIPS = 4;
-
284  const int NUM_INDICES_TRI = 3;
-
285  const int NUM_INDICES_QUAD = 6;
-
286 
-
287  int nverts = ds1*ds1 + ds1*2*NUM_STRIPS;
-
288  int npolys = detail_size*detail_size*2;
-
289  int strip_len = detail_size;
-
290  int total = npolys + strip_len*NUM_STRIPS;
-
291 
-
292  if (water) {
-
293  nverts = ds1*ds1;
-
294  strip_len = 0;
-
295  total = npolys;
-
296  }
-
297 
-
298  Surface* s = new(__FILE__,__LINE__) Surface;
-
299  VertexSet* vset = 0;
-
300 
-
301  if (s) {
-
302  s->SetName("default");
-
303  s->CreateVerts(nverts);
-
304  s->CreatePolys(total);
-
305  s->AddIndices(npolys*NUM_INDICES_TRI + strip_len*NUM_STRIPS*NUM_INDICES_QUAD);
-
306 
-
307  vset = s->GetVertexSet();
-
308  if (!water)
- -
310 
-
311  ZeroMemory(vset->loc, nverts * sizeof(Vec3));
-
312  ZeroMemory(vset->diffuse, nverts * sizeof(DWORD));
-
313  ZeroMemory(vset->specular, nverts * sizeof(DWORD));
-
314  ZeroMemory(vset->tu, nverts * sizeof(float));
-
315  ZeroMemory(vset->tv, nverts * sizeof(float));
-
316  if (!water) {
-
317  ZeroMemory(vset->tu1, nverts * sizeof(float));
-
318  ZeroMemory(vset->tv1, nverts * sizeof(float));
-
319  }
-
320  ZeroMemory(vset->rw, nverts * sizeof(float));
-
321 
-
322  // initialize vertices
-
323  Vec3* pVert = vset->loc;
-
324  float* pTu = vset->tu;
-
325  float* pTv = vset->tv;
-
326  float* pTu1 = vset->tu1;
-
327  float* pTv1 = vset->tv1;
-
328  DWORD* pSpec = vset->specular;
-
329 
-
330  int dscale = (PATCH_SIZE-1)/detail_size;
-
331  double dt = 0.0625 / (ds1-1); // terrain texture scale
-
332  double dtt = 2.0000 / (ds1-1); // tile texture scale
-
333  double tu0 = (double) rect.x / rect.w / 16.0 + 1.0/16.0;
-
334  double tv0 = (double) rect.y / rect.h / 16.0;
-
335 
-
336  // surface verts
-
337  for (i = 0; i < ds1; i++) {
-
338  for (j = 0; j < ds1; j++) {
-
339  *pVert = Vec3((float) (j* scale * dscale - (HALF_PATCH_SIZE*scale)),
-
340  (float) (heights[i*dscale*PATCH_SIZE + j*dscale]),
-
341  (float) (i* scale * dscale - (HALF_PATCH_SIZE*scale)));
-
342 
-
343  if (level >= 2) {
-
344  *pTu++ = (float) (-j*dtt);
-
345  *pTv++ = (float) ( i*dtt);
-
346 
-
347  if (level >= 4 && !water) {
-
348  *pTu1++ = (float) (-j*dtt*3);
-
349  *pTv1++ = (float) ( i*dtt*3);
-
350  }
-
351 
-
352  *pSpec++ = BlendValue(pVert->y);
-
353  }
-
354 
-
355  else {
-
356  *pTu++ = (float) (tu0 - j*dt);
-
357  *pTv++ = (float) (tv0 + i*dt);
-
358  }
-
359 
-
360  pVert++;
-
361  }
-
362  }
-
363 
-
364  if (!water) {
-
365  // strip 1 & 2 verts
-
366  for (i = 0; i < ds1; i += detail_size) {
-
367  for (j = 0; j < ds1; j++) {
-
368  Vec3 vl = Vec3((float) (j* scale * dscale - (HALF_PATCH_SIZE*scale)),
-
369  (float) (heights[i*dscale*PATCH_SIZE + j*dscale]),
-
370  (float) (i* scale * dscale - (HALF_PATCH_SIZE*scale)));
-
371 
-
372  *pVert++ = vl;
-
373 
-
374  DWORD blend = 0;
-
375 
-
376  if (level >= 2) {
-
377  blend = BlendValue(vl.y);
-
378 
-
379  *pSpec++ = blend;
-
380  *pTu++ = (float) (-j*dtt);
-
381  *pTv++ = (float) ( i*dtt);
-
382  }
-
383 
-
384  else {
-
385  *pTu++ = (float) (tu0 - j*dt);
-
386  *pTv++ = (float) (tv0 + i*dt);
-
387  }
-
388 
-
389  vl.y = -5000.0f;
-
390 
-
391  *pVert++ = vl;
-
392 
-
393  if (level >= 2) {
-
394  *pSpec++ = blend;
-
395  *pTu++ = (float) (-j*dtt);
-
396  *pTv++ = (float) ( i*dtt);
-
397  }
-
398 
-
399  else {
-
400  *pTu++ = (float) (tu0 - j*dt);
-
401  *pTv++ = (float) (tv0 + i*dt);
-
402  }
-
403  }
-
404  }
-
405 
-
406  // strip 3 & 4 verts
-
407  for (j = 0; j < ds1; j += detail_size) {
-
408  for (i = 0; i < ds1; i++) {
-
409  Vec3 vl = Vec3((float) (j* scale * dscale - (HALF_PATCH_SIZE*scale)),
-
410  (float) (heights[i*dscale*PATCH_SIZE + j*dscale]),
-
411  (float) (i* scale * dscale - (HALF_PATCH_SIZE*scale)));
-
412 
-
413  *pVert++ = vl;
-
414 
-
415  DWORD blend = 0;
-
416 
-
417  if (level >= 2) {
-
418  blend = BlendValue(vl.y);
-
419 
-
420  *pSpec++ = blend;
-
421  *pTu++ = (float) (-j*dtt);
-
422  *pTv++ = (float) ( i*dtt);
-
423  }
-
424 
-
425  else {
-
426  *pTu++ = (float) (tu0 - j*dt);
-
427  *pTv++ = (float) (tv0 + i*dt);
-
428  }
-
429 
-
430  vl.y = -5000.0f;
-
431 
-
432  *pVert++ = vl;
-
433 
-
434  if (level >= 2) {
-
435  *pSpec++ = blend;
-
436  *pTu++ = (float) (-j*dtt);
-
437  *pTv++ = (float) ( i*dtt);
-
438  }
-
439 
-
440  else {
-
441  *pTu++ = (float) (tu0 - j*dt);
-
442  *pTv++ = (float) (tv0 + i*dt);
-
443  }
-
444  }
-
445  }
-
446  }
-
447 
-
448  Material* m = materials.first();
-
449 
-
450  // initialize the polys
-
451  for (i = 0; i < npolys; i++) {
-
452  Poly* p = s->GetPolys() + i;
-
453  p->nverts = 3;
-
454  p->vertex_set = vset;
-
455  p->visible = 1;
-
456  p->sortval = 0;
-
457  p->material = m;
-
458 
-
459  if (level >= 2 && !water) {
-
460  p->material = materials.at(1);
-
461  p->sortval = 1;
-
462  }
-
463  }
-
464 
-
465  for (i = npolys; i < total; i++) {
-
466  Poly* p = s->GetPolys() + i;
-
467  p->nverts = 4;
-
468  p->vertex_set = vset;
-
469  p->visible = 1;
-
470  p->sortval = 0;
-
471  p->material = m;
-
472  }
-
473 
-
474  int index = 0;
-
475 
-
476  // build main patch polys:
-
477  for (i = 0; i < detail_size; i++) {
-
478  for (j = 0; j < detail_size; j++) {
-
479  int v[4] = {
-
480  (ds1 * (i ) + (j )),
-
481  (ds1 * (i ) + (j+1)),
-
482  (ds1 * (i+1) + (j )),
-
483  (ds1 * (i+1) + (j+1)) };
-
484 
-
485  bisect(vset, v);
-
486 
-
487  // first triangle
-
488  Poly* p = s->GetPolys() + index++;
-
489  p->verts[0] = v[0];
-
490  p->verts[1] = v[1];
-
491  p->verts[2] = v[3];
-
492 
-
493  if (level >= 2 && !water) {
-
494  int layer = CalcLayer(p) + 1;
-
495  p->material = materials.at(layer);
-
496  p->sortval = layer;
-
497  }
-
498 
-
499  // second triangle
-
500  p = s->GetPolys() + index++;
-
501  p->verts[0] = v[0];
-
502  p->verts[1] = v[3];
-
503  p->verts[2] = v[2];
-
504 
-
505  if (level >= 2 && !water) {
-
506  int layer = CalcLayer(p) + 1;
-
507  p->material = materials.at(layer);
-
508  p->sortval = layer;
-
509  }
-
510  }
-
511  }
-
512 
-
513  // build vertical edge strip polys:
-
514 
-
515  if (!water) {
-
516  for (i = 0; i < NUM_STRIPS; i++) {
-
517  Poly* p = s->GetPolys() + npolys + i*strip_len;
-
518  int base_index = ds1*ds1 + ds1*2*i;
-
519 
-
520  for (j = 0; j < strip_len; j++) {
-
521  int v = base_index + j * 2;
-
522  p->nverts = 4;
-
523 
-
524  if (i == 1 || i == 2) {
-
525  p->verts[0] = v;
-
526  p->verts[1] = v+2;
-
527  p->verts[2] = v+3;
-
528  p->verts[3] = v+1;
-
529  }
-
530 
-
531  else {
-
532  p->verts[0] = v;
-
533  p->verts[1] = v+1;
-
534  p->verts[2] = v+3;
-
535  p->verts[3] = v+2;
-
536  }
-
537 
-
538  if (level >= 2) {
-
539  int layer = CalcLayer(p) + 1;
-
540  p->material = materials.at(layer);
-
541  p->sortval = layer;
-
542  }
-
543 
-
544  p++;
-
545  }
-
546  }
-
547  }
-
548 
-
549  // update the poly planes:
-
550  for (i = 0; i < total; i++) {
-
551  Poly* p = s->GetPolys() + i;
-
552  Plane& plane = p->plane;
-
553  WORD* v = p->verts;
-
554 
-
555  plane = Plane(vset->loc[v[0]] + loc,
-
556  vset->loc[v[1]] + loc,
-
557  vset->loc[v[2]] + loc);
-
558  }
-
559 
-
560  s->Normalize();
-
561 
-
562  // create continguous segments for each material:
-
563  // sort the polys by material index:
-
564  qsort((void*) s->GetPolys(), s->NumPolys(), sizeof(Poly), mcomp);
-
565 
-
566  // then assign them to cohesive segments:
-
567  Segment* segment = 0;
-
568  Poly* spolys = s->GetPolys();
-
569 
-
570  for (int n = 0; n < s->NumPolys(); n++) {
-
571  if (segment && segment->material == spolys[n].material) {
-
572  segment->npolys++;
-
573  }
-
574  else {
-
575  segment = 0;
-
576  }
-
577 
-
578  if (!segment) {
-
579  segment = new(__FILE__,__LINE__) Segment;
-
580 
-
581  segment->npolys = 1;
-
582  segment->polys = &spolys[n];
-
583  segment->material = segment->polys->material;
-
584  segment->model = model;
-
585 
-
586  s->GetSegments().append(segment);
-
587  }
-
588  }
-
589 
-
590  Solid::EnableCollision(false);
-
591  model->AddSurface(s);
- -
593 
-
594  // copy vertex normals:
-
595  const Vec3B* tnorms = terrain->Normals();
-
596 
-
597  for (i = 0; i < ds1; i++) {
-
598  for (j = 0; j < ds1; j++) {
-
599 
-
600  if (water) {
-
601  vset->nrm[i*ds1+j] = Point(0,1,0);
-
602  }
-
603 
-
604  // blend adjacent normals:
-
605  else if (dscale > 1) {
-
606  Point normal;
-
607 
-
608  // but don't blend more than 16 normals per vertex:
-
609  int step = 1;
-
610  if (dscale > 4)
-
611  step = dscale / 4;
-
612 
-
613  for (int dy = -dscale/2; dy < dscale/2; dy += step) {
-
614  for (int dx = -dscale/2; dx < dscale/2; dx += step) {
-
615  int ix = rect.x + (ds1-1-j)*dscale + dx;
-
616  int iy = rect.y + i*dscale + dy;
-
617 
-
618  if (ix < 0) ix = 0;
-
619  if (ix > terrain_width-1) ix = terrain_width-1;
-
620  if (iy < 0) iy = 0;
-
621  if (iy > terrain_width-1) iy = terrain_width-1;
-
622 
-
623  Vec3B vbn = tnorms[iy*terrain_width + ix];
-
624  normal += Point((128-vbn.x)/127.0, (vbn.z-128)/127.0, (vbn.y-128)/127.0);
-
625  }
-
626  }
-
627 
-
628  normal.Normalize();
-
629  vset->nrm[i*ds1+j] = normal;
-
630  }
-
631 
-
632  // just copy the one normal:
-
633  else {
-
634  Vec3B vbn = tnorms[(rect.y + i*dscale)*terrain_width + (rect.x + (ds1-1-j) * dscale)];
-
635  Point normal = Point((128-vbn.x)/127.0, (vbn.z-128)/127.0, (vbn.y-128)/127.0);
-
636  vset->nrm[i*ds1+j] = normal;
-
637  }
-
638  }
-
639  }
-
640 
-
641  if (!water) {
-
642  pVert = &vset->nrm[ds1*ds1];
-
643 
-
644  // strip 1 & 2 verts
-
645  for (i = 0; i < ds1; i += detail_size) {
-
646  for (j = 0; j < ds1; j++) {
-
647  Vec3 vn = vset->nrm[i*ds1 + j];
-
648 
-
649  *pVert++ = vn;
-
650  *pVert++ = vn;
-
651  }
-
652  }
-
653 
-
654  // strip 3 & 4 verts
-
655  for (j = 0; j < ds1; j += detail_size) {
-
656  for (i = 0; i < ds1; i++) {
-
657  Vec3 vn = vset->nrm[i*ds1 + j];
-
658 
-
659  *pVert++ = vn;
-
660  *pVert++ = vn;
-
661  }
-
662  }
-
663  }
-
664  }
-
665 
-
666  if (level > max_detail)
-
667  max_detail = level;
-
668 
-
669  return true;
-
670 }
-
671 
-
672 // +--------------------------------------------------------------------+
-
673 
-
674 DWORD
- -
676 {
-
677  if (terrain && y >= 0 && !water) {
-
678  // find the proper layer:
-
679  for (int i = 0; i < terrain->GetLayers().size(); i++) {
-
680  TerrainLayer* layer = terrain->GetLayers().at(i);
-
681 
-
682  if (y >= layer->GetMinHeight() && y < layer->GetMaxHeight()) {
-
683  double scale = (y-layer->GetMinHeight()) / (layer->GetMaxHeight()-layer->GetMinHeight());
-
684 
-
685  if (scale < 0.2)
-
686  scale = 0;
-
687  else if (scale > 0.8)
-
688  scale = 1;
-
689  else
-
690  scale = (scale - 0.2) / 0.6;
-
691 
-
692  if ((i & 1) == 0) {
-
693  scale = 1 - scale;
-
694  }
-
695 
-
696  DWORD val = (DWORD) (scale*255);
-
697 
-
698  return val << 24;
-
699  }
-
700  }
-
701  }
-
702 
-
703  return 0;
-
704 }
-
705 
-
706 int
- -
708 {
-
709  if (terrain && poly) {
-
710  if (water)
-
711  return 0;
-
712 
-
713  double y = 1e6;
-
714 
-
715  for (int i = 0; i < poly->nverts; i++) {
-
716  double h = poly->vertex_set->loc[ poly->verts[i] ].y;
-
717 
-
718  if (h >= 0 && h < y) {
-
719  y = h;
-
720  }
-
721  }
-
722 
-
723  if (y <= terrain->GetLayers().first()->GetMinHeight())
-
724  return 0;
-
725 
-
726  for (int i = 0; i < terrain->GetLayers().size(); i++) {
-
727  TerrainLayer* layer = terrain->GetLayers().at(i);
-
728 
-
729  if (y >= layer->GetMinHeight() && y < layer->GetMaxHeight()) {
-
730  return i;
-
731  }
-
732  }
-
733  }
-
734 
-
735  return -1;
-
736 }
-
737 
-
738 // +--------------------------------------------------------------------+
-
739 
-
740 void
- -
742 {
-
743  if (water && model && model->NumVerts() > 1) {
-
744  Surface* s = model->GetSurfaces().first();
-
745  if (s) {
-
746  VertexSet* vset = s->GetVertexSet();
-
747  for (int i = 0; i < vset->nverts; i++)
-
748  vset->loc[i].y = 0.0f;
-
749 
-
750  water->UpdateSurface(eyePos, vset);
-
751  }
-
752  }
-
753 }
-
754 
-
755 // +--------------------------------------------------------------------+
-
756 
-
757 int
- -
759 {
-
760  return 0;
-
761 }
-
762 
-
763 // +--------------------------------------------------------------------+
-
764 
-
765 void
- -
767 {
-
768  // This is where all the work is done,
-
769  // Delegate to the overall terrain to
-
770  // compute a detail level for every patch:
-
771 
-
772  if (terrain) {
-
773  terrain->SelectDetail(projector);
-
774  }
-
775 
-
776  // Build detail levels on demand:
-
777 
-
778  if (detail_levels[ndetail] == 0)
- -
780 }
-
781 
-
782 void
- -
784 {
-
785  if (nd >= 0 && nd <= max_detail) {
-
786  if (ndetail != nd)
- -
788 
-
789  ndetail = nd;
-
790 
-
791  // build detail levels on demand:
-
792  if (detail_levels[ndetail] == 0)
- -
794 
- -
796 
-
797  if (water)
- -
799  }
-
800 }
-
801 
-
802 // +--------------------------------------------------------------------+
-
803 
-
804 void
- -
806 {
-
807  if (!model || model->NumVerts() < 1) return;
-
808  Surface* s = model->GetSurfaces().first();
-
809  if (!s) return;
-
810 
-
811  illuminating = true;
-
812 
-
813  // clear the solid lights to ambient:
-
814  VertexSet* vset = s->GetVertexSet();
-
815  int nverts = vset->nverts;
-
816  DWORD aval = ambient.Value();
-
817 
-
818  for (int i = 0; i < nverts; i++) {
-
819  vset->diffuse[i] = aval;
-
820  }
-
821 
-
822  TerrainRegion* trgn = terrain->GetRegion();
-
823  bool eclipsed = false;
-
824  bool first = terrain->IsFirstPatch(this);
-
825 
-
826  if (trgn && !first) {
-
827  eclipsed = trgn->IsEclipsed();
-
828  }
-
829 
-
830  // for sun and back lights:
-
831  ListIter<Light> iter = lights;
-
832  while (++iter) {
-
833  Light* light = iter.value();
-
834 
-
835  if (!light->IsDirectional()) // only do sun and
-
836  continue; // back lights
-
837 
-
838  if (light->CastsShadow() && first) {
-
839  eclipsed = light->Location().y < -100 || // has sun set, or
-
840 
-
841  scene->IsLightObscured(vset->loc[0], // is sun in eclipse
-
842  light->Location(), // by orbital body
-
843  radius); // such as a moon?
-
844  }
-
845 
-
846  if (!light->CastsShadow() || !eclipsed) {
-
847  Vec3 vl = light->Location();
-
848  vl.Normalize();
-
849 
-
850  for (int i = 0; i < nverts; i++) {
-
851  Vec3& nrm = vset->nrm[i];
-
852  double val = 0;
-
853  double gain = vl * nrm;
-
854 
-
855  if (gain > 0) {
-
856  val = light->Intensity() * (0.85 * gain);
-
857 
-
858  if (val > 1)
-
859  val = 1;
-
860  }
-
861 
-
862  if (val > 0.01)
-
863  vset->diffuse[i] = ((light->GetColor().dim(val)) + vset->diffuse[i]).Value();
-
864  }
-
865  }
-
866  }
-
867 
-
868  // combine blend weights:
-
869  if (ndetail >= 2) {
-
870  for (int i = 0; i < nverts; i++) {
-
871  vset->diffuse[i] = vset->specular[i] | (vset->diffuse[i] & 0x00ffffff);
-
872  }
-
873  }
-
874 
-
875  if (trgn && first) {
-
876  trgn->SetEclipsed(eclipsed);
-
877  }
-
878 
- -
880  illuminating = false;
-
881 }
-
882 
-
883 // +--------------------------------------------------------------------+
-
884 
-
885 void
-
886 TerrainPatch::Render(Video* video, DWORD flags)
-
887 {
-
888  if (max_height < 0)
-
889  return;
-
890 
-
891  if (flags & RENDER_ADDITIVE)
-
892  return;
-
893 
-
894  if (!model)
-
895  model = detail_levels[0];
-
896 
-
897  if (scene) {
-
898  /***
-
899  *** TWO PASS LIGHTING FOR TERRAIN SHADOWS DOESN'T
-
900  *** WORK - IT MESSES UP THE HARDWARE FOG CALCS
-
901  ***
-
902  *** PLUS, IT'S INCREDIBLY SLOW!!!
-
903  ***/
-
904 
-
905  if ((flags & RENDER_ADD_LIGHT) != 0)
-
906  return;
-
907 
-
908  if (water) {
-
909  UpdateSurfaceWaves(Vec3(0,0,0));
- -
911  }
-
912  else {
- -
914  }
-
915  }
-
916  else {
-
917  if ((flags & RENDER_ADD_LIGHT) != 0)
-
918  return;
-
919  }
-
920 
-
921  Bitmap* details[16];
-
922  ZeroMemory(details, sizeof(details));
-
923 
-
924  if (ndetail < 3) {
-
925  for (int i = 0; i < 16 && i < materials.size(); i++) {
-
926  Material* mtl = materials[i];
-
927 
-
928  if (mtl->tex_detail) {
-
929  details[i] = mtl->tex_detail;
-
930  mtl->tex_detail = 0;
-
931  }
-
932  }
-
933  }
-
934 
-
935  double visibility = terrain->GetRegion()->GetWeather().Visibility();
-
936  FLOAT fog_density = (FLOAT) (terrain->GetRegion()->FogDensity() * 2.5e-5 * 1/visibility);
-
937 
-
938  video->SetRenderState(Video::LIGHTING_ENABLE, false);
-
939  video->SetRenderState(Video::SPECULAR_ENABLE, false); //water != 0);
-
940  video->SetRenderState(Video::FOG_ENABLE, true);
- -
942  video->SetRenderState(Video::FOG_DENSITY, *((DWORD*) &fog_density));
-
943 
-
944  // Too bad this doesn't work right. But it makes the
-
945  // ground mostly disappear. :-(
-
946  //
-
947  //video->SetRenderState(Video::Z_BIAS, -2);
-
948 
-
949  Solid::Render(video, flags);
-
950 
- - -
953  video->SetRenderState(Video::FOG_ENABLE, false);
-
954  //video->SetRenderState(Video::Z_BIAS, 0);
-
955 
-
956  if (ndetail < 3) {
-
957  for (int i = 0; i < 16 && i < materials.size(); i++) {
-
958  Material* mtl = materials[i];
-
959 
-
960  if (details[i] && !mtl->tex_detail) {
-
961  mtl->tex_detail = details[i];
-
962  }
-
963  }
-
964  }
-
965 }
-
966 
-
967 // +--------------------------------------------------------------------+
-
968 
-
969 int
-
970 TerrainPatch::CheckRayIntersection(Point obj_pos, Point dir, double len, Point& ipt, bool ttpas)
-
971 {
-
972  Point light_pos = obj_pos + dir * len;
-
973  int impact = light_pos.y < -100;
-
974 
-
975  // Special case for illumination -
-
976  // just check if sun is above or below the horizon:
-
977 
-
978  if (illuminating || impact) {
-
979  return impact;
-
980  }
-
981 
-
982  if (obj_pos.x != 0 || obj_pos.y != 0 || obj_pos.z != 0) {
-
983  return impact;
-
984  }
-
985 
-
986  // the rest of this code is only used for eclipsing
-
987  // the solar lens flare:
-
988 
-
989  // check right angle spherical distance:
-
990  Point d0 = loc;
-
991  Point d1 = d0.cross(dir);
-
992  double dlen = d1.length(); // distance of point from line
-
993 
-
994  if (dlen > radius) // clean miss
-
995  return 0; // (no impact)
-
996 
-
997  // make sure some part of this patch falls between
-
998  // the camera and the sun:
-
999 
-
1000  Point closest = loc + dir * radius;
-
1001 
-
1002  if (closest * dir < 0)
-
1003  return 0;
-
1004 
-
1005  // probable hit at this point...
-
1006  // test for polygon intersection:
-
1007  if (!model)
-
1008  return 0;
-
1009 
-
1010  Surface* s = model->GetSurfaces().first();
-
1011 
-
1012  if (!s)
-
1013  return 0;
-
1014 
-
1015 
-
1016  // transform ray into object space:
-
1017  Matrix xform(Orientation());
-
1018 
-
1019  Vec3 tmp = dir;
-
1020 
-
1021  dir.x = tmp * Vec3(xform(0,0), xform(0,1), xform(0,2));
-
1022  dir.y = tmp * Vec3(xform(1,0), xform(1,1), xform(1,2));
-
1023  dir.z = tmp * Vec3(xform(2,0), xform(2,1), xform(2,2));
-
1024 
-
1025  tmp = obj_pos-loc;
-
1026 
-
1027  obj_pos.x = tmp * Vec3(xform(0,0), xform(0,1), xform(0,2));
-
1028  obj_pos.y = tmp * Vec3(xform(1,0), xform(1,1), xform(1,2));
-
1029  obj_pos.z = tmp * Vec3(xform(2,0), xform(2,1), xform(2,2));
-
1030 
-
1031  double min = 2 * len;
-
1032 
-
1033  // check each polygon:
-
1034  Poly* p = s->GetPolys();
-
1035 
-
1036  for (int i = 0; i < s->NumPolys(); i++) {
-
1037  Point v = p->plane.normal;
-
1038  double d = p->plane.distance;
-
1039 
-
1040  double denom = dir*v;
-
1041 
-
1042  if (denom < -1.0e-5) {
-
1043  Point P = v * d;
-
1044  double ilen = ((P-obj_pos)*v)/denom;
-
1045 
-
1046  if (ilen > 0 && ilen < min) {
-
1047  Point intersect = obj_pos + dir * ilen;
-
1048 
-
1049  if (p->Contains(intersect)) {
-
1050  ipt = intersect;
-
1051  min = ilen;
-
1052  impact = 1;
-
1053  }
-
1054  }
-
1055  }
-
1056 
-
1057  p++;
-
1058  }
-
1059 
-
1060  // xform impact point back into world coordinates:
-
1061 
-
1062  if (impact) {
-
1063  ipt = (ipt * Orientation()) + loc;
-
1064  }
-
1065 
-
1066  return impact;
-
1067 }
-
1068 
-
1069 // +--------------------------------------------------------------------+
-
1070 
-
1071 double
-
1072 TerrainPatch::Height(double x, double z) const
-
1073 {
-
1074  if (water) return base;
-
1075 
-
1076  double height = 0;
-
1077 
-
1078  x /= scale;
-
1079  z /= scale;
-
1080 
-
1081  int x0 = (int) x;
-
1082  int z0 = (int) z;
-
1083 
-
1084  if (x0 >= 0 && x0 < PATCH_SIZE && z0 >= 0 && z0 < PATCH_SIZE) {
-
1085  double dx = x-x0;
-
1086  double dz = z-z0;
-
1087 
-
1088  double h[4];
-
1089 
-
1090  h[0] = heights[(z0*PATCH_SIZE + x0)];
-
1091  h[1] = heights[((z0+1)*PATCH_SIZE + x0)];
-
1092  h[2] = heights[(z0*PATCH_SIZE + x0+1)];
-
1093  h[3] = heights[((z0+1)*PATCH_SIZE + x0+1)];
-
1094 
-
1095  // if level, just return height of one vertex:
-
1096  if (h[0] == h[1] && h[1] == h[2] && h[2] == h[3]) {
-
1097  height = h[0];
-
1098  }
-
1099 
-
1100  // if sloped, interpolate between vertex heights:
-
1101  else {
-
1102  double hl = h[0]*(1-dz) + h[1]*dz;
-
1103  double hr = h[2]*(1-dz) + h[3]*dz;
-
1104 
-
1105  height = hl*(1-dx) + hr*dx + 5; // fudge
-
1106  }
-
1107  }
-
1108 
-
1109  if (height < 0)
-
1110  height = 0;
-
1111 
-
1112  return height;
-
1113 }
-
-
- - - - -- cgit v1.1