/*
** Command & Conquer Generals(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 .
*/
/* $Header: /Commando/Code/Tools/max2w3d/MeshDeformSave.cpp 6 11/12/99 11:12a Greg_h $ */
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando / G 3D engine *
* *
* File Name : MeshDeformSafe.CPP
* *
* Programmer : Patrick Smith *
* *
* Start Date : 05/28/99 *
* *
* Last Update :
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "MeshDeform.H"
#include "MeshDeformSave.H"
#include "MeshDeformData.H"
#include "MeshDeformSet.H"
#include "MeshDeformSaveSet.H"
#include "Util.H"
#include "ModStack.H"
#include "MeshBuild.H"
#include "MeshSave.H"
///////////////////////////////////////////////////////////////////////////
//
// Initialize
//
///////////////////////////////////////////////////////////////////////////
void
MeshDeformSaveClass::Initialize
(
MeshBuilderClass &builder,
Object * object,
Mesh & mesh,
Matrix3 * transform
)
{
// Start fresh
Reset ();
//
// Attempt to gain access to the IDerivedObject this node references
//
int test = object->SuperClassID ();
int test2 = GEN_DERIVOB_CLASS_ID;
if ((object != NULL) &&
(object->SuperClassID () == GEN_DERIVOB_CLASS_ID)) {
//
// Loop through all the modifiers and see if we can find the
// Westwood Damage Mesh modifier.
//
IDerivedObject *derived_object = static_cast (object);
int modifier_count = derived_object->NumModifiers ();
bool found = false;
for (int index = 0; (index < modifier_count) && !found; index ++) {
//
// If this is the right modifier, then initialize using the
// data it contains.
//
Modifier *modifier = derived_object->GetModifier (index);
if ((modifier != NULL) && (modifier->ClassID () == _MeshDeformClassID)) {
//
// Attempt to get at the modifier data for this context
//
ModContext *mod_context = derived_object->GetModContext (index);
if ((mod_context != NULL) && (mod_context->localData != NULL)) {
MeshDeformModData *mod_data = static_cast (mod_context->localData);
Initialize (builder, mesh, *mod_data, transform);
}
// Found it!
found = true;
}
}
}
return ;
}
///////////////////////////////////////////////////////////////////////////
//
// Initialize
//
///////////////////////////////////////////////////////////////////////////
void
MeshDeformSaveClass::Initialize
(
MeshBuilderClass & builder,
Mesh & mesh,
MeshDeformModData & mod_data,
Matrix3 * transform
)
{
//
// Loop through all the sets in the modifier
//
for (int index = 0; index < mod_data.Get_Set_Count (); index ++) {
//
// If this set isn't empty then add its data to our list
//
MeshDeformSetClass &deform_set = mod_data.Peek_Set (index);
if (deform_set.Is_Empty () == false) {
//
// Add this set to our list
//
MeshDeformSaveSetClass *save_set = new MeshDeformSaveSetClass;
deform_set.Save (builder, mesh, *save_set, transform);
m_DeformSets.Add (save_set);
}
}
return ;
}
///////////////////////////////////////////////////////////////////////////
//
// Reset
//
///////////////////////////////////////////////////////////////////////////
void
MeshDeformSaveClass::Reset (void)
{
//
// Delete all the damage sets
//
for (int index = 0; index < m_DeformSets.Count (); index ++) {
SAFE_DELETE (m_DeformSets[index]);
}
m_DeformSets.Delete_All ();
return ;
}
///////////////////////////////////////////////////////////////////////////
//
// Export
//
///////////////////////////////////////////////////////////////////////////
bool
MeshDeformSaveClass::Export (ChunkSaveClass &chunk_save)
{
bool retval = true;
if (m_DeformSets.Count() > 0) {
retval = chunk_save.Begin_Chunk (W3D_CHUNK_DEFORM);
if (retval) {
//
// Write the deform header to the file
//
W3dMeshDeform header = { 0 };
header.SetCount = m_DeformSets.Count ();
header.AlphaPasses = m_AlphaPasses;
retval &= (chunk_save.Write (&header, sizeof (header)) == sizeof (header));
if (retval) {
//
// Export all the sets in the deformation
//
retval &= Export_Sets (chunk_save);
}
retval &= chunk_save.End_Chunk ();
}
}
// Return the true/false result code
return retval;
}
///////////////////////////////////////////////////////////////////////////
//
// Export_Sets
//
///////////////////////////////////////////////////////////////////////////
bool
MeshDeformSaveClass::Export_Sets (ChunkSaveClass &chunk_save)
{
bool retval = true;
//
// Loop through all the sets and write them to the file
//
for (int set_index = 0; (set_index < m_DeformSets.Count ()) && retval; set_index ++) {
retval &= chunk_save.Begin_Chunk (W3D_CHUNK_DEFORM_SET);
if (retval) {
//
// Write a chunk of information out for this set
//
MeshDeformSaveSetClass *set_save = m_DeformSets[set_index];
W3dDeformSetInfo set_info = { 0 };
set_info.KeyframeCount = set_save->Get_Keyframe_Count ();
set_info.flags = set_save->Get_Flags ();
retval &= (chunk_save.Write (&set_info, sizeof (set_info)) == sizeof (set_info));
if (retval) {
//
// Export all the keyframes for this chunk
//
retval &= Export_Keyframes (chunk_save, *set_save);
}
retval &= chunk_save.End_Chunk ();
}
}
// Return the true/false result code
return retval;
}
///////////////////////////////////////////////////////////////////////////
//
// Export_Keyframes
//
///////////////////////////////////////////////////////////////////////////
bool
MeshDeformSaveClass::Export_Keyframes
(
ChunkSaveClass & chunk_save,
MeshDeformSaveSetClass &set_save
)
{
bool retval = true;
//
// Loop through all the keyframes in the set
//
int count = set_save.Get_Keyframe_Count ();
for (int keyframe_index = 0; (keyframe_index < count) && retval; keyframe_index ++) {
//
// Write a chunk of information out for this keyframe
//
retval &= chunk_save.Begin_Chunk (W3D_CHUNK_DEFORM_KEYFRAME);
if (retval) {
W3dDeformKeyframeInfo keyframe_info = { 0 };
keyframe_info.DeformPercent = set_save.Get_Deform_State (keyframe_index);
keyframe_info.DataCount = set_save.Get_Deform_Data_Count (keyframe_index);
retval &= (chunk_save.Write (&keyframe_info, sizeof (keyframe_info)) == sizeof (keyframe_info));
if (retval) {
//
// Loop through all the verticies in this keyframe
//
int data_count = set_save.Get_Deform_Data_Count (keyframe_index);
for (int index = 0; (index < data_count) && retval; index ++) {
MeshDeformSaveSetClass::DEFORM_DATA &data = set_save.Get_Deform_Data (keyframe_index, index);
//
// Write a chunk of information out for this vertex
//
retval &= chunk_save.Begin_Chunk (W3D_CHUNK_DEFORM_DATA);
if (retval) {
W3dDeformData data_struct = { 0 };
data_struct.VertexIndex = data.vert_index;
data_struct.Position.X = data.position.x;
data_struct.Position.Y = data.position.y;
data_struct.Position.Z = data.position.z;
data_struct.Color.R = data.color.x * 255;
data_struct.Color.G = data.color.y * 255;
data_struct.Color.B = data.color.z * 255;
// If we are using vertex alpha instead of vertex color, then convert
// the v-color into an alpha setting
data_struct.Color.A = 255;
if (m_AlphaPasses != 0) {
data_struct.Color.A = (data_struct.Color.R + data_struct.Color.G + data_struct.Color.B) / 3.0F;
}
retval &= (chunk_save.Write (&data_struct, sizeof (data_struct)) == sizeof (data_struct));
retval &= chunk_save.End_Chunk ();
}
}
}
retval &= chunk_save.End_Chunk ();
}
}
// Return the true/false result code
return retval;
}
///////////////////////////////////////////////////////////////////////////
//
// Re_Index
//
///////////////////////////////////////////////////////////////////////////
/*void
MeshDeformSaveClass::Re_Index (MeshBuilderClass &builder)
{
DynamicVectorClass temp_list;
//
// Reindex each set of deform data
//
for (int set_index = 0; set_index < m_DeformSets.Count (); set_index ++) {
MeshDeformSaveSetClass *set_save = m_DeformSets[set_index];
//
// Loop through all the deform entries in this set
//
for (int keyframe_index = 0; keyframe_index < set_save->Get_Keyframe_Count (); keyframe_index ++) {
temp_list.Delete_All ();
for (int index = 0; index < set_save->Get_Deform_Data_Count (keyframe_index); index ++) {
MeshDeformSaveSetClass::DEFORM_DATA &data = set_save->Get_Deform_Data (keyframe_index, index);
//
// Now try to find the 'W3D' index of this vertex (its different than the max version).
//
//bool found = false;
for (int vert_index = 0; vert_index < builder.Get_Vertex_Count (); vert_index++) {
MeshBuilderClass::VertClass &vert = builder.Get_Vertex (vert_index);
//
// Reindex this vertex if its the one we are looking for.
//
if (vert.Id == (int)data.vert_index) {
MeshDeformSaveSetClass::DEFORM_DATA new_data = data;
new_data.vert_index = vert_index;
temp_list.Add (new_data);
//data.vert_index = vert_index;
//found = true;
}
}
}
set_save->Replace_Deform_Data (keyframe_index, temp_list);
}
}
return ;
}*/
///////////////////////////////////////////////////////////////////////////
//
// Does_Deformer_Modify_DCG
//
///////////////////////////////////////////////////////////////////////////
bool
MeshDeformSaveClass::Does_Deformer_Modify_DCG (void)
{
bool retval = false;
//
// Loop through all the sets
//
for (int set_index = 0; (set_index < m_DeformSets.Count ()) && !retval; set_index ++) {
MeshDeformSaveSetClass *set_save = m_DeformSets[set_index];
if (set_save) {
//
// Loop through all the keyframes in this set
//
int count = set_save->Get_Keyframe_Count ();
for (int keyframe_index = 0; (keyframe_index < count) && !retval; keyframe_index ++) {
//
// Loop through all the entries in this keyframe
//
int data_count = set_save->Get_Deform_Data_Count (keyframe_index);
for (int index = 0; (index < data_count) && !retval; index ++) {
MeshDeformSaveSetClass::DEFORM_DATA &data = set_save->Get_Deform_Data (keyframe_index, index);
//
// If the color is not 'white' then we will
// modify the DCG array.
//
if ((data.color.x != 1) ||
(data.color.y != 1) ||
(data.color.z != 1)) {
retval = true;
}
}
}
}
}
// Return the true/false result code
return retval;
}