Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
hiersave.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/* $Header: /Commando/Code/Tools/max2w3d/hiersave.cpp 56 10/30/00 6:58p Greg_h $ */
20/***********************************************************************************************
21 *** Confidential - Westwood Studios ***
22 ***********************************************************************************************
23 * *
24 * Project Name : Commando / G 3D Engine *
25 * *
26 * $Archive:: /Commando/Code/Tools/max2w3d/hiersave.cpp $*
27 * *
28 * $Author:: Greg_h $*
29 * *
30 * $Modtime:: 10/30/00 6:14p $*
31 * *
32 * $Revision:: 56 $*
33 * *
34 *---------------------------------------------------------------------------------------------*
35 * Functions: *
36 * HierarchySaveClass::HierarchySaveClass -- constructor *
37 * HierarchySaveClass::HierarchySaveClass -- constructor *
38 * HierarchySaveClass::HierarchySaveClass -- constructor *
39 * HierarchySaveClass::~HierarchySaveClass -- destructor *
40 * HierarchySaveClass::Free -- releases all allocated memory *
41 * HierarchySaveClass::Get_Node_Transform -- returns the transformation matrix of specified n*
42 * HierarchySaveClass::get_relative_transform -- retruns tm between this node and its parent *
43 * HierarchySaveClass::Get_Name -- returns the name of this hierarchy *
44 * HierarchySaveClass::Get_Node -- Get the Max INode *
45 * HierarchySaveClass::Get_Node_Name -- returns name of this hierarchy node *
46 * HierarchySaveClass::Find_Named_Node -- returns index of a named node *
47 * HierarchySaveClass::Get_Export_Coordinate_System - find the bone and coordinate system *
48 * HierarchySaveClass::Save -- write the hierarchy into a W3D file *
49 * HierarchySaveClass::Load -- read the hierarchy from a W3D file *
50 * HierarchySaveClass::add_tree -- adds a node and all of its children *
51 * HierarchySaveClass::add_node -- adds a single node to the tree *
52 * HierarchySaveClass::Get_Fixup_Transform -- gets the "fixup" transform for a node *
53 * HierarchySaveClass::fixup_matrix -- conditions a matrix *
54 * HierarchySaveClass::save_header -- writes the header into a W3D file *
55 * HierarchySaveClass::save_pivots -- writes the pivots into a W3D file *
56 * HierarchySaveClass::save_fixups -- writes the fixup transforms into a W3D file *
57 * HierarchySaveClass::load_header -- reads the header from a W3D file *
58 * HierarchySaveClass::load_pivots -- reads the pivots from a W3D file *
59 * HierarchySaveClass::load_fixups -- reads the fixup transforms from a W3D file *
60 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
61
62#include "hiersave.h"
63#include "w3d_file.h"
64#include "nodefilt.h"
65#include "euler.h"
66#include "util.h"
67#include "w3dappdata.h"
68#include "errclass.h"
69#include "exportlog.h"
70
71
72bool HierarchySaveClass::TerrainModeEnabled = false;
73
74
75/***********************************************************************************************
76 * HierarchySaveClass::HierarchySaveClass -- constructor *
77 * *
78 * INPUT: *
79 * root - root INode to construct the HTree from *
80 * time - current time in Max, transforms at this time will be used *
81 * treemeter - progress meter *
82 * hname - name for the hierarchy tree *
83 * fixup_type - can be used to force all transforms to be translation only *
84 * fixuptree - htree loaded from a previous export *
85 * *
86 * OUTPUT: *
87 * *
88 * WARNINGS: *
89 * *
90 * HISTORY: *
91 * 10/26/1997 GH : Created. *
92 *=============================================================================================*/
94(
95 INode * root,
96 TimeValue time,
97 Progress_Meter_Class & treemeter,
98 char * hname,
99 int fixuptype,
100 HierarchySaveClass * fixuptree
101) :
102 Node(DEFAULT_NODE_ARRAY_SIZE),
103 CurNode(0),
104 FixupType(fixuptype),
105 FixupTree(fixuptree)
106{
107 CurNode = 0;
108 CurTime = time;
109
110 /*
111 ** This code-path is activated when the user has created a custom origin. In this case, we
112 ** need to compute the transform which will make all bones relative to this origin.
113 */
114 OriginOffsetTransform = Inverse(root->GetNodeTM(CurTime));
115
116 /*
117 ** Build our tree from the given tree of nodes
118 */
119 int rootidx = add_node(NULL,-1);
120 assert(rootidx == 0);
121 add_tree(root,rootidx);
122
123 HierarchyHeader.Version = W3D_CURRENT_HTREE_VERSION;
124 Set_W3D_Name(HierarchyHeader.Name,hname);
125 HierarchyHeader.NumPivots = CurNode;
126 HierarchyHeader.Center.X = 0.0f;
127 HierarchyHeader.Center.Y = 0.0f;
128 HierarchyHeader.Center.Z = 0.0f;
129}
130
131/***********************************************************************************************
132 * HierarchySaveClass::HierarchySaveClass -- constructor *
133 * *
134 * INPUT: *
135 * *
136 * rootlist - list of root nodes to add to the htree *
137 * time - current time in Max, transforms at this time will be used *
138 * treemeter - progress meter *
139 * hname - name for the hierarchy tree *
140 * fixup_type - can be used to force all transforms to be translation only *
141 * fixuptree - htree loaded from a previous export *
142 * origin_offset - origin offset transform *
143 * *
144 * OUTPUT: *
145 * *
146 * WARNINGS: *
147 * *
148 * HISTORY: *
149 * 10/26/1997 GH : Created. *
150 *=============================================================================================*/
152(
153 INodeListClass * rootlist,
154 TimeValue time,
155 Progress_Meter_Class & treemeter,
156 char * hname,
157 int fixuptype,
158 HierarchySaveClass * fixuptree,
159 const Matrix3 & origin_offset
160) :
161 Node(DEFAULT_NODE_ARRAY_SIZE),
162 CurNode(0),
163 FixupType(fixuptype),
164 FixupTree(fixuptree),
165 OriginOffsetTransform(origin_offset)
166{
167 CurNode = 0;
168 CurTime = time;
169
170 /*
171 ** Build the tree with all leaves of all of the nodes given
172 */
173 int rootidx = add_node(NULL,-1);
174 assert(rootidx == 0);
175
176 for (unsigned int i = 0; i < rootlist->Num_Nodes(); i++) {
177 add_tree((*rootlist)[i],rootidx);
178 }
179
180 HierarchyHeader.Version = W3D_CURRENT_HTREE_VERSION;
181 Set_W3D_Name(HierarchyHeader.Name,hname);
182 HierarchyHeader.NumPivots = CurNode;
183 HierarchyHeader.Center.X = 0.0f;
184 HierarchyHeader.Center.Y = 0.0f;
185 HierarchyHeader.Center.Z = 0.0f;
186
187}
188
189/***********************************************************************************************
190 * HierarchySaveClass::HierarchySaveClass -- constructor *
191 * *
192 * INPUT: *
193 * *
194 * OUTPUT: *
195 * *
196 * WARNINGS: *
197 * *
198 * HISTORY: *
199 * 10/26/1997 GH : Created. *
200 *=============================================================================================*/
202 Node(NULL),
203 CurNode(0),
204 CurTime(0)
205{
206}
207
208/***********************************************************************************************
209 * HierarchySaveClass::~HierarchySaveClass -- destructor *
210 * *
211 * INPUT: *
212 * *
213 * OUTPUT: *
214 * *
215 * WARNINGS: *
216 * *
217 * HISTORY: *
218 * 10/26/1997 GH : Created. *
219 *=============================================================================================*/
221{
222 Free();
223}
224
225/***********************************************************************************************
226 * HierarchySaveClass::Free -- releases all allocated memory *
227 * *
228 * INPUT: *
229 * *
230 * OUTPUT: *
231 * *
232 * WARNINGS: *
233 * *
234 * HISTORY: *
235 * 10/26/1997 GH : Created. *
236 *=============================================================================================*/
237void HierarchySaveClass::Free(void)
238{
239 Node.Clear();
240}
241
242
243/***********************************************************************************************
244 * HierarchySaveClass::Get_Node_Transform -- returns the transformation matrix of specified no *
245 * *
246 * INPUT: *
247 * *
248 * OUTPUT: *
249 * *
250 * WARNINGS: *
251 * *
252 * HISTORY: *
253 * 10/26/1997 GH : Created. *
254 *=============================================================================================*/
256{
257 Matrix3 tm(1);
258
259 int idx = nodeidx;
260
261 while (idx != -1) {
262 tm = tm * get_relative_transform(idx);
263 idx = Node[idx].Pivot.ParentIdx;
264 }
265
266 return tm;
267}
268
269
270/***********************************************************************************************
271 * HierarchySaveClass::get_relative_transform -- retruns tm between this node and its parent *
272 * *
273 * INPUT: *
274 * *
275 * OUTPUT: *
276 * *
277 * WARNINGS: *
278 * *
279 * HISTORY: *
280 * 10/26/1997 GH : Created. *
281 *=============================================================================================*/
282Matrix3 HierarchySaveClass::get_relative_transform(int nodeidx) const
283{
284 assert(nodeidx >= 0);
285 assert(nodeidx < CurNode);
286
287 Point3 trans;
288 Quat rot;
289 Matrix3 tm(true);
290 Matrix3 rtm(true);
291
292 trans.x = Node[nodeidx].Pivot.Translation.X;
293 trans.y = Node[nodeidx].Pivot.Translation.Y;
294 trans.z = Node[nodeidx].Pivot.Translation.Z;
295
296 // WARNING! I had to fudge the orientation
297 // quaternion (Max's representation seems to
298 // rotate in the opposite sense as mine...)
299 rot[0] = -Node[nodeidx].Pivot.Rotation.Q[0];
300 rot[1] = -Node[nodeidx].Pivot.Rotation.Q[1];
301 rot[2] = -Node[nodeidx].Pivot.Rotation.Q[2];
302 rot[3] = Node[nodeidx].Pivot.Rotation.Q[3];
303
304 tm.Translate(trans);
305 rot.MakeMatrix(rtm);
306 tm = rtm * tm;
307
308 return tm;
309}
310
311
312/***********************************************************************************************
313 * HierarchySaveClass::Get_Name -- returns the name of this hierarchy *
314 * *
315 * INPUT: *
316 * *
317 * OUTPUT: *
318 * *
319 * WARNINGS: *
320 * *
321 * HISTORY: *
322 * 10/26/1997 GH : Created. *
323 *=============================================================================================*/
324const char * HierarchySaveClass::Get_Name(void) const
325{
326 return HierarchyHeader.Name;
327}
328
329
330/***********************************************************************************************
331 * HierarchySaveClass::Get_Node -- Get the Max INode *
332 * *
333 * INPUT: *
334 * *
335 * OUTPUT: *
336 * *
337 * WARNINGS: *
338 * *
339 * HISTORY: *
340 * 1/15/98 GTH : Created. *
341 *=============================================================================================*/
342INode * HierarchySaveClass::Get_Node(int node) const
343{
344 assert(node >= 0);
345 assert(node < CurNode);
346
347 return Node[node].MaxNode;
348}
349
350/***********************************************************************************************
351 * HierarchySaveClass::Get_Node_Name -- returns name of this hierarchy node *
352 * *
353 * INPUT: *
354 * *
355 * OUTPUT: *
356 * *
357 * WARNINGS: *
358 * *
359 * HISTORY: *
360 * 10/26/1997 GH : Created. *
361 *=============================================================================================*/
362const char * HierarchySaveClass::Get_Node_Name(int node) const
363{
364 assert(node >= 0);
365 assert(node < CurNode);
366
367 return Node[node].Pivot.Name;
368}
369
370
371/***********************************************************************************************
372 * HierarchySaveClass::Find_Named_Node -- returns index of a named node *
373 * *
374 * INPUT: *
375 * *
376 * OUTPUT: *
377 * *
378 * WARNINGS: *
379 * *
380 * HISTORY: *
381 * 10/26/1997 GH : Created. *
382 *=============================================================================================*/
383int HierarchySaveClass::Find_Named_Node(const char * name) const
384{
385 int match = -1;
386 for (int index=0; index<CurNode; index++) {
387 if (strcmp(Node[index].Pivot.Name,name) == 0) {
388 match = index;
389 }
390 }
391
392 return match;
393}
394
395/***********************************************************************************************
396 * HierarchySaveClass::Get_Export_Coordinate_System - find the bone and coordinate system *
397 * for the given object *
398 * *
399 * INPUT: *
400 * *
401 * OUTPUT: *
402 * *
403 * WARNINGS: *
404 * *
405 * HISTORY: *
406 * 10/17/2000 gth : Created. *
407 *=============================================================================================*/
409(
410 INode * node,
411 int * set_bone_index,
412 INode ** set_bone_node,
413 Matrix3 * set_transform
414)
415{
416 /*
417 ** find the first parent of this node which
418 ** is in the base pose. Note, we're finding the parent bone
419 ** in our hierarchy with the same name as a bone in the "main"
420 ** hierarchy. When we're exporting LOD models, there are multiple
421 ** hierarchies...
422 */
423 bool done = false;
424 int boneidx = -1;
425 INode * pbone = node;
426
427 while (!done) {
428
429 char name[W3D_NAME_LEN];
430 Set_W3D_Name(name,pbone->GetName());
431
432 boneidx = Find_Named_Node(name);
433
434 if (boneidx != -1) {
435
436 /*
437 ** We found the parent bone!
438 */
439 done = true;
440
441 } else if (Is_Origin(pbone)) {
442
443 /*
444 ** Don't go up past our origin, use this as our bone.
445 */
446 boneidx = 0;
447 done = true;
448
449 } else {
450
451 /*
452 ** Nope, try the next parent
453 */
454 pbone = pbone->GetParentNode();
455 assert(pbone != NULL);
456
457#if 0
458 if (pbone == NULL) {
459
460 /*
461 ** mesh isn't connected to a bone, use the root
462 */
463 boneidx = 0;
464 pbone = node;
465 done = true;
466 }
467#endif
468 }
469 }
470
471 if (set_bone_index != NULL) {
472 *set_bone_index = boneidx;
473 }
474 if (set_bone_node != NULL) {
475 *set_bone_node = pbone;
476 }
477 if (set_transform != NULL) {
478 *set_transform = Get_Fixup_Transform(boneidx) * pbone->GetNodeTM(CurTime);
479 }
480}
481
482/***********************************************************************************************
483 * HierarchySaveClass::Save -- write the hierarchy into a W3D file *
484 * *
485 * INPUT: *
486 * *
487 * OUTPUT: *
488 * *
489 * WARNINGS: *
490 * *
491 * HISTORY: *
492 * 10/26/1997 GH : Created. *
493 *=============================================================================================*/
495{
496 ExportLog::printf("\nSaving Hierarchy Tree %s.\n",HierarchyHeader.Name);
497 ExportLog::printf("Node Count: %d\n",CurNode);
498 ExportLog::printf("Nodes: \n");
499 for (int inode = 0; inode < CurNode; inode++) {
500 ExportLog::printf(" %s\n",Node[inode].Pivot.Name);
501 }
502
503 if (!csave.Begin_Chunk(W3D_CHUNK_HIERARCHY)) {
504 return false;
505 }
506
507 if (!save_header(csave)) {
508 return false;
509 }
510
511 if (!save_pivots(csave)) {
512 return false;
513 }
514
515 if (!save_fixups(csave)) {
516 return false;
517 }
518
519 if (!csave.End_Chunk()) {
520 return false;
521 }
522
523 return true;
524}
525
526
527/***********************************************************************************************
528 * HierarchySaveClass::Load -- read the hierarchy from a W3D file *
529 * *
530 * INPUT: *
531 * *
532 * OUTPUT: *
533 * *
534 * WARNINGS: *
535 * *
536 * HISTORY: *
537 * 10/26/1997 GH : Created. *
538 *=============================================================================================*/
540{
541 Free();
542 bool error = false;
543
544 while (cload.Open_Chunk()) {
545 switch (cload.Cur_Chunk_ID()) {
547 if (!load_header(cload)) error = true;
548 break;
549 case W3D_CHUNK_PIVOTS:
550 if (!load_pivots(cload)) error = true;
551 break;
553 if (!load_fixups(cload)) error = true;
554 break;
555 default:
556 break;
557 }
558
559 if (!cload.Close_Chunk() || error) {
560 return false;
561 }
562 }
563
564 CurNode = HierarchyHeader.NumPivots;
565
566 return true;
567}
568
569
570/***********************************************************************************************
571 * HierarchySaveClass::add_tree -- adds a node and all of its children *
572 * *
573 * INPUT: *
574 * *
575 * OUTPUT: *
576 * *
577 * WARNINGS: *
578 * *
579 * HISTORY: *
580 * 10/26/1997 GH : Created. *
581 *=============================================================================================*/
582void HierarchySaveClass::add_tree(INode * node,int pidx)
583{
584 int nextparent;
585
586 if (node->IsHidden ()) {
587
588 // if the node is hidden, do not add it but add its children to the current parent.
589 nextparent = pidx;
590
591 } else if (TerrainModeEnabled && (Is_Normal_Mesh(node) || Is_Null_Object(node))) {
592
593 // terrain optimization, normal meshes are not allowed to have transforms
594 nextparent = pidx;
595
596 } else if (!Is_Bone(node)) {
597
598 // This node isn't a bone, don't add it
599 nextparent = pidx;
600
601 } else {
602
603 // Add new pivot! it will be parent of all below it.
604 nextparent = add_node(node,pidx);
605
606 }
607
608 // Add all of this nodes children
609 for (int i=0; i < node->NumberOfChildren(); i++) {
610 add_tree(node->GetChildNode(i),nextparent);
611 }
612}
613
614
615/***********************************************************************************************
616 * HierarchySaveClass::add_node -- adds a single node to the tree *
617 * *
618 * INPUT: *
619 * *
620 * OUTPUT: *
621 * *
622 * WARNINGS: *
623 * *
624 * HISTORY: *
625 * 10/26/1997 GH : Created. *
626 *=============================================================================================*/
627int HierarchySaveClass::add_node(INode * node,int pidx)
628{
629 /*
630 ** 'grow' the node array if necessary
631 */
632 if (CurNode >= Node.Length ()) {
633 Node.Resize (Node.Length () + NODE_ARRAY_GROWTH_SIZE);
634 }
635
636 /*
637 ** setup the pivot
638 */
639 Node[CurNode].MaxNode = node;
640 Node[CurNode].Pivot.ParentIdx = pidx;
641
642 if (node) {
643 Set_W3D_Name(Node[CurNode].Pivot.Name,node->GetName());
644 } else {
645 Set_W3D_Name(Node[CurNode].Pivot.Name,"RootTransform");
646 }
647
648 /*
649 ** Now, check if there is a bone with this W3D name already
650 ** if there is, scold the user and bail out
651 */
652 if (Find_Named_Node(Node[CurNode].Pivot.Name) != -1) {
653 char buf[128];
654 sprintf(buf,"Bones with duplicate names found!\nDuplicated Name: %s\n",Node[CurNode].Pivot.Name);
655 throw ErrorClass(buf);
656 }
657
658 /*
659 ** Compute the transformation for this node
660 */
661 Matrix3 maxnodeTM(1);
662 Matrix3 ournodeTM(1);
663 Matrix3 fixupTM(1);
664 Point3 trans(0,0,0);
665 Quat rot(1);
666 Point3 scale(1,1,1);
667
668 if (node) {
669 maxnodeTM = node->GetNodeTM(CurTime) * OriginOffsetTransform;
670 } else {
671 maxnodeTM = Matrix3(1);
672 }
673
674 /*
675 ** If this tree is being "fixed up" the first thing we do
676 ** is to transform Max's nodeTM by the fixup transform.
677 ** This is done when a base pose was created using our own
678 ** types of transforms and we want to apply the same
679 ** changes to this tree.
680 **
681 ** Note that if FixupType is not "NONE", FixupTree must be NULL,
682 */
683 assert(!((FixupTree != NULL) && (FixupType != MATRIX_FIXUP_NONE)));
684
685 if (FixupTree != NULL) {
686 int fi = FixupTree->Find_Named_Node(Node[CurNode].Pivot.Name);
687 if (fi == -1) {
688 char buf[128];
689 sprintf(buf,"Incompatible Base Pose!\nMissing Bone: %s\n",Node[CurNode].Pivot.Name);
690 throw ErrorClass(buf);
691 }
692
693 Matrix3 fixup = FixupTree->Get_Fixup_Transform(fi);
694
695 maxnodeTM = fixup * maxnodeTM;
696 }
697
698
699 ournodeTM = fixup_matrix(maxnodeTM);
700 fixupTM = ournodeTM * Inverse(maxnodeTM);
701
702 /*
703 ** Now, make ournodeTM relative to its parent transform. We
704 ** will always store relative transformations. (Also, note
705 ** that it is relative to our version of the parent transform
706 ** which is not necessarily the same as the MAX version...)
707 */
708 if (pidx != -1) {
709 Matrix3 parentTM = Get_Node_Transform(pidx);
710 Matrix3 pinv = Inverse(parentTM);
711 ournodeTM = ournodeTM * pinv;
712 }
713
714
715 /*
716 ** Break the matrix down into a rotation and translation.
717 */
718 DecomposeMatrix(ournodeTM,trans,rot,scale);
719
720 /*
721 ** Save the "fixup" matrix
722 */
723 for (int j=0;j<4;j++) {
724 Point3 row = fixupTM.GetRow(j);
725 Node[CurNode].Fixup.TM[j][0] = row.x;
726 Node[CurNode].Fixup.TM[j][1] = row.y;
727 Node[CurNode].Fixup.TM[j][2] = row.z;
728 }
729
730 /*
731 ** Set the translation and rotation for this pivot.
732 */
733 Node[CurNode].Pivot.Translation.X = trans.x;
734 Node[CurNode].Pivot.Translation.Y = trans.y;
735 Node[CurNode].Pivot.Translation.Z = trans.z;
736
737 Node[CurNode].Pivot.Rotation.Q[0] = -rot[0];
738 Node[CurNode].Pivot.Rotation.Q[1] = -rot[1];
739 Node[CurNode].Pivot.Rotation.Q[2] = -rot[2];
740 Node[CurNode].Pivot.Rotation.Q[3] = rot[3];
741
742 /*
743 ** Compute the Euler angles and set them.
744 */
745 Matrix3 rotmat;
746 rot.MakeMatrix(rotmat);
747 EulerAnglesClass eangs(rotmat,EulerOrderXYZr);
748
749 Node[CurNode].Pivot.EulerAngles.X = eangs.Get_Angle(0);
750 Node[CurNode].Pivot.EulerAngles.Y = eangs.Get_Angle(1);
751 Node[CurNode].Pivot.EulerAngles.Z = eangs.Get_Angle(2);
752
753 return CurNode++;
754}
755
756/***********************************************************************************************
757 * HierarchySaveClass::Get_Fixup_Transform -- gets the "fixup" transform for a node *
758 * *
759 * INPUT: *
760 * *
761 * OUTPUT: *
762 * *
763 * WARNINGS: *
764 * *
765 * HISTORY: *
766 * 10/26/1997 GH : Created. *
767 *=============================================================================================*/
769{
770 assert(node >= 0);
771 assert(node < CurNode);
772
773 Matrix3 m;
774
775 for (int j=0;j<4;j++) {
776 m.SetRow(j,Point3(Node[node].Fixup.TM[j][0],Node[node].Fixup.TM[j][1],Node[node].Fixup.TM[j][2]));
777 }
778
779 return m;
780}
781
782/***********************************************************************************************
783 * HierarchySaveClass::fixup_matrix -- conditions a matrix *
784 * *
785 * INPUT: *
786 * *
787 * OUTPUT: *
788 * *
789 * WARNINGS: *
790 * *
791 * HISTORY: *
792 * 10/26/1997 GH : Created. *
793 *=============================================================================================*/
794Matrix3 HierarchySaveClass::fixup_matrix(const Matrix3 & csrc) const
795{
796 Matrix3 src = csrc; // the GetTrans function is not const correct...
797 Matrix3 newtm(1);
798 Point3 trans;
799 Quat rot;
800 Point3 scale;
801
802 switch (FixupType) {
804 newtm = src;
805 break;
806
808 newtm.SetTrans(src.GetTrans());
809 newtm = Cleanup_Orthogonal_Matrix(newtm);
810 break;
811
813 DecomposeMatrix(src,trans,rot,scale);
814 rot.MakeMatrix(newtm);
815 newtm.SetTrans(trans);
816 newtm = Cleanup_Orthogonal_Matrix(newtm);
817 break;
818 };
819
820 return newtm;
821}
822
823
824/***********************************************************************************************
825 * HierarchySaveClass::save_header -- writes the header into a W3D file *
826 * *
827 * INPUT: *
828 * *
829 * OUTPUT: *
830 * *
831 * WARNINGS: *
832 * *
833 * HISTORY: *
834 * 10/26/1997 GH : Created. *
835 *=============================================================================================*/
836bool HierarchySaveClass::save_header(ChunkSaveClass & csave)
837{
839 return false;
840 }
841
842 if (csave.Write(&HierarchyHeader,sizeof(HierarchyHeader)) != sizeof(HierarchyHeader)) {
843 return false;
844 }
845
846 if (!csave.End_Chunk()) {
847 return false;
848 }
849
850 return true;
851}
852
853
854/***********************************************************************************************
855 * HierarchySaveClass::save_pivots -- writes the pivots into a W3D file *
856 * *
857 * INPUT: *
858 * *
859 * OUTPUT: *
860 * *
861 * WARNINGS: *
862 * *
863 * HISTORY: *
864 * 10/26/1997 GH : Created. *
865 *=============================================================================================*/
866bool HierarchySaveClass::save_pivots(ChunkSaveClass & csave)
867{
868 if (!csave.Begin_Chunk(W3D_CHUNK_PIVOTS)) {
869 return false;
870 }
871
872 for (uint32 i=0; i<HierarchyHeader.NumPivots; i++) {
873 if (csave.Write(&Node[i].Pivot,sizeof(W3dPivotStruct)) != sizeof(W3dPivotStruct)) {
874 return false;
875 }
876 }
877
878 if (!csave.End_Chunk()) {
879 return false;
880 }
881
882 return true;
883}
884
885/***********************************************************************************************
886 * HierarchySaveClass::save_fixups -- writes the fixup transforms into a W3D file *
887 * *
888 * INPUT: *
889 * *
890 * OUTPUT: *
891 * *
892 * WARNINGS: *
893 * *
894 * HISTORY: *
895 * 10/26/1997 GH : Created. *
896 *=============================================================================================*/
897bool HierarchySaveClass::save_fixups(ChunkSaveClass & csave)
898{
900 return false;
901 }
902
903 for (uint32 i=0; i<HierarchyHeader.NumPivots; i++) {
904 if (csave.Write(&Node[i].Fixup,sizeof(W3dPivotFixupStruct)) != sizeof(W3dPivotFixupStruct)) {
905 return false;
906 }
907 }
908
909 if (!csave.End_Chunk()) {
910 return false;
911 }
912
913 return true;
914}
915
916
917/***********************************************************************************************
918 * HierarchySaveClass::load_header -- reads the header from a W3D file *
919 * *
920 * INPUT: *
921 * *
922 * OUTPUT: *
923 * *
924 * WARNINGS: *
925 * *
926 * HISTORY: *
927 * 10/26/1997 GH : Created. *
928 *=============================================================================================*/
929bool HierarchySaveClass::load_header(ChunkLoadClass & cload)
930{
931 /*
932 ** Load the header
933 */
934 if (cload.Read(&HierarchyHeader,sizeof(HierarchyHeader)) != sizeof(HierarchyHeader)) {
935 return false;
936 }
937
938 /*
939 ** Reset the current node count
940 */
941 CurNode = 0;
942 Node.Resize(HierarchyHeader.NumPivots);
943
944 /*
945 ** Initialize everything to a default state (particularly the
946 ** fixup matrices to identity...)
947 */
948 for (unsigned i=0; i < HierarchyHeader.NumPivots; i++) {
949 memset(&(Node[i]),0,sizeof(HierarchyNodeStruct));
950
951 Matrix3 ident(1);
952 for (int j=0; j<3; j++) {
953 Point3 row = ident.GetRow(j);
954 Node[i].Fixup.TM[j][0] = row.x;
955 Node[i].Fixup.TM[j][1] = row.y;
956 Node[i].Fixup.TM[j][2] = row.z;
957 }
958 }
959
960 return true;
961}
962
963
964/***********************************************************************************************
965 * HierarchySaveClass::load_pivots -- reads the pivots from a W3D file *
966 * *
967 * INPUT: *
968 * *
969 * OUTPUT: *
970 * *
971 * WARNINGS: *
972 * *
973 * HISTORY: *
974 * 10/26/1997 GH : Created. *
975 *=============================================================================================*/
976bool HierarchySaveClass::load_pivots(ChunkLoadClass & cload)
977{
978 for (uint32 i=0; i<HierarchyHeader.NumPivots; i++) {
979 Node[i].MaxNode = NULL;
980 if (cload.Read(&Node[i].Pivot,sizeof(W3dPivotStruct)) != sizeof(W3dPivotStruct)) {
981 return false;
982 }
983 }
984 return true;
985}
986
987/***********************************************************************************************
988 * HierarchySaveClass::load_fixups -- reads the fixup transforms from a W3D file *
989 * *
990 * INPUT: *
991 * *
992 * OUTPUT: *
993 * *
994 * WARNINGS: *
995 * *
996 * HISTORY: *
997 * 10/26/1997 GH : Created. *
998 *=============================================================================================*/
999bool HierarchySaveClass::load_fixups(ChunkLoadClass & cload)
1000{
1001 for (uint32 i=0; i<HierarchyHeader.NumPivots; i++) {
1002 if (cload.Read(&Node[i].Fixup,sizeof(W3dPivotFixupStruct)) != sizeof(W3dPivotFixupStruct)) {
1003 return false;
1004 }
1005 }
1006 return true;
1007}
1008
1009
#define NULL
Definition BaseType.h:92
Color scale(const Color &a, const Color &b)
Definition GameMtl.cpp:722
#define W3D_NAME_LEN
Definition w3d_file.h:319
#define W3D_CURRENT_HTREE_VERSION
Definition w3d_file.h:1350
@ W3D_CHUNK_PIVOT_FIXUPS
Definition w3d_file.h:399
@ W3D_CHUNK_HIERARCHY
Definition w3d_file.h:396
@ W3D_CHUNK_HIERARCHY_HEADER
Definition w3d_file.h:397
@ W3D_CHUNK_PIVOTS
Definition w3d_file.h:398
unsigned long uint32
Definition bittype.h:46
int EulerOrderXYZr
Definition euler.cpp:107
bool Close_Chunk()
Definition chunkio.cpp:448
uint32 Cur_Chunk_ID()
Definition chunkio.cpp:484
uint32 Read(void *buf, uint32 nbytes)
Definition chunkio.cpp:692
bool Open_Chunk()
Definition chunkio.cpp:412
uint32 Write(const void *buf, uint32 nbytes)
Definition chunkio.cpp:264
bool Begin_Chunk(uint32 id)
Definition chunkio.cpp:108
bool End_Chunk()
Definition chunkio.cpp:148
static void printf(char *,...)
int Find_Named_Node(const char *name) const
Definition hiersave.cpp:383
Matrix3 Get_Fixup_Transform(int node) const
Definition hiersave.cpp:768
bool Load(ChunkLoadClass &cload)
Definition hiersave.cpp:539
void Get_Export_Coordinate_System(INode *node, int *set_bone_index, INode **set_bone_node, Matrix3 *set_transform)
Definition hiersave.cpp:409
const char * Get_Name(void) const
Definition hiersave.cpp:324
Matrix3 Get_Node_Transform(int node) const
Definition hiersave.cpp:255
const char * Get_Node_Name(int node) const
Definition hiersave.cpp:362
INode * Get_Node(int node) const
Definition hiersave.cpp:342
bool Save(ChunkSaveClass &csave)
Definition hiersave.cpp:494
unsigned Num_Nodes(void) const
Definition nodelist.h:75
WWINLINE Quaternion Inverse(const Quaternion &a)
Definition quat.h:117
Matrix3 Cleanup_Orthogonal_Matrix(Matrix3 &mat)
Definition util.cpp:79
void Set_W3D_Name(char *set_name, const char *src)
Definition util.cpp:112
bool Is_Origin(INode *node)
Definition util.cpp:495
bool Is_Normal_Mesh(INode *node)
bool Is_Null_Object(INode *node)
bool Is_Bone(INode *node)