| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 |
- /*
- ** 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/>.
- */
- /***********************************************************************************************
- *** 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 ***
- ***********************************************************************************************
- * *
- * Project Name : Renegade / G *
- * *
- * $Archive:: /Commando/Code/Tools/max2w3d/hlodsave.cpp $*
- * *
- * $Author:: Greg_h $*
- * *
- * $Modtime:: 11/07/00 5:24p $*
- * *
- * $Revision:: 9 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * -- The constructor builds the whole HLOD tree in a *
- * -- Destructor blows away the dynamic memory we used. *
- * -- Method called when saving to a W3D file. Saves the chunks *
- * -- Write the header *
- * -- Writes each LOD *
- * -- Writes the mesh to bone connectivity info for each mesh in an LOD. *
- * HLodSaveClass::save_aggregate_array -- save the aggregates (if any) *
- * HLodSaveClass::save_proxy_array -- save the array of proxies (if any) *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "hlodsave.h"
- #include "meshcon.h"
- #include "errclass.h"
- #include "util.h"
- #include "w3dappdata.h"
- #include "wwmath.h" // NO_MAX_SCREEN_SIZE
- #include "exportlog.h"
- /* Behold, the applicable snippets of code from w3d_file.h that are applicable to this module!
- W3D_CHUNK_HLOD =0x00000700, // description of an HLod object (see HLodClass)
- W3D_CHUNK_HLOD_HEADER, // general information such as name and version
- W3D_CHUNK_HLOD_LOD_ARRAY, // wrapper around the array of objects for each level of detail
- W3D_CHUNK_HLOD_LOD_ARRAY_HEADER, // info on the objects in this level of detail array
- W3D_CHUNK_HLOD_SUB_OBJECT, // an object in this level of detail array
- struct W3dHLodHeaderStruct
- {
- uint32 Version;
- uint32 LodCount;
- char Name[W3D_NAME_LEN];
- char HierarchyName[W3D_NAME_LEN]; // name of the hierarchy tree to use (\0 if none)
- };
- struct W3dHLodArrayHeaderStruct
- {
- uint32 ModelCount;
- float32 MaxScreenSize; // if model is bigger than this, switch to higher lod.
- };
- struct W3dHLodSubObjectStruct
- {
- uint32 BoneIndex;
- char Name[W3D_NAME_LEN*2];
- };
- */
- /***********************************************************************************************
- * HLodSaveClass -- The constructor builds the whole HLOD tree in a form suitable for saving *
- * to a W3D file. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 9/14/1999 AJA : Created. *
- *=============================================================================================*/
- HLodSaveClass::HLodSaveClass (MeshConnectionsClass **connections, int lod_count, TimeValue CurTime,
- char *name, const char *htree_name, Progress_Meter_Class &meter,
- INodeListClass *origin_list)
- : lod_array(NULL)
- {
- /*
- ** Fill in the W3dHLodHeaderStruct
- */
- header.Version = W3D_CURRENT_HLOD_VERSION;
- header.LodCount = lod_count;
- Set_W3D_Name(header.Name, name);
- Set_W3D_Name(header.HierarchyName, htree_name);
- ExportLog::printf("\nExporting HLOD object: %s\n",header.Name);
- ExportLog::printf(" lod count: %d\n",header.LodCount);
- /*
- ** Create the array of stuff for each LOD.
- */
- lod_array = new HLodArrayEntry[lod_count];
- if (!lod_array)
- throw ErrorClass("Out Of Memory!");
- int i;
- for (i = 0; i < lod_count; i++)
- {
-
- ExportLog::printf(" Exporting LOD Array %d\n",i);
-
- INode *origin = connections[i]->Get_Origin();
- int sub_obj_count = connections[i]->Get_Sub_Object_Count();
- lod_array[i].Allocate_Sub_Objects(sub_obj_count);
- lod_array[i].header.ModelCount = sub_obj_count;
- float screen_size = NO_MAX_SCREEN_SIZE;
- if (origin)
- origin->GetUserPropFloat("MaxScreenSize", screen_size);
- lod_array[i].header.MaxScreenSize = screen_size;
- /*
- ** Create the info per mesh in this LOD.
- */
- int j;
- W3dHLodSubObjectStruct *sub_obj = lod_array[i].sub_obj;
- ExportLog::printf(" sub-object count: %d\n",sub_obj_count);
- for (j = 0; j < sub_obj_count; j++)
- {
- char *mesh_name;
- int bone_index;
- INode *mesh_node;
- if (!connections[i]->Get_Sub_Object_Data(j, &mesh_name, &bone_index, &mesh_node))
- throw ErrorClass("Model %s is missing connection data!", name);
- strcpy(sub_obj[j].Name, mesh_name);
- sub_obj[j].BoneIndex = bone_index;
- ExportLog::printf(" Sub Object: %s Bone: %d\n",mesh_name,bone_index);
- }
- }
- /*
- ** Copy aggregates from the Top-Level LOD
- */
- int agg_count = connections[lod_count-1]->Get_Aggregate_Count();
- aggregate_array.Allocate_Sub_Objects(agg_count);
- aggregate_array.header.ModelCount = agg_count;
- aggregate_array.header.MaxScreenSize = 0.0f;
-
- ExportLog::printf(" Exporting Aggregates:\n");
- ExportLog::printf(" aggregate count: %d\n",agg_count);
- for (i=0; i<agg_count; i++) {
- char *mesh_name;
- int bone_index;
- INode *mesh_node;
- connections[lod_count-1]->Get_Aggregate_Data(i, &mesh_name, &bone_index, &mesh_node);
- W3dHLodSubObjectStruct & sub_obj = aggregate_array.sub_obj[i];
- strcpy(sub_obj.Name, mesh_name);
- sub_obj.BoneIndex = bone_index;
- ExportLog::printf(" Aggregate object: %s Bone: %d\n",mesh_name,bone_index);
- }
- /*
- ** Copy the proxy objects from the Top-Level LOD
- */
- int proxy_count = connections[lod_count-1]->Get_Proxy_Count();
- proxy_array.Allocate_Sub_Objects(proxy_count);
- proxy_array.header.ModelCount = proxy_count;
- proxy_array.header.MaxScreenSize = 0.0f;
-
- ExportLog::printf(" Exporting Proxies\n");
- ExportLog::printf(" proxy count: %d\n",proxy_count);
- for (i=0; i<proxy_count; i++) {
-
- char *mesh_name;
- int bone_index;
- INode *mesh_node;
- connections[lod_count-1]->Get_Proxy_Data(i, &mesh_name, &bone_index, &mesh_node);
- W3dHLodSubObjectStruct & sub_obj = proxy_array.sub_obj[i];
- strcpy(sub_obj.Name, mesh_name);
- sub_obj.BoneIndex = bone_index;
- ExportLog::printf(" Proxy object: %s Bone: %d\n",mesh_name,bone_index);
- }
- }
- /***********************************************************************************************
- * ~HLodSaveClass -- Destructor blows away the dynamic memory we used. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 9/14/1999 AJA : Created. *
- *=============================================================================================*/
- HLodSaveClass::~HLodSaveClass (void)
- {
- if (lod_array)
- {
- delete []lod_array;
- lod_array = NULL;
- }
- }
- /***********************************************************************************************
- * HLodSaveClass::Save -- Method called when saving to a W3D file. Saves the chunks that *
- * define a HLOD. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 9/14/1999 AJA : Created. *
- *=============================================================================================*/
- bool HLodSaveClass::Save(ChunkSaveClass &csave)
- {
- if (!lod_array)
- return false;
- if (!csave.Begin_Chunk(W3D_CHUNK_HLOD))
- return false;
- if (!save_header(csave))
- return false;
- if (!save_lod_arrays(csave))
- return false;
- if (!save_aggregate_array(csave))
- return false;
- if (!save_proxy_array(csave))
- return false;
- if (!csave.End_Chunk())
- return false;
- return true;
- }
- /***********************************************************************************************
- * HLodSaveClass::save_header -- Write the header *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 9/14/1999 AJA : Created. *
- *=============================================================================================*/
- bool HLodSaveClass::save_header (ChunkSaveClass &csave)
- {
- if (!csave.Begin_Chunk(W3D_CHUNK_HLOD_HEADER))
- return false;
- if (csave.Write(&header, sizeof(header)) != sizeof(header))
- return false;
- if (!csave.End_Chunk())
- return false;
- return true;
- }
- /***********************************************************************************************
- * HLodSaveClass::save_lod_arrays -- Writes each LOD *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 9/14/1999 AJA : Created. *
- *=============================================================================================*/
- bool HLodSaveClass::save_lod_arrays(ChunkSaveClass &csave)
- {
- for (int i = 0; i < header.LodCount; i++)
- {
- if (!csave.Begin_Chunk(W3D_CHUNK_HLOD_LOD_ARRAY))
- return false;
- if (!save_sub_object_array(csave, lod_array[i]))
- return false;
- if (!csave.End_Chunk())
- return false;
- }
- return true;
- }
- /***********************************************************************************************
- * HLodSaveClass::save_aggregate_array -- save the aggregates (if any) *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 10/25/2000 gth : Created. *
- *=============================================================================================*/
- bool HLodSaveClass::save_aggregate_array(ChunkSaveClass & csave)
- {
- if (aggregate_array.num_sub_objects > 0) {
- if (!csave.Begin_Chunk(W3D_CHUNK_HLOD_AGGREGATE_ARRAY))
- return false;
- if (!save_sub_object_array(csave, aggregate_array))
- return false;
- if (!csave.End_Chunk())
- return false;
- }
- return true;
- }
- /***********************************************************************************************
- * HLodSaveClass::save_proxy_array -- save the array of proxies (if any) *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 10/27/2000 gth : Created. *
- *=============================================================================================*/
- bool HLodSaveClass::save_proxy_array(ChunkSaveClass & csave)
- {
- if (proxy_array.num_sub_objects > 0) {
- if (!csave.Begin_Chunk(W3D_CHUNK_HLOD_PROXY_ARRAY))
- return false;
- if (!save_sub_object_array(csave, proxy_array))
- return false;
- if (!csave.End_Chunk())
- return false;
- }
- return true;
- }
- /***********************************************************************************************
- * HLodSaveClass::save_sub_object_array -- Writes the mesh to bone connectivity info for each *
- * mesh in an LOD. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 9/14/1999 AJA : Created. *
- *=============================================================================================*/
- bool HLodSaveClass::save_sub_object_array(ChunkSaveClass &csave, const HLodArrayEntry & array)
- {
- if (!csave.Begin_Chunk(W3D_CHUNK_HLOD_SUB_OBJECT_ARRAY_HEADER))
- return false;
-
- if (csave.Write(&(array.header), sizeof(array.header)) != sizeof(array.header))
- return false;
- if (!csave.End_Chunk())
- return false;
- for (int j = 0; j < array.num_sub_objects; j++)
- {
- if (!csave.Begin_Chunk(W3D_CHUNK_HLOD_SUB_OBJECT))
- return false;
- if (csave.Write(&(array.sub_obj[j]), sizeof(array.sub_obj[j])) != sizeof(array.sub_obj[j]))
- return false;
- if (!csave.End_Chunk())
- return false;
- }
- return true;
- }
|