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/_solid_8cpp_source.html | 2586 ------------------------------ 1 file changed, 2586 deletions(-) delete mode 100644 Doc/doxygen/html/_solid_8cpp_source.html (limited to 'Doc/doxygen/html/_solid_8cpp_source.html') diff --git a/Doc/doxygen/html/_solid_8cpp_source.html b/Doc/doxygen/html/_solid_8cpp_source.html deleted file mode 100644 index c38b70e..0000000 --- a/Doc/doxygen/html/_solid_8cpp_source.html +++ /dev/null @@ -1,2586 +0,0 @@ - - - - - -Starshatter_Open: D:/SRC/StarshatterSVN/nGenEx/Solid.cpp Source File - - - - - - - - - - - - - -
-
- - - - - - -
-
Starshatter_Open -
-
Open source Starshatter engine
-
-
- - - - - -
-
- -
-
-
- -
- - - - -
- -
- -
-
-
Solid.cpp
-
-
-Go to the documentation of this file.
1 /* Project nGenEx
-
2  Destroyer Studios LLC
-
3  Copyright © 1997-2004. All Rights Reserved.
-
4 
-
5  SUBSYSTEM: nGenEx.lib
-
6  FILE: Solid.cpp
-
7  AUTHOR: John DiCamillo
-
8 
-
9 
-
10  OVERVIEW
-
11  ========
-
12  Classes for rendering solid meshes of polygons
-
13 */
-
14 
-
15 #include "MemDebug.h"
-
16 #include "Solid.h"
-
17 #include "Scene.h"
-
18 #include "Bitmap.h"
-
19 #include "DataLoader.h"
-
20 #include "Light.h"
-
21 #include "Shadow.h"
-
22 #include "Projector.h"
-
23 #include "OPCODE.h"
-
24 
-
25 #ifdef for
-
26 #undef for
-
27 #endif
-
28 
-
29 void Print(const char* fmt, ...);
-
30 
-
31 // +--------------------------------------------------------------------+
-
32 
-
33 static bool use_collision_detection = true;
-
34 
-
35 bool Solid::IsCollisionEnabled() { return use_collision_detection; }
-
36 void Solid::EnableCollision(bool e) { use_collision_detection = e; }
-
37 
-
38 // +--------------------------------------------------------------------+
-
39 
-
40 Opcode::AABBTreeCollider opcode_collider;
-
41 
- -
43 {
-
44 public:
- -
46  bool status = false;
-
47 
-
48  if (s) {
-
49  using namespace Opcode;
-
50  opcode_collider.SetFirstContact(true);
-
51 
-
52  npolys = s->NumPolys();
-
53  nverts = s->NumVerts();
-
54  ntris = s->NumIndices() / 3;
-
55 
-
56  locs = new(__FILE__,__LINE__) IcePoint[nverts];
-
57  tris = new(__FILE__,__LINE__) IndexedTriangle[ntris];
-
58 
-
59  if (locs && tris) {
-
60  int i, n = 0;
-
61 
-
62  for (i = 0; i < nverts; i++) {
-
63  IcePoint* p = locs + i;
-
64  Vec3* v = s->GetVertexSet()->loc + i;
-
65 
-
66  p->Set(v->x, v->y, v->z);
-
67  }
-
68 
-
69  for (i = 0; i < npolys; i++) {
-
70  Poly* p = s->GetPolys() + i;
-
71 
-
72  if (p->nverts == 3) {
-
73  IndexedTriangle& t = tris[n++];
-
74 
-
75  t.mVRef[0] = p->verts[0];
-
76  t.mVRef[1] = p->verts[2];
-
77  t.mVRef[2] = p->verts[1];
-
78  }
-
79  else {
-
80  IndexedTriangle& t1 = tris[n++];
-
81  IndexedTriangle& t2 = tris[n++];
-
82 
-
83  t1.mVRef[0] = p->verts[0];
-
84  t1.mVRef[1] = p->verts[2];
-
85  t1.mVRef[2] = p->verts[1];
-
86 
-
87  t2.mVRef[0] = p->verts[0];
-
88  t2.mVRef[1] = p->verts[3];
-
89  t2.mVRef[2] = p->verts[2];
-
90  }
-
91  }
-
92 
-
93  mesh.SetNbVertices(nverts);
-
94  mesh.SetNbTriangles(ntris);
-
95  mesh.SetPointers(tris, locs);
-
96 
-
97  OPCODECREATE creator;
-
98  creator.mIMesh = &mesh;
-
99  status = model.Build(creator);
-
100  }
-
101  }
-
102  else {
-
103  tris = 0;
-
104  locs = 0;
-
105  npolys = 0;
-
106  nverts = 0;
-
107  ntris = 0;
-
108  }
-
109  }
-
110 
- -
112  delete [] tris;
-
113  delete [] locs;
-
114  }
-
115 
-
116  Opcode::Model model;
-
117  Opcode::MeshInterface mesh;
-
118  IndexedTriangle* tris;
-
119  IcePoint* locs;
-
120  int npolys;
-
121  int nverts;
-
122  int ntris;
-
123 };
-
124 
-
125 // +--------------------------------------------------------------------+
-
126 // +--------------------------------------------------------------------+
-
127 // +--------------------------------------------------------------------+
-
128 
- -
130 : model(0), own_model(1),
-
131 roll(0.0f), pitch(0.0f), yaw(0.0f), intersection_poly(0)
-
132 {
-
133  shadow = true;
-
134  sprintf_s(name, "Solid %d", id);
-
135 }
-
136 
-
137 // +--------------------------------------------------------------------+
-
138 
- -
140 {
-
141  if (own_model)
-
142  delete model;
-
143 
-
144  shadows.destroy();
-
145 }
-
146 
-
147 // +--------------------------------------------------------------------+
-
148 
-
149 void
- -
151 {
-
152 }
-
153 
-
154 // +--------------------------------------------------------------------+
-
155 
-
156 void
- -
158 {
-
159  orientation = o;
-
160 }
-
161 
-
162 void
- -
164 {
-
165  luminous = l;
-
166 
-
167  if (model && luminous) {
-
168  model->luminous = luminous;
-
169 
- -
171 
-
172  while (++iter) {
-
173  Material* mtl = iter.value();
-
174 
-
175  mtl->Ka = Color::Black;
-
176  mtl->Kd = Color::Black;
-
177  mtl->Ks = Color::Black;
-
178  mtl->Ke = Color::White;
-
179 
-
180  if (mtl->tex_diffuse && !mtl->tex_emissive)
-
181  mtl->tex_emissive = mtl->tex_diffuse;
-
182  }
-
183 
-
184  ListIter<Surface> s_iter = model->GetSurfaces();
-
185  while (++s_iter) {
-
186  Surface* surface = s_iter.value();
-
187  VertexSet* vset = surface->GetVertexSet();
-
188 
-
189  for (int i = 0; i < vset->nverts; i++) {
-
190  vset->diffuse[i] = Color::White.Value();
-
191  vset->specular[i] = Color::Black.Value();
-
192  }
-
193  }
-
194  }
-
195 }
-
196 
-
197 // +--------------------------------------------------------------------+
-
198 
-
199 void
- -
201 {
-
202  if (!model || infinite)
-
203  return;
-
204 
-
205  // copy the orientation matrix from the solid we are matching:
-
206  orientation = match.Orientation();
-
207 }
-
208 
-
209 // +--------------------------------------------------------------------+
-
210 
-
211 void
-
212 Solid::Render(Video* video, DWORD flags)
-
213 {
-
214  if (flags & RENDER_ADDITIVE)
-
215  return;
-
216 
-
217  if (video && model && model->NumPolys()) {
-
218  DWORD blend_modes = Video::BLEND_SOLID;
-
219 
-
220  if (flags == RENDER_ALPHA)
- -
222 
-
223  video->DrawSolid(this, blend_modes);
-
224  }
-
225 }
-
226 
-
227 // +--------------------------------------------------------------------+
-
228 
-
229 void
- -
231 {
-
232 }
-
233 
-
234 // +--------------------------------------------------------------------+
-
235 
-
236 void
- -
238 {
-
239  if (model && p) {
-
240  Point tmp = loc;
-
241  p->Transform(tmp);
-
242 
-
243  if (tmp.z > 1) {
-
244  int l = 2000;
-
245  int r = -2000;
-
246  int t = 2000;
-
247  int b = -2000;
-
248 
-
249  for (int i = 0; i < 6; i++) {
-
250  Point extent;
-
251 
-
252  if (i < 2)
-
253  extent.x = model->extents[i];
-
254 
-
255  else if (i < 4)
-
256  extent.y = model->extents[i];
-
257 
-
258  else
-
259  extent.z = model->extents[i];
-
260 
-
261  extent = extent * orientation + loc;
-
262 
-
263  p->Transform(extent);
-
264  p->Project(extent);
-
265 
-
266  if (extent.x < l) l = (int) extent.x;
-
267  if (extent.x > r) r = (int) extent.x;
-
268  if (extent.y < t) t = (int) extent.y;
-
269  if (extent.y > b) b = (int) extent.y;
-
270  }
-
271 
-
272  screen_rect.x = l;
-
273  screen_rect.y = t;
-
274  screen_rect.w = r-l;
-
275  screen_rect.h = b-t;
-
276  return;
-
277  }
-
278  }
-
279 
-
280  screen_rect.x = 2000;
-
281  screen_rect.y = 2000;
-
282  screen_rect.w = 0;
-
283  screen_rect.h = 0;
-
284 }
-
285 
-
286 // +--------------------------------------------------------------------+
-
287 // Polygon Interference Detection:
-
288 
-
289 int
- -
291 {
-
292  Vec3 delta_loc = Location() - o.Location();
-
293 
-
294  // bounding spheres test:
-
295  if (delta_loc.length() > Radius() + o.Radius())
-
296  return 0;
-
297 
-
298  // possible collision, but no further refinement can be done:
-
299  if (!o.IsSolid())
-
300  return 1;
-
301 
-
302  Solid& s = (Solid&) o;
-
303 
-
304  // use the OPCODE library to check for polygon interference:
-
305  if (model && s.model) {
-
306  using namespace Opcode;
-
307 
-
308  bool contact = false;
-
309 
-
310  // first, reverse the orientation matrices for OPCODE:
-
311  Matrix m1 = orientation;
-
312  Matrix m2 = s.orientation;
-
313 
-
314  Matrix4x4 world0;
-
315  Matrix4x4 world1;
-
316 
-
317  world0.m[0][0] = (float) m1.elem[0][0];
-
318  world0.m[0][1] = (float) m1.elem[0][1];
-
319  world0.m[0][2] = (float) m1.elem[0][2];
-
320  world0.m[0][3] = 0.0f;
-
321 
-
322  world0.m[1][0] = (float) m1.elem[1][0];
-
323  world0.m[1][1] = (float) m1.elem[1][1];
-
324  world0.m[1][2] = (float) m1.elem[1][2];
-
325  world0.m[1][3] = 0.0f;
-
326 
-
327  world0.m[2][0] = (float) m1.elem[2][0];
-
328  world0.m[2][1] = (float) m1.elem[2][1];
-
329  world0.m[2][2] = (float) m1.elem[2][2];
-
330  world0.m[2][3] = 0.0f;
-
331 
-
332  world0.m[3][0] = (float) Location().x;
-
333  world0.m[3][1] = (float) Location().y;
-
334  world0.m[3][2] = (float) Location().z;
-
335  world0.m[3][3] = 1.0f;
-
336 
-
337  world1.m[0][0] = (float) m2.elem[0][0];
-
338  world1.m[0][1] = (float) m2.elem[1][0];
-
339  world1.m[0][2] = (float) m2.elem[2][0];
-
340  world1.m[0][3] = 0.0f;
-
341 
-
342  world1.m[1][0] = (float) m2.elem[0][1];
-
343  world1.m[1][1] = (float) m2.elem[1][1];
-
344  world1.m[1][2] = (float) m2.elem[2][1];
-
345  world1.m[1][3] = 0.0f;
-
346 
-
347  world1.m[2][0] = (float) m2.elem[0][2];
-
348  world1.m[2][1] = (float) m2.elem[1][2];
-
349  world1.m[2][2] = (float) m2.elem[2][2];
-
350  world1.m[2][3] = 0.0f;
-
351 
-
352  world1.m[3][0] = (float) s.Location().x;
-
353  world1.m[3][1] = (float) s.Location().y;
-
354  world1.m[3][2] = (float) s.Location().z;
-
355  world1.m[3][3] = 1.0f;
-
356 
-
357  ListIter<Surface> s1_iter = model->surfaces;
-
358  while (++s1_iter && !contact) {
-
359  Surface* s1 = s1_iter.value();
-
360 
-
361  ListIter<Surface> s2_iter = s.model->surfaces;
-
362  while (++s2_iter && !contact) {
-
363  Surface* s2 = s2_iter.value();
-
364 
-
365  if (s1->opcode && s2->opcode) {
-
366  BVTCache bvt;
-
367  bvt.Model0 = &s1->opcode->model;
-
368  bvt.Model1 = &s2->opcode->model;
-
369 
-
370  if (opcode_collider.Collide(bvt, &world0, &world1))
-
371  if (opcode_collider.GetContactStatus() != 0)
-
372  contact = true;
-
373  }
-
374  }
-
375  }
-
376 
-
377  return contact;
-
378  }
-
379 
-
380 
-
381  return 1;
-
382 }
-
383 
-
384 // +--------------------------------------------------------------------+
-
385 // Find the intersection of the ray (Q + w*len) with the solid.
-
386 // If the ray intersects a polygon of the solid, place the intersection
-
387 // point in ipt, and return 1. Otherwise, return 0.
-
388 
-
389 int
- -
391 bool treat_translucent_polys_as_solid)
-
392 {
-
393  int impact = 0;
-
394 
-
395  if (!model || model->npolys < 1)
-
396  return impact;
-
397 
-
398  // check right angle spherical distance:
-
399  Point d0 = loc - Q;
-
400  Point d1 = d0.cross(w);
-
401  double dlen = d1.length(); // distance of point from line
-
402 
-
403  if (dlen > radius) // clean miss
-
404  return 0; // (no impact)
-
405 
-
406  // possible collision course...
-
407 
-
408  /**********************************
-
409 
-
410 
-
411  /--- + leading_edge = Q + w * len
-
412  / / \
-
413  delta2 / delta 0
-
414  / / \
-
415  / *........x <- solid location
-
416  / /
-
417  / / delta1
-
418 /--- Q * = closest point
-
419 
-
420 
-
421 ************************************/
-
422 
-
423  // find the point on the ray that is closest
-
424  // to the solid's location:
-
425  Point closest = Q + w * (d0 * w);
-
426 
-
427  // find the leading edge, and it's distance from the location:
-
428  Point leading_edge = Q + w*len;
-
429  Point leading_delta = leading_edge - loc;
-
430  double leading_dist = leading_delta.length();
-
431 
-
432  // if the leading edge is not within the bounding sphere,
-
433  if (leading_dist > radius) {
-
434  // check to see if the closest point is between the
-
435  // ray's endpoints:
-
436  Point delta1 = closest - Q;
-
437  Point delta2 = leading_edge - Q; // this is w*len
-
438 
-
439  // if the closest point is not between the leading edge
-
440  // and the origin, this ray does not intersect:
-
441  if (delta1 * delta2 < 0 || delta1.length() > len) {
-
442  return 0;
-
443  }
-
444  }
-
445 
-
446  // probable hit at this point...
-
447 
-
448  // if not active, that's good enough:
-
449  if (GetScene() == 0) {
-
450  ipt = closest;
-
451  return 1;
-
452  }
-
453 
-
454  // transform ray into object space:
-
455  Matrix xform(Orientation());
-
456 
-
457  Vec3 tmp = w;
-
458 
-
459  w.x = tmp * Vec3(xform(0,0), xform(0,1), xform(0,2));
-
460  w.y = tmp * Vec3(xform(1,0), xform(1,1), xform(1,2));
-
461  w.z = tmp * Vec3(xform(2,0), xform(2,1), xform(2,2));
-
462 
-
463  tmp = Q-loc;
-
464 
-
465  Q.x = tmp * Vec3(xform(0,0), xform(0,1), xform(0,2));
-
466  Q.y = tmp * Vec3(xform(1,0), xform(1,1), xform(1,2));
-
467  Q.z = tmp * Vec3(xform(2,0), xform(2,1), xform(2,2));
-
468 
-
469  double min = len;
-
470  intersection_poly = 0;
-
471 
-
472  // check each polygon:
-
473  ListIter<Surface> iter = model->surfaces;
-
474  while (++iter) {
-
475  Surface* s = iter.value();
-
476  Poly* p = s->GetPolys();
-
477 
-
478  for (int i = 0; i < s->NumPolys(); i++) {
-
479  if (!treat_translucent_polys_as_solid && p->material && !p->material->IsSolid()) {
-
480  p++;
-
481  continue;
-
482  }
-
483 
-
484  Point v = p->plane.normal;
-
485  double d = p->plane.distance;
-
486 
-
487  double denom = w*v;
-
488 
-
489  if (denom < -1.0e-5) {
-
490  Point P = v * d;
-
491  double ilen = ((P-Q)*v)/denom;
-
492 
-
493  if (ilen > 0 && ilen < min) {
-
494  Point intersect = Q + w * ilen;
-
495 
-
496  if (p->Contains(intersect)) {
-
497  intersection_poly = p;
-
498  ipt = intersect;
-
499  min = ilen;
-
500  impact = 1;
-
501  }
-
502  }
-
503  }
-
504 
-
505  p++;
-
506  }
-
507  }
-
508 
-
509  // xform impact point back into world coordinates:
-
510 
-
511  if (impact) {
-
512  ipt = (ipt * Orientation()) + loc;
-
513  }
-
514 
-
515  return impact;
-
516 }
-
517 
-
518 // +--------------------------------------------------------------------+
-
519 
-
520 void
- -
522 {
-
523  if (own_model && model) {
-
524  delete model;
-
525  model = 0;
-
526  }
-
527 
-
528  radius = 0.0f;
-
529 }
-
530 
-
531 // +--------------------------------------------------------------------+
-
532 
-
533 void
- -
535 {
-
536  // get rid of the existing model:
-
537  ClearModel();
-
538 
-
539  // point to the new model:
-
540  own_model = 0;
-
541  model = m;
-
542  radius = m->radius;
-
543 }
-
544 
-
545 // +--------------------------------------------------------------------+
-
546 
-
547 bool
-
548 Solid::Load(const char* mag_file, double scale)
-
549 {
-
550  // get ready to load, delete existing model:
-
551  ClearModel();
-
552 
-
553  // loading our own copy, so we own the model:
-
554  model = new(__FILE__,__LINE__) Model;
-
555  own_model = 1;
-
556 
-
557  // now load the model:
-
558  if (model->Load(mag_file, scale)) {
-
559  radius = model->radius;
-
560  strncpy_s(name, model->name, sizeof(name));
-
561  return true;
-
562  }
-
563 
-
564  // load failed:
-
565  ClearModel();
-
566  return false;
-
567 }
-
568 
-
569 bool
-
570 Solid::Load(ModelFile* mod_file, double scale)
-
571 {
-
572  // get ready to load, delete existing model:
-
573  ClearModel();
-
574 
-
575  // loading our own copy, so we own the model:
-
576  model = new(__FILE__,__LINE__) Model;
-
577  own_model = 1;
-
578 
-
579  // now load the model:
-
580  if (model->Load(mod_file, scale)) {
-
581  radius = model->radius;
-
582  return true;
-
583  }
-
584 
-
585  // load failed:
-
586  ClearModel();
-
587  return false;
-
588 }
-
589 
-
590 bool
-
591 Solid::Rescale(double scale)
-
592 {
-
593  if (!own_model || !model)
-
594  return false;
-
595 
-
596  radius = 0;
-
597 
- -
599  while (++iter) {
-
600  Surface* s = iter.value();
-
601 
-
602  for (int v = 0; v < s->NumVerts(); v++) {
-
603  s->vertex_set->loc[v] *= (float) scale;
-
604  s->vloc[v] *= (float) scale;
-
605 
-
606  float lvi = s->vloc[v].length();
-
607  if (lvi > radius)
-
608  radius = lvi;
-
609  }
-
610  }
-
611 
-
612  model->radius = radius;
-
613 
- -
615 
-
616  return true;
-
617 }
-
618 
-
619 void
- -
621 {
-
622  while (shadows.size() < nlights) {
-
623  shadows.append(new(__FILE__,__LINE__) Shadow(this));
-
624  }
-
625 }
-
626 
-
627 void
- -
629 {
-
630  List<Light> active_lights;
-
631  ListIter<Light> iter = lights;
-
632 
-
633  while (++iter) {
-
634  Light* light = iter.value();
-
635 
-
636  if (light->IsActive() && light->CastsShadow()) {
-
637  double distance = Point(Location() - light->Location()).length();
-
638  double intensity = light->Intensity();
-
639 
-
640  if (light->Type() == Light::LIGHT_POINT) {
-
641  if (intensity / distance > 1)
-
642  active_lights.append(light);
-
643  }
-
644 
-
645  else if (light->Type() == Light::LIGHT_DIRECTIONAL) {
-
646  if (intensity > 0.65)
-
647  active_lights.insert(light);
-
648  }
-
649  }
-
650  }
-
651 
-
652  iter.attach(active_lights);
-
653 
-
654  while (++iter) {
-
655  Light* light = iter.value();
-
656  int index = iter.index();
-
657 
-
658  if (index < shadows.size()) {
-
659  shadows[index]->Update(light);
-
660  }
-
661  }
-
662 }
-
663 
-
664 // +--------------------------------------------------------------------+
-
665 
-
666 void
- -
668 {
-
669  if (model)
- -
671 }
-
672 
-
673 // +--------------------------------------------------------------------+
-
674 
-
675 void
- -
677 {
-
678  if (!model)
-
679  return;
-
680 
-
681  bool invalidate = model->IsDynamic();
-
682 
- -
684  while (++iter) {
-
685  Surface* s = iter.value();
- -
687 
-
688  if (vpd) {
-
689  if (invalidate) {
-
690  vpd->Invalidate();
-
691  }
-
692  else {
-
693  delete vpd;
-
694  s->SetVideoPrivateData(0);
-
695  }
-
696  }
-
697  }
-
698 }
-
699 
-
700 void
- -
702 {
-
703  if (!model)
-
704  return;
-
705 
-
706  bool invalidate = model->IsDynamic();
-
707 
- -
709  while (++iter) {
-
710  Surface* s = iter.value();
-
711 
-
712  ListIter<Segment> seg_iter = s->GetSegments();
-
713  while (++seg_iter) {
-
714  Segment* segment = seg_iter.value();
-
715  VideoPrivateData* vpd = segment->GetVideoPrivateData();
-
716 
-
717  if (vpd) {
-
718  if (invalidate) {
-
719  vpd->Invalidate();
-
720  }
-
721  else {
-
722  delete vpd;
-
723  segment->SetVideoPrivateData(0);
-
724  }
-
725  }
-
726  }
-
727  }
-
728 }
-
729 
-
730 // +--------------------------------------------------------------------+
-
731 
-
732 bool
- -
734 {
-
735  if (model)
-
736  return model->IsDynamic();
-
737 
-
738  return false;
-
739 }
-
740 
-
741 void
- -
743 {
-
744  if (model && own_model)
-
745  model->SetDynamic(d);
-
746 }
-
747 
-
748 // +--------------------------------------------------------------------+
-
749 
-
750 void
- -
752 {
-
753  if (model)
-
754  model->GetAllTextures(textures);
-
755 }
-
756 
-
757 void
- -
759 {
-
760  ListIter<Material> m_iter = materials;
-
761  while (++m_iter) {
-
762  Material* m = m_iter.value();
-
763 
-
764  if (m->tex_diffuse && !textures.contains(m->tex_diffuse))
-
765  textures.append(m->tex_diffuse);
-
766 
-
767  if (m->tex_specular && !textures.contains(m->tex_specular))
-
768  textures.append(m->tex_specular);
-
769 
-
770  if (m->tex_emissive && !textures.contains(m->tex_emissive))
-
771  textures.append(m->tex_emissive);
-
772 
-
773  if (m->tex_bumpmap && !textures.contains(m->tex_bumpmap))
-
774  textures.append(m->tex_bumpmap);
-
775 
-
776  if (m->tex_detail && !textures.contains(m->tex_detail))
-
777  textures.append(m->tex_detail);
-
778  }
-
779 }
-
780 
-
781 // +--------------------------------------------------------------------+
-
782 // +--------------------------------------------------------------------+
-
783 // +--------------------------------------------------------------------+
-
784 
- -
786 : nverts(0), npolys(0), radius(0), luminous(false), dynamic(false)
-
787 {
-
788  ZeroMemory(name, sizeof(name));
-
789 }
-
790 
- -
792 : nverts(0), npolys(0), radius(0), luminous(false), dynamic(false)
-
793 {
-
794  operator=(m);
-
795 }
-
796 
-
797 // +--------------------------------------------------------------------+
-
798 
- -
800 {
-
801  surfaces.destroy();
-
802  materials.destroy();
-
803 }
-
804 
-
805 Model&
- -
807 {
-
808  if (this != &m) {
-
809  surfaces.destroy();
-
810  materials.destroy();
-
811 
-
812  CopyMemory(name, m.name, Solid::NAMELEN);
-
813 
-
814  nverts = m.nverts;
-
815  npolys = m.npolys;
-
816  radius = m.radius;
-
817  luminous = m.luminous;
-
818  dynamic = m.dynamic;
-
819 
-
820  Model* pmod = (Model*) &m;
-
821 
-
822  ListIter<Material> m_iter = pmod->materials;
-
823  while (++m_iter) {
-
824  Material* matl1 = m_iter.value();
-
825  Material* matl2 = new(__FILE__,__LINE__) Material;
-
826 
-
827  CopyMemory(matl2, matl1, sizeof(Material));
-
828  matl2->thumbnail = 0;
-
829 
-
830  materials.append(matl2);
-
831  }
-
832 
-
833  ListIter<Surface> s_iter = pmod->surfaces;
-
834  while (++s_iter) {
-
835  Surface* surf1 = s_iter.value();
-
836  Surface* surf2 = new(__FILE__,__LINE__) Surface;
-
837 
-
838  surf2->Copy(*surf1, this);
-
839  surfaces.append(surf2);
-
840  }
-
841  }
-
842 
-
843  return *this;
-
844 }
-
845 
-
846 // +--------------------------------------------------------------------+
-
847 
-
848 int
- -
850 {
-
851  int nsegments = 0;
-
852 
-
853  for (int i = 0; i < surfaces.size(); i++) {
-
854  const Surface* s = surfaces[i];
-
855  nsegments += s->NumSegments();
-
856  }
-
857 
-
858  return nsegments;
-
859 }
-
860 
-
861 // +--------------------------------------------------------------------+
-
862 
-
863 inline bool Collinear(const double* a, const double* b, const double* c)
-
864 {
-
865  Point ab(b[0]-a[0], b[1]-a[1], b[2]-a[2]);
-
866  Point ac(c[0]-a[0], c[1]-a[1], c[2]-a[2]);
-
867  Point cross = ab.cross(ac);
-
868  return (cross.length() == 0);
-
869 }
-
870 
-
871 struct HomogenousPlane
-
872 {
-
873  double distance;
-
874  double normal_x;
-
875  double normal_y;
-
876  double normal_z;
-
877  double normal_w;
-
878 };
-
879 
-
880 static void LoadPlane(Plane& p, DataLoader* l, BYTE*& fp)
-
881 {
-
882  HomogenousPlane tmp;
-
883  l->fread(&tmp, sizeof(HomogenousPlane), 1, fp);
-
884 }
-
885 
-
886 static void LoadFlags(LPDWORD flags, DataLoader* l, BYTE*& fp)
-
887 {
-
888  DWORD magic_flags;
-
889  l->fread(&magic_flags, sizeof(DWORD), 1, fp);
-
890 
-
902  const DWORD magic_mask = 0x0fc3;
-
903 
-
904  *flags = magic_flags & magic_mask;
-
905 }
-
906 
-
907 // +--------------------------------------------------------------------+
-
908 
-
909 bool
-
910 Model::Load(const char* mag_file, double scale)
-
911 {
-
912  BYTE* block;
-
913  DataLoader* loader = DataLoader::GetLoader();
-
914  bool result = false;
-
915 
-
916  radius = 0.0f;
-
917  extents[0] = 0.0f;
-
918  extents[1] = 0.0f;
-
919  extents[2] = 0.0f;
-
920  extents[3] = 0.0f;
-
921  extents[4] = 0.0f;
-
922  extents[5] = 0.0f;
-
923 
-
924  if (!loader) {
-
925  Print("MAG Open Failed: no data loader for file '%s'\n", mag_file);
-
926  return result;
-
927  }
-
928 
-
929  int size = loader->LoadBuffer(mag_file, block);
-
930  BYTE* fp = block;
-
931 
-
932  // check MAG file:
-
933  if (!size) {
-
934  Print("MAG Open Failed: could not open file '%s'\n", mag_file);
-
935  return result;
-
936  }
-
937 
-
938  strncpy_s(name, mag_file, 31);
-
939  name[31] = 0;
-
940 
-
941  char file_id[5];
-
942  CopyMemory(file_id, block, 4);
-
943  file_id[4] = '\0';
-
944  int version = 1;
-
945 
-
946  if (!strcmp(file_id, "MAG6")) {
-
947  version = 6;
-
948  }
-
949  else if (!strcmp(file_id, "MAG5")) {
-
950  version = 5;
-
951  }
-
952  else if (!strcmp(file_id, "MAG4")) {
-
953  version = 4;
-
954  }
-
955  else {
-
956  Print("MAG Open Failed: File '%s' Invalid file type '%s'\n", mag_file, file_id);
-
957  loader->ReleaseBuffer(block);
-
958  return result;
-
959  }
-
960 
-
961  // get ready to load, delete existing model:
-
962  surfaces.destroy();
-
963  materials.destroy();
-
964  nverts = 0;
-
965  npolys = 0;
-
966 
-
967  // now load the model:
-
968  switch (version) {
-
969  case 4:
-
970  case 5:
-
971  result = LoadMag5(block, size, scale);
-
972  break;
-
973 
-
974  case 6:
-
975  result = LoadMag6(block, size, scale);
-
976  break;
-
977 
-
978  default:
-
979  break;
-
980  }
-
981 
-
982  loader->ReleaseBuffer(block);
-
983  return result;
-
984 }
-
985 
-
986 // +--------------------------------------------------------------------+
-
987 
-
988 bool
-
989 Model::Load(ModelFile* mod_file, double scale)
-
990 {
-
991  if (mod_file) {
-
992  return mod_file->Load(this, scale);
-
993  }
-
994 
-
995  return false;
-
996 }
-
997 
-
998 // +--------------------------------------------------------------------+
-
999 
-
1000 static int mcomp(const void* a, const void* b)
-
1001 {
-
1002  Poly* pa = (Poly*) a;
-
1003  Poly* pb = (Poly*) b;
-
1004 
-
1005  if (pa->sortval == pb->sortval)
-
1006  return 0;
-
1007 
-
1008  if (pa->sortval < pb->sortval)
-
1009  return 1;
-
1010 
-
1011  return -1;
-
1012 }
-
1013 
-
1014 bool
-
1015 Model::LoadMag5(BYTE* block, int len, double scale)
-
1016 {
-
1017  bool result = false;
-
1018 
-
1019  DataLoader* loader = DataLoader::GetLoader();
-
1020  BYTE* fp = block + 4;
-
1021  int ntex = 0;
-
1022  int nsurfs = 0;
-
1023 
-
1024  loader->fread(&ntex, sizeof(ntex), 1, fp);
-
1025  loader->fread(&nsurfs, sizeof(nsurfs), 1, fp);
-
1026 
-
1027  // create a default gray material:
-
1028  Material* mtl = new Material;
-
1029 
-
1030  if (mtl) {
-
1031  mtl->Ka = Color::LightGray;
-
1032  mtl->Kd = Color::LightGray;
-
1033  mtl->Ks = ColorValue(0.2f,0.2f,0.2f);
-
1034  mtl->power = 20.0f;
-
1035 
-
1036  mtl->ambient_value = 1.0f;
- -
1038  mtl->diffuse_value = 1.0f;
- -
1040  mtl->specular_value = 0.2f;
- -
1042  strcpy_s(mtl->name, "(default)");
-
1043 
-
1044  materials.append(mtl);
-
1045  }
-
1046 
-
1047  // read texture list:
-
1048  for (int i = 0; i < ntex; i++) {
-
1049  mtl = new(__FILE__,__LINE__) Material;
-
1050  char tname[32];
-
1051 
-
1052  if (mtl) {
-
1053  mtl->Ka = ColorValue(0.5f,0.5f,0.5f);
-
1054  mtl->Kd = ColorValue(1.0f,1.0f,1.0f);
-
1055  mtl->Ks = ColorValue(0.2f,0.2f,0.2f);
-
1056  mtl->power = 20.0f;
-
1057 
-
1058  mtl->ambient_value = 1.0f;
-
1059  mtl->ambient_color = Color::Gray;
-
1060  mtl->diffuse_value = 1.0f;
-
1061  mtl->diffuse_color = Color::White;
-
1062  mtl->specular_value = 0.2f;
- -
1064 
-
1065  loader->fread(tname, 32, 1, fp);
-
1066  loader->LoadTexture(tname, mtl->tex_diffuse, Bitmap::BMP_SOLID, true);
-
1067  strcpy_s(mtl->name, tname);
-
1068 
-
1069  char* dot = strrchr(mtl->name, '.');
-
1070  if (dot)
-
1071  *dot = 0;
-
1072 
-
1073  char* plus = strrchr(mtl->name, '+');
-
1074  if (plus)
-
1075  *plus = 0;
-
1076 
-
1077  materials.append(mtl);
-
1078  }
-
1079  }
-
1080 
-
1081 
-
1082  loader->fread(&nverts, 4, 1, fp);
-
1083  loader->fread(&npolys, 4, 1, fp);
-
1084 
-
1085  // plan on creating four verts per poly:
-
1086  int mag_nverts = nverts;
-
1087  int next_vert = nverts;
-
1088 
-
1089  nverts = npolys * 4;
-
1090 
-
1091  Surface* s = new(__FILE__,__LINE__) Surface;
-
1092  VertexSet* vset = 0;
-
1093 
-
1094  if (s) {
-
1095  strcpy_s(s->name, "default");
-
1096 
-
1097  s->model = this;
-
1098  s->vertex_set = new(__FILE__,__LINE__) VertexSet(nverts);
-
1099  s->vloc = new(__FILE__,__LINE__) Vec3[nverts];
-
1100 
-
1101  ZeroMemory(s->vertex_set->loc, nverts * sizeof(Vec3));
-
1102  ZeroMemory(s->vertex_set->diffuse, nverts * sizeof(DWORD));
-
1103  ZeroMemory(s->vertex_set->specular, nverts * sizeof(DWORD));
-
1104  ZeroMemory(s->vertex_set->tu, nverts * sizeof(float));
-
1105  ZeroMemory(s->vertex_set->tv, nverts * sizeof(float));
-
1106  ZeroMemory(s->vertex_set->rw, nverts * sizeof(float));
-
1107  ZeroMemory(s->vloc, nverts * sizeof(Vec3));
-
1108 
-
1109  s->npolys = npolys;
-
1110  s->polys = new(__FILE__,__LINE__) Poly[npolys];
-
1111 
-
1112  ZeroMemory(s->polys, sizeof(Poly) * npolys);
-
1113  surfaces.append(s);
-
1114 
-
1115  vset = s->vertex_set;
-
1116 
-
1117  int v;
-
1118  // read vertex set:
-
1119  for (v = 0; v < mag_nverts; v++) {
-
1120  Vec3 vert, norm;
-
1121  DWORD vstate;
-
1122 
-
1123  loader->fread(&vert, sizeof(Vec3), 1, fp);
-
1124  loader->fread(&norm, sizeof(Vec3), 1, fp);
-
1125  loader->fread(&vstate, sizeof(DWORD), 1, fp);
-
1126 
-
1127  vert.SwapYZ();
-
1128  vert *= (float) scale;
-
1129 
-
1130  vset->loc[v] = vert;
-
1131  vset->nrm[v] = norm;
-
1132 
-
1133  double d = vert.length();
-
1134  if (d > radius)
-
1135  radius = (float) d;
-
1136 
-
1137  if (vert.x > extents[0]) extents[0] = vert.x;
-
1138  if (vert.x < extents[1]) extents[1] = vert.x;
-
1139  if (vert.y > extents[2]) extents[2] = vert.y;
-
1140  if (vert.y < extents[3]) extents[3] = vert.y;
-
1141  if (vert.z > extents[4]) extents[4] = vert.z;
-
1142  if (vert.z < extents[5]) extents[5] = vert.z;
-
1143  }
-
1144 
-
1145  while (v < nverts)
-
1146  vset->nrm[v++] = Vec3(1,0,0);
-
1147 
-
1148  // read polys:
-
1149  Vec3 dummy_center;
-
1150  DWORD dummy_flags;
-
1151  DWORD dummy_color;
-
1152  Plane dummy_plane;
-
1153  int texture_num;
-
1154  int poly_nverts;
-
1155  int vert_index_buffer[32];
-
1156  float texture_index_buffer[32];
-
1157 
-
1158  for (int n = 0; n < npolys; n++) {
-
1159  Poly& poly = s->polys[n];
-
1160  poly.vertex_set = vset;
-
1161 
-
1162  loader->fread(&dummy_flags, sizeof(DWORD), 1, fp);
-
1163  loader->fread(&dummy_center, sizeof(Vec3), 1, fp);
-
1164 
-
1165  LoadPlane(dummy_plane, loader, fp);
-
1166 
-
1167  loader->fread(&dummy_color, sizeof(DWORD), 1, fp);
-
1168  loader->fread(&texture_num, sizeof(int), 1, fp);
-
1169 
-
1170  if (texture_num >= 0 && texture_num < ntex) {
-
1171  int mtl_num = texture_num + 1;
-
1172  poly.material = materials[mtl_num];
-
1173  poly.sortval = texture_num;
-
1174 
-
1175  bool flag_translucent = (dummy_flags & 0x04) ? true : false;
-
1176  bool flag_transparent = (dummy_flags & 0x08) ? true : false;
-
1177 
-
1178  // luminous
-
1179  if (dummy_flags & 2) {
-
1180  mtl = materials[mtl_num];
-
1181 
-
1182  mtl->Ka = ColorValue(0,0,0,0);
-
1183  mtl->Kd = ColorValue(0,0,0,0);
-
1184  mtl->Ks = ColorValue(0,0,0,0);
-
1185  mtl->Ke = ColorValue(1,1,1,1);
-
1186 
-
1187  mtl->tex_emissive = mtl->tex_diffuse;
-
1188  }
-
1189 
-
1190  // glowing (additive)
-
1191  if (flag_translucent && flag_transparent)
-
1192  materials[mtl_num]->blend = Material::MTL_ADDITIVE;
-
1193 
-
1194  // translucent (alpha)
-
1195  else if (flag_translucent)
-
1196  materials[mtl_num]->blend = Material::MTL_TRANSLUCENT;
-
1197 
-
1198  // transparent (just use alpha for this)
-
1199  else if (flag_transparent)
-
1200  materials[mtl_num]->blend = Material::MTL_TRANSLUCENT;
-
1201  }
-
1202  else {
-
1203  poly.material = materials.first();
-
1204  poly.sortval = 1000;
-
1205  }
-
1206 
-
1207  // hack: store flat shaded flag in unused visible byte
-
1208  poly.visible = (BYTE) (dummy_flags & 1);
-
1209 
-
1210  loader->fread(&poly_nverts, sizeof(int), 1, fp);
-
1211  loader->fread(vert_index_buffer, sizeof(int), poly_nverts, fp);
-
1212 
-
1213  if (poly_nverts == 3)
-
1214  s->nindices += 3;
-
1215 
-
1216  else if (poly_nverts == 4)
-
1217  s->nindices += 6;
-
1218 
-
1219  poly.nverts = poly_nverts;
-
1220  for (int vi = 0; vi < poly_nverts; vi++) {
-
1221  v = vert_index_buffer[vi];
-
1222 
-
1223  if (vset->rw[v] > 0) {
-
1224  vset->CopyVertex(next_vert, v);
-
1225  v = next_vert++;
-
1226  }
-
1227 
-
1228  vset->rw[v] = 1;
-
1229  poly.verts[vi] = v;
-
1230  }
-
1231 
-
1232  loader->fread(texture_index_buffer, sizeof(float), poly_nverts, fp); // tu's
-
1233  for (int vi = 0; vi < poly_nverts; vi++) {
-
1234  v = poly.verts[vi];
-
1235  vset->tu[v] = texture_index_buffer[vi];
-
1236  }
-
1237 
-
1238  loader->fread(texture_index_buffer, sizeof(float), poly_nverts, fp); // tv's
-
1239  for (int vi = 0; vi < poly_nverts; vi++) {
-
1240  v = poly.verts[vi];
-
1241  vset->tv[v] = texture_index_buffer[vi];
-
1242  }
-
1243 
-
1244  fp += 16;
-
1245  }
-
1246 
-
1247  // pass 2 (adjust vertex normals for flat polys):
-
1248  for (int n = 0; n < npolys; n++) {
-
1249  Poly& poly = s->polys[n];
-
1250  poly.plane = Plane(vset->loc[poly.verts[0]],
-
1251  vset->loc[poly.verts[2]],
-
1252  vset->loc[poly.verts[1]]);
-
1253 
-
1254  // hack: retrieve flat shaded flag from unused visible byte
-
1255  if (poly.visible) {
-
1256  poly_nverts = poly.nverts;
-
1257 
-
1258  for (int vi = 0; vi < poly_nverts; vi++) {
-
1259  v = poly.verts[vi];
-
1260  vset->nrm[v] = poly.plane.normal;
-
1261  }
-
1262  }
-
1263  }
-
1264 
-
1265  // sort the polys by material index:
-
1266  qsort((void*) s->polys, s->npolys, sizeof(Poly), mcomp);
-
1267 
-
1268  // then assign them to cohesive segments:
-
1269  Segment* segment = 0;
-
1270 
-
1271  for (int n = 0; n < npolys; n++) {
-
1272  if (segment && segment->material == s->polys[n].material) {
-
1273  segment->npolys++;
-
1274  }
-
1275  else {
-
1276  segment = 0;
-
1277  }
-
1278 
-
1279  if (!segment) {
-
1280  segment = new(__FILE__,__LINE__) Segment;
-
1281 
-
1282  segment->npolys = 1;
-
1283  segment->polys = &s->polys[n];
-
1284  segment->material = segment->polys->material;
-
1285  segment->model = this;
-
1286 
-
1287  s->segments.append(segment);
-
1288  }
-
1289  }
-
1290 
-
1291  s->BuildHull();
-
1292 
-
1293  result = nverts && npolys;
-
1294  }
-
1295 
-
1296  return result;
-
1297 }
-
1298 
-
1299 // +--------------------------------------------------------------------+
-
1300 
-
1301 struct MaterialMag6 {
-
1302  char name[Material::NAMELEN];
-
1303  char shader[Material::NAMELEN];
-
1304  float power; // highlight sharpness (big=shiny)
-
1305  float brilliance; // diffuse power function
-
1306  float bump; // bump level (0=none)
-
1307  DWORD blend; // alpha blend type
-
1308  bool shadow; // material casts shadow
-
1309  bool luminous; // verts have their own lighting
-
1310 
- - - - -
1315 
-
1316  float ambient_value;
-
1317  float diffuse_value;
-
1318  float specular_value;
-
1319  float emissive_value;
-
1320 
-
1321  BYTE tex_diffuse;
-
1322  BYTE tex_specular;
-
1323  BYTE tex_bumpmap;
-
1324  BYTE tex_emissive;
-
1325 };
-
1326 
-
1327 // +--------------------------------------------------------------------+
-
1328 
-
1329 bool
-
1330 Model::LoadMag6(BYTE* block, int len, double scale)
-
1331 {
-
1332  bool result = false;
-
1333 
-
1334  DataLoader* loader = DataLoader::GetLoader();
-
1335  BYTE* fp = block + 4;
-
1336  int ntex = 0;
-
1337  int nmtls = 0;
-
1338  int nsurfs = 0;
-
1339  List<Bitmap> textures;
-
1340 
-
1341  loader->fread(&ntex, sizeof(ntex), 1, fp); // size of texture block
-
1342  loader->fread(&nmtls, sizeof(nmtls), 1, fp); // number of materials
-
1343  loader->fread(&nsurfs, sizeof(nsurfs), 1, fp); // number of surfaces
-
1344 
-
1345  // read texture list:
-
1346  if (ntex) {
-
1347  char* buffer = new(__FILE__,__LINE__) char[ntex];
-
1348  char* p = buffer;
-
1349  Bitmap* bmp = 0;
-
1350 
-
1351  loader->fread(buffer, ntex, 1, fp);
-
1352 
-
1353  while (p < buffer + ntex) {
-
1354  loader->LoadTexture(p, bmp, Bitmap::BMP_SOLID, true);
-
1355  textures.append(bmp);
-
1356 
-
1357  p += strlen(p) + 1;
-
1358  }
-
1359 
-
1360  delete [] buffer;
-
1361  }
-
1362 
-
1363  for (int i = 0; i < nmtls; i++) {
-
1364  MaterialMag6 m6;
-
1365  Material* mtl = new(__FILE__,__LINE__) Material;
-
1366 
-
1367  loader->fread(&m6, sizeof(m6), 1, fp);
-
1368 
-
1369  if (mtl) {
-
1370  CopyMemory(mtl->name, m6.name, Material::NAMELEN);
-
1371  CopyMemory(mtl->shader, m6.shader, Material::NAMELEN);
-
1372 
-
1373  mtl->ambient_value = m6.ambient_value;
-
1374  mtl->ambient_color = m6.ambient_color;
-
1375  mtl->diffuse_value = m6.diffuse_value;
-
1376  mtl->diffuse_color = m6.diffuse_color;
-
1377  mtl->specular_value = m6.specular_value;
-
1378  mtl->specular_color = m6.specular_color;
-
1379  mtl->emissive_value = m6.emissive_value;
-
1380  mtl->emissive_color = m6.emissive_color;
-
1381 
-
1382  mtl->Ka = ColorValue(mtl->ambient_color) * mtl->ambient_value;
-
1383  mtl->Kd = ColorValue(mtl->diffuse_color) * mtl->diffuse_value;
-
1384  mtl->Ks = ColorValue(mtl->specular_color) * mtl->specular_value;
-
1385  mtl->Ke = ColorValue(mtl->emissive_color) * mtl->emissive_value;
-
1386 
-
1387  mtl->power = m6.power;
-
1388  mtl->brilliance = m6.brilliance;
-
1389  mtl->bump = m6.bump;
-
1390  mtl->blend = m6.blend;
-
1391  mtl->shadow = m6.shadow;
-
1392  mtl->luminous = m6.luminous;
-
1393 
-
1394  if (m6.tex_diffuse && m6.tex_diffuse <= textures.size())
-
1395  mtl->tex_diffuse = textures[m6.tex_diffuse - 1];
-
1396 
-
1397  if (m6.tex_specular && m6.tex_specular <= textures.size())
-
1398  mtl->tex_specular = textures[m6.tex_specular - 1];
-
1399 
-
1400  if (m6.tex_emissive && m6.tex_emissive <= textures.size())
-
1401  mtl->tex_emissive = textures[m6.tex_emissive - 1];
-
1402 
-
1403  if (m6.tex_bumpmap && m6.tex_bumpmap <= textures.size())
-
1404  mtl->tex_bumpmap = textures[m6.tex_bumpmap - 1];
-
1405 
-
1406  materials.append(mtl);
-
1407  }
-
1408  }
-
1409 
-
1410  for (int i = 0; i < nsurfs; i++) {
-
1411  int nverts = 0;
-
1412  int npolys = 0;
-
1413  BYTE namelen = 0;
-
1414  char name[128];
-
1415 
-
1416  loader->fread(&nverts, 4, 1, fp);
-
1417  loader->fread(&npolys, 4, 1, fp);
-
1418  loader->fread(&namelen, 1, 1, fp);
-
1419  loader->fread(name, 1, namelen, fp);
-
1420 
-
1421  Surface* surface = new(__FILE__,__LINE__) Surface;
-
1422  surface->model = this;
-
1423  surface->SetName(name);
-
1424  surface->CreateVerts(nverts);
-
1425  surface->CreatePolys(npolys);
-
1426 
-
1427  VertexSet* vset = surface->GetVertexSet();
-
1428  Poly* polys = surface->GetPolys();
-
1429 
-
1430  ZeroMemory(polys, sizeof(Poly) * npolys);
-
1431 
-
1432  // read vertex set:
-
1433  for (int v = 0; v < nverts; v++) {
-
1434  loader->fread(&vset->loc[v], sizeof(float), 3, fp);
-
1435  loader->fread(&vset->nrm[v], sizeof(float), 3, fp);
-
1436  loader->fread(&vset->tu[v], sizeof(float), 1, fp);
-
1437  loader->fread(&vset->tv[v], sizeof(float), 1, fp);
-
1438 
-
1439  vset->loc[v] *= (float) scale;
-
1440 
-
1441  Vec3 vert = vset->loc[v];
-
1442 
-
1443  double d = vert.length();
-
1444  if (d > radius)
-
1445  radius = (float) d;
-
1446 
-
1447  if (vert.x > extents[0]) extents[0] = vert.x;
-
1448  if (vert.x < extents[1]) extents[1] = vert.x;
-
1449  if (vert.y > extents[2]) extents[2] = vert.y;
-
1450  if (vert.y < extents[3]) extents[3] = vert.y;
-
1451  if (vert.z > extents[4]) extents[4] = vert.z;
-
1452  if (vert.z < extents[5]) extents[5] = vert.z;
-
1453  }
-
1454 
-
1455  // read polys:
-
1456  for (int n = 0; n < npolys; n++) {
-
1457  Poly& poly = polys[n];
-
1458  BYTE poly_nverts = 0;
-
1459  BYTE material_index = 0;
-
1460  WORD poly_verts[8];
-
1461 
-
1462  loader->fread(&poly_nverts, sizeof(BYTE), 1, fp);
-
1463  loader->fread(&material_index, sizeof(BYTE), 1, fp);
-
1464  loader->fread(&poly_verts[0], sizeof(WORD), poly_nverts, fp);
-
1465 
-
1466  if (poly_nverts >= 3) {
-
1467  poly.nverts = poly_nverts;
-
1468 
-
1469  for (int i = 0; i < poly_nverts; i++) {
-
1470  poly.verts[i] = poly_verts[i];
-
1471  }
-
1472  }
-
1473  else {
-
1474  poly.sortval = 666;
-
1475  }
-
1476 
-
1477  if (material_index > 0) {
-
1478  poly.material = materials[material_index-1];
-
1479  poly.sortval = material_index;
-
1480  }
-
1481  else if (materials.size()) {
-
1482  poly.material = materials.first();
-
1483  poly.sortval = 1;
-
1484  }
-
1485  else {
-
1486  poly.sortval = 1000;
-
1487  }
-
1488 
-
1489  if (poly.nverts == 3)
-
1490  surface->AddIndices(3);
-
1491 
-
1492  else if (poly.nverts == 4)
-
1493  surface->AddIndices(6);
-
1494 
-
1495  poly.vertex_set = vset;
-
1496  poly.plane = Plane(vset->loc[poly.verts[0]],
-
1497  vset->loc[poly.verts[2]],
-
1498  vset->loc[poly.verts[1]]);
-
1499  }
-
1500 
-
1501  // sort the polys by material index:
-
1502  qsort((void*) polys, npolys, sizeof(Poly), mcomp);
-
1503 
-
1504  // then assign them to cohesive segments:
-
1505  Segment* segment = 0;
-
1506 
-
1507  for (int n = 0; n < npolys; n++) {
-
1508  if (segment && segment->material == polys[n].material) {
-
1509  segment->npolys++;
-
1510  }
-
1511  else {
-
1512  segment = 0;
-
1513  }
-
1514 
-
1515  if (!segment) {
-
1516  segment = new(__FILE__,__LINE__) Segment;
-
1517 
-
1518  segment->npolys = 1;
-
1519  segment->polys = &polys[n];
-
1520  segment->material = segment->polys->material;
-
1521  segment->model = this;
-
1522 
-
1523  surface->GetSegments().append(segment);
-
1524  }
-
1525  }
-
1526 
-
1527  surface->BuildHull();
-
1528  surfaces.append(surface);
-
1529 
-
1530  this->nverts += nverts;
-
1531  this->npolys += npolys;
-
1532  }
-
1533 
-
1534 
-
1535  result = nverts && npolys;
-
1536  return result;
-
1537 }
-
1538 
-
1539 void
- -
1541 {
-
1542  if (surface) {
-
1543  surface->model = this;
-
1544 
-
1545  ListIter<Segment> iter = surface->segments;
-
1546  while (++iter) {
-
1547  Segment* segment = iter.value();
-
1548  segment->model = this;
-
1549  }
-
1550 
-
1551  surface->BuildHull();
-
1552  surfaces.append(surface);
-
1553 
-
1554  nverts += surface->NumVerts();
-
1555  npolys += surface->NumPolys();
-
1556  }
-
1557 }
-
1558 
-
1559 
-
1560 // +--------------------------------------------------------------------+
-
1561 
-
1562 const Material*
-
1563 Model::FindMaterial(const char* mtl_name) const
-
1564 {
-
1565  if (mtl_name && *mtl_name) {
-
1566  Model* pThis = (Model*) this;
-
1567 
-
1568  ListIter<Material> iter = pThis->materials;
-
1569  while (++iter) {
-
1570  Material* mtl = iter.value();
-
1571 
-
1572  if (!strcmp(mtl->name, mtl_name))
-
1573  return mtl;
-
1574  }
-
1575  }
-
1576 
-
1577  return 0;
-
1578 }
-
1579 
-
1580 const Material*
- -
1582 {
-
1583  const Material* mtl_orig = 0;
-
1584 
-
1585  if (mtl) {
-
1586  mtl_orig = FindMaterial(mtl->name);
-
1587 
-
1588  if (mtl_orig) {
-
1589  int n = materials.index(mtl_orig);
-
1590  materials[n] = (Material*) mtl;
-
1591 
-
1592  ListIter<Surface> surf_iter = surfaces;
-
1593  while (++surf_iter) {
-
1594  Surface* surf = surf_iter.value();
-
1595 
-
1596  ListIter<Segment> seg_iter = surf->GetSegments();
-
1597  while (++seg_iter) {
-
1598  Segment* segment = seg_iter.value();
-
1599 
-
1600  if (segment->material == mtl_orig)
-
1601  segment->material = (Material*) mtl;
-
1602  }
-
1603  }
-
1604  }
-
1605  }
-
1606 
-
1607  return mtl_orig;
-
1608 }
-
1609 
-
1610 // +--------------------------------------------------------------------+
-
1611 
-
1612 Poly*
-
1613 Model::AddPolys(int nsurf, int np, int nv)
-
1614 {
-
1615  if (nsurf >= 0 && nsurf < surfaces.size())
-
1616  return surfaces[nsurf]->AddPolys(np, nv);
-
1617 
-
1618  ::Print("WARNING: AddPolys(%d,%d,%d) invalid surface\n", nsurf, np, nv);
-
1619  return 0;
-
1620 }
-
1621 
-
1622 // +--------------------------------------------------------------------+
-
1623 
-
1624 void
- -
1626 {
-
1627  ListIter<Surface> iter = surfaces;
-
1628 
-
1629  int nv = 0;
-
1630  int np = 0;
-
1631 
-
1632  while (++iter) {
-
1633  Surface* s = iter.value();
-
1634  s->ExplodeMesh();
-
1635 
-
1636  nv += s->NumVerts();
-
1637  np += s->NumPolys();
-
1638  }
-
1639 
-
1640  nverts = nv;
-
1641  npolys = np;
-
1642 }
-
1643 
-
1644 // +--------------------------------------------------------------------+
-
1645 
-
1646 void
- -
1648 {
-
1649  ListIter<Surface> iter = surfaces;
-
1650 
-
1651  int nv = 0;
-
1652  int np = 0;
-
1653 
-
1654  while (++iter) {
-
1655  Surface* s = iter.value();
-
1656  s->OptimizeMesh();
-
1657 
-
1658  nv += s->NumVerts();
-
1659  np += s->NumPolys();
-
1660  }
-
1661 
-
1662  nverts = nv;
-
1663  npolys = np;
-
1664 }
-
1665 
-
1666 // +--------------------------------------------------------------------+
-
1667 
-
1668 void
- -
1670 {
-
1671  for (int i = 0; i < materials.size(); i++) {
-
1672  Material* m1 = materials[i];
-
1673 
-
1674  for (int n = i; n < materials.size(); n++) {
-
1675  Material* m2 = materials[n];
-
1676 
-
1677  // if they match, merge them:
-
1678  if (*m1 == *m2) {
-
1679  List<Poly> polys;
-
1680  SelectPolys(polys, m2);
-
1681 
-
1682  ListIter<Poly> iter = polys;
-
1683  while (++iter) {
-
1684  Poly* p = iter.value();
-
1685  p->material = m1;
-
1686  }
-
1687 
-
1688  // and discard the duplicate:
-
1689  materials.remove(m2);
-
1690  delete m2;
-
1691  }
-
1692  }
-
1693  }
-
1694 }
-
1695 
-
1696 void
-
1697 Model::ScaleBy(double factor)
-
1698 {
-
1699  ListIter<Surface> iter = surfaces;
-
1700 
-
1701  while (++iter) {
-
1702  Surface* s = iter.value();
-
1703  s->ScaleBy(factor);
-
1704  }
-
1705 }
-
1706 
-
1707 // +--------------------------------------------------------------------+
-
1708 
-
1709 void
- -
1711 {
-
1712  ListIter<Surface> iter = surfaces;
-
1713 
-
1714  while (++iter) {
-
1715  Surface* s = iter.value();
-
1716  s->Normalize();
-
1717  }
-
1718 }
-
1719 
-
1720 void
- -
1722 {
-
1723  ListIter<Surface> iter = surfaces;
-
1724 
-
1725  while (++iter) {
-
1726  Surface* s = iter.value();
-
1727  s->SelectPolys(polys, loc);
-
1728  }
-
1729 }
-
1730 
-
1731 void
- -
1733 {
-
1734  ListIter<Surface> iter = surfaces;
-
1735 
-
1736  while (++iter) {
-
1737  Surface* s = iter.value();
-
1738  s->SelectPolys(polys, m);
-
1739  }
-
1740 }
-
1741 
-
1742 void
- -
1744 {
-
1745  ListIter<Surface> iter = surfaces;
-
1746 
-
1747  while (++iter) {
-
1748  Surface* s = iter.value();
-
1749  s->ComputeTangents();
-
1750  }
-
1751 }
-
1752 
-
1753 // +--------------------------------------------------------------------+
-
1754 
-
1755 void
- -
1757 {
-
1758  ListIter<Surface> iter = surfaces;
-
1759  while (++iter) {
-
1760  Surface* s = iter.value();
- -
1762 
-
1763  if (vpd) {
-
1764  delete vpd;
-
1765  s->SetVideoPrivateData(0);
-
1766  }
-
1767 
-
1768  ListIter<Segment> seg_iter = s->GetSegments();
-
1769  while (++seg_iter) {
-
1770  Segment* segment = seg_iter.value();
-
1771  VideoPrivateData* vpdp = segment->video_data;
-
1772 
-
1773  if (vpdp) {
-
1774  delete vpdp;
-
1775  segment->video_data = 0;
-
1776  }
-
1777  }
-
1778  }
-
1779 }
-
1780 
-
1781 // +--------------------------------------------------------------------+
-
1782 // +--------------------------------------------------------------------+
-
1783 // +--------------------------------------------------------------------+
-
1784 
- -
1786 : model(0), vertex_set(0), vloc(0), nhull(0), npolys(0), nindices(0),
-
1787 polys(0), state(0), video_data(0), opcode(0)
-
1788 {
-
1789  ZeroMemory(name, sizeof(name));
-
1790 }
-
1791 
- -
1793 {
-
1794  segments.destroy();
-
1795 
-
1796  delete opcode;
-
1797  delete vertex_set;
-
1798  delete [] vloc;
-
1799  delete [] polys;
-
1800  delete video_data;
-
1801 
-
1802  model = 0;
-
1803 }
-
1804 
-
1805 // +--------------------------------------------------------------------+
-
1806 
-
1807 void
- -
1809 {
-
1810  segments.destroy();
-
1811 
-
1812  delete opcode;
-
1813  delete vertex_set;
-
1814  delete [] vloc;
-
1815  delete [] polys;
-
1816  delete video_data;
-
1817 
-
1818  CopyMemory(name, s.name, Solid::NAMELEN);
-
1819 
-
1820  model = m;
-
1821  radius = s.radius;
-
1822  nhull = s.nhull;
-
1823  npolys = s.npolys;
-
1824  nindices = s.nindices;
-
1825  state = s.state;
-
1826  offset = s.offset;
-
1827  orientation = s.orientation;
-
1828  opcode = 0;
-
1829  video_data = 0;
-
1830 
-
1831  vertex_set = s.vertex_set->Clone();
-
1832 
-
1833  if (nhull > 0) {
-
1834  vloc = new(__FILE__,__LINE__) Vec3[nhull];
-
1835  CopyMemory(vloc, s.vloc, nhull * sizeof(Vec3));
-
1836  }
-
1837  else {
-
1838  vloc = 0;
-
1839  }
-
1840 
-
1841  polys = new(__FILE__,__LINE__) Poly[npolys];
-
1842  CopyMemory(polys, s.polys, npolys * sizeof(Poly));
-
1843 
-
1844  for (int i = 0; i < npolys; i++) {
-
1845  polys[i].vertex_set = vertex_set;
-
1846 
-
1847  if (s.polys[i].material)
-
1848  polys[i].material = (Material*) model->FindMaterial(s.polys[i].material->name);
-
1849  }
-
1850 
-
1851  ListIter<Segment> iter = s.segments;
-
1852  while (++iter) {
-
1853  Segment* seg1 = iter.value();
-
1854  Segment* seg2 = new(__FILE__,__LINE__) Segment;
-
1855 
-
1856  seg2->npolys = seg1->npolys;
-
1857  seg2->polys = polys + (seg1->polys - s.polys);
-
1858 
-
1859  if (seg2->polys[0].material)
-
1860  seg2->material = seg2->polys[0].material;
-
1861 
-
1862  seg2->model = model;
-
1863  seg2->video_data = 0;
-
1864 
-
1865  segments.append(seg2);
-
1866  }
-
1867 }
-
1868 
-
1869 // +--------------------------------------------------------------------+
-
1870 
-
1871 void
-
1872 Surface::SetName(const char* n)
-
1873 {
-
1874  int len = sizeof(name);
-
1875 
-
1876  ZeroMemory(name, len);
-
1877  strncpy_s(name, n, len-1);
-
1878 }
-
1879 
-
1880 void
- -
1882 {
-
1883  if (b)
-
1884  state = state | HIDDEN;
-
1885 
-
1886  else
-
1887  state = state & ~HIDDEN;
-
1888 }
-
1889 
-
1890 void
- -
1892 {
-
1893  if (b)
-
1894  state = state | LOCKED;
-
1895 
-
1896  else
-
1897  state = state & ~LOCKED;
-
1898 }
-
1899 
-
1900 void
- -
1902 {
-
1903  if (b)
-
1904  state = state | SIMPLE;
-
1905 
-
1906  else
-
1907  state = state & ~SIMPLE;
-
1908 }
-
1909 
-
1910 void
- -
1912 {
-
1913  if (!vertex_set && !vloc) {
-
1914  vertex_set = new(__FILE__,__LINE__) VertexSet(nverts);
-
1915  vloc = new(__FILE__,__LINE__) Vec3[nverts];
-
1916  }
-
1917 }
-
1918 
-
1919 void
- -
1921 {
-
1922  if (!polys && !npolys) {
-
1923  npolys = np;
-
1924  polys = new(__FILE__,__LINE__) Poly[npolys];
-
1925 
-
1926  ZeroMemory(polys, npolys * sizeof(Poly));
-
1927  }
-
1928 }
-
1929 
-
1930 // +--------------------------------------------------------------------+
-
1931 
-
1932 Poly*
-
1933 Surface::AddPolys(int np, int nv)
-
1934 {
-
1935  if ( polys && vertex_set &&
-
1936  np > 0 && np + npolys < MAX_POLYS &&
-
1937  nv > 0 && nv + vertex_set->nverts < MAX_VERTS)
-
1938  {
-
1939  int newverts = nv + vertex_set->nverts;
-
1940  int newpolys = np + npolys;
-
1941 
-
1942  vertex_set->Resize(newverts, true);
-
1943 
-
1944  Poly* pset = new(__FILE__,__LINE__) Poly[newpolys];
-
1945  Poly* pnew = pset + npolys;
-
1946 
-
1947  CopyMemory(pset, polys, npolys * sizeof(Poly));
-
1948  ZeroMemory(pnew, np * sizeof(Poly));
-
1949 
-
1950  if (segments.size() > 0) {
-
1951  Segment* seg = segments.last();
-
1952  Material* mtl = seg->material;
-
1953 
-
1954  for (int i = 0; i < np; i++) {
-
1955  Poly* p = pnew + i;
-
1956  p->material = mtl;
-
1957  }
-
1958 
-
1959  seg->npolys += np;
-
1960  }
-
1961  }
-
1962 
-
1963  return 0;
-
1964 }
-
1965 
-
1966 // +--------------------------------------------------------------------+
-
1967 
-
1968 void
- -
1970 {
-
1971  if (!vertex_set || vertex_set->nverts < 3)
-
1972  return;
-
1973 
-
1974  int i, j, v;
-
1975  int nverts = 0;
-
1976 
-
1977  // count max verts:
-
1978  for (i = 0; i < npolys; i++) {
-
1979  Poly* p = polys + i;
-
1980  nverts += p->nverts;
-
1981  }
-
1982 
-
1983  // create target vertex set:
-
1984  VertexSet* vset = new(__FILE__,__LINE__) VertexSet(nverts);
-
1985  v = 0;
-
1986 
-
1987  // explode verts:
-
1988  for (i = 0; i < npolys; i++) {
-
1989  Poly* p = polys + i;
-
1990  p->vertex_set = vset;
-
1991 
-
1992  for (j = 0; j < p->nverts; j++) {
-
1993  int vsrc = p->verts[j];
-
1994 
-
1995  vset->loc[v] = vertex_set->loc[vsrc];
-
1996  vset->nrm[v] = vertex_set->nrm[vsrc];
-
1997  vset->tu[v] = vertex_set->tu[vsrc];
-
1998  vset->tv[v] = vertex_set->tv[vsrc];
-
1999  vset->rw[v] = vertex_set->rw[vsrc];
-
2000  vset->diffuse[v] = vertex_set->diffuse[vsrc];
-
2001  vset->specular[v] = vertex_set->specular[vsrc];
-
2002 
-
2003  p->verts[j] = v++;
-
2004  }
-
2005  }
-
2006 
-
2007  // finalize:
-
2008  if (vset) {
-
2009  delete vertex_set;
-
2010  vertex_set = vset;
-
2011  }
-
2012 
-
2013  if (vloc)
-
2014  delete [] vloc;
-
2015 
-
2016  vloc = new(__FILE__,__LINE__) Vec3[nverts];
-
2017 
-
2018  ComputeTangents();
-
2019  BuildHull();
-
2020 }
-
2021 
-
2022 // +--------------------------------------------------------------------+
-
2023 
-
2024 const double SELECT_EPSILON = 0.05;
-
2025 const double SELECT_TEXTURE = 0.0001;
-
2026 
-
2027 static bool MatchVerts(VertexSet* vset, int i, int j)
-
2028 {
-
2029  double d = 0;
-
2030  const Vec3& vl1 = vset->loc[i];
-
2031  const Vec3& vn1 = vset->nrm[i];
-
2032  float tu1 = vset->tu[i];
-
2033  float tv1 = vset->tv[i];
-
2034  const Vec3& vl2 = vset->loc[j];
-
2035  const Vec3& vn2 = vset->nrm[j];
-
2036  float tu2 = vset->tu[j];
-
2037  float tv2 = vset->tv[j];
-
2038 
-
2039  d = fabs(vl1.x - vl2.x);
-
2040  if (d > SELECT_EPSILON)
-
2041  return false;
-
2042 
-
2043  d = fabs(vl1.y - vl2.y);
-
2044  if (d > SELECT_EPSILON)
-
2045  return false;
-
2046 
-
2047  d = fabs(vl1.z - vl2.z);
-
2048  if (d > SELECT_EPSILON)
-
2049  return false;
-
2050 
-
2051  d = fabs(vn1.x - vn2.x);
-
2052  if (d > SELECT_EPSILON)
-
2053  return false;
-
2054 
-
2055  d = fabs(vn1.y - vn2.y);
-
2056  if (d > SELECT_EPSILON)
-
2057  return false;
-
2058 
-
2059  d = fabs(vn1.z - vn2.z);
-
2060  if (d > SELECT_EPSILON)
-
2061  return false;
-
2062 
-
2063  d = fabs(tu1 - tu2);
-
2064  if (d > SELECT_TEXTURE)
-
2065  return false;
-
2066 
-
2067  d = fabs(tv1 - tv2);
-
2068  if (d > SELECT_TEXTURE)
-
2069  return false;
-
2070 
-
2071  return true;
-
2072 }
-
2073 
-
2074 void
- -
2076 {
-
2077  if (!vertex_set || vertex_set->nverts < 3)
-
2078  return;
-
2079 
-
2080  int nverts = vertex_set->nverts;
-
2081  int used = 0;
-
2082  int final = 0;
-
2083  int nmatch = 0;
-
2084 
-
2085  // create vertex maps:
-
2086  BYTE* vert_map = new BYTE[nverts];
-
2087  WORD* vert_dst = new WORD[nverts];
-
2088  ZeroMemory(vert_map, nverts * sizeof(BYTE));
-
2089  ZeroMemory(vert_dst, nverts * sizeof(WORD));
-
2090 
-
2091  // count used verts:
-
2092  for (int i = 0; i < npolys; i++) {
-
2093  Poly* p = polys + i;
-
2094 
-
2095  for (int j = 0; j < p->nverts; j++) {
-
2096  WORD vert = p->verts[j];
-
2097 
-
2098  if (vert < nverts) {
-
2099  vert_map[vert]++;
-
2100  used++;
-
2101  }
-
2102  }
-
2103  }
-
2104 
-
2105  // create target vertex set:
-
2106  VertexSet* vset = new(__FILE__,__LINE__) VertexSet(used);
-
2107  int v = 0;
-
2108 
-
2109  // compress verts:
-
2110  for (int i = 0; i < nverts; i++) {
-
2111  if (vert_map[i] == 0) continue;
-
2112 
-
2113  vert_dst[i] = v;
-
2114  vset->loc[v] = vertex_set->loc[i];
-
2115  vset->nrm[v] = vertex_set->nrm[i];
-
2116  vset->tu[v] = vertex_set->tu[i];
-
2117  vset->tv[v] = vertex_set->tv[i];
-
2118  vset->rw[v] = vertex_set->rw[i];
-
2119  vset->diffuse[v] = vertex_set->diffuse[i];
-
2120  vset->specular[v] = vertex_set->specular[i];
-
2121 
-
2122  for (int j = i+1; j < nverts; j++) {
-
2123  if (vert_map[j] == 0) continue;
-
2124 
-
2125  if (MatchVerts(vertex_set, i, j)) {
-
2126  vert_map[j] = 0;
-
2127  vert_dst[j] = v;
-
2128  nmatch++;
-
2129  }
-
2130  }
-
2131 
-
2132  v++;
-
2133  }
-
2134 
-
2135  final = v;
-
2136 
-
2137  // remap polys:
-
2138  for (int n = 0; n < npolys; n++) {
-
2139  Poly* p = polys + n;
-
2140  p->vertex_set = vset;
-
2141  for (int v = 0; v < p->nverts; v++) {
-
2142  p->verts[v] = vert_dst[ p->verts[v] ];
-
2143  }
-
2144  }
-
2145 
-
2146  // finalize:
-
2147  if (vset && final < nverts) {
-
2148  delete vertex_set;
-
2149  vertex_set = vset;
-
2150  vset->Resize(final, true);
-
2151  nverts = final;
-
2152  }
-
2153 
-
2154  // clean up and rebuild hull:
-
2155  delete [] vert_map;
-
2156 
-
2157  if (vloc)
-
2158  delete [] vloc;
-
2159 
-
2160  vloc = new(__FILE__,__LINE__) Vec3[nverts];
-
2161 
-
2162  ComputeTangents();
-
2163  BuildHull();
-
2164 }
-
2165 
-
2166 // +--------------------------------------------------------------------+
-
2167 
-
2168 void
-
2169 Surface::ScaleBy(double factor)
-
2170 {
-
2171  offset *= factor;
-
2172 
-
2173  if (vertex_set && vertex_set->nverts) {
-
2174  for (int i = 0; i < vertex_set->nverts; i++) {
-
2175  vertex_set->loc[i] *= (float) factor;
-
2176  }
-
2177  }
-
2178 }
-
2179 
-
2180 // +--------------------------------------------------------------------+
-
2181 
-
2182 void
- -
2184 {
-
2185  if (npolys < 1 || !vertex_set || vertex_set->nverts < 1)
-
2186  return;
-
2187 
-
2188  nhull = 0;
-
2189 
-
2190  for (int i = 0; i < npolys; i++) {
-
2191  Poly* p = polys + i;
-
2192 
-
2193  for (int n = 0; n < p->nverts; n++) {
-
2194  WORD v = p->verts[n];
-
2195  WORD h;
-
2196 
-
2197  for (h = 0; h < nhull; h++) {
-
2198  Vec3& vl = vertex_set->loc[v];
-
2199  Vec3& loc = vloc[h];
-
2200 
-
2201  double d = vl.x - loc.x;
-
2202 
-
2203  if (d < -SELECT_EPSILON || d > SELECT_EPSILON)
-
2204  continue;
-
2205 
-
2206  d = vl.y - loc.y;
-
2207 
-
2208  if (d < -SELECT_EPSILON || d > SELECT_EPSILON)
-
2209  continue;
-
2210 
-
2211  d = vl.z - loc.z;
-
2212 
-
2213  if (d < -SELECT_EPSILON || d > SELECT_EPSILON)
-
2214  continue;
-
2215 
-
2216  // found a match:
-
2217  break;
-
2218  }
-
2219 
-
2220  // didn't find a match:
-
2221  if (h >= nhull) {
-
2222  vloc[h] = vertex_set->loc[v];
-
2223  nhull = h+1;
-
2224  }
-
2225 
-
2226  p->vlocs[n] = h;
-
2227  }
-
2228  }
-
2229 
-
2230  if (use_collision_detection)
- -
2232 }
-
2233 
-
2234 // +--------------------------------------------------------------------+
-
2235 
-
2236 void
- -
2238 {
-
2239  if (npolys < 1 || !vertex_set || vertex_set->nverts < 1)
-
2240  return;
-
2241 
-
2242  // STEP ONE: initialize poly planes
-
2243 
-
2244  for (int i = 0; i < npolys; i++) {
-
2245  Poly* p = polys + i;
-
2246 
-
2247  p->plane = Plane( vertex_set->loc[ p->verts[0] ],
-
2248  vertex_set->loc[ p->verts[2] ],
-
2249  vertex_set->loc[ p->verts[1] ] );
-
2250  }
-
2251 
-
2252  // STEP TWO: compute vertex normals by averaging adjecent poly planes
-
2253 
-
2254  List<Poly> faces;
-
2255  for (int v = 0; v < vertex_set->nverts; v++) {
-
2256  faces.clear();
-
2257  SelectPolys(faces, vertex_set->loc[v]);
-
2258 
-
2259  if (faces.size()) {
-
2260  vertex_set->nrm[v] = Vec3(0.0f, 0.0f, 0.0f);
-
2261 
-
2262  for (int i = 0; i < faces.size(); i++) {
-
2263  vertex_set->nrm[v] += faces[i]->plane.normal;
-
2264  }
-
2265 
-
2266  vertex_set->nrm[v].Normalize();
-
2267  }
-
2268 
-
2269  else if (vertex_set->loc[v].length() > 0) {
-
2270  vertex_set->nrm[v] = vertex_set->loc[v];
-
2271  vertex_set->nrm[v].Normalize();
-
2272  }
-
2273 
-
2274  else {
-
2275  vertex_set->nrm[v] = Vec3(0.0f, 1.0f, 0.0f);
-
2276  }
-
2277  }
-
2278 
-
2279  // STEP THREE: adjust vertex normals for poly flatness
-
2280 
-
2281  for (int i = 0; i < npolys; i++) {
-
2282  Poly* p = polys + i;
-
2283 
-
2284  for (int n = 0; n < p->nverts; n++) {
-
2285  int v = p->verts[n];
-
2286 
-
2287  vertex_set->nrm[v] = vertex_set->nrm[v] * (1.0f - p->flatness) +
-
2288  p->plane.normal * ( p->flatness);
-
2289  }
-
2290  }
-
2291 }
-
2292 
-
2293 void
- -
2295 {
-
2296  const double SELECT_EPSILON = 0.05;
-
2297 
-
2298  for (int i = 0; i < npolys; i++) {
-
2299  Poly* p = polys + i;
-
2300 
-
2301  for (int n = 0; n < p->nverts; n++) {
-
2302  int v = p->verts[n];
-
2303  Vec3& vl = vertex_set->loc[v];
-
2304  double d = vl.x - loc.x;
-
2305 
-
2306  if (d < -SELECT_EPSILON || d > SELECT_EPSILON)
-
2307  continue;
-
2308 
-
2309  d = vl.y - loc.y;
-
2310 
-
2311  if (d < -SELECT_EPSILON || d > SELECT_EPSILON)
-
2312  continue;
-
2313 
-
2314  d = vl.z - loc.z;
-
2315 
-
2316  if (d < -SELECT_EPSILON || d > SELECT_EPSILON)
-
2317  continue;
-
2318 
-
2319  selection.append(p);
-
2320  break;
-
2321  }
-
2322  }
-
2323 }
-
2324 
-
2325 void
- -
2327 {
-
2328  for (int i = 0; i < npolys; i++) {
-
2329  Poly* p = polys + i;
-
2330 
-
2331  if (p->material == m)
-
2332  selection.append(p);
-
2333  }
-
2334 }
-
2335 
-
2336 // +--------------------------------------------------------------------+
-
2337 
-
2338 void
- -
2340 {
-
2341  Vec3 tangent;
-
2342  Vec3 binormal;
-
2343 
-
2344  if (!vertex_set || !vertex_set->nverts)
-
2345  return;
-
2346 
-
2347  if (vertex_set->tangent)
-
2348  return;
-
2349 
-
2350  vertex_set->CreateTangents();
-
2351 
-
2352  for (int i = 0; i < npolys; i++) {
-
2353  Poly* p = polys + i;
-
2354 
-
2355  CalcGradients(*p, tangent, binormal);
-
2356 
-
2357  for (int n = 0; n < p->nverts; n++) {
-
2358  vertex_set->tangent[p->verts[n]] = tangent;
-
2359  vertex_set->binormal[p->verts[n]] = binormal;
-
2360  }
-
2361  }
-
2362 }
-
2363 
-
2364 void
-
2365 Surface::CalcGradients(Poly& p, Vec3& tangent, Vec3& binormal)
-
2366 {
-
2367  // using Eric Lengyel's approach with a few modifications
-
2368  // from Mathematics for 3D Game Programmming and Computer Graphics
-
2369  // want to be able to trasform a vector in Object Space to Tangent Space
-
2370  // such that the x-axis cooresponds to the 's' direction and the
-
2371  // y-axis corresponds to the 't' direction, and the z-axis corresponds
-
2372  // to <0,0,1>, straight up out of the texture map
-
2373 
-
2374  VertexSet* vset = p.vertex_set;
-
2375 
-
2376  Vec3 P = vset->loc[p.verts[1]] - vset->loc[p.verts[0]];
-
2377  Vec3 Q = vset->loc[p.verts[2]] - vset->loc[p.verts[0]];
-
2378 
-
2379  float s1 = vset->tu[p.verts[1]] - vset->tu[p.verts[0]];
-
2380  float t1 = vset->tv[p.verts[1]] - vset->tv[p.verts[0]];
-
2381  float s2 = vset->tu[p.verts[2]] - vset->tu[p.verts[0]];
-
2382  float t2 = vset->tv[p.verts[2]] - vset->tv[p.verts[0]];
-
2383 
-
2384  float tmp = 1.0f;
-
2385  float denom = s1*t2 - s2*t1;
-
2386 
-
2387  if (fabsf(denom) > 0.0001f)
-
2388  tmp = 1.0f/(denom);
-
2389 
-
2390  tangent.x = (t2*P.x - t1*Q.x) * tmp;
-
2391  tangent.y = (t2*P.y - t1*Q.y) * tmp;
-
2392  tangent.z = (t2*P.z - t1*Q.z) * tmp;
-
2393 
-
2394  tangent.Normalize();
-
2395 
-
2396  binormal.x = (s1*Q.x - s2*P.x) * tmp;
-
2397  binormal.y = (s1*Q.y - s2*P.y) * tmp;
-
2398  binormal.z = (s1*Q.z - s2*P.z) * tmp;
-
2399 
-
2400  binormal.Normalize();
-
2401 }
-
2402 
-
2403 void
- -
2405 {
-
2406  opcode = new(__FILE__,__LINE__) OPCODE_data(this);
-
2407 }
-
2408 
-
2409 // +--------------------------------------------------------------------+
-
2410 // +--------------------------------------------------------------------+
-
2411 // +--------------------------------------------------------------------+
-
2412 
- -
2414 {
-
2415  ZeroMemory(this, sizeof(Segment));
-
2416 }
-
2417 
-
2418 Segment::Segment(int n, Poly* p, Material* mtl, Model* mod)
-
2419 : npolys(n), polys(p), material(mtl), model(mod), video_data(0)
-
2420 {
-
2421 }
-
2422 
- -
2424 {
-
2425  delete video_data;
-
2426 
-
2427  ZeroMemory(this, sizeof(Segment));
-
2428 }
-
2429 
-
2430 // +--------------------------------------------------------------------+
-
2431 // +--------------------------------------------------------------------+
-
2432 // +--------------------------------------------------------------------+
-
2433 
-
2434 ModelFile::ModelFile(const char* fname)
-
2435 : model(0), pname(0), pnverts(0), pnpolys(0), pradius(0)
-
2436 {
-
2437  int len = sizeof(filename);
-
2438  ZeroMemory(filename, len);
-
2439  strncpy_s(filename, fname, len);
-
2440  filename[len-1] = 0;
-
2441 }
-
2442 
- -
2444 {
-
2445 }
-
2446 
-
2447 bool
-
2448 ModelFile::Load(Model* m, double scale)
-
2449 {
-
2450  model = m;
-
2451 
-
2452  // expose model innards for child classes:
-
2453 
-
2454  if (model) {
-
2455  pname = model->name;
-
2456  pnverts = &model->nverts;
-
2457  pnpolys = &model->npolys;
-
2458  pradius = &model->radius;
-
2459  }
-
2460 
-
2461  return false;
-
2462 }
-
2463 
-
2464 bool
- -
2466 {
-
2467  model = m;
-
2468 
-
2469  // expose model innards for child classes:
-
2470 
-
2471  if (model) {
-
2472  pname = model->name;
-
2473  pnverts = &model->nverts;
-
2474  pnpolys = &model->npolys;
-
2475  pradius = &model->radius;
-
2476  }
-
2477 
-
2478  return false;
-
2479 }
-
2480 
-
-
- - - - -- cgit v1.1