1010 lines
47 KiB
C++
Raw Permalink Normal View History

/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* $Header: /Commando/Code/Tools/max2w3d/hiersave.cpp 56 10/30/00 6:58p Greg_h $ */
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando / G 3D Engine *
* *
* $Archive:: /Commando/Code/Tools/max2w3d/hiersave.cpp $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 10/30/00 6:14p $*
* *
* $Revision:: 56 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* HierarchySaveClass::HierarchySaveClass -- constructor *
* HierarchySaveClass::HierarchySaveClass -- constructor *
* HierarchySaveClass::HierarchySaveClass -- constructor *
* HierarchySaveClass::~HierarchySaveClass -- destructor *
* HierarchySaveClass::Free -- releases all allocated memory *
* HierarchySaveClass::Get_Node_Transform -- returns the transformation matrix of specified n*
* HierarchySaveClass::get_relative_transform -- retruns tm between this node and its parent *
* HierarchySaveClass::Get_Name -- returns the name of this hierarchy *
* HierarchySaveClass::Get_Node -- Get the Max INode *
* HierarchySaveClass::Get_Node_Name -- returns name of this hierarchy node *
* HierarchySaveClass::Find_Named_Node -- returns index of a named node *
* HierarchySaveClass::Get_Export_Coordinate_System - find the bone and coordinate system *
* HierarchySaveClass::Save -- write the hierarchy into a W3D file *
* HierarchySaveClass::Load -- read the hierarchy from a W3D file *
* HierarchySaveClass::add_tree -- adds a node and all of its children *
* HierarchySaveClass::add_node -- adds a single node to the tree *
* HierarchySaveClass::Get_Fixup_Transform -- gets the "fixup" transform for a node *
* HierarchySaveClass::fixup_matrix -- conditions a matrix *
* HierarchySaveClass::save_header -- writes the header into a W3D file *
* HierarchySaveClass::save_pivots -- writes the pivots into a W3D file *
* HierarchySaveClass::save_fixups -- writes the fixup transforms into a W3D file *
* HierarchySaveClass::load_header -- reads the header from a W3D file *
* HierarchySaveClass::load_pivots -- reads the pivots from a W3D file *
* HierarchySaveClass::load_fixups -- reads the fixup transforms from a W3D file *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "hiersave.h"
#include "w3d_file.h"
#include "nodefilt.h"
#include "euler.h"
#include "util.h"
#include "w3dappdata.h"
#include "errclass.h"
#include "exportlog.h"
bool HierarchySaveClass::TerrainModeEnabled = false;
/***********************************************************************************************
* HierarchySaveClass::HierarchySaveClass -- constructor *
* *
* INPUT: *
* root - root INode to construct the HTree from *
* time - current time in Max, transforms at this time will be used *
* treemeter - progress meter *
* hname - name for the hierarchy tree *
* fixup_type - can be used to force all transforms to be translation only *
* fixuptree - htree loaded from a previous export *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/26/1997 GH : Created. *
*=============================================================================================*/
HierarchySaveClass::HierarchySaveClass
(
INode * root,
TimeValue time,
Progress_Meter_Class & treemeter,
char * hname,
int fixuptype,
HierarchySaveClass * fixuptree
) :
Node(DEFAULT_NODE_ARRAY_SIZE),
CurNode(0),
FixupType(fixuptype),
FixupTree(fixuptree)
{
CurNode = 0;
CurTime = time;
/*
** This code-path is activated when the user has created a custom origin. In this case, we
** need to compute the transform which will make all bones relative to this origin.
*/
OriginOffsetTransform = Inverse(root->GetNodeTM(CurTime));
/*
** Build our tree from the given tree of nodes
*/
int rootidx = add_node(NULL,-1);
assert(rootidx == 0);
add_tree(root,rootidx);
HierarchyHeader.Version = W3D_CURRENT_HTREE_VERSION;
Set_W3D_Name(HierarchyHeader.Name,hname);
HierarchyHeader.NumPivots = CurNode;
HierarchyHeader.Center.X = 0.0f;
HierarchyHeader.Center.Y = 0.0f;
HierarchyHeader.Center.Z = 0.0f;
}
/***********************************************************************************************
* HierarchySaveClass::HierarchySaveClass -- constructor *
* *
* INPUT: *
* *
* rootlist - list of root nodes to add to the htree *
* time - current time in Max, transforms at this time will be used *
* treemeter - progress meter *
* hname - name for the hierarchy tree *
* fixup_type - can be used to force all transforms to be translation only *
* fixuptree - htree loaded from a previous export *
* origin_offset - origin offset transform *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/26/1997 GH : Created. *
*=============================================================================================*/
HierarchySaveClass::HierarchySaveClass
(
INodeListClass * rootlist,
TimeValue time,
Progress_Meter_Class & treemeter,
char * hname,
int fixuptype,
HierarchySaveClass * fixuptree,
const Matrix3 & origin_offset
) :
Node(DEFAULT_NODE_ARRAY_SIZE),
CurNode(0),
FixupType(fixuptype),
FixupTree(fixuptree),
OriginOffsetTransform(origin_offset)
{
CurNode = 0;
CurTime = time;
/*
** Build the tree with all leaves of all of the nodes given
*/
int rootidx = add_node(NULL,-1);
assert(rootidx == 0);
for (unsigned int i = 0; i < rootlist->Num_Nodes(); i++) {
add_tree((*rootlist)[i],rootidx);
}
HierarchyHeader.Version = W3D_CURRENT_HTREE_VERSION;
Set_W3D_Name(HierarchyHeader.Name,hname);
HierarchyHeader.NumPivots = CurNode;
HierarchyHeader.Center.X = 0.0f;
HierarchyHeader.Center.Y = 0.0f;
HierarchyHeader.Center.Z = 0.0f;
}
/***********************************************************************************************
* HierarchySaveClass::HierarchySaveClass -- constructor *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/26/1997 GH : Created. *
*=============================================================================================*/
HierarchySaveClass::HierarchySaveClass():
Node(NULL),
CurNode(0),
CurTime(0)
{
}
/***********************************************************************************************
* HierarchySaveClass::~HierarchySaveClass -- destructor *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/26/1997 GH : Created. *
*=============================================================================================*/
HierarchySaveClass::~HierarchySaveClass(void)
{
Free();
}
/***********************************************************************************************
* HierarchySaveClass::Free -- releases all allocated memory *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/26/1997 GH : Created. *
*=============================================================================================*/
void HierarchySaveClass::Free(void)
{
Node.Clear();
}
/***********************************************************************************************
* HierarchySaveClass::Get_Node_Transform -- returns the transformation matrix of specified no *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/26/1997 GH : Created. *
*=============================================================================================*/
Matrix3 HierarchySaveClass::Get_Node_Transform(int nodeidx) const
{
Matrix3 tm(1);
int idx = nodeidx;
while (idx != -1) {
tm = tm * get_relative_transform(idx);
idx = Node[idx].Pivot.ParentIdx;
}
return tm;
}
/***********************************************************************************************
* HierarchySaveClass::get_relative_transform -- retruns tm between this node and its parent *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/26/1997 GH : Created. *
*=============================================================================================*/
Matrix3 HierarchySaveClass::get_relative_transform(int nodeidx) const
{
assert(nodeidx >= 0);
assert(nodeidx < CurNode);
Point3 trans;
Quat rot;
Matrix3 tm(true);
Matrix3 rtm(true);
trans.x = Node[nodeidx].Pivot.Translation.X;
trans.y = Node[nodeidx].Pivot.Translation.Y;
trans.z = Node[nodeidx].Pivot.Translation.Z;
// WARNING! I had to fudge the orientation
// quaternion (Max's representation seems to
// rotate in the opposite sense as mine...)
rot[0] = -Node[nodeidx].Pivot.Rotation.Q[0];
rot[1] = -Node[nodeidx].Pivot.Rotation.Q[1];
rot[2] = -Node[nodeidx].Pivot.Rotation.Q[2];
rot[3] = Node[nodeidx].Pivot.Rotation.Q[3];
tm.Translate(trans);
rot.MakeMatrix(rtm);
tm = rtm * tm;
return tm;
}
/***********************************************************************************************
* HierarchySaveClass::Get_Name -- returns the name of this hierarchy *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/26/1997 GH : Created. *
*=============================================================================================*/
const char * HierarchySaveClass::Get_Name(void) const
{
return HierarchyHeader.Name;
}
/***********************************************************************************************
* HierarchySaveClass::Get_Node -- Get the Max INode *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/15/98 GTH : Created. *
*=============================================================================================*/
INode * HierarchySaveClass::Get_Node(int node) const
{
assert(node >= 0);
assert(node < CurNode);
return Node[node].MaxNode;
}
/***********************************************************************************************
* HierarchySaveClass::Get_Node_Name -- returns name of this hierarchy node *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/26/1997 GH : Created. *
*=============================================================================================*/
const char * HierarchySaveClass::Get_Node_Name(int node) const
{
assert(node >= 0);
assert(node < CurNode);
return Node[node].Pivot.Name;
}
/***********************************************************************************************
* HierarchySaveClass::Find_Named_Node -- returns index of a named node *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/26/1997 GH : Created. *
*=============================================================================================*/
int HierarchySaveClass::Find_Named_Node(const char * name) const
{
int match = -1;
for (int index=0; index<CurNode; index++) {
if (strcmp(Node[index].Pivot.Name,name) == 0) {
match = index;
}
}
return match;
}
/***********************************************************************************************
* HierarchySaveClass::Get_Export_Coordinate_System - find the bone and coordinate system *
* for the given object *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/17/2000 gth : Created. *
*=============================================================================================*/
void HierarchySaveClass::Get_Export_Coordinate_System
(
INode * node,
int * set_bone_index,
INode ** set_bone_node,
Matrix3 * set_transform
)
{
/*
** find the first parent of this node which
** is in the base pose. Note, we're finding the parent bone
** in our hierarchy with the same name as a bone in the "main"
** hierarchy. When we're exporting LOD models, there are multiple
** hierarchies...
*/
bool done = false;
int boneidx = -1;
INode * pbone = node;
while (!done) {
char name[W3D_NAME_LEN];
Set_W3D_Name(name,pbone->GetName());
boneidx = Find_Named_Node(name);
if (boneidx != -1) {
/*
** We found the parent bone!
*/
done = true;
} else if (Is_Origin(pbone)) {
/*
** Don't go up past our origin, use this as our bone.
*/
boneidx = 0;
done = true;
} else {
/*
** Nope, try the next parent
*/
pbone = pbone->GetParentNode();
assert(pbone != NULL);
#if 0
if (pbone == NULL) {
/*
** mesh isn't connected to a bone, use the root
*/
boneidx = 0;
pbone = node;
done = true;
}
#endif
}
}
if (set_bone_index != NULL) {
*set_bone_index = boneidx;
}
if (set_bone_node != NULL) {
*set_bone_node = pbone;
}
if (set_transform != NULL) {
*set_transform = Get_Fixup_Transform(boneidx) * pbone->GetNodeTM(CurTime);
}
}
/***********************************************************************************************
* HierarchySaveClass::Save -- write the hierarchy into a W3D file *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/26/1997 GH : Created. *
*=============================================================================================*/
bool HierarchySaveClass::Save(ChunkSaveClass & csave)
{
ExportLog::printf("\nSaving Hierarchy Tree %s.\n",HierarchyHeader.Name);
ExportLog::printf("Node Count: %d\n",CurNode);
ExportLog::printf("Nodes: \n");
for (int inode = 0; inode < CurNode; inode++) {
ExportLog::printf(" %s\n",Node[inode].Pivot.Name);
}
if (!csave.Begin_Chunk(W3D_CHUNK_HIERARCHY)) {
return false;
}
if (!save_header(csave)) {
return false;
}
if (!save_pivots(csave)) {
return false;
}
if (!save_fixups(csave)) {
return false;
}
if (!csave.End_Chunk()) {
return false;
}
return true;
}
/***********************************************************************************************
* HierarchySaveClass::Load -- read the hierarchy from a W3D file *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/26/1997 GH : Created. *
*=============================================================================================*/
bool HierarchySaveClass::Load(ChunkLoadClass & cload)
{
Free();
bool error = false;
while (cload.Open_Chunk()) {
switch (cload.Cur_Chunk_ID()) {
case W3D_CHUNK_HIERARCHY_HEADER:
if (!load_header(cload)) error = true;
break;
case W3D_CHUNK_PIVOTS:
if (!load_pivots(cload)) error = true;
break;
case W3D_CHUNK_PIVOT_FIXUPS:
if (!load_fixups(cload)) error = true;
break;
default:
break;
}
if (!cload.Close_Chunk() || error) {
return false;
}
}
CurNode = HierarchyHeader.NumPivots;
return true;
}
/***********************************************************************************************
* HierarchySaveClass::add_tree -- adds a node and all of its children *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/26/1997 GH : Created. *
*=============================================================================================*/
void HierarchySaveClass::add_tree(INode * node,int pidx)
{
int nextparent;
if (node->IsHidden ()) {
// if the node is hidden, do not add it but add its children to the current parent.
nextparent = pidx;
} else if (TerrainModeEnabled && (Is_Normal_Mesh(node) || Is_Null_Object(node))) {
// terrain optimization, normal meshes are not allowed to have transforms
nextparent = pidx;
} else if (!Is_Bone(node)) {
// This node isn't a bone, don't add it
nextparent = pidx;
} else {
// Add new pivot! it will be parent of all below it.
nextparent = add_node(node,pidx);
}
// Add all of this nodes children
for (int i=0; i < node->NumberOfChildren(); i++) {
add_tree(node->GetChildNode(i),nextparent);
}
}
/***********************************************************************************************
* HierarchySaveClass::add_node -- adds a single node to the tree *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/26/1997 GH : Created. *
*=============================================================================================*/
int HierarchySaveClass::add_node(INode * node,int pidx)
{
/*
** 'grow' the node array if necessary
*/
if (CurNode >= Node.Length ()) {
Node.Resize (Node.Length () + NODE_ARRAY_GROWTH_SIZE);
}
/*
** setup the pivot
*/
Node[CurNode].MaxNode = node;
Node[CurNode].Pivot.ParentIdx = pidx;
if (node) {
Set_W3D_Name(Node[CurNode].Pivot.Name,node->GetName());
} else {
Set_W3D_Name(Node[CurNode].Pivot.Name,"RootTransform");
}
/*
** Now, check if there is a bone with this W3D name already
** if there is, scold the user and bail out
*/
if (Find_Named_Node(Node[CurNode].Pivot.Name) != -1) {
char buf[128];
sprintf(buf,"Bones with duplicate names found!\nDuplicated Name: %s\n",Node[CurNode].Pivot.Name);
throw ErrorClass(buf);
}
/*
** Compute the transformation for this node
*/
Matrix3 maxnodeTM(1);
Matrix3 ournodeTM(1);
Matrix3 fixupTM(1);
Point3 trans(0,0,0);
Quat rot(1);
Point3 scale(1,1,1);
if (node) {
maxnodeTM = node->GetNodeTM(CurTime) * OriginOffsetTransform;
} else {
maxnodeTM = Matrix3(1);
}
/*
** If this tree is being "fixed up" the first thing we do
** is to transform Max's nodeTM by the fixup transform.
** This is done when a base pose was created using our own
** types of transforms and we want to apply the same
** changes to this tree.
**
** Note that if FixupType is not "NONE", FixupTree must be NULL,
*/
assert(!((FixupTree != NULL) && (FixupType != MATRIX_FIXUP_NONE)));
if (FixupTree != NULL) {
int fi = FixupTree->Find_Named_Node(Node[CurNode].Pivot.Name);
if (fi == -1) {
char buf[128];
sprintf(buf,"Incompatible Base Pose!\nMissing Bone: %s\n",Node[CurNode].Pivot.Name);
throw ErrorClass(buf);
}
Matrix3 fixup = FixupTree->Get_Fixup_Transform(fi);
maxnodeTM = fixup * maxnodeTM;
}
ournodeTM = fixup_matrix(maxnodeTM);
fixupTM = ournodeTM * Inverse(maxnodeTM);
/*
** Now, make ournodeTM relative to its parent transform. We
** will always store relative transformations. (Also, note
** that it is relative to our version of the parent transform
** which is not necessarily the same as the MAX version...)
*/
if (pidx != -1) {
Matrix3 parentTM = Get_Node_Transform(pidx);
Matrix3 pinv = Inverse(parentTM);
ournodeTM = ournodeTM * pinv;
}
/*
** Break the matrix down into a rotation and translation.
*/
DecomposeMatrix(ournodeTM,trans,rot,scale);
/*
** Save the "fixup" matrix
*/
for (int j=0;j<4;j++) {
Point3 row = fixupTM.GetRow(j);
Node[CurNode].Fixup.TM[j][0] = row.x;
Node[CurNode].Fixup.TM[j][1] = row.y;
Node[CurNode].Fixup.TM[j][2] = row.z;
}
/*
** Set the translation and rotation for this pivot.
*/
Node[CurNode].Pivot.Translation.X = trans.x;
Node[CurNode].Pivot.Translation.Y = trans.y;
Node[CurNode].Pivot.Translation.Z = trans.z;
Node[CurNode].Pivot.Rotation.Q[0] = -rot[0];
Node[CurNode].Pivot.Rotation.Q[1] = -rot[1];
Node[CurNode].Pivot.Rotation.Q[2] = -rot[2];
Node[CurNode].Pivot.Rotation.Q[3] = rot[3];
/*
** Compute the Euler angles and set them.
*/
Matrix3 rotmat;
rot.MakeMatrix(rotmat);
EulerAnglesClass eangs(rotmat,EulerOrderXYZr);
Node[CurNode].Pivot.EulerAngles.X = eangs.Get_Angle(0);
Node[CurNode].Pivot.EulerAngles.Y = eangs.Get_Angle(1);
Node[CurNode].Pivot.EulerAngles.Z = eangs.Get_Angle(2);
return CurNode++;
}
/***********************************************************************************************
* HierarchySaveClass::Get_Fixup_Transform -- gets the "fixup" transform for a node *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/26/1997 GH : Created. *
*=============================================================================================*/
Matrix3 HierarchySaveClass::Get_Fixup_Transform(int node) const
{
assert(node >= 0);
assert(node < CurNode);
Matrix3 m;
for (int j=0;j<4;j++) {
m.SetRow(j,Point3(Node[node].Fixup.TM[j][0],Node[node].Fixup.TM[j][1],Node[node].Fixup.TM[j][2]));
}
return m;
}
/***********************************************************************************************
* HierarchySaveClass::fixup_matrix -- conditions a matrix *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/26/1997 GH : Created. *
*=============================================================================================*/
Matrix3 HierarchySaveClass::fixup_matrix(const Matrix3 & csrc) const
{
Matrix3 src = csrc; // the GetTrans function is not const correct...
Matrix3 newtm(1);
Point3 trans;
Quat rot;
Point3 scale;
switch (FixupType) {
case MATRIX_FIXUP_NONE:
newtm = src;
break;
case MATRIX_FIXUP_TRANS:
newtm.SetTrans(src.GetTrans());
newtm = Cleanup_Orthogonal_Matrix(newtm);
break;
case MATRIX_FIXUP_TRANS_ROT:
DecomposeMatrix(src,trans,rot,scale);
rot.MakeMatrix(newtm);
newtm.SetTrans(trans);
newtm = Cleanup_Orthogonal_Matrix(newtm);
break;
};
return newtm;
}
/***********************************************************************************************
* HierarchySaveClass::save_header -- writes the header into a W3D file *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/26/1997 GH : Created. *
*=============================================================================================*/
bool HierarchySaveClass::save_header(ChunkSaveClass & csave)
{
if (!csave.Begin_Chunk(W3D_CHUNK_HIERARCHY_HEADER)) {
return false;
}
if (csave.Write(&HierarchyHeader,sizeof(HierarchyHeader)) != sizeof(HierarchyHeader)) {
return false;
}
if (!csave.End_Chunk()) {
return false;
}
return true;
}
/***********************************************************************************************
* HierarchySaveClass::save_pivots -- writes the pivots into a W3D file *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/26/1997 GH : Created. *
*=============================================================================================*/
bool HierarchySaveClass::save_pivots(ChunkSaveClass & csave)
{
if (!csave.Begin_Chunk(W3D_CHUNK_PIVOTS)) {
return false;
}
for (uint32 i=0; i<HierarchyHeader.NumPivots; i++) {
if (csave.Write(&Node[i].Pivot,sizeof(W3dPivotStruct)) != sizeof(W3dPivotStruct)) {
return false;
}
}
if (!csave.End_Chunk()) {
return false;
}
return true;
}
/***********************************************************************************************
* HierarchySaveClass::save_fixups -- writes the fixup transforms into a W3D file *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/26/1997 GH : Created. *
*=============================================================================================*/
bool HierarchySaveClass::save_fixups(ChunkSaveClass & csave)
{
if (!csave.Begin_Chunk(W3D_CHUNK_PIVOT_FIXUPS)) {
return false;
}
for (uint32 i=0; i<HierarchyHeader.NumPivots; i++) {
if (csave.Write(&Node[i].Fixup,sizeof(W3dPivotFixupStruct)) != sizeof(W3dPivotFixupStruct)) {
return false;
}
}
if (!csave.End_Chunk()) {
return false;
}
return true;
}
/***********************************************************************************************
* HierarchySaveClass::load_header -- reads the header from a W3D file *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/26/1997 GH : Created. *
*=============================================================================================*/
bool HierarchySaveClass::load_header(ChunkLoadClass & cload)
{
/*
** Load the header
*/
if (cload.Read(&HierarchyHeader,sizeof(HierarchyHeader)) != sizeof(HierarchyHeader)) {
return false;
}
/*
** Reset the current node count
*/
CurNode = 0;
Node.Resize(HierarchyHeader.NumPivots);
/*
** Initialize everything to a default state (particularly the
** fixup matrices to identity...)
*/
for (unsigned i=0; i < HierarchyHeader.NumPivots; i++) {
memset(&(Node[i]),0,sizeof(HierarchyNodeStruct));
Matrix3 ident(1);
for (int j=0; j<3; j++) {
Point3 row = ident.GetRow(j);
Node[i].Fixup.TM[j][0] = row.x;
Node[i].Fixup.TM[j][1] = row.y;
Node[i].Fixup.TM[j][2] = row.z;
}
}
return true;
}
/***********************************************************************************************
* HierarchySaveClass::load_pivots -- reads the pivots from a W3D file *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/26/1997 GH : Created. *
*=============================================================================================*/
bool HierarchySaveClass::load_pivots(ChunkLoadClass & cload)
{
for (uint32 i=0; i<HierarchyHeader.NumPivots; i++) {
Node[i].MaxNode = NULL;
if (cload.Read(&Node[i].Pivot,sizeof(W3dPivotStruct)) != sizeof(W3dPivotStruct)) {
return false;
}
}
return true;
}
/***********************************************************************************************
* HierarchySaveClass::load_fixups -- reads the fixup transforms from a W3D file *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/26/1997 GH : Created. *
*=============================================================================================*/
bool HierarchySaveClass::load_fixups(ChunkLoadClass & cload)
{
for (uint32 i=0; i<HierarchyHeader.NumPivots; i++) {
if (cload.Read(&Node[i].Fixup,sizeof(W3dPivotFixupStruct)) != sizeof(W3dPivotFixupStruct)) {
return false;
}
}
return true;
}