Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
meshgeometry.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/***********************************************************************************************
20 *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
21 ***********************************************************************************************
22 * *
23 * Project Name : WW3D *
24 * *
25 * $Archive:: /Commando/Code/ww3d2/meshgeometry.cpp $*
26 * *
27 * Original Author:: Greg Hjelstrom *
28 * *
29 * $Author:: Jani_p $*
30 * *
31 * $Modtime:: 11/24/01 5:34p $*
32 * *
33 * $Revision:: 14 $*
34 * *
35 *---------------------------------------------------------------------------------------------*
36 * Functions: *
37 * MeshGeometryClass::MeshGeometryClass -- Constructor *
38 * MeshGeometryClass::MeshGeometryClass -- Copy Constructor *
39 * -- assignment operator *
40 * MeshGeometryClass::~MeshGeometryClass -- destructor *
41 * MeshGeometryClass::Reset_Geometry -- releases current resources and allocates space if ne *
42 * MeshGeometryClass::Get_Name -- returns the name *
43 * MeshGeometryClass::Set_Name -- set the name of this model *
44 * MeshGeometryClass::Get_User_Text -- get the user-text buffer *
45 * MeshGeometryClass::Set_User_Text -- set the user text buffer *
46 * MeshGeometryClass::Get_Bounding_Box -- get the bounding box *
47 * MeshGeometryClass::Get_Bounding_Sphere -- get the bounding sphere *
48 * MeshGeometryClass::Generate_Rigid_APT -- generate active polygon table *
49 * MeshGeometryClass::Generate_Skin_APT -- generate an active polygon table *
50 * MeshGeometryClass::Contains -- test if the mesh contains the given point *
51 * MeshGeometryClass::Cast_Ray -- compute a ray intersection with this mesh *
52 * MeshGeometryClass::Cast_AABox -- cast an AABox against this mesh *
53 * MeshGeometryClass::Cast_OBBox -- Cast an obbox against this mesh *
54 * MeshGeometryClass::Intersect_OBBox -- test for intersection with the given OBBox *
55 * MeshGeometryClass::Cast_World_Space_AABox -- test for intersection with a worldspace AABox*
56 * MeshGeometryClass::cast_semi_infinite_axis_aligned_ray -- casts an axis aligned ray *
57 * MeshGeometryClass::cast_aabox_identity -- aligned aabox test *
58 * MeshGeometryClass::cast_aabox_z90 -- aabox test which is rotated about z by 90 *
59 * MeshGeometryClass::cast_aabox_z180 -- aabox test which is rotated about z by 180 *
60 * MeshGeometryClass::cast_aabox_z270 -- aabox test which is rotated about z by 270 *
61 * MeshGeometryClass::cast_ray_brute_force -- brute force ray-cast *
62 * MeshGeometryClass::cast_aabox_brute_force -- brute force aabox cast *
63 * MeshGeometryClass::cast_obbox_brute_force -- brute force obbox cast *
64 * MeshGeometryClass::intersect_obbox_brute_force -- brute force intersection check *
65 * MeshGeometryClass::Compute_Plane_Equations -- Recalculates the plane equations *
66 * MeshGeometryClass::Compute_Vertex_Normals -- recompute the vertex normals *
67 * MeshGeometryClass::Compute_Bounds -- recomputes the bounding volumes *
68 * MeshGeometryClass::get_vert_normals -- get the vertex normal array *
69 * MeshGeometryClass::Get_Vertex_Normal_Array -- validates and returns the vertex normal arr *
70 * MeshGeometryClass::get_planes -- get the plane array memory (internal) *
71 * MeshGeometryClass::Get_Plane_Array -- validates and returns the array of plane equations *
72 * MeshGeometryClass::Compute_Plane -- compute the plane equation of a single poly *
73 * MeshGeometryClass::Generate_Culling_Tree -- Generate an AABTree for this mesh *
74 * MeshGeometryClass::Load_W3D -- Load a mesh from a w3d *
75 * MeshGeometryClass::read_chunks -- read w3d chunks *
76 * MeshGeometryClass::read_vertices -- read the vertex chunk from a W3D file *
77 * MeshGeometryClass::read_vertex_normals -- read the vertex normals chunk from a w3d file *
78 * MeshGeometryClass::read_triangles -- read the triangles chunk from a w3d file *
79 * MeshGeometryClass::read_user_text -- read the user text chunk from a w3d file *
80 * MeshGeometryClass::read_vertex_influences -- read the vertex influences chunk from a w3d *
81 * MeshGeometryClass::read_vertex_shade_indices -- read the vertex shade indices chunk *
82 * MeshGeometryClass::read_aabtree -- read the AABTree chunk from a w3d file *
83 * MeshGeometryClass::Generate_APT -- generate an apt for a box and view direction *
84 * MeshGeometryClass::Generate_Rigid_APT -- generate an apt using backface culling *
85 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
86
87
88#include "meshgeometry.h"
89#include "aabtree.h"
90#include "chunkio.h"
91#include "aabox.h"
92#include "obbox.h"
93#include "sphere.h"
94#include "plane.h"
95#include "wwdebug.h"
96#include "wwmemlog.h"
97#include "w3d_file.h"
98#include "vp.h"
99#include "htree.h"
100#include "matrix4.h"
101#include "rinfo.h"
102#include "camera.h"
103
104
105#if (OPTIMIZE_PLANEEQ_RAM)
106static SimpleVecClass<Vector4> _PlaneEQArray(1024);
107#endif
108
109
110#if (OPTIMIZE_VNORM_RAM)
111static SimpleVecClass<Vector3> _VNormArray(1024);
112#endif
113
114
115/***********************************************************************************************
116 * MeshGeometryClass::MeshGeometryClass -- Constructor *
117 * *
118 * INPUT: *
119 * *
120 * OUTPUT: *
121 * *
122 * WARNINGS: *
123 * *
124 * HISTORY: *
125 * 11/9/2000 gth : Created. *
126 *=============================================================================================*/
149
150
151/***********************************************************************************************
152 * MeshGeometryClass::MeshGeometryClass -- Copy Constructor *
153 * *
154 * INPUT: *
155 * *
156 * OUTPUT: *
157 * *
158 * WARNINGS: *
159 * *
160 * HISTORY: *
161 * 11/9/2000 gth : Created. *
162 *=============================================================================================*/
164 MeshName(NULL),
165 UserText(NULL),
166 Flags(0),
168 W3dAttributes(0),
169 PolyCount(0),
170 VertexCount(0),
171 Poly(NULL),
173 Vertex(NULL),
175 PlaneEq(NULL),
178 BoundBoxMin(0,0,0),
179 BoundBoxMax(1,1,1),
180 BoundSphereCenter(0,0,0),
183{
184 *this = that;
185}
186
187
188/***********************************************************************************************
189 * -- assignment operator *
190 * *
191 * INPUT: *
192 * *
193 * OUTPUT: *
194 * *
195 * WARNINGS: *
196 * *
197 * HISTORY: *
198 * 11/9/2000 gth : Created. *
199 *=============================================================================================*/
201{
202 if (this != &that) {
203 Flags = that.Flags;
204 SortLevel = that.SortLevel;
206 PolyCount = that.PolyCount;
208
213
216 REF_PTR_SET(Poly,that.Poly);
223
224 // Clone the cull tree..
226
227 if (that.CullTree) {
229 *CullTree = *that.CullTree;
230 CullTree->Set_Mesh(this);
231 }
232 }
233 return * this;
234}
235
236
237/***********************************************************************************************
238 * MeshGeometryClass::~MeshGeometryClass -- destructor *
239 * *
240 * INPUT: *
241 * *
242 * OUTPUT: *
243 * *
244 * WARNINGS: *
245 * *
246 * HISTORY: *
247 * 11/9/2000 gth : Created. *
248 *=============================================================================================*/
253
254
255/***********************************************************************************************
256 * MeshGeometryClass::Reset_Geometry -- releases current resources and allocates space if need *
257 * *
258 * INPUT: *
259 * *
260 * OUTPUT: *
261 * *
262 * WARNINGS: *
263 * *
264 * HISTORY: *
265 * 11/9/2000 gth : Created. *
266 *=============================================================================================*/
267void MeshGeometryClass::Reset_Geometry(int polycount,int vertcount)
268{
269 // Release everything we have and reset to initial state
270 Flags = 0;
271 PolyCount = 0;
272 VertexCount = 0;
274
285
286 PolyCount = polycount;
287 VertexCount = vertcount;
288
289 // allocate new geometry arrays
290 if ((polycount != 0) && (vertcount != 0)) {
291 Poly = NEW_REF(ShareBufferClass<TriIndex>,(PolyCount, "MeshGeometryClass::Poly"));
292 PolySurfaceType = NEW_REF(ShareBufferClass<uint8>,(PolyCount, "MeshGeometryClass::PolySurfaceType"));
293 Vertex = NEW_REF(ShareBufferClass<Vector3>,(VertexCount, "MeshGeometryClass::Vertex"));
294
295 Poly->Clear();
296 PolySurfaceType->Clear();
297 Vertex->Clear();
298
299#if (!OPTIMIZE_VNORM_RAM)
300 VertexNorm = NEW_REF(ShareBufferClass<Vector3>,(VertexCount, "MeshGeometryClass::VertexNorm"));
301 VertexNorm->Clear();
302#endif
303 }
304
305 return ;
306}
307
308
309/***********************************************************************************************
310 * MeshGeometryClass::Get_Name -- returns the name *
311 * *
312 * INPUT: *
313 * *
314 * OUTPUT: *
315 * *
316 * WARNINGS: *
317 * *
318 * HISTORY: *
319 * 11/9/2000 gth : Created. *
320 *=============================================================================================*/
321const char * MeshGeometryClass::Get_Name(void) const
322{
323 if (MeshName) {
324 return MeshName->Get_Array();
325 }
326 return NULL;
327}
328
329
330/***********************************************************************************************
331 * MeshGeometryClass::Set_Name -- set the name of this model *
332 * *
333 * INPUT: *
334 * *
335 * OUTPUT: *
336 * *
337 * WARNINGS: *
338 * *
339 * HISTORY: *
340 * 11/9/2000 gth : Created. *
341 *=============================================================================================*/
342void MeshGeometryClass::Set_Name(const char * newname)
343{
344 if (MeshName) {
345 MeshName->Release_Ref();
346 }
347 if (newname) {
348 MeshName = NEW_REF(ShareBufferClass<char>,(strlen(newname)+1, "MeshGeometryClass::MeshName"));
349 strcpy(MeshName->Get_Array(),newname);
350 }
351}
352
353
354/***********************************************************************************************
355 * MeshGeometryClass::Get_User_Text -- get the user-text buffer *
356 * *
357 * INPUT: *
358 * *
359 * OUTPUT: *
360 * *
361 * WARNINGS: *
362 * *
363 * HISTORY: *
364 * 11/9/2000 gth : Created. *
365 *=============================================================================================*/
367{
368 if (UserText) {
369 return UserText->Get_Array();
370 }
371 return NULL;
372}
373
374
375/***********************************************************************************************
376 * MeshGeometryClass::Set_User_Text -- set the user text buffer *
377 * *
378 * INPUT: *
379 * *
380 * OUTPUT: *
381 * *
382 * WARNINGS: *
383 * *
384 * HISTORY: *
385 * 11/9/2000 gth : Created. *
386 *=============================================================================================*/
388{
389 if (UserText) {
390 UserText->Release_Ref();
391 }
392 if (usertext) {
393 UserText = NEW_REF(ShareBufferClass<char>,(strlen(usertext)+1, "MeshGeometryClass::UserText"));
394 strcpy(UserText->Get_Array(),usertext);
395 }
396}
397
398
399/***********************************************************************************************
400 * MeshGeometryClass::Get_Bounding_Box -- get the bounding box *
401 * *
402 * INPUT: *
403 * *
404 * OUTPUT: *
405 * *
406 * WARNINGS: *
407 * *
408 * HISTORY: *
409 * 11/9/2000 gth : Created. *
410 *=============================================================================================*/
412{
413 WWASSERT(set_box != NULL);
414 set_box->Center = (BoundBoxMax + BoundBoxMin) * 0.5f;
415 set_box->Extent = (BoundBoxMax - BoundBoxMin) * 0.5f;
416}
417
418
419/***********************************************************************************************
420 * MeshGeometryClass::Get_Bounding_Sphere -- get the bounding sphere *
421 * *
422 * INPUT: *
423 * *
424 * OUTPUT: *
425 * *
426 * WARNINGS: *
427 * *
428 * HISTORY: *
429 * 11/9/2000 gth : Created. *
430 *=============================================================================================*/
432{
433 WWASSERT(set_sphere != NULL);
434 set_sphere->Center = BoundSphereCenter;
435 set_sphere->Radius = BoundSphereRadius;
436}
437
438
439/***********************************************************************************************
440 * MeshGeometryClass::Generate_Rigid_APT -- generate an apt using backface culling *
441 * *
442 * INPUT: *
443 * *
444 * OUTPUT: *
445 * *
446 * WARNINGS: *
447 * *
448 * HISTORY: *
449 * 5/10/2001 gth : Created. *
450 *=============================================================================================*/
452{
453 const Vector3 * loc = Get_Vertex_Array();
454 const Vector4 * norms = Get_Plane_Array();
455 const TriIndex * polys = Get_Polygon_Array();
456 TriClass tri;
457
458 for (int poly_counter = 0; poly_counter < PolyCount; poly_counter++) {
459
460 tri.V[0] = &(loc[ polys[poly_counter][0] ]);
461 tri.V[1] = &(loc[ polys[poly_counter][1] ]);
462 tri.V[2] = &(loc[ polys[poly_counter][2] ]);
463 tri.N = (Vector3*)&(norms[poly_counter]);
464
465 if (Vector3::Dot_Product(*tri.N,view_dir) < 0.0f) {
466 apt.Add(poly_counter);
467 }
468 }
469}
470
471
472/***********************************************************************************************
473 * MeshGeometryClass::Generate_Rigid_APT -- generate active polygon table *
474 * *
475 * This function will cull the mesh against the specified volume *
476 * *
477 * INPUT: *
478 * *
479 * OUTPUT: *
480 * *
481 * WARNINGS: *
482 * *
483 * HISTORY: *
484 * 11/9/2000 gth : Created. *
485 *=============================================================================================*/
487{
488 if (CullTree != NULL) {
489 CullTree->Generate_APT(local_box, apt);
490 } else {
491
492 // Beware, this is gonna be expensive!
493 const Vector3 * loc = Get_Vertex_Array();
494 const Vector4 * norms = Get_Plane_Array();
495 const TriIndex * polys = Get_Polygon_Array();
496 TriClass tri;
497
498 for (int poly_counter = 0; poly_counter < PolyCount; poly_counter++) {
499
500 tri.V[0] = &(loc[ polys[poly_counter][0] ]);
501 tri.V[1] = &(loc[ polys[poly_counter][1] ]);
502 tri.V[2] = &(loc[ polys[poly_counter][2] ]);
503 tri.N = (Vector3*)&(norms[poly_counter]);
504
505 if (CollisionMath::Intersection_Test(local_box, tri)) {;
506 apt.Add(poly_counter);
507 }
508 }
509 }
510}
511
512
513/***********************************************************************************************
514 * MeshGeometryClass::Generate_APT -- generate an apt for a box and view direction *
515 * *
516 * INPUT: *
517 * *
518 * OUTPUT: *
519 * *
520 * WARNINGS: *
521 * *
522 * HISTORY: *
523 * 5/10/2001 gth : Created. *
524 *=============================================================================================*/
526{
527 if (CullTree != NULL) {
528 CullTree->Generate_APT(local_box, viewdir,apt);
529 } else {
530
531 // Beware, this is gonna be expensive!
532 const Vector3 * loc = Get_Vertex_Array();
533 const Vector4 * norms = Get_Plane_Array();
534 const TriIndex * polys = Get_Polygon_Array();
535 TriClass tri;
536
537 for (int poly_counter = 0; poly_counter < PolyCount; poly_counter++) {
538
539 tri.V[0] = &(loc[ polys[poly_counter][0] ]);
540 tri.V[1] = &(loc[ polys[poly_counter][1] ]);
541 tri.V[2] = &(loc[ polys[poly_counter][2] ]);
542 tri.N = (Vector3*)&(norms[poly_counter]);
543
544 if (Vector3::Dot_Product(*tri.N,viewdir) < 0.0f) {
545 if (CollisionMath::Intersection_Test(local_box,tri)) {
546 apt.Add(poly_counter);
547 }
548 }
549 }
550 }
551}
552
553/***********************************************************************************************
554 * MeshGeometryClass::Generate_Skin_APT -- generate an active polygon table *
555 * *
556 * This function culls the mesh against the specified volume *
557 * *
558 * INPUT: *
559 * *
560 * OUTPUT: *
561 * *
562 * WARNINGS: *
563 * *
564 * HISTORY: *
565 * 11/9/2000 gth : Created. *
566 *=============================================================================================*/
567void MeshGeometryClass::Generate_Skin_APT(const OBBoxClass & world_box, SimpleDynVecClass<uint32> & apt, const Vector3 *world_vertex_locs)
568{
569 WWASSERT(world_vertex_locs);
570
571 // Beware, this is gonna be expensive!
572 const TriIndex * polys = Get_Polygon_Array();
573 TriClass tri;
574
575 for (int poly_counter=0; poly_counter < PolyCount; poly_counter++) {
576
577 tri.V[0] = &(world_vertex_locs[ polys[poly_counter][0] ]);
578 tri.V[1] = &(world_vertex_locs[ polys[poly_counter][1] ]);
579 tri.V[2] = &(world_vertex_locs[ polys[poly_counter][2] ]);
580
581 // We would have to do a non-trivial amount of computation to get the triangle normal
582 // (since this is a skin we have no valid plane equations) and we know that N is not used
583 // in the Intersection_Test, so we set it to a dummy value.
584 static const Vector3 dummy_vec(0.0f, 0.0f, 1.0f);
585 tri.N = &dummy_vec;
586
587 if (CollisionMath::Intersection_Test(world_box,tri)) {;
588 apt.Add(poly_counter);
589 }
590 }
591}
592
593
594/***********************************************************************************************
595 * MeshGeometryClass::Contains -- test if the mesh contains the given point *
596 * *
597 * INPUT: *
598 * *
599 * OUTPUT: *
600 * *
601 * WARNINGS: *
602 * *
603 * HISTORY: *
604 * 11/9/2000 gth : Created. *
605 *=============================================================================================*/
607{
608 // To determine whether the mesh contains a point, we will use the parity method (cast a
609 // semi-infinite ray from the point and check the number of intersections with the mesh.
610 // An even number of intersections means the point is outside the mesh, and an odd number
611 // means the point is inside the mesh. Since we can cast the ray in any direction we will
612 // use axis-aligned rays for speed.
613
614 // The method fails if the ray goes through any triangle edge or corner. For robustness
615 // we will cast rays in all six axis-aligned directions, and take a majority vote. We will
616 // significantly reduce the weighting of rays which go through corners/edges.
617 // Also, if any raycast reports that the point is embedded in a triangle, we will stop and
618 // report that the point is contained in the mesh (using the normal algorithm in this case
619 // could lead to errors).
620 float yes = 0.0f; // weighted sum of rays indicating the point is contained in the mesh
621 float no = 0.0f; // weighted sum of rays indicating the point is not contained in the mesh
622 for (int axis_dir = 0; axis_dir < 6; axis_dir++) {
623 unsigned char flags = TRI_RAYCAST_FLAG_NONE;
624 int intersections = cast_semi_infinite_axis_aligned_ray(point, axis_dir, flags);
625 if (flags & TRI_RAYCAST_FLAG_START_IN_TRI) return true;
626 float weight = flags & TRI_RAYCAST_FLAG_HIT_EDGE ? 0.1f : 1.0f;
627 if (intersections & 0x01) {
628 yes += weight;
629 } else {
630 no += weight;
631 }
632 }
633
634 return yes > no;
635}
636
637
638/***********************************************************************************************
639 * MeshGeometryClass::Cast_Ray -- compute a ray intersection with this mesh *
640 * *
641 * INPUT: *
642 * *
643 * OUTPUT: *
644 * *
645 * WARNINGS: *
646 * *
647 * HISTORY: *
648 * 3/1/2001 NH : Created. *
649 *=============================================================================================*/
651{
652 bool hit = false;
653
654 if (CullTree) {
655 hit = CullTree->Cast_Ray(raytest);
656 } else {
657 hit = cast_ray_brute_force(raytest);
658 }
659
660 return hit;
661}
662
663
664/***********************************************************************************************
665 * MeshGeometryClass::Cast_AABox -- cast an AABox against this mesh *
666 * *
667 * INPUT: *
668 * *
669 * OUTPUT: *
670 * *
671 * WARNINGS: *
672 * *
673 * HISTORY: *
674 * 3/1/2001 NH : Created. *
675 *=============================================================================================*/
677{
678 bool hit = false;
679
680 if (CullTree) {
681 hit = CullTree->Cast_AABox(boxtest);
682 } else {
683 hit = cast_aabox_brute_force(boxtest);
684 }
685
686 return hit;
687}
688
689
690/***********************************************************************************************
691 * MeshGeometryClass::Cast_OBBox -- Cast an obbox against this mesh *
692 * *
693 * INPUT: *
694 * *
695 * OUTPUT: *
696 * *
697 * WARNINGS: *
698 * *
699 * HISTORY: *
700 * 3/1/2001 NH : Created. *
701 *=============================================================================================*/
703{
704 bool hit = false;
705
706 if (CullTree) {
707 hit = CullTree->Cast_OBBox(boxtest);
708 } else {
709 hit = cast_obbox_brute_force(boxtest);
710 }
711
712 return hit;
713}
714
715
716/***********************************************************************************************
717 * MeshGeometryClass::Intersect_OBBox -- test for intersection with the given OBBox *
718 * *
719 * INPUT: *
720 * *
721 * OUTPUT: *
722 * *
723 * WARNINGS: *
724 * *
725 * HISTORY: *
726 * 3/1/2001 NH : Created. *
727 *=============================================================================================*/
729{
730 bool hit = false;
731
732 if (CullTree) {
733 hit = CullTree->Intersect_OBBox(boxtest);
734 } else {
735 hit = intersect_obbox_brute_force(boxtest);
736 }
737
738 return hit;
739}
740
741
742/***********************************************************************************************
743 * MeshGeometryClass::Cast_World_Space_AABox -- test for intersection with a worldspace AABox*
744 * *
745 * INPUT: *
746 * *
747 * OUTPUT: *
748 * *
749 * WARNINGS: *
750 * *
751 * HISTORY: *
752 * 3/1/2001 NH : Created. *
753 *=============================================================================================*/
755{
756 /*
757 ** Attempt to classify the transform:
758 ** NOTE: This code assumes that the matrix is orthogonal! Much code in W3D assumes
759 ** orthogonal matrices, if that convention is broken this code is also broken.
760 ** Basically what I'm doing here is doing the minimum number of compares needed
761 ** to identify a transform which is a 90 degree rotation about the z axis.
762 ** TODO: cache some transform flags somewhere to reduce the number of times
763 ** that these compares are done
764 */
765 bool hit = false;
766
767 if ((transform[0][0] == 1.0f) && (transform[1][1] == 1.0f)) {
768
769 hit = cast_aabox_identity(boxtest,-transform.Get_Translation());
770
771 } else if ((transform[0][1] == -1.0f) && (transform[1][0] == 1.0f)) {
772
773 // this mesh has been rotated 90 degrees about z
774 hit = cast_aabox_z90(boxtest,-transform.Get_Translation());
775
776 } else if ((transform[0][0] == -1.0f) && (transform[1][1] == -1.0f)) {
777
778 // this mesh has been rotated 180
779 hit = cast_aabox_z180(boxtest,-transform.Get_Translation());
780
781 } else if ((transform[0][1] == 1.0f) && (transform[1][0] == -1.0f)) {
782
783 // this mesh has been rotated 270
784 hit = cast_aabox_z270(boxtest,-transform.Get_Translation());
785
786 } else {
787
788 /*
789 ** Ok, we fell through to here, that means there is a more general
790 ** transform on this mesh. In this case, I create a new test which
791 ** is an oriented box test in the coordinate system of the mesh and cast it.
792 */
793 Matrix3D world_to_obj;
794 transform.Get_Orthogonal_Inverse(world_to_obj);
795 OBBoxCollisionTestClass obbox(boxtest, world_to_obj);
796
797 if (CullTree) {
798 hit = CullTree->Cast_OBBox(obbox);
799 } else {
800 hit = cast_obbox_brute_force(obbox);
801 }
802
803 /*
804 ** now, we must transform the results of the test back to the original
805 ** coordinate system.
806 */
807 if (hit) {
808 Matrix3D::Rotate_Vector(transform, obbox.Result->Normal, &(obbox.Result->Normal));
809 if (boxtest.Result->ComputeContactPoint) {
811 }
812 }
813 }
814
815 return hit;
816}
817
818
819/***********************************************************************************************
820 * MeshGeometryClass::cast_semi_infinite_axis_aligned_ray -- casts an axis aligned ray *
821 * *
822 * This function is used by the 'Contains' function *
823 * *
824 * INPUT: *
825 * *
826 * OUTPUT: *
827 * *
828 * WARNINGS: *
829 * *
830 * HISTORY: *
831 * 11/9/2000 gth : Created. *
832 *=============================================================================================*/
834 unsigned char & flags)
835{
836 int count = 0;
837 if (CullTree) {
838 count = CullTree->Cast_Semi_Infinite_Axis_Aligned_Ray(start_point, axis_dir, flags);
839 } else {
840
841 const Vector3 * loc = Get_Vertex_Array();
842 const Vector4 * plane = Get_Plane_Array();
843 const TriIndex * polyverts = Get_Polygon_Array();
844
845 // These tables translate between the axis_dir representation (which is an integer in which 0
846 // indicates a ray along the positive x axis, 1 along the negative x axis, 2 the positive y
847 // axis, 3 negative y axis, 4 positive z axis, 5 negative z axis) and a four-integer
848 // representation (axis_r is the axis number - 0, 1 or 2 - of the axis along which the ray is
849 // cast; axis_1 and axis_2 are the axis numbers of the other two axes; direction is 0 for
850 // negative and 1 for positive direction of the ray).
851 static const int axis_r[6] = { 0, 0, 1, 1, 2, 2 };
852 static const int axis_1[6] = { 1, 1, 2, 2, 0, 0 };
853 static const int axis_2[6] = { 2, 2, 0, 0, 1, 1 };
854 static const int direction[6] = { 1, 0, 1, 0, 1, 0 };
855 WWASSERT(axis_dir >= 0);
856 WWASSERT(axis_dir < 6);
857
858 // The functions called after this point will 'or' bits into this variable, so it needs to
859 // be initialized here to TRI_RAYCAST_FLAG_NONE.
860 flags = TRI_RAYCAST_FLAG_NONE;
861
862 /*
863 ** Loop over each polygon
864 */
865 int poly_count = Get_Polygon_Count();
866 for (int poly_counter=0; poly_counter < poly_count; poly_counter++) {
867
868 const Vector3 &v0 = loc[ polyverts[poly_counter][0] ];
869 const Vector3 &v1 = loc[ polyverts[poly_counter][1] ];
870 const Vector3 &v2 = loc[ polyverts[poly_counter][2] ];
871 const Vector4 &tri_plane = plane[poly_counter];
872
873 // Since (int)true is defined as 1, and (int)false as 0:
874 count += (unsigned int)Cast_Semi_Infinite_Axis_Aligned_Ray_To_Triangle(v0, v1, v2,
875 tri_plane, start_point, axis_r[axis_dir], axis_1[axis_dir], axis_2[axis_dir],
876 direction[axis_dir], flags);
877 }
878 }
879
880 return count;
881}
882
883
884/***********************************************************************************************
885 * MeshGeometryClass::cast_aabox_identity -- aligned aabox test *
886 * *
887 * INPUT: *
888 * *
889 * OUTPUT: *
890 * *
891 * WARNINGS: *
892 * *
893 * HISTORY: *
894 * 3/1/2001 NH : Created. *
895 *=============================================================================================*/
897{
898 // transform the test into the mesh's coordinate system
899 AABoxCollisionTestClass newbox(boxtest);
900 newbox.Translate(translation);
901
902 // cast the box against the mesh
903 if (CullTree) {
904 return CullTree->Cast_AABox(newbox);
905 } else {
906 return cast_aabox_brute_force(newbox);
907 }
908}
909
910
911/***********************************************************************************************
912 * MeshGeometryClass::cast_aabox_z90 -- aabox test which is rotated about z by 90 *
913 * *
914 * INPUT: *
915 * *
916 * OUTPUT: *
917 * *
918 * WARNINGS: *
919 * *
920 * HISTORY: *
921 * 3/1/2001 NH : Created. *
922 *=============================================================================================*/
924{
925 // transform the test into the mesh's coordinate system
926 AABoxCollisionTestClass newbox(boxtest);
927 newbox.Translate(translation);
929
930 // cast the box against the mesh, using culling if possible
931 bool hit;
932 if (CullTree) {
933 hit = CullTree->Cast_AABox(newbox);
934 } else {
935 hit = cast_aabox_brute_force(newbox);
936 }
937
938 // if we hit something, we need to rotate the normal back out of the mesh coordinate system
939 if (hit) {
940 // rotating the normal by 90 degrees about Z
941 float tmp = boxtest.Result->Normal.X;
942 boxtest.Result->Normal.X = -boxtest.Result->Normal.Y;
943 boxtest.Result->Normal.Y = tmp;
944 }
945
946 return hit;
947}
948
949
950/***********************************************************************************************
951 * MeshGeometryClass::cast_aabox_z180 -- aabox test which is rotated about z by 180 *
952 * *
953 * INPUT: *
954 * *
955 * OUTPUT: *
956 * *
957 * WARNINGS: *
958 * *
959 * HISTORY: *
960 * 3/1/2001 NH : Created. *
961 *=============================================================================================*/
963{
964 // transform the test into the meshes coordinate system
965 AABoxCollisionTestClass newbox(boxtest);
966 newbox.Translate(translation);
968
969 // cast the box against the mesh, using culling if possible
970 bool hit;
971 if (CullTree) {
972 hit = CullTree->Cast_AABox(newbox);
973 } else {
974 hit = cast_aabox_brute_force(newbox);
975 }
976
977 // if we hit something, we need to rotate the normal back out of the mesh coordinate system
978 if (hit) {
979 // rotating the normal by 180 degrees about Z
980 boxtest.Result->Normal.X = -boxtest.Result->Normal.X;
981 boxtest.Result->Normal.Y = -boxtest.Result->Normal.Y;
982 }
983
984 return hit;
985}
986
987
988/***********************************************************************************************
989 * MeshGeometryClass::cast_aabox_z270 -- aabox test which is rotated about z by 270 *
990 * *
991 * INPUT: *
992 * *
993 * OUTPUT: *
994 * *
995 * WARNINGS: *
996 * *
997 * HISTORY: *
998 * 3/1/2001 NH : Created. *
999 *=============================================================================================*/
1001{
1002 // transform the test into the mesh's coordinate system
1003 AABoxCollisionTestClass newbox(boxtest);
1004 newbox.Translate(translation);
1006
1007 // cast the box against the mesh, using culling if possible
1008 bool hit;
1009 if (CullTree) {
1010 hit = CullTree->Cast_AABox(newbox);
1011 } else {
1012 hit = cast_aabox_brute_force(newbox);
1013 }
1014
1015 // if we hit something, we need to rotate the normal back out of the mesh coordinate system
1016 if (hit) {
1017 // rotating the normal by 270 degrees about Z
1018 float tmp = boxtest.Result->Normal.X;
1019 boxtest.Result->Normal.X = boxtest.Result->Normal.Y;
1020 boxtest.Result->Normal.Y = -tmp;
1021 }
1022
1023 return hit;
1024}
1025
1026
1027/***********************************************************************************************
1028 * MeshGeometryClass::intersect_obbox_brute_force -- brute force intersection check *
1029 * *
1030 * This function gets used if the mesh does not have a CullTree *
1031 * *
1032 * INPUT: *
1033 * *
1034 * OUTPUT: *
1035 * *
1036 * WARNINGS: *
1037 * *
1038 * HISTORY: *
1039 * 3/1/2001 NH : Created. *
1040 *=============================================================================================*/
1042{
1043 TriClass tri;
1044 const Vector3 * loc = Get_Vertex_Array();
1045 const TriIndex * polyverts = Get_Polygon_Array();
1046#ifndef COMPUTE_NORMALS
1047 const Vector4 * norms = Get_Plane_Array();
1048#endif
1049
1050 /*
1051 ** Loop over each polygon
1052 */
1053 for (int srtri=0; srtri < Get_Polygon_Count(); srtri++) {
1054
1055 tri.V[0] = &(loc[ polyverts[srtri][0] ]);
1056 tri.V[1] = &(loc[ polyverts[srtri][1] ]);
1057 tri.V[2] = &(loc[ polyverts[srtri][2] ]);
1058
1059#ifdef COMPUTE_NORMALS
1060 static Vector3 _normal;
1061 tri.N = &_normal;
1062 tri.Compute_Normal();
1063#else
1064 tri.N = (Vector3 *)&(norms[srtri]);
1065#endif
1066
1067 if (CollisionMath::Intersection_Test(localtest.Box, tri)) {
1068 return true;
1069 }
1070 }
1071 return false;
1072}
1073
1074
1075/***********************************************************************************************
1076 * MeshGeometryClass::cast_ray_brute_force -- brute force ray-cast *
1077 * *
1078 * This function gets used if the mesh does not have a CullTree *
1079 * *
1080 * INPUT: *
1081 * *
1082 * OUTPUT: *
1083 * *
1084 * WARNINGS: *
1085 * *
1086 * HISTORY: *
1087 * 3/1/2001 NH : Created. *
1088 *=============================================================================================*/
1090{
1091 int srtri;
1092 TriClass tri;
1093 const Vector3 * loc = Get_Vertex_Array();
1094 const TriIndex * polyverts = Get_Polygon_Array();
1095#ifndef COMPUTE_NORMALS
1096 const Vector4 * norms = Get_Plane_Array();
1097#endif
1098
1099 /*
1100 ** Loop over each polygon
1101 */
1102 bool hit = false;
1103 for (srtri=0; srtri < Get_Polygon_Count(); srtri++) {
1104
1105 // TODO: find a better way to do this?
1106 tri.V[0] = &(loc[ polyverts[srtri][0] ]);
1107 tri.V[1] = &(loc[ polyverts[srtri][1] ]);
1108 tri.V[2] = &(loc[ polyverts[srtri][2] ]);
1109
1110#ifdef COMPUTE_NORMALS
1111 static Vector3 _normal;
1112 tri.N = &_normal;
1113 tri.Compute_Normal();
1114#else
1115 tri.N = (Vector3 *)&(norms[srtri]);
1116#endif
1117
1118 if (CollisionMath::Collide(raytest.Ray, tri, raytest.Result)) {
1119 hit = true;
1120 raytest.Result->SurfaceType = Get_Poly_Surface_Type (srtri);
1121 }
1122
1123 if (raytest.Result->StartBad) return true;
1124
1125 }
1126 return hit;
1127}
1128
1129
1130/***********************************************************************************************
1131 * MeshGeometryClass::cast_aabox_brute_force -- brute force aabox cast *
1132 * *
1133 * This function gets used only if the mesh doesn't have a CullTree *
1134 * *
1135 * INPUT: *
1136 * *
1137 * OUTPUT: *
1138 * *
1139 * WARNINGS: *
1140 * *
1141 * HISTORY: *
1142 * 3/1/2001 NH : Created. *
1143 *=============================================================================================*/
1145{
1146 /*
1147 ** Loop over each polygon
1148 */
1149 TriClass tri;
1150 int polyhit = -1;
1151
1152 const Vector3 * loc = Get_Vertex_Array();
1153 const TriIndex * polyverts = Get_Polygon_Array();
1154#ifndef COMPUTE_NORMALS
1155 const Vector4 * norms = Get_Plane_Array();
1156#endif
1157
1158 for (int srtri = 0; srtri < Get_Polygon_Count(); srtri++) {
1159
1160 tri.V[0] = &(loc[ polyverts[srtri][0] ]);
1161 tri.V[1] = &(loc[ polyverts[srtri][1] ]);
1162 tri.V[2] = &(loc[ polyverts[srtri][2] ]);
1163
1164#ifdef COMPUTE_NORMALS
1165 static Vector3 _normal;
1166 tri.N = &_normal;
1167 tri.Compute_Normal();
1168#else
1169 tri.N = (Vector3 *)&(norms[srtri]);
1170#endif
1171
1172 if (CollisionMath::Collide(boxtest.Box, boxtest.Move, tri, boxtest.Result)) {
1173 polyhit = srtri;
1174 }
1175
1176 if (boxtest.Result->StartBad) {
1177 return true;
1178 }
1179 }
1180 if (polyhit != -1) {
1181 boxtest.Result->SurfaceType = Get_Poly_Surface_Type(polyhit);
1182 return true;
1183 }
1184 return false;
1185}
1186
1187
1188/***********************************************************************************************
1189 * MeshGeometryClass::cast_obbox_brute_force -- brute force obbox cast *
1190 * *
1191 * This function gets used only if the mesh doesn't have a CullTree *
1192 * *
1193 * INPUT: *
1194 * *
1195 * OUTPUT: *
1196 * *
1197 * WARNINGS: *
1198 * *
1199 * HISTORY: *
1200 * 3/1/2001 NH : Created. *
1201 *=============================================================================================*/
1203{
1204 /*
1205 ** Loop over each polygon
1206 */
1207 TriClass tri;
1208 int polyhit = -1;
1209
1210 const Vector3 * loc = Get_Vertex_Array();
1211 const TriIndex * polyverts = Get_Polygon_Array();
1212#ifndef COMPUTE_NORMALS
1213 const Vector4 * norms = Get_Plane_Array();
1214#endif
1215
1216 for (int srtri = 0; srtri < Get_Polygon_Count(); srtri++) {
1217
1218 tri.V[0] = &(loc[ polyverts[srtri][0] ]);
1219 tri.V[1] = &(loc[ polyverts[srtri][1] ]);
1220 tri.V[2] = &(loc[ polyverts[srtri][2] ]);
1221
1222#ifdef COMPUTE_NORMALS
1223 static Vector3 _normal;
1224 tri.N = &_normal;
1225 tri.Compute_Normal();
1226#else
1227 tri.N = (Vector3 *)&(norms[srtri]);
1228#endif
1229
1230 if (CollisionMath::Collide(boxtest.Box, boxtest.Move, tri, Vector3(0,0,0), boxtest.Result)) {
1231 polyhit = srtri;
1232 }
1233
1234 if (boxtest.Result->StartBad) {
1235 return true;
1236 }
1237 }
1238 if (polyhit != -1) {
1239 boxtest.Result->SurfaceType = Get_Poly_Surface_Type(polyhit);
1240 return true;
1241 }
1242 return false;
1243}
1244
1245
1246/***********************************************************************************************
1247 * MeshGeometryClass::Compute_Plane_Equations -- Recalculates the plane equations *
1248 * *
1249 * INPUT: *
1250 * *
1251 * OUTPUT: *
1252 * *
1253 * WARNINGS: *
1254 * This function should not normally be needed during run-time. *
1255 * The array pointer must point to enough memory to hold a plane equation per polygon *
1256 * *
1257 * HISTORY: *
1258 * 11/9/2000 gth : Created. *
1259 *=============================================================================================*/
1261{
1262 WWASSERT(peq!=NULL);
1263
1264 TriIndex * poly = Poly->Get_Array();
1265 Vector3 * vert = Vertex->Get_Array();
1266
1267 for(int pidx = 0; pidx < PolyCount; pidx++)
1268 {
1269 Vector3 a,b,normal;
1270 const Vector3 & p0= vert[poly[pidx][0]];
1271
1272 Vector3::Subtract(vert[poly[pidx][1]],p0,&a);
1273 Vector3::Subtract(vert[poly[pidx][2]],p0,&b);
1274 Vector3::Cross_Product(a,b,&normal);
1275 normal.Normalize();
1276
1277 peq[pidx].Set( normal.X, normal.Y, normal.Z, -(Vector3::Dot_Product(p0,normal)) );
1278 }
1279 Set_Flag(DIRTY_PLANES,false);
1280}
1281
1282
1283/***********************************************************************************************
1284 * MeshGeometryClass::Compute_Vertex_Normals -- recompute the vertex normals *
1285 * *
1286 * INPUT: *
1287 * *
1288 * OUTPUT: *
1289 * *
1290 * WARNINGS: *
1291 * This function should not normally be needed during run-time. *
1292 * The array pointer must point to an array of Vector3's of size NumVerts *
1293 * *
1294 * HISTORY: *
1295 * 11/9/2000 gth : Created. *
1296 *=============================================================================================*/
1298{
1299 WWASSERT(vnorm != NULL);
1300 if ((PolyCount == 0)|| (VertexCount == 0)) {
1301 return;
1302 }
1303
1304 const Vector4 * peq = Get_Plane_Array();
1305 TriIndex * poly = Poly->Get_Array();
1306 const uint32 * shadeIx = Get_Vertex_Shade_Index_Array(false);
1307
1308 // Two cases, with or without vertex shade indices. The vertex shade indices
1309 // implicitly contain the smoothing groups information from the original mesh.
1310 // In their abscesnce, the entire mesh is smoothed.
1311 if (!shadeIx) {
1312
1314
1315 for(int pidx = 0; pidx < PolyCount; pidx++) {
1316
1317 vnorm[poly[pidx].I].X += peq[pidx].X;
1318 vnorm[poly[pidx].I].Y += peq[pidx].Y;
1319 vnorm[poly[pidx].I].Z += peq[pidx].Z;
1320
1321 vnorm[poly[pidx].J].X += peq[pidx].X;
1322 vnorm[poly[pidx].J].Y += peq[pidx].Y;
1323 vnorm[poly[pidx].J].Z += peq[pidx].Z;
1324
1325 vnorm[poly[pidx].K].X += peq[pidx].X;
1326 vnorm[poly[pidx].K].Y += peq[pidx].Y;
1327 vnorm[poly[pidx].K].Z += peq[pidx].Z;
1328 }
1329
1330 } else {
1331
1333
1334 for (int pidx = 0; pidx < PolyCount; pidx++) {
1335
1336 vnorm[shadeIx[poly[pidx].I]].X += peq[pidx].X;
1337 vnorm[shadeIx[poly[pidx].I]].Y += peq[pidx].Y;
1338 vnorm[shadeIx[poly[pidx].I]].Z += peq[pidx].Z;
1339
1340 vnorm[shadeIx[poly[pidx].J]].X += peq[pidx].X;
1341 vnorm[shadeIx[poly[pidx].J]].Y += peq[pidx].Y;
1342 vnorm[shadeIx[poly[pidx].J]].Z += peq[pidx].Z;
1343
1344 vnorm[shadeIx[poly[pidx].K]].X += peq[pidx].X;
1345 vnorm[shadeIx[poly[pidx].K]].Y += peq[pidx].Y;
1346 vnorm[shadeIx[poly[pidx].K]].Z += peq[pidx].Z;
1347 }
1348
1349 // normalize the "master" vertex normals and copy the smoothed ones
1350 // (note: we always encounter the "master" ones first)
1351 for (unsigned vidx = 0; vidx < (unsigned)VertexCount; vidx ++) {
1352 if (shadeIx[vidx] == vidx) {
1353 vnorm[vidx].Normalize();
1354 } else {
1355 vnorm[vidx] = vnorm[shadeIx[vidx]];
1356 }
1357 }
1358 }
1359
1361
1362 Set_Flag(DIRTY_VNORMALS,false);
1363}
1364
1365
1366/***********************************************************************************************
1367 * MeshGeometryClass::Compute_Bounds -- recomputes the bounding volumes *
1368 * *
1369 * INPUT: *
1370 * *
1371 * OUTPUT: *
1372 * *
1373 * WARNINGS: *
1374 * This function should not normally be needed during run-time. *
1375 * *
1376 * HISTORY: *
1377 * 11/9/2000 gth : Created. *
1378 *=============================================================================================*/
1380{
1381 BoundBoxMin.Set(0,0,0);
1382 BoundBoxMax.Set(0,0,0);
1383 BoundSphereCenter.Set(0,0,0);
1384 BoundSphereRadius = 0.0;
1385
1386 if (VertexCount == 0) {
1387 return;
1388 }
1389
1390 // find bounding box minimum and maximum
1391 if (verts == NULL) {
1392 verts = Vertex->Get_Array();
1393 }
1395
1396 // calculate the bounding sphere
1398 BoundSphereRadius = (float)(BoundBoxMax-BoundSphereCenter).Length2();
1399 BoundSphereRadius = ((float)sqrt(BoundSphereRadius))*1.00001f;
1400 Set_Flag(DIRTY_BOUNDS,false);
1401}
1402
1403
1404
1405/***********************************************************************************************
1406 * MeshGeometryClass::get_vert_normals -- get the vertex normal array *
1407 * *
1408 * INPUT: *
1409 * *
1410 * OUTPUT: *
1411 * *
1412 * WARNINGS: *
1413 * *
1414 * HISTORY: *
1415 * 6/14/2001 gth : Created. *
1416 *=============================================================================================*/
1418{
1419#if (OPTIMIZE_VNORM_RAM)
1420 _VNormArray.Uninitialised_Grow(VertexCount);
1421 return &(_VNormArray[0]);
1422#else
1424 return VertexNorm->Get_Array();
1425#endif
1426}
1427
1428
1429/***********************************************************************************************
1430 * MeshGeometryClass::Get_Vertex_Normal_Array -- validates and returns the vertex normal array *
1431 * *
1432 * INPUT: *
1433 * *
1434 * OUTPUT: *
1435 * *
1436 * WARNINGS: *
1437 * *
1438 * HISTORY: *
1439 * 6/14/2001 gth : Created. *
1440 *=============================================================================================*/
1442{
1443#if (OPTIMIZE_VNORM_RAM)
1445 return get_vert_normals();
1446#else
1447 if (Get_Flag(DIRTY_VNORMALS)) {
1449 }
1450 return get_vert_normals();
1451#endif
1452}
1453
1454
1455
1456/***********************************************************************************************
1457 * MeshGeometryClass::get_planes -- get the plane array memory (internal) *
1458 * *
1459 * INPUT: *
1460 * *
1461 * OUTPUT: *
1462 * *
1463 * WARNINGS: *
1464 * *
1465 * HISTORY: *
1466 * 6/14/2001 gth : Created. *
1467 *=============================================================================================*/
1469{
1470#if (OPTIMIZE_PLANEEQ_RAM)
1471 _PlaneEQArray.Uninitialised_Grow(PolyCount);
1472 return &(_PlaneEQArray[0]);
1473#else
1474 if (create && !PlaneEq) {
1475 PlaneEq = NEW_REF(ShareBufferClass<Vector4>,(PolyCount, "MeshGeometryClass::PlaneEq"));
1476 }
1477 if (PlaneEq) {
1478 return PlaneEq->Get_Array();
1479 }
1480 return NULL;
1481#endif
1482}
1483
1484
1485/***********************************************************************************************
1486 * MeshGeometryClass::Get_Plane_Array -- validates and returns the array of plane equations *
1487 * *
1488 * INPUT: *
1489 * *
1490 * OUTPUT: *
1491 * *
1492 * WARNINGS: *
1493 * *
1494 * HISTORY: *
1495 * 6/14/2001 gth : Created. *
1496 *=============================================================================================*/
1498{
1499#if (OPTIMIZE_PLANEEQ_RAM)
1500 Vector4 * planes = get_planes(create);
1502 return planes;
1503#else
1504 Vector4 * planes = get_planes(create);
1505 if (planes && Get_Flag(DIRTY_PLANES)) {
1507 }
1508 return planes;
1509#endif
1510}
1511
1512/***********************************************************************************************
1513 * MeshGeometryClass::Compute_Plane -- compute the plane equation of a single poly *
1514 * *
1515 * INPUT: *
1516 * *
1517 * OUTPUT: *
1518 * *
1519 * WARNINGS: *
1520 * *
1521 * HISTORY: *
1522 * 6/14/2001 gth : Created. *
1523 *=============================================================================================*/
1524void MeshGeometryClass::Compute_Plane(int pidx,PlaneClass * set_plane) const
1525{
1526 WWASSERT(pidx >= 0);
1527 WWASSERT(pidx < PolyCount);
1528 TriIndex & poly = Poly->Get_Array()[pidx];
1529 Vector3 * verts = Vertex->Get_Array();
1530
1531 set_plane->Set(verts[poly.I],verts[poly.J],verts[poly.K]);
1532}
1533
1534
1535/***********************************************************************************************
1536 * MeshGeometryClass::Generate_Culling_Tree -- Generate an AABTree for this mesh *
1537 * *
1538 * INPUT: *
1539 * *
1540 * OUTPUT: *
1541 * *
1542 * WARNINGS: *
1543 * This function should not normally be needed during run-time. *
1544 * *
1545 * HISTORY: *
1546 * 11/9/2000 gth : Created. *
1547 *=============================================================================================*/
1549{
1551 {
1552 AABTreeBuilderClass builder;
1553 builder.Build_AABTree(PolyCount,Poly->Get_Array(),VertexCount,Vertex->Get_Array());
1554
1555 CullTree = NEW_REF(AABTreeClass,(&builder));
1556 CullTree->Set_Mesh(this);
1557 }
1558}
1559
1560
1561/***********************************************************************************************
1562 * MeshGeometryClass::Load_W3D -- Load a mesh from a w3d file *
1563 * *
1564 * This function will extract just the geometry information from a W3D mesh. It must *
1565 * be completely replaced by any derived classes that want to handle all of the chunks. *
1566 * *
1567 * INPUT: *
1568 * *
1569 * OUTPUT: *
1570 * *
1571 * WARNINGS: *
1572 * *
1573 * HISTORY: *
1574 * 11/9/2000 gth : Created. *
1575 *=============================================================================================*/
1577{
1578 /*
1579 ** This function will initialize this MeshGeometryClass from the contents of a W3D file.
1580 ** Note that derived classes need to completely replace this function; only re-using the individual
1581 ** chunk handling functions.
1582 */
1583
1584 /*
1585 ** Open the first chunk, it should be the mesh header
1586 */
1587 cload.Open_Chunk();
1588
1589 if (cload.Cur_Chunk_ID() != W3D_CHUNK_MESH_HEADER3) {
1590 WWDEBUG_SAY(("Old format mesh mesh, no longer supported.\n"));
1591 goto Error;
1592 }
1593
1594 W3dMeshHeader3Struct header;
1595 if (cload.Read(&header,sizeof(W3dMeshHeader3Struct)) != sizeof(W3dMeshHeader3Struct)) {
1596 goto Error;
1597 }
1598 cload.Close_Chunk();
1599
1600 /*
1601 ** Process the header
1602 */
1603 char * tmpname;
1604 int namelen;
1605
1606 Reset_Geometry(header.NumTris,header.NumVertices);
1607
1608 namelen = strlen(header.ContainerName);
1609 namelen += strlen(header.MeshName);
1610 namelen += 2;
1611 W3dAttributes = header.Attributes;
1612 SortLevel = header.SortLevel;
1613 tmpname = W3DNEWARRAY char[namelen];
1614 memset(tmpname,0,namelen);
1615
1616 if (strlen(header.ContainerName) > 0) {
1617 strcpy(tmpname,header.ContainerName);
1618 strcat(tmpname,".");
1619 }
1620 strcat(tmpname,header.MeshName);
1621
1622 Set_Name(tmpname);
1623
1624 delete[] tmpname;
1625 tmpname = NULL;
1626
1627 /*
1628 ** Set Bounding Info
1629 */
1630 BoundBoxMin.Set(header.Min.X,header.Min.Y,header.Min.Z);
1631 BoundBoxMax.Set(header.Max.X,header.Max.Y,header.Max.Z);
1632
1633 BoundSphereCenter.Set(header.SphCenter.X,header.SphCenter.Y,header.SphCenter.Z);
1635
1636 /*
1637 ** Flags
1638 */
1639 if (header.Version >= W3D_MAKE_VERSION(4,1)) {
1640 int geometry_type = header.Attributes & W3D_MESH_FLAG_GEOMETRY_TYPE_MASK;
1641 switch (geometry_type)
1642 {
1644 break;
1646 Set_Flag(ALIGNED,true);
1647 break;
1649 Set_Flag(ORIENTED,true);
1650 break;
1652 Set_Flag(SKIN,true);
1653 break;
1654 }
1655 }
1656
1657 if (header.Attributes & W3D_MESH_FLAG_TWO_SIDED) {
1658 Set_Flag(TWO_SIDED,true);
1659 }
1660
1662 Set_Flag(CAST_SHADOW,true);
1663 }
1664
1665 read_chunks(cload);
1666
1667 /*
1668 ** If this is a pre-3.0 mesh and it has vertex influences,
1669 ** fixup the bone indices to account for the new root node
1670 */
1671 if ((header.Version < W3D_MAKE_VERSION(3,0)) && (Get_Flag(SKIN))) {
1672
1673 uint16 * links = get_bone_links();
1674 WWASSERT(links);
1675
1676 for (int bi = 0; bi < Get_Vertex_Count(); bi++) {
1677 links[bi] += 1;
1678 }
1679 }
1680
1681 /*
1682 ** If this mesh is collideable and no AABTree was in the file, generate one now
1683 */
1685 (CullTree == NULL))
1686 {
1688 }
1689
1690 return WW3D_ERROR_OK;
1691
1692Error:
1693
1695}
1696
1697
1698/***********************************************************************************************
1699 * MeshGeometryClass::read_chunks -- read w3d chunks *
1700 * *
1701 * Again, derived classes must replace this function with one that handles all of their *
1702 * chunks in addition to calling to this class for the individual chunks that it handles. *
1703 * *
1704 * INPUT: *
1705 * *
1706 * OUTPUT: *
1707 * *
1708 * WARNINGS: *
1709 * *
1710 * HISTORY: *
1711 * 11/9/2000 gth : Created. *
1712 *=============================================================================================*/
1714{
1715 /*
1716 ** Read in the chunk header
1717 ** If there are no more chunks within the mesh chunk,
1718 ** we are done.
1719 */
1720 while (cload.Open_Chunk()) {
1721
1722 /*
1723 ** Process the chunk
1724 */
1726
1727 switch (cload.Cur_Chunk_ID()) {
1728
1729 case W3D_CHUNK_VERTICES:
1730 error = read_vertices(cload);
1731 break;
1732
1735 error = read_vertex_normals(cload);
1736 break;
1737
1739 error = read_triangles(cload);
1740 break;
1741
1743 error = read_user_text(cload);
1744 break;
1745
1747 error = read_vertex_influences(cload);
1748 break;
1749
1751 error = read_vertex_shade_indices(cload);
1752 break;
1753
1754 case W3D_CHUNK_AABTREE:
1755 read_aabtree(cload);
1756 break;
1757
1758 default:
1759 break;
1760
1761 }
1762
1763 cload.Close_Chunk();
1764
1765 if (error != WW3D_ERROR_OK) {
1766 return error;
1767 }
1768 }
1769
1770 return WW3D_ERROR_OK;
1771}
1772
1773
1774/***********************************************************************************************
1775 * MeshGeometryClass::read_vertices -- read the vertex chunk from a W3D file *
1776 * *
1777 * INPUT: *
1778 * *
1779 * OUTPUT: *
1780 * *
1781 * WARNINGS: *
1782 * *
1783 * HISTORY: *
1784 * 11/9/2000 gth : Created. *
1785 *=============================================================================================*/
1787{
1788 W3dVectorStruct vert;
1789 Vector3 * loc = Vertex->Get_Array();
1790 assert(loc);
1791
1792 for (int i=0; i<Get_Vertex_Count(); i++) {
1793
1794 if (cload.Read(&vert,sizeof(W3dVectorStruct)) != sizeof(W3dVectorStruct)) {
1796 }
1797
1798 loc[i].X = vert.X;
1799 loc[i].Y = vert.Y;
1800 loc[i].Z = vert.Z;
1801 }
1802
1803 return WW3D_ERROR_OK;
1804}
1805
1806
1807/***********************************************************************************************
1808 * MeshGeometryClass::read_vertex_normals -- read the vertex normals chunk from a w3d file *
1809 * *
1810 * INPUT: *
1811 * *
1812 * OUTPUT: *
1813 * *
1814 * WARNINGS: *
1815 * *
1816 * HISTORY: *
1817 * 11/9/2000 gth : Created. *
1818 *=============================================================================================*/
1820{
1821 W3dVectorStruct norm;
1822 Vector3 * mdlnorms = get_vert_normals();
1823 WWASSERT(mdlnorms);
1824
1825 for (int i=0; i<VertexCount; i++) {
1826 if (cload.Read(&norm,sizeof(W3dVectorStruct)) != sizeof(W3dVectorStruct)) {
1828 }
1829
1830 mdlnorms[i].Set(norm.X,norm.Y,norm.Z);
1831 }
1832
1833 return WW3D_ERROR_OK;
1834}
1835
1836
1837/***********************************************************************************************
1838 * MeshGeometryClass::read_triangles -- read the triangles chunk from a w3d file *
1839 * *
1840 * INPUT: *
1841 * *
1842 * OUTPUT: *
1843 * *
1844 * WARNINGS: *
1845 * *
1846 * HISTORY: *
1847 * 11/9/2000 gth : Created. *
1848 *=============================================================================================*/
1850{
1851 W3dTriStruct tri;
1852
1853 // cache pointers to various arrays in the surrender mesh
1854 TriIndex * vi = get_polys();
1855 Set_Flag(DIRTY_PLANES,false);
1856 Vector4 * peq = get_planes();
1857 uint8 * surface_types = Get_Poly_Surface_Type_Array();
1858
1859 // read in each polygon one by one
1860 for (int i=0; i<Get_Polygon_Count(); i++) {
1861
1862 if (cload.Read(&tri,sizeof(W3dTriStruct)) != sizeof(W3dTriStruct)) {
1864 }
1865
1866 // set the vertex indices
1867 vi[i].I = tri.Vindex[0];
1868 vi[i].J = tri.Vindex[1];
1869 vi[i].K = tri.Vindex[2];
1870
1871 // set the normal
1872 peq[i].X = tri.Normal.X;
1873 peq[i].Y = tri.Normal.Y;
1874 peq[i].Z = tri.Normal.Z;
1875 peq[i].W = -tri.Dist;
1876
1877 // set the surface type
1878 WWASSERT(tri.Attributes < 256);
1879 surface_types[i] = (uint8)(tri.Attributes);
1880 }
1881
1882 return WW3D_ERROR_OK;
1883}
1884
1885
1886/***********************************************************************************************
1887 * MeshGeometryClass::read_user_text -- read the user text chunk from a w3d file *
1888 * *
1889 * INPUT: *
1890 * *
1891 * OUTPUT: *
1892 * *
1893 * WARNINGS: *
1894 * *
1895 * HISTORY: *
1896 * 11/9/2000 gth : Created. *
1897 *=============================================================================================*/
1899{
1900 unsigned int textlen = cload.Cur_Chunk_Length();
1901
1902 /*
1903 ** This shouldn't happen but if there are more than one
1904 ** USER_TEXT chunks in the mesh file, store only the first
1905 ** one. I am assuming that if the UserText buffer is not
1906 ** NULL, then a previous user text chunk has been read in...
1907 */
1908 if (UserText != NULL) {
1909 return WW3D_ERROR_OK;
1910 }
1911
1912 /*
1913 ** Allocate the buffer and read in the text
1914 */
1915 UserText = NEW_REF(ShareBufferClass<char>,(textlen, "MeshGeometryClass::UserText"));
1916
1917 if (cload.Read(UserText->Get_Array(),textlen) != textlen) {
1919 }
1920
1921 return WW3D_ERROR_OK;
1922}
1923
1924
1925/***********************************************************************************************
1926 * MeshGeometryClass::read_vertex_influences -- read the vertex influences chunk from a w3d fi *
1927 * *
1928 * INPUT: *
1929 * *
1930 * OUTPUT: *
1931 * *
1932 * WARNINGS: *
1933 * *
1934 * HISTORY: *
1935 * 11/9/2000 gth : Created. *
1936 *=============================================================================================*/
1938{
1939 W3dVertInfStruct vinf;
1940 uint16 * links = get_bone_links(true);
1941 WWASSERT(links);
1942
1943 for (int i=0; i<Get_Vertex_Count(); i++) {
1944
1945 if (cload.Read(&vinf,sizeof(W3dVertInfStruct)) != sizeof(W3dVertInfStruct)) {
1947 }
1948 links[i] = vinf.BoneIdx;
1949 }
1950 Set_Flag(SKIN,true);
1951
1952 return WW3D_ERROR_OK;
1953}
1954
1955
1956/***********************************************************************************************
1957 * MeshGeometryClass::read_vertex_shade_indices -- read the vertex shade indices chunk *
1958 * *
1959 * INPUT: *
1960 * *
1961 * OUTPUT: *
1962 * *
1963 * WARNINGS: *
1964 * *
1965 * HISTORY: *
1966 * 11/9/2000 gth : Created. *
1967 *=============================================================================================*/
1969{
1970 uint32 * shade_index = get_shade_indices(true);
1971 uint32 si;
1972
1973 for (int i=0; i<Get_Vertex_Count(); i++) {
1974 if (cload.Read(&si,sizeof(uint32)) != sizeof(uint32)) {
1976 }
1977 shade_index[i] = si;
1978 }
1979 return WW3D_ERROR_OK;
1980}
1981
1982
1983/***********************************************************************************************
1984 * MeshGeometryClass::read_aabtree -- read the AABTree chunk from a w3d file *
1985 * *
1986 * INPUT: *
1987 * *
1988 * OUTPUT: *
1989 * *
1990 * WARNINGS: *
1991 * *
1992 * HISTORY: *
1993 * 11/9/2000 gth : Created. *
1994 *=============================================================================================*/
1996{
1999 CullTree->Load_W3D(cload);
2000 CullTree->Set_Mesh(this);
2001 return (WW3D_ERROR_OK);
2002}
2003
2005{
2007 Vector3 * vert = Vertex->Get_Array();
2008
2009 for (int i=0;i<VertexCount; i++) {
2010 vert[i].X *= sc.X;
2011 vert[i].Y *= sc.Y;
2012 vert[i].Z *= sc.Z;
2013 }
2014
2015 BoundBoxMin.Scale(sc);
2016 BoundBoxMax.Scale(sc);
2017 BoundSphereCenter.Scale(sc);
2018
2019 float max;
2020 max = (sc.X > sc.Y) ? sc.X : sc.Y;
2021 max = (max > sc.Z) ? max : sc.Z;
2023
2024 // If scaling uniformly normals are OK:
2025 if (sc.X != sc.Y || sc.Y != sc.Z) {
2027 }
2028 // pnormals are plane equations...
2029 Set_Flag(DIRTY_PLANES,true);
2030
2031 // the cull tree is invalid, release it and make a new one
2032 if (CullTree) {
2033 // If the scale is uniform, we can scale the cull tree, which is a lot faster than creating a new one
2034 if (fabs(sc[0]-sc[1])<WWMATH_EPSILON && fabs(sc[0]-sc[2])<WWMATH_EPSILON) {
2035 // create a copy of the old culltree
2036 AABTreeClass *temp = NEW_REF(AABTreeClass, ());
2037 *temp = *CullTree;
2038 temp->Set_Mesh(this);
2039 REF_PTR_SET(CullTree, temp);
2040 REF_PTR_RELEASE(temp);
2041 CullTree->Scale(sc[0]);
2042 }
2043 else {
2046 }
2047 }
2048}
2049
2050
2051// Destination pointers MUST point to arrays large enough to hold all vertices
2053{
2054 Vector3 * src_vert = Vertex->Get_Array();
2055 uint16 * bonelink = VertexBoneLink->Get_Array();
2056 for (int vi = 0; vi < Get_Vertex_Count(); vi++) {
2057 const Matrix3D & tm = htree->Get_Transform(bonelink[vi]);
2058 Matrix3D::Transform_Vector(tm, src_vert[vi], &(dst_vert[vi]));
2059 }
2060}
2061
2062
2063// Destination pointers MUST point to arrays large enough to hold all vertices
2065{
2066 int vi;
2067 int vertex_count=Get_Vertex_Count();
2068 Vector3 * src_vert = Vertex->Get_Array();
2069#if (OPTIMIZE_VNORMS)
2070 Vector3 * src_norm = (Vector3 *)Get_Vertex_Normal_Array();
2071#else
2072 Vector3 * src_norm = VertexNorm->Get_Array();
2073#endif
2074 uint16 * bonelink = VertexBoneLink->Get_Array();
2075
2076 for (vi = 0; vi < vertex_count;) {
2077 const Matrix3D & tm = htree->Get_Transform(bonelink[vi]);
2078
2079 // Make a copy so we can set the translation to zero
2080 Matrix3D mytm=tm;
2081
2082 int idx=bonelink[vi];
2083 int cnt;
2084 for (cnt = vi; cnt < vertex_count; cnt++) {
2085 if (idx!=bonelink[cnt]) {
2086 break;
2087 }
2088 }
2089
2090 VectorProcessorClass::Transform(dst_vert+vi,src_vert+vi,mytm,cnt-vi);
2091 mytm.Set_Translation(Vector3(0.0f,0.0f,0.0f));
2092 VectorProcessorClass::Transform(dst_norm+vi,src_norm+vi,mytm,cnt-vi);
2093 vi=cnt;
2094 }
2095}
2096
2097// Destination pointers MUST point to arrays large enough to hold all vertices
2098void MeshGeometryClass::get_deformed_screenspace_vertices(Vector4 *dst_vert,const RenderInfoClass & rinfo,const Matrix3D & mesh_transform,const HTreeClass * htree)
2099{
2100 Matrix4x4 prj = rinfo.Camera.Get_Projection_Matrix() * rinfo.Camera.Get_View_Matrix() * mesh_transform;
2101
2102 Vector3 * src_vert = Vertex->Get_Array();
2103 int vertex_count=Get_Vertex_Count();
2104
2105 if (Get_Flag(SKIN) && VertexBoneLink && htree) {
2106 uint16 * bonelink = VertexBoneLink->Get_Array();
2107 for (int vi = 0; vi < vertex_count;) {
2108 int idx=bonelink[vi];
2109
2110 Matrix4x4 tm = prj * htree->Get_Transform(idx);
2111
2112 // Count equal matrices (the vertices should be pre-sorted by matrices they use)
2113 for (int cnt = vi; cnt < vertex_count; cnt++) if (idx!=bonelink[cnt]) break;
2114
2115 // Transform to screenspace (x,y,z,w)
2117 dst_vert+vi,
2118 src_vert+vi,
2119 tm,
2120 cnt-vi);
2121
2122 vi=cnt;
2123 }
2124 } else {
2126 dst_vert,
2127 src_vert,
2128 prj,
2129 vertex_count);
2130 }
2131}
#define NULL
Definition BaseType.h:92
#define max(x, y)
Definition BaseType.h:105
#define WWASSERT
#define W3D_MESH_FLAG_GEOMETRY_TYPE_MASK
Definition w3d_file.h:1157
#define W3D_MESH_FLAG_TWO_SIDED
Definition w3d_file.h:1152
#define SORT_LEVEL_NONE
Definition w3d_file.h:1195
#define W3D_MESH_FLAG_COLLISION_TYPE_SHIFT
Definition w3d_file.h:1144
#define W3D_MESH_FLAG_CAST_SHADOW
Definition w3d_file.h:1155
@ W3D_CHUNK_TRIANGLES
Definition w3d_file.h:347
@ W3D_CHUNK_VERTEX_SHADE_INDICES
Definition w3d_file.h:348
@ W3D_CHUNK_MESH_USER_TEXT
Definition w3d_file.h:344
@ W3D_CHUNK_VERTEX_NORMALS
Definition w3d_file.h:343
@ W3D_CHUNK_MESH_HEADER3
Definition w3d_file.h:346
@ W3D_CHUNK_VERTEX_INFLUENCES
Definition w3d_file.h:345
@ W3D_CHUNK_AABTREE
Definition w3d_file.h:391
@ W3D_CHUNK_VERTICES
Definition w3d_file.h:342
#define W3D_MESH_FLAG_GEOMETRY_TYPE_NORMAL
Definition w3d_file.h:1158
#define W3D_MESH_FLAG_COLLISION_TYPE_MASK
Definition w3d_file.h:1143
#define W3D_MAKE_VERSION(major, minor)
Definition w3d_file.h:315
#define W3D_MESH_FLAG_GEOMETRY_TYPE_SKIN
Definition w3d_file.h:1160
#define W3D_MESH_FLAG_GEOMETRY_TYPE_CAMERA_ALIGNED
Definition w3d_file.h:1159
#define W3D_MESH_FLAG_GEOMETRY_TYPE_CAMERA_ORIENTED
Definition w3d_file.h:1164
@ W3D_CHUNK_SURRENDER_NORMALS
#define W3DNEWARRAY
Definition always.h:110
unsigned short uint16
Definition bittype.h:45
unsigned long uint32
Definition bittype.h:46
unsigned char uint8
Definition bittype.h:44
#define WWMATH_EPSILON
Definition wwmath.h:54
void Build_AABTree(int polycount, TriIndex *polys, int vertcount, Vector3 *verts)
void Set_Mesh(MeshGeometryClass *mesh)
Definition aabtree.cpp:318
Vector3 Center
Definition aabox.h:123
Vector3 Extent
Definition aabox.h:124
void Translate(const Vector3 &translation)
Definition coltest.h:231
void Rotate(ROTATION_TYPE rotation)
Definition coltest.cpp:99
void Get_View_Matrix(Matrix3D *set_tm)
Definition camera.cpp:801
void Get_Projection_Matrix(Matrix4x4 *set_tm)
Definition camera.cpp:772
bool Close_Chunk()
Definition chunkio.cpp:448
uint32 Cur_Chunk_ID()
Definition chunkio.cpp:484
uint32 Cur_Chunk_Length()
Definition chunkio.cpp:503
uint32 Read(void *buf, uint32 nbytes)
Definition chunkio.cpp:692
bool Open_Chunk()
Definition chunkio.cpp:412
static bool Collide(const LineSegClass &line, const AAPlaneClass &plane, CastResultStruct *result)
static bool Intersection_Test(const AABoxClass &box, const TriClass &tri)
CastResultStruct * Result
Definition coltest.h:98
WWINLINE const Matrix3D & Get_Transform(int pivot) const
Definition htree.h:202
WWINLINE void Set_Translation(const Vector3 &t)
Definition matrix3d.h:219
Vector3 Rotate_Vector(const Vector3 &vect) const
Definition matrix3d.cpp:300
void Get_Orthogonal_Inverse(Matrix3D &set_inverse) const
Definition matrix3d.cpp:570
static WWINLINE void Transform_Vector(const Matrix3D &tm, const Vector3 &in, Vector3 *out)
Definition matrix3d.h:1742
WWINLINE Vector3 Get_Translation(void) const
Definition matrix3d.h:217
WW3DErrorType read_vertex_shade_indices(ChunkLoadClass &cload)
uint32 * get_shade_indices(bool create=true)
void Get_Bounding_Sphere(SphereClass *set_sphere)
ShareBufferClass< uint8 > * PolySurfaceType
void Reset_Geometry(int polycount, int vertcount)
ShareBufferClass< uint16 > * VertexBoneLink
WW3DErrorType read_vertex_influences(ChunkLoadClass &cload)
virtual void Compute_Plane_Equations(Vector4 *array)
ShareBufferClass< char > * UserText
void Generate_Skin_APT(const OBBoxClass &world_box, SimpleDynVecClass< uint32 > &apt, const Vector3 *world_vertex_locs)
bool cast_aabox_brute_force(AABoxCollisionTestClass &boxtest)
bool Intersect_OBBox(OBBoxIntersectionTestClass &boxtest)
ShareBufferClass< Vector3 > * Vertex
ShareBufferClass< uint32 > * VertexShadeIdx
void get_deformed_screenspace_vertices(Vector4 *dst_vert, const RenderInfoClass &rinfo, const Matrix3D &mesh_tm, const HTreeClass *htree)
bool cast_ray_brute_force(RayCollisionTestClass &raytest)
virtual void Compute_Bounds(Vector3 *verts)
WW3DErrorType read_vertex_normals(ChunkLoadClass &cload)
virtual WW3DErrorType Load_W3D(ChunkLoadClass &cload)
ShareBufferClass< Vector4 > * PlaneEq
const Vector3 * Get_Vertex_Normal_Array(void)
bool cast_obbox_brute_force(OBBoxCollisionTestClass &boxtest)
bool Cast_World_Space_AABox(AABoxCollisionTestClass &boxtest, const Matrix3D &transform)
bool Contains(const Vector3 &point)
int Get_Vertex_Count(void) const
bool Cast_AABox(AABoxCollisionTestClass &boxtest)
virtual ~MeshGeometryClass(void)
const char * Get_Name(void) const
void Compute_Plane(int pidx, PlaneClass *set_plane) const
TriIndex * get_polys(void)
const TriIndex * Get_Polygon_Array(void)
ShareBufferClass< Vector3 > * VertexNorm
AABTreeClass * CullTree
MeshGeometryClass & operator=(const MeshGeometryClass &that)
bool Cast_OBBox(OBBoxCollisionTestClass &boxtest)
WW3DErrorType read_user_text(ChunkLoadClass &cload)
WW3DErrorType read_vertices(ChunkLoadClass &cload)
bool Cast_Ray(RayCollisionTestClass &raytest)
uint16 * get_bone_links(bool create=true)
virtual void Compute_Vertex_Normals(Vector3 *array)
Vector4 * get_planes(bool create=true)
uint8 * Get_Poly_Surface_Type_Array(void)
ShareBufferClass< TriIndex > * Poly
void Scale(const Vector3 &sc)
Vector3 * Get_Vertex_Array(void)
WW3DErrorType read_chunks(ChunkLoadClass &cload)
bool intersect_obbox_brute_force(OBBoxIntersectionTestClass &localtest)
int cast_semi_infinite_axis_aligned_ray(const Vector3 &start_point, int axis_dir, unsigned char &flags)
void Generate_Rigid_APT(const Vector3 &view_dir, SimpleDynVecClass< uint32 > &apt)
void Generate_Culling_Tree(void)
void Set_Flag(FlagsType flag, bool onoff)
bool cast_aabox_z270(AABoxCollisionTestClass &boxtest, const Vector3 &trans)
ShareBufferClass< char > * MeshName
bool cast_aabox_z90(AABoxCollisionTestClass &boxtest, const Vector3 &trans)
WW3DErrorType read_aabtree(ChunkLoadClass &cload)
void Set_Name(const char *newname)
void Set_User_Text(char *usertext)
int Get_Polygon_Count(void) const
bool cast_aabox_z180(AABoxCollisionTestClass &boxtest, const Vector3 &trans)
const char * Get_User_Text(void)
void get_deformed_vertices(Vector3 *dst_vert, Vector3 *dst_norm, const HTreeClass *htree)
uint8 Get_Poly_Surface_Type(int poly_index) const
void Get_Bounding_Box(AABoxClass *set_box)
Vector3 BoundSphereCenter
WW3DErrorType read_triangles(ChunkLoadClass &cload)
int Get_Flag(FlagsType flag)
const uint32 * Get_Vertex_Shade_Index_Array(bool create=true)
Vector3 * get_vert_normals(void)
const Vector4 * Get_Plane_Array(bool create=true)
bool cast_aabox_identity(AABoxCollisionTestClass &boxtest, const Vector3 &trans)
void Set(float a, float b, float c, float d)
Definition plane.h:117
LineSegClass Ray
Definition coltest.h:139
CameraClass & Camera
Definition rinfo.h:100
bool Add(T const &object, int new_size_hint=0)
Definition simplevec.h:371
float Radius
Definition sphere.h:91
Vector3 Center
Definition sphere.h:90
Definition tri.h:61
const Vector3 * N
Definition tri.h:64
void Compute_Normal()
Definition tri.h:67
const Vector3 * V[3]
Definition tri.h:65
static WWINLINE float Dot_Product(const Vector3 &a, const Vector3 &b)
Definition vector3.h:293
float X
Definition vector3.h:90
float Z
Definition vector3.h:92
float Y
Definition vector3.h:91
static WWINLINE void Subtract(const Vector3 &a, const Vector3 &b, Vector3 *c)
Definition vector3.h:576
void Normalize(void)
Definition vector3.h:417
static WWINLINE void Cross_Product(const Vector3 &a, const Vector3 &b, Vector3 *result)
Definition vector3.h:374
WWINLINE void Set(float x, float y, float z)
Definition vector3.h:103
unsigned short K
Definition Vector3i.h:102
unsigned short J
Definition Vector3i.h:101
unsigned short I
Definition Vector3i.h:100
float Y
Definition vector4.h:67
float Z
Definition vector4.h:68
WWINLINE void Set(float x, float y, float z, float w)
Definition vector4.h:80
float X
Definition vector4.h:66
float W
Definition vector4.h:69
static void Normalize(Vector3 *dst, const int count)
Definition vp.cpp:487
static void Transform(Vector3 *dst, const Vector3 *src, const Matrix3D &matrix, const int count)
Definition vp.cpp:80
static void Clear(Vector3 *dst, const int count)
Definition vp.cpp:480
static void MinMax(Vector3 *src, Vector3 &min, Vector3 &max, const int count)
Definition vp.cpp:496
Vector3i16 TriIndex
else return(RetVal)
#define REF_PTR_RELEASE(x)
Definition refcount.h:80
#define REF_PTR_SET(dst, src)
Definition refcount.h:79
#define NEW_REF(C, P)
Definition refcount.h:62
Vector3 ContactPoint
Definition castres.h:70
bool ComputeContactPoint
Definition castres.h:69
uint32 SurfaceType
Definition castres.h:67
Vector3 Normal
Definition castres.h:66
W3dVectorStruct Min
Definition w3d_file.h:1226
char MeshName[W3D_NAME_LEN]
Definition w3d_file.h:1206
W3dVectorStruct Max
Definition w3d_file.h:1227
char ContainerName[W3D_NAME_LEN]
Definition w3d_file.h:1207
W3dVectorStruct SphCenter
Definition w3d_file.h:1228
uint32 Vindex[3]
Definition w3d_file.h:1051
uint32 Attributes
Definition w3d_file.h:1052
float32 Dist
Definition w3d_file.h:1054
W3dVectorStruct Normal
Definition w3d_file.h:1053
bool Cast_Semi_Infinite_Axis_Aligned_Ray_To_Triangle(const Vector3 &tri_point0, const Vector3 &tri_point1, const Vector3 &tri_point2, const Vector4 &tri_plane, const Vector3 &ray_start, int axis_r, int axis_1, int axis_2, int direction, unsigned char &flags)
Definition tri.h:219
@ TRI_RAYCAST_FLAG_NONE
Definition tri.h:93
@ TRI_RAYCAST_FLAG_START_IN_TRI
Definition tri.h:95
@ TRI_RAYCAST_FLAG_HIT_EDGE
Definition tri.h:94
WW3DErrorType
Definition w3derr.h:51
@ WW3D_ERROR_LOAD_FAILED
Definition w3derr.h:54
@ WW3D_ERROR_OK
Definition w3derr.h:52
#define WWDEBUG_SAY(x)
Definition wwdebug.h:114
@ MEM_CULLINGDATA
Definition wwmemlog.h:65
#define WWMEMLOG(category)
Definition wwmemlog.h:183