mirror of
https://github.com/OpenTrespasser/JurassicParkTrespasser.git
synced 2024-12-20 07:31:56 +00:00
825 lines
24 KiB
C++
825 lines
24 KiB
C++
|
/**********************************************************************************************
|
||
|
*
|
||
|
* Copyright (c) DreamWorks Interactive. 1997
|
||
|
*
|
||
|
* Contents: Geometry class for validation and conversion of objects into a format consistent
|
||
|
* with the renderer.
|
||
|
*
|
||
|
* Bugs:
|
||
|
*
|
||
|
* To do:
|
||
|
*
|
||
|
**********************************************************************************************
|
||
|
*
|
||
|
* $Log:: /JP2_PC/Source/Tools/GroffExp/Geometry.cpp $
|
||
|
*
|
||
|
* 16 7/15/97 6:58p Gstull
|
||
|
* Made organizational changes to make management of the exporter more reasonable.
|
||
|
*
|
||
|
* 15 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.
|
||
|
*
|
||
|
* 14 6/18/97 7:33p Gstull
|
||
|
* Added changes to support fast exporting.
|
||
|
*
|
||
|
* 13 4/15/97 10:38p Gstull
|
||
|
* Added changes to support export options specified in a dialog box at export time.
|
||
|
*
|
||
|
* 12 4/14/97 7:19p Gstull
|
||
|
* Added changes to support log file management.
|
||
|
*
|
||
|
* 11 3/19/97 6:05p Gstull
|
||
|
* Added fixes for Bug #18 and bug #19, which resolved the problems of exporting objects
|
||
|
* without geometry and material ID range errors.
|
||
|
*
|
||
|
* 10 2/25/97 7:51p Gstull
|
||
|
* Resolved issues with proper object placement in the scene and object validation.
|
||
|
*
|
||
|
*********************************************************************************************/
|
||
|
|
||
|
#include <math.h>
|
||
|
|
||
|
#include "StandardTypes.hpp"
|
||
|
#include "ObjectDef.hpp"
|
||
|
#include "Geometry.hpp"
|
||
|
#include "Mathematics.hpp"
|
||
|
|
||
|
#include "Lib/Sys/SysLog.hpp"
|
||
|
#include "Lib/Sys/SmartBuffer.hpp"
|
||
|
#include "Lib/Groff/FileIO.hpp"
|
||
|
#include "Lib/Groff/Groff.hpp"
|
||
|
#include "Tools/GroffExp/GUIInterface.hpp"
|
||
|
|
||
|
extern CGUIInterface guiInterface;
|
||
|
|
||
|
|
||
|
const float TOO_CLOSE = 0.000001f;
|
||
|
|
||
|
|
||
|
//******************************************************************************************
|
||
|
//
|
||
|
// Floating point comparision function for fuzzy equality checks.
|
||
|
//
|
||
|
bool bTooClose(fvector3& fv3_vector_1, fvector3& fv3_vector_2)
|
||
|
{
|
||
|
// Determine if these points are ~ equal.
|
||
|
if (fabs(fv3_vector_1.X - fv3_vector_2.X) > TOO_CLOSE)
|
||
|
{
|
||
|
// No! These points are not equal.
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// Determine if these points are ~ equal.
|
||
|
if (fabs(fv3_vector_1.Y - fv3_vector_2.Y) > TOO_CLOSE)
|
||
|
{
|
||
|
// No! These points are not ~ equal.
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// Determine if these points are essentially equal.
|
||
|
if (fabs(fv3_vector_1.Z - fv3_vector_2.Z) > TOO_CLOSE)
|
||
|
{
|
||
|
// No! These points are not ~ equal.
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// These points are essentially equal.
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
//******************************************************************************************
|
||
|
//
|
||
|
// Function for looping through the object list and processing each object.
|
||
|
//
|
||
|
bool CGeometry::bCheckScene(CObjectDefList* podl_scene, const CEasyString& estr_export_filename)
|
||
|
{
|
||
|
bool b_result = true;
|
||
|
int i_index = 0;
|
||
|
CObjectDef* pod_node = podl_scene->podHead;
|
||
|
|
||
|
// Open the log file.
|
||
|
char str_logfile[256];
|
||
|
|
||
|
// Determine whether the file should be active or not.
|
||
|
if (guiInterface.bGenerateLogfiles())
|
||
|
{
|
||
|
// Construct the proper path for the logfile.
|
||
|
guiInterface.BuildPath(str_logfile, guiInterface.strGetLogfileDirPath(), "Geometry.log");
|
||
|
slLogfile.Open(str_logfile);
|
||
|
|
||
|
// Activate the logfile.
|
||
|
slLogfile.Enable();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Deactivate the logfile.
|
||
|
slLogfile.Disable();
|
||
|
}
|
||
|
|
||
|
// Place a startup message in the logfile.
|
||
|
slLogfile.Printf("Processing scene file: %s\n", estr_export_filename.strData());
|
||
|
|
||
|
// Process the scene list
|
||
|
do
|
||
|
{
|
||
|
// Print a message to the log
|
||
|
slLogfile.Printf("\n***** Processing object(%d): %s *****\n", i_index++, pod_node->estrObjectName.strData());
|
||
|
|
||
|
// Reset the statistics.
|
||
|
ResetStatistics();
|
||
|
|
||
|
// Analyze the placement and geometric information and put it in normal form.
|
||
|
b_result &= bCheckGeometry(pod_node);
|
||
|
|
||
|
// Check for degenerate polygons.
|
||
|
b_result &= bCheckFaces(pod_node);
|
||
|
|
||
|
// Check for legal texture coordinates.
|
||
|
b_result &= bCheckTexCoords(pod_node);
|
||
|
|
||
|
// Make sure the material indices are valid. Were we successful?
|
||
|
b_result &= bCheckMaterials(pod_node);
|
||
|
|
||
|
// Log the results.
|
||
|
PrintStatistics();
|
||
|
|
||
|
// Move to the next object in the scene list.
|
||
|
pod_node = pod_node->podNext;
|
||
|
|
||
|
} while (pod_node != 0);
|
||
|
|
||
|
|
||
|
// Close the logfile.
|
||
|
slLogfile.Close();
|
||
|
|
||
|
// Return a successful result
|
||
|
return b_result;
|
||
|
}
|
||
|
|
||
|
|
||
|
//*****************************************************************************************
|
||
|
//
|
||
|
// Function to validate the objects geometry.
|
||
|
//
|
||
|
bool CGeometry::bCheckGeometry
|
||
|
(
|
||
|
CObjectDef* pod_object
|
||
|
)
|
||
|
{
|
||
|
//
|
||
|
// Determine what coordinate system the objects geometry exists in.
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Make sure the object is being uniformly scaled on an axis boundry. If not, report this
|
||
|
// condition as an error.
|
||
|
//
|
||
|
|
||
|
// Decompose the matrix.
|
||
|
|
||
|
// Display the uniform scale value.
|
||
|
slLogfile.Printf("Object found to be using uniform scaling: %f\n", pod_object->fGetScale());
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
{
|
||
|
bool b_result = true;
|
||
|
uint u_i;
|
||
|
float f_min_x = 100000000.0f;
|
||
|
float f_max_x = -100000000.0f;
|
||
|
float f_min_y = 100000000.0f;
|
||
|
float f_max_y = -100000000.0f;
|
||
|
float f_min_z = 100000000.0f;
|
||
|
float f_max_z = -100000000.0f;
|
||
|
// float f_delta_x;
|
||
|
// float f_delta_y;
|
||
|
// float f_delta_z;
|
||
|
float f_trans_x;
|
||
|
float f_trans_y;
|
||
|
float f_trans_z;
|
||
|
float f_scale = 1.0f;
|
||
|
|
||
|
|
||
|
// Adjust the object position vector against the pivot offset.
|
||
|
Point3 p3_position = pod_object->p3GetPosition();
|
||
|
Point3 p3_pivot_offset = pod_object->p3GetPivotOffset();
|
||
|
|
||
|
// Display the uniform scale value.
|
||
|
slLogfile.Printf("Adjusting position by pivot offset: %f %f %f\n", p3_pivot_offset.x, p3_pivot_offset.y, p3_pivot_offset.z);
|
||
|
|
||
|
// Subtract the pivot offset from the position.
|
||
|
p3_position.x -= p3_pivot_offset.x;
|
||
|
p3_position.y-= p3_pivot_offset.y;
|
||
|
p3_position.z -= p3_pivot_offset.z;
|
||
|
|
||
|
// Save the updated position.
|
||
|
pod_object->Position(p3_position);
|
||
|
|
||
|
// Loop through all the vertices
|
||
|
for (u_i = 0; u_i < pod_object->uVertexCount; u_i++)
|
||
|
{
|
||
|
//
|
||
|
// Adjust each point to reflect the center of mass.
|
||
|
//
|
||
|
|
||
|
// Get each vertex and adjust it against the pivot offset if it is non-zero.
|
||
|
pod_object->afv3Vertex[u_i].X += p3_pivot_offset.x;
|
||
|
pod_object->afv3Vertex[u_i].Y += p3_pivot_offset.y;
|
||
|
pod_object->afv3Vertex[u_i].Z += p3_pivot_offset.z;
|
||
|
|
||
|
//
|
||
|
// Is this coordinate either the smallest we have seen?
|
||
|
if (pod_object->afv3Vertex[u_i].X < f_min_x)
|
||
|
{
|
||
|
// Replace it
|
||
|
f_min_x = pod_object->afv3Vertex[u_i].X;
|
||
|
}
|
||
|
|
||
|
// Is this coordinate either the largest we have seen?
|
||
|
if (pod_object->afv3Vertex[u_i].X > f_max_x)
|
||
|
{
|
||
|
// Replace it
|
||
|
f_max_x = pod_object->afv3Vertex[u_i].X;
|
||
|
}
|
||
|
|
||
|
// Is this coordinate either the smallest we have seen?
|
||
|
if (pod_object->afv3Vertex[u_i].Y < f_min_y)
|
||
|
{
|
||
|
// Replace it
|
||
|
f_min_y = pod_object->afv3Vertex[u_i].Y;
|
||
|
}
|
||
|
|
||
|
// Is this coordinate either the largest we have seen?
|
||
|
if (pod_object->afv3Vertex[u_i].Y > f_max_y)
|
||
|
{
|
||
|
// Replace it
|
||
|
f_max_y = pod_object->afv3Vertex[u_i].Y;
|
||
|
}
|
||
|
|
||
|
// Is this coordinate either the smallest we have seen?
|
||
|
if (pod_object->afv3Vertex[u_i].Z < f_min_z)
|
||
|
{
|
||
|
// Replace it
|
||
|
f_min_z = pod_object->afv3Vertex[u_i].Z;
|
||
|
}
|
||
|
|
||
|
// Is this coordinate either the largest we have seen?
|
||
|
if (pod_object->afv3Vertex[u_i].Z > f_max_z)
|
||
|
{
|
||
|
// Replace it
|
||
|
f_max_z = pod_object->afv3Vertex[u_i].Z;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Calculate the threshold for
|
||
|
// Is the origin of the object contained by it's extent?
|
||
|
if (f_min_x <= 0.00001f && f_max_x >= 0.00001f && f_min_y <= 0.00001f && f_max_x >= 0.00001f && f_min_z <= 0.00001f && f_max_z >= 0.00001f)
|
||
|
{
|
||
|
slLogfile.Printf("No object recentering required.\n");
|
||
|
|
||
|
//
|
||
|
// Yes! Then only scaling of the object into unit space is needed. Determine
|
||
|
// this by finding the largest relative offset and using that value for the
|
||
|
// scaling constant.
|
||
|
//
|
||
|
|
||
|
// Calculate the range of each of the coordinates on the respective axis
|
||
|
float f_range = -f_min_x;
|
||
|
|
||
|
if (f_max_x > f_min_x)
|
||
|
f_range = f_max_x;
|
||
|
if (-f_min_y > f_range)
|
||
|
f_range = -f_min_y;
|
||
|
if (f_max_y > f_range)
|
||
|
f_range = f_max_y;
|
||
|
if (-f_min_z > f_range)
|
||
|
f_range = -f_min_z;
|
||
|
if (f_max_z > f_range)
|
||
|
f_range = f_max_z;
|
||
|
|
||
|
f_trans_x = 0.0f;
|
||
|
f_trans_y = 0.0f;
|
||
|
f_trans_z = 0.0f;
|
||
|
|
||
|
// Adjust the scale for the unit cube
|
||
|
f_scale = 1.0f / f_range;
|
||
|
|
||
|
// Log the results.
|
||
|
slLogfile.Printf("Object space definition contains the origin.\n");
|
||
|
slLogfile.Printf("Object space scaling factor is: %f\n", f_scale);
|
||
|
slLogfile.Printf("Translation: x -> 0.0, y -> 0.0, z -> 0.0\n\n");
|
||
|
|
||
|
// Loop through all the vertices, translate them to the object center of mass then
|
||
|
// scale the object into the unit cube.
|
||
|
for (u_i = 0; u_i < pod_object->uVertexCount; u_i++)
|
||
|
{
|
||
|
// Adjust the coordinates
|
||
|
pod_object->afv3Vertex[u_i].X /= f_range;
|
||
|
pod_object->afv3Vertex[u_i].Y /= f_range;
|
||
|
pod_object->afv3Vertex[u_i].Z /= f_range;
|
||
|
|
||
|
// Log the results
|
||
|
slLogfile.Printf("World Vertex %3d: %f %f %f\n", u_i,
|
||
|
pod_object->afv3Vertex[u_i].X,
|
||
|
pod_object->afv3Vertex[u_i].Y,
|
||
|
pod_object->afv3Vertex[u_i].Z);
|
||
|
}
|
||
|
|
||
|
// Place the object scale in the object so it can be restored.
|
||
|
pod_object->Scale(pod_object->fGetScale() / f_scale);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// No! The object needs to be recentered and scaled into the unit cube.
|
||
|
//
|
||
|
slLogfile.Printf("Recentering object since origin is not within object's extent.\n");
|
||
|
|
||
|
// Calculate the range of each of the coordinates on the respective axis
|
||
|
f_trans_x = ((f_min_x + f_max_x) / 2.0f);
|
||
|
f_trans_y = ((f_min_y + f_max_y) / 2.0f);
|
||
|
f_trans_z = ((f_min_z + f_max_z) / 2.0f);
|
||
|
|
||
|
// Log the results.
|
||
|
slLogfile.Printf("Object space definition does not contain the origin.\n");
|
||
|
// slLogfile.Printf("Range values: x -> %f, y -> %f, z -> %f\n", f_delta_x, f_delta_y, f_delta_z);
|
||
|
slLogfile.Printf("Translation: x -> %f, y -> %f, z -> %f\n\n", f_trans_x, f_trans_y, f_trans_z);
|
||
|
slLogfile.Printf("Object space scaling factor is: %f\n", f_scale);
|
||
|
|
||
|
// Loop through all the vertices, translate them to the object center of mass then
|
||
|
// scale the object into the unit cube.
|
||
|
for (u_i = 0; u_i < pod_object->uVertexCount; u_i++)
|
||
|
{
|
||
|
// Adjust the coordinates
|
||
|
pod_object->afv3Vertex[u_i].X -= f_trans_x;
|
||
|
pod_object->afv3Vertex[u_i].Y -= f_trans_y;
|
||
|
pod_object->afv3Vertex[u_i].Z -= f_trans_z;
|
||
|
|
||
|
// Log the results
|
||
|
slLogfile.Printf("Vertex %3d: %7.2f, %7.2f, %7.2f\n", u_i, pod_object->afv3Vertex[u_i].X, pod_object->afv3Vertex[u_i].Y,
|
||
|
pod_object->afv3Vertex[u_i].Z);
|
||
|
}
|
||
|
|
||
|
// Relocate the object to the origin by getting the previous position and updating it with respect to the origin.
|
||
|
Point3 p3_old_position = pod_object->p3GetPosition();
|
||
|
Point3 p3_new_position(p3_old_position.x+f_trans_x, p3_old_position.y+f_trans_y, p3_old_position.z+f_trans_z);
|
||
|
|
||
|
// Update the position.
|
||
|
pod_object->Position(p3_new_position);
|
||
|
}
|
||
|
/* else
|
||
|
{
|
||
|
//
|
||
|
// No! The object needs to be recentered and scaled into the unit cube.
|
||
|
//
|
||
|
|
||
|
// Calculate the range of each of the coordinates on the respective axis
|
||
|
f_delta_x = (f_max_x - f_min_x);
|
||
|
f_delta_y = (f_max_y - f_min_y);
|
||
|
f_delta_z = (f_max_z - f_min_z);
|
||
|
|
||
|
f_trans_x = ((f_min_x + f_max_x) / 2.0f);
|
||
|
f_trans_y = ((f_min_y + f_max_y) / 2.0f);
|
||
|
f_trans_z = ((f_min_z + f_max_z) / 2.0f);
|
||
|
|
||
|
// Find the largest delta. Is this the largest?
|
||
|
f_scale = f_delta_x;
|
||
|
if (f_delta_y > f_scale)
|
||
|
{
|
||
|
// Replace it
|
||
|
f_scale = f_delta_y;
|
||
|
}
|
||
|
|
||
|
// Find the largest delta. Is this the largest?
|
||
|
if (f_delta_z > f_scale)
|
||
|
{
|
||
|
// Replace it
|
||
|
f_scale = f_delta_z;
|
||
|
}
|
||
|
|
||
|
// Adjust the scale for the unit cube
|
||
|
f_scale /= 2.0f;
|
||
|
|
||
|
// Log the results.
|
||
|
slLogfile.Printf("Object space definition does not contain the origin.\n");
|
||
|
slLogfile.Printf("Range values: x -> %f, y -> %f, z -> %f\n", f_delta_x, f_delta_y, f_delta_z);
|
||
|
slLogfile.Printf("Translation: x -> %f, y -> %f, z -> %f\n\n", f_trans_x, f_trans_y, f_trans_z);
|
||
|
slLogfile.Printf("Object space scaling factor is: %f\n", f_scale);
|
||
|
|
||
|
// Find the largest range since we can only use uniform scaling. Is this the largest?
|
||
|
f_scale = f_delta_x;
|
||
|
if (f_delta_y > f_scale)
|
||
|
{
|
||
|
// Replace it.
|
||
|
f_scale = f_delta_y;
|
||
|
}
|
||
|
|
||
|
// Find the largest delta. Is this the largest?
|
||
|
if (f_delta_z > f_scale)
|
||
|
{
|
||
|
// Replace it
|
||
|
f_scale = f_delta_z;
|
||
|
}
|
||
|
|
||
|
// Adjust the scale for the unit cube
|
||
|
f_scale /= 2.0f;
|
||
|
|
||
|
// Loop through all the vertices, translate them to the object center of mass then
|
||
|
// scale the object into the unit cube.
|
||
|
for (u_i = 0; u_i < pod_object->uVertexCount; u_i++)
|
||
|
{
|
||
|
// Adjust the coordinates
|
||
|
pod_object->afv3Vertex[u_i].X = (pod_object->afv3Vertex[u_i].X - f_trans_x) / f_scale;
|
||
|
pod_object->afv3Vertex[u_i].Y = (pod_object->afv3Vertex[u_i].Y - f_trans_y) / f_scale;
|
||
|
pod_object->afv3Vertex[u_i].Z = (pod_object->afv3Vertex[u_i].Z - f_trans_z) / f_scale;
|
||
|
|
||
|
// Log the results
|
||
|
// slLogfile.Printf("Vertex %3d: %7.2f, %7.2f, %7.2f\n", u_i, pod_object->afv3Vertex[u_i].X, pod_object->afv3Vertex[u_i].Y,
|
||
|
// pod_object->afv3Vertex[u_i].Z);
|
||
|
}
|
||
|
|
||
|
// Relocate the object to the origin.
|
||
|
float f_old_x;
|
||
|
float f_old_y;
|
||
|
float f_old_z;
|
||
|
|
||
|
// Get the previous position.
|
||
|
pod_object->GetPosition(f_old_x, f_old_y, f_old_z);
|
||
|
|
||
|
// Update the translation of the object to the newly centered position.
|
||
|
pod_object->Position(f_old_x + (f_trans_x * pod_object->fGetScale()),
|
||
|
f_old_y + (f_trans_y * pod_object->fGetScale()),
|
||
|
f_old_z + (f_trans_z * pod_object->fGetScale()));
|
||
|
|
||
|
// Place the object scale in the object so it can be restored.
|
||
|
pod_object->Scale(f_scale * pod_object->fGetScale());
|
||
|
|
||
|
// Loop through all the vertices, translate them to the object center of mass then
|
||
|
// scale the object into the unit cube.
|
||
|
for (u_i = 0; u_i < pod_object->uVertexCount; u_i++)
|
||
|
{
|
||
|
// Adjust the coordinates
|
||
|
pod_object->afv3Vertex[u_i].X /= f_scale;
|
||
|
pod_object->afv3Vertex[u_i].Y /= f_scale;
|
||
|
pod_object->afv3Vertex[u_i].Z /= f_scale;
|
||
|
|
||
|
// Log the results
|
||
|
slLogfile.Printf("Vertex %3d: %7.2f, %7.2f, %7.2f\n", u_i, pod_object->afv3Vertex[u_i].X, pod_object->afv3Vertex[u_i].Y,
|
||
|
pod_object->afv3Vertex[u_i].Z);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
slLogfile.Printf("\n");
|
||
|
|
||
|
|
||
|
// Return the result to the caller.
|
||
|
return b_result;
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
|
||
|
//******************************************************************************************
|
||
|
//
|
||
|
// Function for validating the geometry of an object.
|
||
|
//
|
||
|
bool CGeometry::bCheckFaces(CObjectDef* pod_object)
|
||
|
{
|
||
|
bool b_error = true; // Success.
|
||
|
|
||
|
//
|
||
|
// Start out by checking all the faces for degenerate polygons, then verify that the
|
||
|
// face normals are valid. This will occur by checking the following:
|
||
|
//
|
||
|
|
||
|
// Loop through all the vertices
|
||
|
for (uint u_i = 0; u_i < pod_object->uFaceCount; u_i++)
|
||
|
{
|
||
|
// All all the vertex indices in range?
|
||
|
if (pod_object->auv3Face[u_i].X >= pod_object->uVertexCount ||
|
||
|
pod_object->auv3Face[u_i].Y >= pod_object->uVertexCount ||
|
||
|
pod_object->auv3Face[u_i].Z >= pod_object->uVertexCount)
|
||
|
{
|
||
|
// Flag the error.
|
||
|
b_error = false;
|
||
|
|
||
|
// No! Log the error in the file.
|
||
|
slLogfile.Printf("Error: One or more vertex indices is out of range (0..%d): %d %d %d\n", pod_object->uVertexCount-1,
|
||
|
pod_object->auv3Face[u_i].X, pod_object->auv3Face[u_i].Y, pod_object->auv3Face[u_i].Z);
|
||
|
}
|
||
|
|
||
|
// Is the polygon degenerate due to vertex indices?
|
||
|
if (pod_object->auv3Face[u_i].X == pod_object->auv3Face[u_i].Y ||
|
||
|
pod_object->auv3Face[u_i].Y == pod_object->auv3Face[u_i].Z ||
|
||
|
pod_object->auv3Face[u_i].Z == pod_object->auv3Face[u_i].X)
|
||
|
{
|
||
|
// Flag the error.
|
||
|
b_error = false;
|
||
|
|
||
|
// No! Log the error in the file.
|
||
|
slLogfile.Printf("Error: Degenerate polygon detected: Polygon (%d): %d %d %d\n", pod_object->uFaceCount,
|
||
|
pod_object->auv3Face[u_i].X, pod_object->auv3Face[u_i].Y, pod_object->auv3Face[u_i].Z);
|
||
|
}
|
||
|
|
||
|
// Is the polygon degenerate due to vertices being to close together?
|
||
|
fvector3 fv3_vertex_0 = pod_object->afv3Vertex[pod_object->auv3Face[u_i].X];
|
||
|
fvector3 fv3_vertex_1 = pod_object->afv3Vertex[pod_object->auv3Face[u_i].Y];
|
||
|
fvector3 fv3_vertex_2 = pod_object->afv3Vertex[pod_object->auv3Face[u_i].Z];
|
||
|
|
||
|
// Is vertex 0 too close to vertex 1?
|
||
|
if (bTooClose(fv3_vertex_0, fv3_vertex_1))
|
||
|
{
|
||
|
// Flag the error.
|
||
|
b_error = false;
|
||
|
|
||
|
// No! Log the error in the file.
|
||
|
slLogfile.Printf("Error: Vertex proximity error: Polygon (%d): Vertices: 0:(%d) (%.3f %.3f %.3f), 1:(%d) (%.3f %.3f %.3f)\n",
|
||
|
u_i,
|
||
|
pod_object->auv3Face[u_i].X, fv3_vertex_0.X, fv3_vertex_0.Y, fv3_vertex_0.Z,
|
||
|
pod_object->auv3Face[u_i].Y, fv3_vertex_1.X, fv3_vertex_1.Y, fv3_vertex_1.Z);
|
||
|
}
|
||
|
|
||
|
// Is vertex 1 too close to vertex 2?
|
||
|
if (bTooClose(fv3_vertex_1, fv3_vertex_2))
|
||
|
{
|
||
|
// Flag the error.
|
||
|
b_error = false;
|
||
|
|
||
|
// No! Log the error in the file.
|
||
|
slLogfile.Printf("Error: Vertex proximity error: Polygon (%d): Vertices: 1:(%d) (%.3f %.3f %.3f), 2:(%d) (%.3f %.3f %.3f)\n",
|
||
|
u_i,
|
||
|
pod_object->auv3Face[u_i].Y, fv3_vertex_1.X, fv3_vertex_1.Y, fv3_vertex_1.Z,
|
||
|
pod_object->auv3Face[u_i].Z, fv3_vertex_2.X, fv3_vertex_2.Y, fv3_vertex_2.Z);
|
||
|
}
|
||
|
|
||
|
// Is vertex 0 too close to vertex 2?
|
||
|
if (bTooClose(fv3_vertex_0, fv3_vertex_2))
|
||
|
{
|
||
|
// Flag the error.
|
||
|
b_error = false;
|
||
|
|
||
|
// No! Log the error in the file.
|
||
|
slLogfile.Printf("Error: Vertex proximity error: Polygon (%d): Vertices: 0:(%d) (%.3f %.3f %.3f), 2:(%d) (%.3f %.3f %.3f)\n",
|
||
|
u_i,
|
||
|
pod_object->auv3Face[u_i].X, fv3_vertex_0.X, fv3_vertex_0.Y, fv3_vertex_0.Z,
|
||
|
pod_object->auv3Face[u_i].Z, fv3_vertex_2.X, fv3_vertex_2.Y, fv3_vertex_2.Z);
|
||
|
}
|
||
|
|
||
|
// Is the face normal valid?
|
||
|
if (fabs(pod_object->afv3FaceNormal[u_i].X) < TOO_CLOSE &&
|
||
|
fabs(pod_object->afv3FaceNormal[u_i].Y) < TOO_CLOSE &&
|
||
|
fabs(pod_object->afv3FaceNormal[u_i].Z) < TOO_CLOSE)
|
||
|
{
|
||
|
// Flag the error.
|
||
|
b_error = false;
|
||
|
|
||
|
// No! Log the error in the file.
|
||
|
slLogfile.Printf("Error: Degenerate normal detected on polygon %d\n", u_i);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Are the vertex normals valid?
|
||
|
//
|
||
|
for (uint u_j = 0; u_j < 3; u_j++)
|
||
|
{
|
||
|
// Is the face normal valid?
|
||
|
if (fabs(pod_object->afv3VertexNormal[u_i*3+u_j].X) < TOO_CLOSE &&
|
||
|
fabs(pod_object->afv3VertexNormal[u_i*3+u_j].Y) < TOO_CLOSE &&
|
||
|
fabs(pod_object->afv3VertexNormal[u_i*3+u_j].Z) < TOO_CLOSE)
|
||
|
{
|
||
|
// Flag the error.
|
||
|
b_error = false;
|
||
|
|
||
|
// No! Log the error in the file.
|
||
|
slLogfile.Printf("Error: Degenerate vertex normal detected on polygon %d, vertex %d: (0.0, 0.0, 0.0)\n", u_i, u_j);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Were any errors detected?
|
||
|
if (!b_error)
|
||
|
{
|
||
|
char str_msg[256];
|
||
|
// Yes! Throw up a dialog box reporting that something went wrong.
|
||
|
sprintf(str_msg, "Geometry errors detected when processing object: %s. See Geometry.log for details.\n",
|
||
|
pod_object->estrObjectName.strData());
|
||
|
|
||
|
guiInterface.bErrorMsg(str_msg);
|
||
|
}
|
||
|
|
||
|
|
||
|
// Return the result.
|
||
|
return b_error;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//******************************************************************************************
|
||
|
//
|
||
|
// Function for checking the texture coordinate information of an object.
|
||
|
//
|
||
|
bool CGeometry::bCheckTexCoords(CObjectDef* pod_object)
|
||
|
{
|
||
|
// Does this object have any textured materials?
|
||
|
if (pod_object->uTextureVertexCount > 0)
|
||
|
{
|
||
|
// Loop through all the texture vertices and make sure it falls in [0..1]
|
||
|
for (uint u_i = 0; u_i < pod_object->uTextureVertexCount; u_i++)
|
||
|
{
|
||
|
// Is the U coordinate < 0?
|
||
|
if (pod_object->afv2TextureVertex[u_i].X < -0.000001f)
|
||
|
{
|
||
|
// Log this to the file
|
||
|
slLogfile.Printf("Clamping u coordinate (%d) from %f to 0.0\n", u_i, pod_object->afv2TextureVertex[u_i].X);
|
||
|
|
||
|
// Clamp to 0.0
|
||
|
pod_object->afv2TextureVertex[u_i].X = 0.0f;
|
||
|
|
||
|
// Increment the UV clamp counter
|
||
|
iClampUVCoords++;
|
||
|
}
|
||
|
|
||
|
// Is the U coordinate > 1.0?
|
||
|
if (pod_object->afv2TextureVertex[u_i].X > 1.000001f)
|
||
|
{
|
||
|
// Log this to the file
|
||
|
slLogfile.Printf("Clamping u coordinate (%d) from %f to 1.0\n", u_i, pod_object->afv2TextureVertex[u_i].X);
|
||
|
|
||
|
// Clamp to 1.0
|
||
|
pod_object->afv2TextureVertex[u_i].X = 1.0f;
|
||
|
|
||
|
// Increment the UV clamp counter
|
||
|
iClampUVCoords++;
|
||
|
}
|
||
|
|
||
|
float y = (float) fabs(pod_object->afv2TextureVertex[u_i].Y);
|
||
|
|
||
|
// Is the V coordinate < 0?
|
||
|
if (pod_object->afv2TextureVertex[u_i].Y < -0.000001f)
|
||
|
{
|
||
|
// Log this to the file
|
||
|
slLogfile.Printf("Clamping V coordinate (%d) from %f to 0.0\n", u_i, pod_object->afv2TextureVertex[u_i].Y);
|
||
|
|
||
|
// Clamp to 0.0
|
||
|
pod_object->afv2TextureVertex[u_i].Y = 0.0f;
|
||
|
|
||
|
// Increment the UV clamp counter
|
||
|
iClampUVCoords++;
|
||
|
}
|
||
|
|
||
|
// Is the V coordinate > 1.0?
|
||
|
if (pod_object->afv2TextureVertex[u_i].Y > 1.000001f)
|
||
|
{
|
||
|
// Log this to the file
|
||
|
slLogfile.Printf("Clamping V coordinate (%d) from %f to 1.0\n", u_i, pod_object->afv2TextureVertex[u_i].Y);
|
||
|
|
||
|
// Clamp to 1.0
|
||
|
pod_object->afv2TextureVertex[u_i].Y = 1.0f;
|
||
|
|
||
|
// Increment the UV clamp counter
|
||
|
iClampUVCoords++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// No texture vertices. This is definitely an error.
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// Were any errors detected?
|
||
|
if (iClampUVCoords > 0)
|
||
|
{
|
||
|
// Yes! Throw up a dialog box reporting that something went wrong.
|
||
|
slLogfile.Printf("Texture coordinate errors detected when processing: %s. See Geometry.log for details.\n",
|
||
|
pod_object->estrObjectName.strData());
|
||
|
}
|
||
|
|
||
|
// Advance the log file.
|
||
|
slLogfile.Printf("\n");
|
||
|
|
||
|
|
||
|
// Return a successful result
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
//******************************************************************************************
|
||
|
//
|
||
|
// Function for checking the material information associated with an object.
|
||
|
//
|
||
|
bool CGeometry::bCheckMaterials(CObjectDef* pod_object)
|
||
|
{
|
||
|
char str_message[256];
|
||
|
uint u_i;
|
||
|
bool b_result = true;
|
||
|
bool b_processing_error = false;
|
||
|
uint u_material_count = pod_object->uMaterialCount;
|
||
|
|
||
|
|
||
|
// Does this object have any materials?
|
||
|
if (u_material_count > 0)
|
||
|
{
|
||
|
// Make sure all the material slots have at least a diffuse map.
|
||
|
for (u_i = 0; u_i < u_material_count; u_i++)
|
||
|
{
|
||
|
// Does this slot have a material?
|
||
|
if (pod_object->astrTextureMap[u_i] == 0)
|
||
|
{
|
||
|
// No! This is definitely an error so report it.
|
||
|
sprintf(str_message, "Error: Object %s has %d materials and slot %d is empty.\n",
|
||
|
pod_object->estrObjectName.strData(), u_material_count, u_i);
|
||
|
slLogfile.Printf(str_message);
|
||
|
|
||
|
// Display the error in a dialog box to the user.
|
||
|
guiInterface.bErrorMsg(str_message);
|
||
|
|
||
|
// Signal the fact that there was an error.
|
||
|
b_result = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Loop through all the texture vertices and make sure it falls in [0..1]
|
||
|
for (u_i = 0; u_i < pod_object->uFaceCount; u_i++)
|
||
|
{
|
||
|
// Is the material ID in range?
|
||
|
if (pod_object->auFaceMaterialIndex[u_i] >= u_material_count)
|
||
|
{
|
||
|
//
|
||
|
// No! Determine if this is a single material object since single material objects
|
||
|
// can have multiple material ID's but only one material.
|
||
|
//
|
||
|
if (u_material_count == 1)
|
||
|
{
|
||
|
slLogfile.Printf("Single-material requires ID's to be clamped to 0 from (%d).\n", pod_object->auFaceMaterialIndex[u_i]);
|
||
|
// Clamp the material ID to 0.
|
||
|
pod_object->auFaceMaterialIndex[u_i] = 0;
|
||
|
|
||
|
iClampMaterialIDs++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sprintf(str_message, "Multi-material ID (%d) is out of range (0..%d).\n", pod_object->auFaceMaterialIndex[u_i], u_material_count-1);
|
||
|
|
||
|
// Set the error flag.
|
||
|
b_result = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// There are no materials for this node, return an error. At some point it would be nice if a 'default' material
|
||
|
// representing a visual error message, could be mapped onto the object so it could be rendered flat.
|
||
|
//
|
||
|
slLogfile.Printf("Error: No materials are present for object: %s\n", pod_object->estrObjectName.strData());
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (iClampMaterialIDs)
|
||
|
{
|
||
|
// Advance the log file.
|
||
|
slLogfile.Printf("\n");
|
||
|
}
|
||
|
|
||
|
// Return the result
|
||
|
return b_result;
|
||
|
}
|
||
|
|
||
|
|
||
|
//******************************************************************************************
|
||
|
//
|
||
|
// Function for reseting the export statistics.
|
||
|
//
|
||
|
void CGeometry::ResetStatistics()
|
||
|
{
|
||
|
// Reset these before processing each object
|
||
|
iDegenerateFaces = 0;
|
||
|
iRemovedVertices = 0;
|
||
|
iClampUVCoords = 0;
|
||
|
iClampMaterialIDs = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
//******************************************************************************************
|
||
|
//
|
||
|
// Function for printing the statistics.
|
||
|
//
|
||
|
void CGeometry::PrintStatistics()
|
||
|
{
|
||
|
// Reset these before processing each object
|
||
|
slLogfile.Printf("\nProcessing complete.\n");
|
||
|
slLogfile.Printf(" Degenerate polygons : %d\n", iDegenerateFaces);
|
||
|
slLogfile.Printf(" Dangling vertices : %d\n", iRemovedVertices);
|
||
|
slLogfile.Printf(" Clamped UV coordinates : %d\n", iClampUVCoords);
|
||
|
slLogfile.Printf(" Clamped Material ID's : %d\n\n", iClampMaterialIDs);
|
||
|
}
|
||
|
|