From 8898ad9b25fca6afe2374d293a981db02a83d7e9 Mon Sep 17 00:00:00 2001 From: "FWoltermann@gmail.com" Date: Thu, 31 May 2012 14:46:27 +0000 Subject: Committing the documentation to svn to have it accessible online --- Doc/doxygen/html/_terrain_patch_8cpp_source.html | 1230 ++++++++++++++++++++++ 1 file changed, 1230 insertions(+) create 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 new file mode 100644 index 0000000..1f1f81e --- /dev/null +++ b/Doc/doxygen/html/_terrain_patch_8cpp_source.html @@ -0,0 +1,1230 @@ + + + + + +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