/********************************************************************************************** * * Copyright (c) DreamWorks Interactive. 1996-1997 * * Contents: Implementation of classes for managing object definition information. * * Bugs: * ********************************************************************************************** * * $Log:: /JP2_PC/Source/Tools/GroffExp/ObjectDef.cpp $ * * 14 7/15/97 6:58p Gstull * Made organizational changes to make management of the exporter more reasonable. * * 13 7/14/97 3:36p Gstull * Made substantial changes to support tasks for the August 18th milestone for attributes, * object representation, geometry checking, dialog interfacing, logfile support, string tables * and string support. * *********************************************************************************************/ #include #include #include #include #include #include "StandardTypes.hpp" #include "Lib/Sys/SysLog.hpp" #include "ObjectDef.hpp" #include "Lib/Groff/FileIO.hpp" #include "Tools/GroffExp/GUIInterface.hpp" extern CGUIInterface guiInterface; CSysLog slExportLog; //********************************************************************************************** // CObjectDef::CObjectDef(const char *str_object_name) { // Setup the object name. estrObjectName = str_object_name; // Set the ID number of this node. iID = -1; // Initialize everything to sane values. podNext = 0; // Set the positional information to the correct default values. memset(&uv3DefaultColor, 128, sizeof(uvector3)); // Initialize the geometric info. uVertexCount = 0; afv3Vertex = 0; uFaceCount = 0; auv3Face = 0; uFaceNormalCount = 0; afv3FaceNormal = 0; afv3VertexNormal = 0; // Initialize the mapping info. uTextureVertexCount = 0; afv2TextureVertex = 0; uTextureFaceCount = 0; auv3TextureFace = 0; auFaceMaterialIndex = 0; uMaterialCount = 0; astrTextureMap = 0; astrOpacityMap = 0; astrBumpMap = 0; auv3MeanColor = 0; alvLightingValues = 0; uWarnings = 0; uErrors = 0; } //********************************************************************************************** // void CObjectDef::Destroy() { // Deallocate all allocated memory estrObjectName = ""; // Reset the next node pointer. podNext = 0; // Reset the node ID number. iID = -1; // Set the positional information to the correct default values. memset(&uv3DefaultColor, 128, sizeof(uvector3)); fUniformScale = 1.0f; // Are there any vertices? if (afv3Vertex != 0) { // Deallocate the object vertex list delete [] afv3Vertex; afv3Vertex = 0; } // Are there any faces? if (auv3Face != 0) { // Deallocate the object face list delete [] auv3Face; auv3Face = 0; } // Are there any face normals. if (afv3FaceNormal != 0) { // Deallocate the normal list delete [] afv3FaceNormal; afv3FaceNormal = 0; } // Are there any vertex normals? if (afv3VertexNormal != 0) { // Dealocate the texture vertex list delete [] afv3VertexNormal; afv3VertexNormal = 0; } // Are there any texture vertices? if (afv2TextureVertex != 0) { // Dealocate the texture vertex list delete [] afv2TextureVertex; afv2TextureVertex = 0; } // Are there any texture faces? if (auv3TextureFace != 0) { // Deallocate the texture face list delete [] auv3TextureFace; auv3TextureFace = 0; } // Is there a face/material index list. if (auFaceMaterialIndex != 0) { // Dealocate the face material index list delete [] auFaceMaterialIndex; auFaceMaterialIndex = 0; } // Was a mean color array allocated? if (auv3MeanColor != 0) { // Dealocate the face material index list delete [] auv3MeanColor; auv3MeanColor = 0; } // Was a lighting values list allocated? if (alvLightingValues != 0) { // Deallocate the lighting values list. delete [] alvLightingValues; alvLightingValues = 0; } // Are there any materials in the list. for (uint u_i = 0; u_i < uMaterialCount; u_i++) { // Were any texture maps allocated? if (astrTextureMap != 0) { // Yes! Does this material have a texture map? if (astrTextureMap[u_i] != 0) { // Yes! Deallocate it from the list. delete [] astrTextureMap[u_i]; astrTextureMap[u_i] = 0; } } // Were any opacity maps allocated? if (astrOpacityMap != 0) { // Yes! Does this material have an opacity map? if (astrOpacityMap[u_i] != 0) { // Yes! Deallocate it from the list. delete [] astrOpacityMap[u_i]; astrOpacityMap[u_i] = 0; } } // Were any bump maps allocated? if (astrBumpMap != 0) { // Yes! Does this material have a bump map? if (astrBumpMap[u_i] != 0) { // Yes! Deallocate it from the list. delete [] astrBumpMap[u_i]; astrBumpMap[u_i] = 0; } } } // Now free each of the lists, if they were allocated. if (astrTextureMap != 0) { delete [] astrTextureMap; astrTextureMap = 0; } if (astrOpacityMap != 0) { delete [] astrOpacityMap; astrOpacityMap = 0; } if (astrBumpMap != 0) { delete [] astrBumpMap; astrBumpMap = 0; } // Set all the counts to 0. uMaterialCount = 0; uVertexCount = 0; uFaceCount = 0; uFaceNormalCount = 0; uVertexNormalCount = 0; uTextureVertexCount = 0; uTextureFaceCount = 0; // Set all the warning and error counters to 0. uWarnings = 0; uErrors = 0; } //********************************************************************************************** // CObjectDef::~CObjectDef() { Destroy(); } //********************************************************************************************** // void CObjectDef::Position ( Point3& p3_position ) { p3Position = p3_position; } //********************************************************************************************** // Point3& CObjectDef::p3GetPosition ( ) { return p3Position; } //********************************************************************************************** // void CObjectDef::Rotation ( Point3& p3_rotation ) { p3Rotation = p3_rotation; EulerToQuat(&p3_rotation.x, qRotation); } //********************************************************************************************** // Point3& CObjectDef::p3GetRotation ( ) { return p3Rotation; } //********************************************************************************************** // void CObjectDef::Rotation ( Quat& q_rotation ) { qRotation = q_rotation; QuatToEuler(qRotation, &p3Rotation.x); } //********************************************************************************************** // Quat& CObjectDef::qGetRotation ( ) { return qRotation; } //********************************************************************************************** // void CObjectDef::Scale ( float f_scale_value ) { fUniformScale = f_scale_value; } //********************************************************************************************** // float CObjectDef::fGetScale ( ) { return fUniformScale; } //********************************************************************************************** // void CObjectDef::PivotOffset ( Point3& p3_pivot_offset ) { p3PivotOffset = p3_pivot_offset; } //********************************************************************************************** // Point3& CObjectDef::p3GetPivotOffset ( ) { return p3PivotOffset; } //********************************************************************************************** // void CObjectDef::PivotRotation ( Quat& q_pivot_rotation ) { q_pivot_rotation = q_pivot_rotation; } //********************************************************************************************** // Quat& CObjectDef::qGetPivotRotation ( ) { return qPivotRotation; } //********************************************************************************************** // void CObjectDef::BoundingBox ( Box3& bx3_bounding_box ) { bx3BoundingBox = bx3_bounding_box; } //********************************************************************************************** // Box3& CObjectDef::bx3GetBoundingBox ( ) { return bx3BoundingBox; } //********************************************************************************************** // void CObjectDef::ObjectTM ( Matrix3& m3_matrix ) { m3ObjectTM = m3_matrix; } //********************************************************************************************** // Matrix3& CObjectDef::m3GetObjectTM ( ) { return m3ObjectTM; } //********************************************************************************************** // void CObjectDef::NodeTM ( Matrix3& m3_matrix ) { m3NodeTM = m3_matrix; } //********************************************************************************************** // Matrix3& CObjectDef::m3GetNodeTM ( ) { return m3NodeTM; } //********************************************************************************************** // void CObjectDef::ParentTM ( Matrix3& m3_matrix ) { m3ParentTM = m3_matrix; } //********************************************************************************************** // Matrix3& CObjectDef::m3GetParentTM ( ) { return m3ParentTM; } //********************************************************************************************** // void CObjectDef::RelativeTM ( Matrix3& m3_matrix ) { m3RelativeTM = m3_matrix; } //********************************************************************************************** // Matrix3& CObjectDef::m3GetRelativeTM ( ) { return m3RelativeTM; } //********************************************************************************************** // void CObjectDef::TMBeforeWSM(Matrix3& m3_matrix) { m3TMBeforeWSM = m3_matrix; } //********************************************************************************************** // Matrix3& CObjectDef::m3GetTMBeforeWSM() { return m3TMBeforeWSM; } //********************************************************************************************** // void CObjectDef::TMAfterWSM(Matrix3& m3_matrix) { m3TMAfterWSM = m3_matrix; } //********************************************************************************************** // Matrix3& CObjectDef::m3GetTMAfterWSM() { return m3TMAfterWSM; } //********************************************************************************************** // bool CObjectDef::VertexCount(uint u_vertex_count) { // Allocate memory for the vertex list afv3Vertex = new fvector3[u_vertex_count]; // Were we successful? if (afv3Vertex == 0) { // Log an error to the export log slExportLog.Printf("Error: Unable to allocate vertex list of size %d for object: %s\n", u_vertex_count, estrObjectName.strData()); // No! Return an error. return false; } // Setup the vertex count. uVertexCount = u_vertex_count; // Initialize the vertex list to known values; for (uint u_i = 0; u_i < u_vertex_count; u_i++) { // Set each component to 0.0 afv3Vertex[u_i].X = 0.0f; afv3Vertex[u_i].Y = 0.0f; afv3Vertex[u_i].Z = 0.0f; } // Return a successful result. return true; } //********************************************************************************************** // bool CObjectDef::Vertex(uint u_vertex_index, float f_x, float f_y, float f_z) { // Is the specified index in range? if (u_vertex_index >= uVertexCount || afv3Vertex == 0) { // Range error. Return an error. return false; } // The index is in range, so setup the vector afv3Vertex[u_vertex_index].X = f_x; afv3Vertex[u_vertex_index].Y = f_y; afv3Vertex[u_vertex_index].Z = f_z; // Return a successful result. return true; } //********************************************************************************************** // bool CObjectDef::FaceCount(uint u_face_count) { // Allocate memory for the face list. auv3Face = new uvector3[u_face_count]; // Were we successful? if (auv3Face == 0) { // Log an error to the export log slExportLog.Printf("Error: Unable to allocate face list of size %d for object: %s\n", u_face_count, estrObjectName.strData()); // No! Return an error. return false; } // Setup the face count. uFaceCount = u_face_count; // Initialize all the face list for (uint u_i = 0; u_i < u_face_count; u_i++) { // Set each component to 0. auv3Face[u_i].X = 0; auv3Face[u_i].Y = 0; auv3Face[u_i].Z = 0; } // Return a successful result. return true; } //********************************************************************************************** // bool CObjectDef::Face(uint u_face_index, uint u_v0, uint u_v1, uint u_v2) { // Is the specified index in range? if (u_face_index >= uFaceCount || auv3Face == 0) { // Range error. Return an error. return false; } // Check and make sure there are no degenerate faces if (u_v0 == u_v1 || u_v1 == u_v2 || u_v0 == u_v2) { // Bummer! This should not happen. 3DS Max is generating degenerate // polygons where at least two of the three vertices are the same. // Log an error to the export log slExportLog.Printf("Error: Degenerate polygon detected in object: %s\n", estrObjectName.strData()); slExportLog.Printf("Polygon: %d, Vertices: (%d, %d, %d)\n\n", u_face_index, u_v0, u_v1, u_v2); // Increment the counters for keeping track of the errors. uErrors++; } // The index is in range, so setup the vector. auv3Face[u_face_index].X = u_v0; auv3Face[u_face_index].Y = u_v1; auv3Face[u_face_index].Z = u_v2; // Return a successful result. return true; } //********************************************************************************************** // bool CObjectDef::VertexNormalCount(uint u_face_count) { // Allocate memory for the face list afv3VertexNormal = new fvector3[u_face_count * 3]; // Were we successful? if (afv3VertexNormal == 0) { // Log an error to the export log slExportLog.Printf("Error: Unable to allocate vertex normal list of size %d for object: %s\n", u_face_count, estrObjectName.strData()); // No! Return an error. return false; } // Setup the number of normals. The number of faces * 3 vertices per face. uVertexNormalCount = u_face_count * 3; // Initialize all the face list for (uint u_i = 0; u_i < u_face_count * 3; u_i++) { // Set each component to 0 afv3VertexNormal[u_i].X = 0.0f; afv3VertexNormal[u_i].Y = 0.0f; afv3VertexNormal[u_i].Z = 0.0f; } // Return a successful result. return true; } //********************************************************************************************** // bool CObjectDef::VertexNormal(uint u_face_index, uint u_vertex_index, float f_x, float f_y, float f_z) { // Setup a variable which defines the into the vertex normal array. const uint u_offset = u_face_index * 3 + u_vertex_index; // Is the specified index in range? if (u_offset >= uVertexNormalCount || afv3VertexNormal == 0) { // Range error. Return an error. return false; } // The index is in range, so setup the vector afv3VertexNormal[u_offset].X = f_x; afv3VertexNormal[u_offset].Y = f_y; afv3VertexNormal[u_offset].Z = f_z; // Return a successful result. return true; } //********************************************************************************************** // bool CObjectDef::FaceNormalCount(uint u_face_count) { // Allocate memory for the face list afv3FaceNormal = new fvector3[u_face_count]; // Were we successful? if (afv3FaceNormal == 0) { // Log an error to the export log slExportLog.Printf("Error: Unable to allocate face normal list of size %d for object: %s\n", u_face_count, estrObjectName.strData()); // No! Return an error. return false; } // Setup the number of normals. uFaceNormalCount = u_face_count; // Initialize all the face list for (uint u_i = 0; u_i < u_face_count; u_i++) { // Set each component to 0 afv3FaceNormal[u_i].X = 0.0f; afv3FaceNormal[u_i].Y = 0.0f; afv3FaceNormal[u_i].Z = 0.0f; } // Return a successful result. return true; } //********************************************************************************************** // bool CObjectDef::FaceNormal(uint u_face_index, float f_x, float f_y, float f_z) { // Is the specified index in range? if (u_face_index >= uFaceCount || afv3FaceNormal == 0) { // Range error. Return an error. return false; } // The index is in range, so setup the vector afv3FaceNormal[u_face_index].X = f_x; afv3FaceNormal[u_face_index].Y = f_y; afv3FaceNormal[u_face_index].Z = f_z; // Return a successful result. return true; } //********************************************************************************************** // bool CObjectDef::TextureVertexCount(uint u_texture_vertex_count) { // Allocate memory for the texture vertex list afv2TextureVertex = new fvector2[u_texture_vertex_count]; // Were we successful? if (afv2TextureVertex == 0) { // Log an error to the export log slExportLog.Printf("Error: Unable to allocate texture vertex list of size %d for object: %s\n", u_texture_vertex_count, estrObjectName.strData()); // No! Return an error. return false; } uTextureVertexCount = u_texture_vertex_count; // Initialize the texture vertex list for (uint u_i = 0; u_i < u_texture_vertex_count; u_i++) { // Set each component to 0.0 afv2TextureVertex[u_i].X = 0.0f; afv2TextureVertex[u_i].Y = 0.0f; } // Return a successful result. return true; } //********************************************************************************************** // bool CObjectDef::TextureVertex(uint u_texture_vertex_index, float f_u, float f_v) { // Is the specified index in range? if (u_texture_vertex_index >= uTextureVertexCount || afv2TextureVertex == 0) { // Range error. Return an error. return false; } // The index is in range, so setup the vector afv2TextureVertex[u_texture_vertex_index].X = f_u; afv2TextureVertex[u_texture_vertex_index].Y = f_v; // Return a successful result. return true; } //********************************************************************************************** // bool CObjectDef::TextureFaceCount(uint u_face_count) { // Allocate memory for the texture vertex list auv3TextureFace = new uvector3[u_face_count]; // Were we successful? if (auv3TextureFace == 0) { // Log an error to the export log slExportLog.Printf("Error: Unable to allocate texture face list of size %d for object: %s\n", u_face_count, estrObjectName.strData()); // No! Return an error. return false; } uTextureFaceCount = u_face_count; // Setup an array to keep track of the material index for each face. auFaceMaterialIndex = new uint[u_face_count]; // Were we successful? if (auFaceMaterialIndex == 0) { // No! Return an error. return false; } // Initialize the texture face list and the material index list. for (uint u_i = 0; u_i < u_face_count; u_i++) { // Set each component to 0.0 auv3TextureFace[u_i].X = 0; auv3TextureFace[u_i].Y = 0; auv3TextureFace[u_i].Z = 0; // Initialize this material index to an invalid value. auFaceMaterialIndex[u_i] = 0xFFFFFFFF; } // Return a successful result. return true; } //********************************************************************************************** // bool CObjectDef::TextureFace(uint u_face_index, uint u_v0, uint u_v1, uint u_v2) { bool bResult = true; // Is the specified index in range? if (u_face_index >= uTextureFaceCount || auv3TextureFace == 0) { // Range error. Return an error. return false; } // Check and make sure there are no degenerate texture faces if (u_v0 == u_v1 || u_v1 == u_v2 || u_v0 == u_v2) { // Bummer! This should not happen. 3DS Max is generating degenerate // polygons where at least two of the three vertices are the same. // Log an error to the export log slExportLog.Printf("Error: Degenerate texture face detected in object: %s\n", estrObjectName.strData()); slExportLog.Printf("Face: %d, Texture vertices: (%d, %d, %d)\n", u_face_index, u_v0, u_v1, u_v2); // Increment the counters for keeping track of the errors. uErrors++; // Return an error bResult = false; } // The index is in range, so setup the vector auv3TextureFace[u_face_index].X = u_v0; auv3TextureFace[u_face_index].Y = u_v1; auv3TextureFace[u_face_index].Z = u_v2; // Return the result. return bResult; } //********************************************************************************************** // void CObjectDef::LightingValues(uint u_material_index, SLightingValues* plv_lighting_values) { // Was a lighting value array allocated? if (alvLightingValues != 0) { // Is the material index value in range? if (u_material_index < uMaterialCount) { alvLightingValues[u_material_index].fAmbient = plv_lighting_values->fAmbient; alvLightingValues[u_material_index].fDiffuse = plv_lighting_values->fDiffuse; alvLightingValues[u_material_index].fSpecular = plv_lighting_values->fSpecular; alvLightingValues[u_material_index].fOpacity = plv_lighting_values->fOpacity; alvLightingValues[u_material_index].fBumpiness = plv_lighting_values->fBumpiness; } } } //********************************************************************************************** // void CObjectDef::MeanColor(uint u_material_index, uint8 u1_blue, uint8 u1_green, uint8 u1_red) { // Was a mean color array allocated? if (auv3MeanColor != 0) { // Is the material index value in range? if (u_material_index < uMaterialCount) { auv3MeanColor[u_material_index].X = u1_blue; auv3MeanColor[u_material_index].Y = u1_green; auv3MeanColor[u_material_index].Z = u1_red; } } else { // Log an error to the export log slExportLog.Printf("Warning: Attempted to assign mean color with index %d to null list for object: %s\n", u_material_index, estrObjectName.strData()); } } //********************************************************************************************** // void CObjectDef::DefaultColor(uint8 u1_blue, uint8 u1_green, uint8 u1_red) { uv3DefaultColor.X = u1_blue; uv3DefaultColor.Y = u1_green; uv3DefaultColor.Z = u1_red; } //********************************************************************************************** // bool CObjectDef::FaceMaterialIndex(uint u_face_index, uint u_material_index) { // Is the specified index in range? if (u_face_index >= uTextureFaceCount || auFaceMaterialIndex == 0) { // Range error. Return an error. return false; } // // Is the material index in range? // // 11/05/96 - Greg Stull // // Removed the code to range check the materials because single materials are allowed to // have materials ID's which are out of range, as absurd as this might sound. This // condition is later resolved by the validation code in the geomety class. // // Add the index into the list auFaceMaterialIndex[u_face_index] = u_material_index; // Return a successful result. return true; } //********************************************************************************************** // bool CObjectDef::MaterialCount(uint u_material_count) { // Allocate memory for the texture map list. astrTextureMap = new char *[u_material_count]; // Were we successful? if (astrTextureMap == 0) { // Log an error to the export log slExportLog.Printf("Error: Unable to allocate texture map list of size %d for object: %s\n", u_material_count, estrObjectName.strData()); // No! Return an error. return false; } // Allocate memory for the texture map list. astrOpacityMap = new char *[u_material_count]; // Were we successful? if (astrOpacityMap == 0) { // Log an error to the export log slExportLog.Printf("Error: Unable to allocate opacity map list of size %d for object: %s\n", u_material_count, estrObjectName.strData()); // No! Deallocate the texture map list. delete [] astrTextureMap; astrTextureMap = 0; // Return an error. return false; } // Allocate memory for the texture map list. astrBumpMap = new char *[u_material_count]; // Were we successful? if (astrBumpMap == 0) { // Log an error to the export log slExportLog.Printf("Error: Unable to allocate bump map list of size %d for object: %s\n", u_material_count, estrObjectName.strData()); // No! Deallocate the texture map list. delete [] astrTextureMap; astrTextureMap = 0; // No! Deallocate the texture map list. delete [] astrOpacityMap; astrOpacityMap = 0; // No! Return an error. return false; } // Allocate memory for the texture map list. alvLightingValues = new SLightingValues[u_material_count]; // Were we successful? if (alvLightingValues == 0) { // Log an error to the export log slExportLog.Printf("Error: Unable to allocate lighting values list of size %d for object: %s\n", u_material_count, estrObjectName.strData()); // No! Deallocate the texture map list. delete [] astrTextureMap; astrTextureMap = 0; // No! Deallocate the texture map list. delete [] astrOpacityMap; astrOpacityMap = 0; // No! Deallocate the texture map list. delete [] astrBumpMap; astrBumpMap = 0; // No! Return an error. return false; } // Allocate memory for the mean colors. auv3MeanColor = new uvector3[u_material_count]; // Were we successful? if (auv3MeanColor == 0) { // Log an error to the export log slExportLog.Printf("Error: Unable to allocate mean color list of size %d for object: %s\n", u_material_count, estrObjectName.strData()); // No! Deallocate the texture map list. delete [] astrTextureMap; astrTextureMap = 0; // No! Deallocate the texture map list. delete [] astrOpacityMap; astrOpacityMap = 0; // No! Deallocate the texture map list. delete [] alvLightingValues; alvLightingValues = 0; // No! Deallocate the lighting values list. delete [] alvLightingValues; // No! Return an error. return false; } uMaterialCount = u_material_count; // Initialize the normal list for (uint u_i = 0; u_i < u_material_count; u_i++) { // Set each of the indices in the bitmap name lists to null. astrTextureMap[u_i] = 0; astrOpacityMap[u_i] = 0; astrBumpMap[u_i] = 0; alvLightingValues[u_i].fAmbient = -1.0f; alvLightingValues[u_i].fDiffuse = -1.0f; alvLightingValues[u_i].fSpecular = -1.0f; alvLightingValues[u_i].fOpacity = -1.0f; alvLightingValues[u_i].fBumpiness = -1.0f; auv3MeanColor[u_i].X = 0; auv3MeanColor[u_i].Y = 0; auv3MeanColor[u_i].Z = 0; } // Return a successful result. return true; } //********************************************************************************************** // bool CObjectDef::TextureName(uint u_material_index, const char* str_mapname) { // Is the specified index in range? if (u_material_index >= uMaterialCount) { // Range error. Return an error. return false; } // The index is in range, so setup the string. If memory for a string already // exists, deallocate it and add a new string since the lengths could be off. if (astrTextureMap[u_material_index] != 0) { // Free the previous string. delete [] astrTextureMap[u_material_index]; astrTextureMap[u_material_index] = 0; } // Allocate a new string astrTextureMap[u_material_index] = new char[strlen(str_mapname) + 1]; // Were we successful? if (astrTextureMap[u_material_index] == 0) { // Log an error to the export log slExportLog.Printf("Error: Unable to allocate texture name %s at index %d for object: %s\n", str_mapname, u_material_index, estrObjectName.strData()); // Return an error return false; } strcpy(astrTextureMap[u_material_index], str_mapname); // Return a successful result. return true; } //********************************************************************************************** // bool CObjectDef::OpacityName(uint u_material_index, const char* str_mapname) { // Is the specified index in range? if (u_material_index >= uMaterialCount) { // Range error. Return an error. return false; } // The index is in range, so setup the string. If memory for a string already // exists, deallocate it and add a new string since the lengths could be off. if (astrOpacityMap[u_material_index] != 0) { // Free the previous string. delete [] astrOpacityMap[u_material_index]; astrOpacityMap[u_material_index] = 0; } // Allocate a new string astrOpacityMap[u_material_index] = new char[strlen(str_mapname) + 1]; // Were we successful? if (astrOpacityMap[u_material_index] == 0) { // Log an error to the export log slExportLog.Printf("Error: Unable to allocate opacity name %s at index %d for object: %s\n", str_mapname, u_material_index, estrObjectName.strData()); // Return an error return false; } strcpy(astrOpacityMap[u_material_index], str_mapname); // Return a successful result. return true; } //********************************************************************************************** // bool CObjectDef::BumpmapName(uint u_material_index, const char* str_mapname) { // Is the specified index in range? if (u_material_index >= uMaterialCount) { // Range error. Return an error. return false; } // The index is in range, so setup the string. If memory for a string already // exists, deallocate it and add a new string since the lengths could be off. if (astrBumpMap[u_material_index] != 0) { // Free the previous string. delete [] astrBumpMap[u_material_index]; astrBumpMap[u_material_index] = 0; } // Allocate a new string astrBumpMap[u_material_index] = new char[strlen(str_mapname) + 1]; // Were we successful? if (astrBumpMap[u_material_index] == 0) { // Log an error to the export log slExportLog.Printf("Error: Unable to allocate bump map name %s at index %d for object: %s\n", str_mapname, u_material_index, estrObjectName.strData()); // Return an error return false; } strcpy(astrBumpMap[u_material_index], str_mapname); // Return a successful result. return true; } /* //********************************************************************************************** // // Methods for adjusting the list. // //********************************************************************************************** // bool CObjectDef::OrderVertices() { fvector3* pfv3_v0; fvector3* pfv3_v1; fvector3* pfv3_v2; fvector3 fv3_v0; fvector3 fv3_v1; fvector3 fv3_cross_product; fvector3* pfv3_normal; uint u_tmp; float f_dir; // In order to generate these we need both the vertices and the normals if (afv3FaceNormal == 0 || afv3Vertex == 0) { // Both structures are not present, so return and error. return false; } // The rendering engine prefers to have all polygons ordered in so that // when facing the polygon (i.e. the normal is pointing towards me), the // vertices are ordered counter clockwise . // // This can asily be checked by generating to vectors, generating a cross // product, then taking the inner product of the cross product of the two // vectors and the polygon normal. If the result is positive, then the // vertices are properly ordered. If the the result is negative, then the // vertices are ordered incorrectly. This condition can be easily resolved // by switching the first two vertices. This only works because we are // working with three sided polygons. // Process each polygon in the object for (uint u_i = 0; u_i < uFaceCount; u_i++) { // Get the polygon normal pfv3_normal = &afv3FaceNormal[u_i]; // First build the direction vectors for the cross product.. Start by // getting all three vertices. pfv3_v0 = &afv3Vertex[auv3Face[u_i].X]; pfv3_v1 = &afv3Vertex[auv3Face[u_i].Y]; pfv3_v2 = &afv3Vertex[auv3Face[u_i].Z]; // Now build the direction vectors fv3_v0.X = pfv3_v1->X - pfv3_v0->X; fv3_v0.Y = pfv3_v1->Y - pfv3_v0->Y; fv3_v0.Z = pfv3_v1->Z - pfv3_v0->Z; fv3_v1.X = pfv3_v2->X - pfv3_v1->X; fv3_v1.Y = pfv3_v2->Y - pfv3_v1->Y; fv3_v1.Z = pfv3_v2->Z - pfv3_v1->Z; // Calculate the cross product fv3_cross_product.X = fv3_v0.Y * fv3_v1.Z - fv3_v0.Z * fv3_v1.Y; fv3_cross_product.Y = fv3_v0.Z * fv3_v1.X - fv3_v0.X * fv3_v1.Z; fv3_cross_product.Z = fv3_v0.X * fv3_v1.Y - fv3_v0.Y * fv3_v1.X; // Now calculate the dot product. f_dir = fv3_cross_product.X * pfv3_normal->X + fv3_cross_product.Y * pfv3_normal->Y + fv3_cross_product.Z * pfv3_normal->Z; // Do these vertics need to be reordered? if (f_dir < 0.0f) { // Log an error to the export log slExportLog.Printf("Warning: Object: %s has polygon with vertices in clockwise order.\n", estrObjectName.strData()); slExportLog.Printf("Polygon: %d, Vertices: (%d, %d, %d)\n", u_i, auv3Face[u_i].X, auv3Face[u_i].Y, auv3Face[u_i].Z); // Yes! So reorder the polygon u_tmp = auv3Face[u_i].Y; auv3Face[u_i].Y = auv3Face[u_i].Z; auv3Face[u_i].Z = u_tmp; // Keep track of the number of reordered polygons. FYI uWarnings++; } } // Return a successful result return true; } //********************************************************************************************** // bool CObjectDef::BuildNormals() { fvector3* pfv3_v0; fvector3* pfv3_v1; fvector3* pfv3_v2; fvector3 fv3_v0; fvector3 fv3_v1; fvector3* pfv3_normal; float f_length; // In order to generate these we need both the vertices and the normals if (afv3FaceNormal == 0 || afv3Vertex == 0) { // Both structures are not present, so return and error(true) return false; } // The rendering engine prefers to have all polygons ordered in so that // when facing the polygon (i.e. the normal is pointing towards me), the // vertices are ordered counter clockwise . // // This can asily be checked by generating to vectors, generating a cross // product, then taking the inner product of the cross product of the two // vectors and the polygon normal. If the result is positive, then the // vertices are properly ordered. If the the result is negative, then the // vertices are ordered incorrectly. This condition can be easily resolved // by switching the first two vertices. This only works because we are // working with three sided polygons. // Process each polygon in the object for (uint u_i = 0; u_i < uFaceCount; u_i++) { // Get the polygon normal pfv3_normal = &afv3FaceNormal[u_i]; // First build the direction vectors for the cross product.. Start by // getting all three vertices. pfv3_v0 = &afv3Vertex[auv3Face[u_i].X]; pfv3_v1 = &afv3Vertex[auv3Face[u_i].Y]; pfv3_v2 = &afv3Vertex[auv3Face[u_i].Z]; // Now build the direction vectors fv3_v0.X = pfv3_v1->X - pfv3_v0->X; fv3_v0.Y = pfv3_v1->Y - pfv3_v0->Y; fv3_v0.Z = pfv3_v1->Z - pfv3_v0->Z; fv3_v1.X = pfv3_v2->X - pfv3_v1->X; fv3_v1.Y = pfv3_v2->Y - pfv3_v1->Y; fv3_v1.Z = pfv3_v2->Z - pfv3_v1->Z; // Calculate the cross product pfv3_normal->X = fv3_v0.Y * fv3_v1.Z - fv3_v0.Z * fv3_v1.Y; pfv3_normal->Y = fv3_v0.Z * fv3_v1.X - fv3_v0.X * fv3_v1.Z; pfv3_normal->Z = fv3_v0.X * fv3_v1.Y - fv3_v0.Y * fv3_v1.X; // Calculate the length of the vectors f_length = (float) sqrt((double) pfv3_normal->X * pfv3_normal->X + pfv3_normal->Y * pfv3_normal->Y + pfv3_normal->Z * pfv3_normal->Z); // Now, make the normals unit length pfv3_normal->X /= f_length; pfv3_normal->Y /= f_length; pfv3_normal->Z /= f_length; } // Return a successful result return true; } */ static bool b_open = false; //********************************************************************************************** // CObjectDefList::CObjectDefList() { // Set the list pointers to 0 podHead = 0; podTail = 0; // Set the total object node count to 0 uNodeCount = 0; b_open = false; } //********************************************************************************************** // CObjectDefList::~CObjectDefList() { // Log a final message to the export logfile slExportLog.Printf("Export complete:\n"); // Close the export logfile slExportLog.Close(); } //********************************************************************************************** // CObjectDef* CObjectDefList::podAddObject(const char* str_object_name) { CObjectDef* pod_new_node = new CObjectDef(str_object_name); CObjectDef* pod_last = podTail; // Is the logfile open? if (!b_open) { // Indicate that the file is now open. b_open = true; // Determine whether the file should be active or not. if (guiInterface.bGenerateLogfiles()) { // Open a logfile. char str_logfile[256]; guiInterface.BuildPath(str_logfile, guiInterface.strGetLogfileDirPath(), "ObjectDefRaw.log"); slExportLog.Open(str_logfile); // Activate the logfile. slExportLog.Enable(); } else { // Deactivate the logfile. slExportLog.Disable(); } } // Were we able to allocate a new node? if (pod_new_node == false) { // Log a final message to the export logfile slExportLog.Printf("Error: Unable to allocate a node for object: %s", str_object_name); } // Set the ID number of the new node. pod_new_node->iID = uNodeCount++; // Insert the node into the list if (podHead == false) { // This is easy since the list is empty podHead = pod_new_node; podTail = pod_new_node; } else { // Append this object to the end of the list; podTail->podNext = pod_new_node; podTail = pod_new_node; } // Return this new node to the caller return pod_new_node; } //********************************************************************************************** // void CObjectDefList::DeleteObjects() { CObjectDef* pod_next = podHead; // Delete all memobers from the list while(podHead) { // Setup a pointer to the next node pod_next = podHead->podNext; // Deallocate the contents of the node. podHead->Destroy(); // Delete this node delete podHead; // Update the pointer to the next node podHead = pod_next; } // Reset the pointers to reasonable initial values podHead = 0; podTail = 0; uNodeCount = 0; } //********************************************************************************************** // CObjectDef* CObjectDefList::podLookup(uint u_object_index) { // Perform a simple range check if (u_object_index >= uNodeCount) // Return an invalid pointer return 0; // We now know there is a correcsponding node in the list. So start looking... CObjectDef* pod_node = podHead; // Walk the node list for (; pod_node != 0 && u_object_index; u_object_index--) pod_node = pod_node->podNext; // This must be the node we are looking for, so return it return pod_node; } //********************************************************************************************** // CObjectDef* CObjectDefList::podLookup(const char* str_object_name) { // Search until we are at the end of the list or have foudn a match. CObjectDef* pod_node = podHead; while(pod_node) { // Is this the Node we are looking for? if (pod_node->estrObjectName != str_object_name) { // Aha! We have found the node. Return it! return pod_node; } // Move onto the next node pod_node = pod_node->podNext; } // Was unable to locate a matching node. Return an invalid pointer return 0; } //********************************************************************************************** // uint CObjectDefList::uWarnings() { uint uWarnings = 0; CObjectDef* pod_node = podHead; // Determine the total number of warnings. while(pod_node) { uWarnings += pod_node->uWarnings; // Advance to the next node. pod_node = pod_node->podNext; } // Return the total number of warnings. return uWarnings; } //********************************************************************************************** // uint CObjectDefList::uErrors() { uint uErrors = 0; CObjectDef* pod_node = podHead; // Determine the total number of Normals while(pod_node) { uErrors += pod_node->uErrors; // Advance to the next node pod_node = pod_node->podNext; } // Return the total number of errors. return uErrors; } //********************************************************************************************** // void CObjectDefList::Dump() { // Open the log file. CSysLog sl_glog; CObjectDef* pod_node = podHead; struct tm* tm_current_time; time_t tt_clock; // Is the user generating log_files? if (!guiInterface.bGenerateLogfiles()) { // No! The return immediately. return; } // Get the currrent time time(&tt_clock); tm_current_time = localtime(&tt_clock); // Determine whether the file should be active or not. if (guiInterface.bGenerateLogfiles()) { // Construct the proper path for the logfile. char str_logfile[256]; guiInterface.BuildPath(str_logfile, guiInterface.strGetLogfileDirPath(), "ObjectDefDump.log"); sl_glog.Open(str_logfile); // Activate the logfile. sl_glog.Enable(); } else { // Deactivate the logfile. sl_glog.Disable(); } // Display a banner sl_glog.Printf("----- Geometry logfile: -----\nFile creation date: %s \n", asctime(tm_current_time)); // Are there any nodes to display? if (pod_node == 0) { // No. Log completion message, close file and return sl_glog.Printf("Geometry list is .\n"); return; } while(pod_node != 0) { // First display the name of the object sl_glog.Printf("\nObject name: \"%s\", ID %d\n\n", pod_node->estrObjectName.strData(), pod_node->iID); // Record the object's position. Point3 p3_position = pod_node->p3GetPosition(); sl_glog.Printf("Position: x -> %.3f, y -> %.3f, z -> %.3f\n", p3_position[0], p3_position[1], p3_position[2]); // Record the object's orientation. Point3 p3_rotation(pod_node->p3GetRotation()); sl_glog.Printf("Rotation: x -> %.3f, y -> %.3f, z -> %.3f\n", p3_rotation[0], p3_rotation[1], p3_rotation[2]); // Record the object's uniform scaling constant. sl_glog.Printf("Uniform Scaling value: %3f\n", pod_node->fGetScale()); // Display the vertices for this object sl_glog.Printf("Object vertices: %d\n", pod_node->uVertexCount); // Dump the object vertices for (uint u_i = 0; u_i < pod_node->uVertexCount; u_i++) { // Display the vertex sl_glog.Printf("Vertex %4d: x -> %.3f, y -> %.3f, z -> %.3f\n", u_i, pod_node->afv3Vertex[u_i].X, pod_node->afv3Vertex[u_i].Y, pod_node->afv3Vertex[u_i].Z); } // Display the polygon face definitions sl_glog.Printf("\nObject faces: %d\n", pod_node->uFaceCount); // Dump the object faces for (uint u_i = 0; u_i < pod_node->uFaceCount; u_i++) { // Display the vertex sl_glog.Printf("Face %4d: x -> %4d, y -> %4d, z -> %4d\n", u_i, pod_node->auv3Face[u_i].X, pod_node->auv3Face[u_i].Y, pod_node->auv3Face[u_i].Z); } sl_glog.Printf("\nObject face normals: %d\n", pod_node->uFaceNormalCount); // Dump the object normals for (uint u_i = 0; u_i < pod_node->uFaceNormalCount; u_i++) { // Display the normals sl_glog.Printf("Normal %4d: x -> %.3f, y -> %3.f, z -> %.3f\n", u_i, pod_node->afv3FaceNormal[u_i].X, pod_node->afv3FaceNormal[u_i].Y, pod_node->afv3FaceNormal[u_i].Z); } sl_glog.Printf("\nObject face vertex normals: %d\n", pod_node->uVertexNormalCount); // Dump the object normals for (uint u_i = 0; u_i < pod_node->uVertexNormalCount; u_i+=3) { // Display the vertex normals. sl_glog.Printf("Face %4d: Vertex 0: x -> %.3f, y -> %.3f, z -> %.3f\n", u_i/3, pod_node->afv3VertexNormal[u_i].X, pod_node->afv3VertexNormal[u_i].Y, pod_node->afv3VertexNormal[u_i].Z); sl_glog.Printf("Face %4d: Vertex 1: x -> %.3f, y -> %.3f, z -> %.3f\n", u_i/3, pod_node->afv3VertexNormal[u_i+1].X, pod_node->afv3VertexNormal[u_i+1].Y, pod_node->afv3VertexNormal[u_i+1].Z); sl_glog.Printf("Face %4d: Vertex 2: x -> %.3f, y -> %.3f, z -> %.3f\n", u_i/3, pod_node->afv3VertexNormal[u_i+2].X, pod_node->afv3VertexNormal[u_i+2].Y, pod_node->afv3VertexNormal[u_i+2].Z); } // Optional stuff which may be associated with an object if (pod_node->uTextureVertexCount > 0) { sl_glog.Printf("\nObject texture vertices: %d\n", pod_node->uTextureVertexCount); // Dump the object vertices for (uint u_i = 0; u_i < pod_node->uTextureVertexCount; u_i++) { // Display the texture vertices sl_glog.Printf("Texture vertex %4d: u -> %.3f, v -> %.3f\n", u_i, pod_node->afv2TextureVertex[u_i].X, pod_node->afv2TextureVertex[u_i].Y); } // Display the polygon face definitions sl_glog.Printf("\nObject texture faces: %d\n", pod_node->uTextureFaceCount); // Is this a single-material object? if (pod_node->uMaterialCount == 1) { // Dump the object faces for (uint u_i = 0; u_i < pod_node->uTextureFaceCount; u_i++) { // Display the texture faces sl_glog.Printf("Texture face %4d: x -> %4d, y -> %4d, z -> %4d\n", u_i, pod_node->auv3TextureFace[u_i].X, pod_node->auv3TextureFace[u_i].Y, pod_node->auv3TextureFace[u_i].Z); } sl_glog.Printf("\n"); // Display any materials which may be present. if (pod_node->astrTextureMap != 0) { if (pod_node->astrTextureMap[0] != 0) { sl_glog.Printf("Diffuse map: %s\n", pod_node->astrTextureMap[0]); } // Display the mean color. if (pod_node->auv3MeanColor != 0) { sl_glog.Printf("Mean color : R -> %d, G -> %d, B -> %d\n", pod_node->auv3MeanColor[0].Z, pod_node->auv3MeanColor[0].Y, pod_node->auv3MeanColor[0].X); } } if (pod_node->astrOpacityMap != 0) { if (pod_node->astrOpacityMap[0] != 0) { sl_glog.Printf("Opacity map: %s\n", pod_node->astrOpacityMap[0]); } } if (pod_node->astrBumpMap != 0) { if (pod_node->astrBumpMap[0] != 0) { sl_glog.Printf("Bumpmap : %s\n", pod_node->astrBumpMap[0]); } } if (pod_node->alvLightingValues != 0) { sl_glog.Printf("\n"); if (pod_node->alvLightingValues[0].fAmbient != -1.0f) { sl_glog.Printf("Ambient : %f\n", pod_node->alvLightingValues[0].fAmbient); } if (pod_node->alvLightingValues[0].fDiffuse != -1.0f) { sl_glog.Printf("Diffuse : %f\n", pod_node->alvLightingValues[0].fDiffuse); } if (pod_node->alvLightingValues[0].fSpecular != -1.0f) { sl_glog.Printf("Specular : %f\n", pod_node->alvLightingValues[0].fSpecular); } if (pod_node->alvLightingValues[0].fOpacity != -1.0f) { sl_glog.Printf("Opacity : %f\n", pod_node->alvLightingValues[0].fOpacity); } if (pod_node->alvLightingValues[0].fBumpiness != -1.0f) { sl_glog.Printf("Bumpiness : %f\n\n\n", pod_node->alvLightingValues[0].fBumpiness); } } } else { // Dump the object faces for (uint u_i = 0; u_i < pod_node->uTextureFaceCount; u_i++) { // Display the texture faces sl_glog.Printf("Texture face %4d: x -> %4d, y -> %4d, z -> %4d\n", u_i, pod_node->auv3TextureFace[u_i].X, pod_node->auv3TextureFace[u_i].Y, pod_node->auv3TextureFace[u_i].Z); } // Display the polygon face definitions sl_glog.Printf("Object materials: %d\n", (int) pod_node->uMaterialCount); // Dump the object faces for (uint u_i = 0; u_i < pod_node->uMaterialCount; u_i++) { // Display any materials which may be present. if (pod_node->astrTextureMap != 0) { if (pod_node->astrTextureMap[u_i] != 0) { sl_glog.Printf("Diffuse map: %s\n", pod_node->astrTextureMap[u_i]); // Display the mean color. if (pod_node->auv3MeanColor != 0) { sl_glog.Printf("Mean color : R -> %d, G -> %d, B -> %d\n", pod_node->auv3MeanColor[u_i].Z, pod_node->auv3MeanColor[u_i].Y, pod_node->auv3MeanColor[u_i].X); } } } if (pod_node->astrOpacityMap != 0) { if (pod_node->astrOpacityMap[u_i] != 0) { sl_glog.Printf("Opacity map: %s\n", pod_node->astrOpacityMap[u_i]); } } if (pod_node->astrBumpMap != 0) { if (pod_node->astrBumpMap[u_i] != 0) { sl_glog.Printf("Bumpmap : %s\n", pod_node->astrBumpMap[u_i]); } } if (pod_node->alvLightingValues != 0) { sl_glog.Printf("\n"); if (pod_node->alvLightingValues[u_i].fAmbient != -1.0f) { sl_glog.Printf("Ambient : %.3f\n", pod_node->alvLightingValues[u_i].fAmbient); } if (pod_node->alvLightingValues[u_i].fDiffuse != -1.0f) { sl_glog.Printf("Diffuse : %.3f\n", pod_node->alvLightingValues[u_i].fDiffuse); } if (pod_node->alvLightingValues[u_i].fSpecular != -1.0f) { sl_glog.Printf("Specular : %.3f\n", pod_node->alvLightingValues[u_i].fSpecular); } if (pod_node->alvLightingValues[u_i].fOpacity != -1.0f) { sl_glog.Printf("Opacity : %.3f\n", pod_node->alvLightingValues[u_i].fOpacity); } if (pod_node->alvLightingValues[u_i].fBumpiness != -1.0f) { sl_glog.Printf("Bumpiness : %.3f\n", pod_node->alvLightingValues[u_i].fBumpiness); } sl_glog.Printf("\n"); } } sl_glog.Printf("\n"); } } // Advance to the next node in the list pod_node = pod_node->podNext; } // All done. Display the completion message and return. sl_glog.Printf("----- Geometry file complete -----\n"); }