/*=========================================================================== * * File: DF_3DSTex.CPP * Author: Dave Humphrey (uesp@m0use.net) * Created On: Friday, March 22, 2002 * * Implements 3DS specific texture and material related export functions * for Daggerfall 3D objects. * *=========================================================================*/ /* Include Files */ #include "df3dexpo.h" #include "bsa/df3dutil.h" #include "dagger/image/dftexdat.h" /*=========================================================================== * * Begin Local Variable Definitions * *=========================================================================*/ DEFINE_FILE(); /* Local type for matrix conversion parameters */ typedef struct { float X[4], Y[4], Z[4]; float U[4], V[4]; } df3duvparams_lt; /*=========================================================================== * End of Local Variable Definitions *=========================================================================*/ /*=========================================================================== * * Local Function - boolean l_ComputeDFUVMatrixXY (Matrix, Params); * * Computes the UV conversion parameters from the given input based on * the formula: * U = AX + BY + D * * Returns FALSE on any error. For use on faces with 0 Z-coordinates. * *=========================================================================*/ boolean l_ComputeDFUVMatrixXY (df3duvmatrix_t& Matrix, const df3duvparams_lt& Params) { float Determinant; float Xi[3], Yi[3], Zi[3]; /* Compute the determinant of the coefficient matrix */ Determinant = Params.X[0]*Params.Y[1] + Params.Y[0]*Params.X[2] + Params.X[1]*Params.Y[2] - Params.Y[1]*Params.X[2] - Params.Y[0]*Params.X[1] - Params.X[0]*Params.Y[2]; /* Check for a singular matrix indicating no valid solution */ if (Determinant == 0) { ErrorHandler.AddError(ERR_CUSTOM, "Cannot compute the UV conversion matrix, singular XY determinant!"); return (FALSE); } /* Compute parameters of the the inverted XYZ matrix */ Xi[0] = ( Params.Y[1] - Params.Y[2]) / Determinant; Xi[1] = (-Params.X[1] + Params.X[2]) / Determinant; Xi[2] = ( Params.X[1]*Params.Y[2] - Params.X[2]*Params.Y[1]) / Determinant; Yi[0] = (-Params.Y[0] + Params.Y[2]) / Determinant; Yi[1] = ( Params.X[0] - Params.X[2]) / Determinant; Yi[2] = (-Params.X[0]*Params.Y[2] + Params.X[2]*Params.Y[0]) / Determinant; Zi[0] = ( Params.Y[0] - Params.Y[1]) / Determinant; Zi[1] = (-Params.X[0] + Params.X[1]) / Determinant; Zi[2] = ( Params.X[0]*Params.Y[1] - Params.X[1]*Params.Y[0]) / Determinant; /* Compute the UV conversion parameters */ Matrix.UA = (Params.U[0]*Xi[0] + Params.U[1]*Yi[0] + Params.U[2]*Zi[0]); Matrix.UB = (Params.U[0]*Xi[1] + Params.U[1]*Yi[1] + Params.U[2]*Zi[1]); Matrix.UC = (float) 0.0; Matrix.UD = (Params.U[0]*Xi[2] + Params.U[1]*Yi[2] + Params.U[2]*Zi[2]);; Matrix.VA = (Params.V[0]*Xi[0] + Params.V[1]*Yi[0] + Params.V[2]*Zi[0]); Matrix.VB = (Params.V[0]*Xi[1] + Params.V[1]*Yi[1] + Params.V[2]*Zi[1]); Matrix.VC = (float) 0.0; Matrix.VD = (Params.V[0]*Xi[2] + Params.V[1]*Yi[2] + Params.V[2]*Zi[2]); return (TRUE); } /*=========================================================================== * End of Function l_ComputeDFUVMatrixXY() *=========================================================================*/ /*=========================================================================== * * Local Function - boolean l_ComputeDFUVMatrixXZ (Matrix, Params); * * Computes the UV conversion parameters from the given input based on * the formula: * U = AX + CZ + D * * Returns FALSE on any error. For use on faces with 0 Y-coordinates. * *=========================================================================*/ boolean l_ComputeDFUVMatrixXZ (df3duvmatrix_t& Matrix, const df3duvparams_lt& Params) { float Determinant; float Xi[3], Yi[3], Zi[3]; /* Compute the determinant of the coefficient matrix */ Determinant = Params.X[0]*Params.Z[2] + Params.Z[1]*Params.X[2] + Params.Z[0]*Params.X[1] - Params.Z[0]*Params.X[2] - Params.X[1]*Params.Z[2] - Params.X[0]*Params.Z[1]; /* Check for a singular matrix indicating no valid solution */ if (Determinant == 0) { ErrorHandler.AddError(ERR_CUSTOM, "Cannot compute the UV conversion matrix, singular XZ determinant!"); return (FALSE); } /* Compute parameters of the the inverted XYZ matrix */ Xi[0] = ( Params.Z[2] - Params.Z[1]) / Determinant; Xi[1] = (-Params.X[1]*Params.Z[2] + Params.X[2]*Params.Z[1]) / Determinant; Xi[2] = ( Params.X[1] - Params.X[2]) / Determinant; Yi[0] = (-Params.Z[2] + Params.Z[0]) / Determinant; Yi[1] = ( Params.X[0]*Params.Z[2] - Params.X[2]*Params.Z[0]) / Determinant; Yi[2] = (-Params.X[0] + Params.X[2]) / Determinant; Zi[0] = ( Params.Z[1] - Params.Z[0]) / Determinant; Zi[1] = (-Params.X[0]*Params.Z[1] + Params.X[1]*Params.Z[0]) / Determinant; Zi[2] = ( Params.X[0] - Params.X[1]) / Determinant; /* Compute the UV conversion parameters */ Matrix.UA = (Params.U[0]*Xi[0] + Params.U[1]*Yi[0] + Params.U[2]*Zi[0]); Matrix.UB = (float) 0.0; Matrix.UC = (Params.U[0]*Xi[2] + Params.U[1]*Yi[2] + Params.U[2]*Zi[2]); Matrix.UD = (Params.U[0]*Xi[1] + Params.U[1]*Yi[1] + Params.U[2]*Zi[1]); Matrix.VA = (Params.V[0]*Xi[0] + Params.V[1]*Yi[0] + Params.V[2]*Zi[0]); Matrix.VB = (float) 0.0; Matrix.VC = (Params.V[0]*Xi[2] + Params.V[1]*Yi[2] + Params.V[2]*Zi[2]); Matrix.VD = (Params.V[0]*Xi[1] + Params.V[1]*Yi[1] + Params.V[2]*Zi[1]); return (TRUE); } /*=========================================================================== * End of Function l_ComputeDFUVMatrixXZ() *=========================================================================*/ /*=========================================================================== * * Local Function - boolean l_ComputeDFUVMatrixYZ (Matrix, Params); * * Computes the UV conversion parameters from the given input based on * the formula: * U = BY + CZ + D * * Returns FALSE on any error. For use on faces with 0 X-coordinates. * *=========================================================================*/ boolean l_ComputeDFUVMatrixYZ (df3duvmatrix_t& Matrix, const df3duvparams_lt& Params) { float Determinant; float Xi[3], Yi[3], Zi[3]; /* Compute the determinant of the coefficient matrix */ Determinant = Params.Y[1]*Params.Z[2] + Params.Y[0]*Params.Z[1] + Params.Z[0]*Params.Y[2] - Params.Z[0]*Params.Y[1] - Params.Y[0]*Params.Z[2] - Params.Z[1]*Params.Y[2]; /* Check for a singular matrix indicating no valid solution */ if (Determinant == 0) { ErrorHandler.AddError(ERR_CUSTOM, "Cannot compute the UV conversion matrix, singular YZ determinant!"); return (FALSE); } /* Compute parameters of the the inverted XYZ matrix */ Xi[0] = ( Params.Y[1]*Params.Z[2] - Params.Y[2]*Params.Z[1]) / Determinant; Xi[1] = (-Params.Z[2] + Params.Z[1]) / Determinant; Xi[2] = ( Params.Y[2] - Params.Y[1]) / Determinant; Yi[0] = (-Params.Y[0]*Params.Z[2] + Params.Y[2]*Params.Z[0]) / Determinant; Yi[1] = ( Params.Z[2] - Params.Z[0]) / Determinant; Yi[2] = (-Params.Y[2] + Params.Y[0]) / Determinant; Zi[0] = ( Params.Y[0]*Params.Z[1] - Params.Y[1]*Params.Z[0]) / Determinant; Zi[1] = (-Params.Z[1] + Params.Z[0]) / Determinant; Zi[2] = ( Params.Y[1] - Params.Y[0]) / Determinant; /* Compute the UV conversion parameters */ Matrix.UA = (float) 0.0; Matrix.UB = (Params.U[0]*Xi[1] + Params.U[1]*Yi[1] + Params.U[2]*Zi[1]); Matrix.UC = (Params.U[0]*Xi[2] + Params.U[1]*Yi[2] + Params.U[2]*Zi[2]); Matrix.UD = (Params.U[0]*Xi[0] + Params.U[1]*Yi[0] + Params.U[2]*Zi[0]); Matrix.VA = (float) 0.0; Matrix.VB = (Params.V[0]*Xi[1] + Params.V[1]*Yi[1] + Params.V[2]*Zi[1]); Matrix.VC = (Params.V[0]*Xi[2] + Params.V[1]*Yi[2] + Params.V[2]*Zi[2]); Matrix.VD = (Params.V[0]*Xi[0] + Params.V[1]*Yi[0] + Params.V[2]*Zi[0]); return (TRUE); } /*=========================================================================== * End of Function l_ComputeDFUVMatrixYZ() *=========================================================================*/ /*=========================================================================== * * Local Function - boolean l_ComputeDFUVMatrixXYZ (Matrix, Params); * * Computes the UV conversion parameters from the given input based on * the formula: * U = AX + BY + CZ * * Returns FALSE on any error. * *=========================================================================*/ boolean l_ComputeDFUVMatrixXYZ (df3duvmatrix_t& Matrix, const df3duvparams_lt& Params) { float Determinant; float Xi[3], Yi[3], Zi[3]; /* Compute the determinant of the coefficient matrix */ Determinant = Params.X[0]*Params.Y[1]*Params.Z[2] + Params.Y[0]*Params.Z[1]*Params.X[2] + Params.Z[0]*Params.X[1]*Params.Y[2] - Params.Z[0]*Params.Y[1]*Params.X[2] - Params.Y[0]*Params.X[1]*Params.Z[2] - Params.X[0]*Params.Z[1]*Params.Y[2]; /* Check for a singular matrix indicating no valid solution */ if (Determinant == 0) { ErrorHandler.AddError(ERR_CUSTOM, "Cannot compute the UV conversion matrix, singular XYZ determinant!"); return (FALSE); } /* Compute values of the the inverted XYZ matrix */ Xi[0] = ( Params.Y[1]*Params.Z[2] - Params.Y[2]*Params.Z[1]) / Determinant; Xi[1] = (-Params.X[1]*Params.Z[2] + Params.X[2]*Params.Z[1]) / Determinant; Xi[2] = ( Params.X[1]*Params.Y[2] - Params.X[2]*Params.Y[1]) / Determinant; Yi[0] = (-Params.Y[0]*Params.Z[2] + Params.Y[2]*Params.Z[0]) / Determinant; Yi[1] = ( Params.X[0]*Params.Z[2] - Params.X[2]*Params.Z[0]) / Determinant; Yi[2] = (-Params.X[0]*Params.Y[2] + Params.X[2]*Params.Y[0]) / Determinant; Zi[0] = ( Params.Y[0]*Params.Z[1] - Params.Y[1]*Params.Z[0]) / Determinant; Zi[1] = (-Params.X[0]*Params.Z[1] + Params.X[1]*Params.Z[0]) / Determinant; Zi[2] = ( Params.X[0]*Params.Y[1] - Params.X[1]*Params.Y[0]) / Determinant; /* Compute the UV conversion parameters */ Matrix.UA = (Params.U[0]*Xi[0] + Params.U[1]*Yi[0] + Params.U[2]*Zi[0]); Matrix.UB = (Params.U[0]*Xi[1] + Params.U[1]*Yi[1] + Params.U[2]*Zi[1]); Matrix.UC = (Params.U[0]*Xi[2] + Params.U[1]*Yi[2] + Params.U[2]*Zi[2]); Matrix.UD = (float) 0.0; Matrix.VA = (Params.V[0]*Xi[0] + Params.V[1]*Yi[0] + Params.V[2]*Zi[0]); Matrix.VB = (Params.V[0]*Xi[1] + Params.V[1]*Yi[1] + Params.V[2]*Zi[1]); Matrix.VC = (Params.V[0]*Xi[2] + Params.V[1]*Yi[2] + Params.V[2]*Zi[2]); Matrix.VD = (float) 0.0; return (TRUE); } /*=========================================================================== * End of Function l_ComputeDFUVMatrixXYZ() *=========================================================================*/ /*=========================================================================== * * Local Function - boolean l_ComputeDFUVMatrixXYZ1 (Matrix, Params); * * Computes the UV conversion parameters from the given input based on * the formula: * U = AX + BY + CZ + D * * Returns FALSE on any error. Only valid for faces that have more than * 3 points. * *=========================================================================*/ boolean l_ComputeDFUVMatrixXYZ1 (df3duvmatrix_t& Matrix, const df3duvparams_lt& Params) { float Determinant; float Xi[4], Yi[4], Zi[4], Ai[4]; /* Compute the determinant of the coefficient matrix */ Determinant = Params.X[0]*Params.Y[1]*Params.Z[2] -Params.X[0]*Params.Y[1]*Params.Z[3] +Params.X[0]*Params.Z[1]*Params.Y[3] -Params.X[0]*Params.Z[1]*Params.Y[2] +Params.X[0]*Params.Y[2]*Params.Z[3] -Params.X[0]*Params.Z[2]*Params.Y[3] -Params.Y[0]*Params.Z[1]*Params.X[3] +Params.Y[0]*Params.Z[1]*Params.X[2] -Params.Y[0]*Params.X[2]*Params.Z[3] +Params.Y[0]*Params.Z[2]*Params.X[3] -Params.Y[0]*Params.X[1]*Params.Z[2] +Params.Y[0]*Params.X[1]*Params.Z[3] +Params.Z[0]*Params.X[2]*Params.Y[3] -Params.Z[0]*Params.Y[2]*Params.X[3] +Params.Z[0]*Params.X[1]*Params.Y[2] -Params.Z[0]*Params.X[1]*Params.Y[3] +Params.Z[0]*Params.Y[1]*Params.X[3] -Params.Z[0]*Params.Y[1]*Params.X[2] -Params.X[1]*Params.Y[2]*Params.Z[3] +Params.X[1]*Params.Z[2]*Params.Y[3] -Params.Y[1]*Params.Z[2]*Params.X[3] +Params.Y[1]*Params.X[2]*Params.Z[3] -Params.Z[1]*Params.X[2]*Params.Y[3] +Params.Z[1]*Params.Y[2]*Params.X[3]; /* Check for a singular matrix indicating no valid solution */ if (Determinant == 0) { ErrorHandler.AddError(ERR_CUSTOM, "Cannot compute the UV conversion matrix, singular XYZ1 determinant!"); return (FALSE); } /* Compute values of the the inverted XYZ matrix */ Xi[0] = Params.Y[1]*Params.Z[2] + Params.Z[1]*Params.Y[3] + Params.Y[2]*Params.Z[3] - Params.Y[3]*Params.Z[2] - Params.Y[2]*Params.Z[1] - Params.Y[1]*Params.Z[3]; Xi[1] = -Params.X[1]*Params.Z[2] - Params.Z[1]*Params.X[3] - Params.X[2]*Params.Z[3] + Params.X[3]*Params.Z[2] + Params.X[2]*Params.Z[1] + Params.X[1]*Params.Z[3]; Xi[2] = Params.X[1]*Params.Y[2] + Params.Y[1]*Params.X[3] + Params.X[2]*Params.Y[3] - Params.X[3]*Params.Y[2] - Params.X[2]*Params.Y[1] - Params.X[1]*Params.Y[3]; Xi[3] = -Params.X[1]*Params.Y[2]*Params.Z[3] - Params.Y[1]*Params.Z[2]*Params.X[3] - Params.Z[1]*Params.X[2]*Params.Y[3] + Params.X[3]*Params.Y[2]*Params.Z[1] + Params.X[2]*Params.Y[1]*Params.Z[3] + Params.X[1]*Params.Y[3]*Params.Z[2]; Yi[0] = -Params.Y[0]*Params.Z[2] - Params.Z[0]*Params.Y[3] - Params.Y[2]*Params.Z[3] + Params.Y[3]*Params.Z[2] + Params.Y[2]*Params.Z[0] + Params.Y[0]*Params.Z[3]; Yi[1] = Params.X[0]*Params.Z[2] + Params.Z[0]*Params.X[3] + Params.X[2]*Params.Z[3] - Params.X[3]*Params.Z[2] - Params.X[2]*Params.Z[0] - Params.X[0]*Params.Z[3]; Yi[2] = -Params.X[0]*Params.Y[2] - Params.Y[0]*Params.X[3] - Params.X[2]*Params.Y[3] + Params.X[3]*Params.Y[2] + Params.X[2]*Params.Y[0] + Params.X[0]*Params.Y[3]; Yi[3] = Params.X[0]*Params.Y[2]*Params.Z[3] + Params.Y[0]*Params.Z[2]*Params.X[3] + Params.Z[0]*Params.X[2]*Params.Y[3] - Params.X[3]*Params.Y[2]*Params.Z[0] - Params.X[2]*Params.Y[0]*Params.Z[3] - Params.X[0]*Params.Y[3]*Params.Z[2]; Zi[0] = Params.Y[0]*Params.Z[1] + Params.Z[0]*Params.Y[3] + Params.Y[1]*Params.Z[3] -Params.Y[3]*Params.Z[1] - Params.Y[0]*Params.Z[0] - Params.Y[0]*Params.Z[3]; Zi[1] = -Params.X[0]*Params.Z[1] - Params.Z[0]*Params.Y[3] - Params.X[1]*Params.Z[3] + Params.X[3]*Params.Z[1] + Params.X[1]*Params.Z[0] + Params.X[0]*Params.Z[3]; Zi[2] = Params.X[0]*Params.Y[1] + Params.Y[0]*Params.X[3] + Params.X[1]*Params.Y[3] - Params.X[3]*Params.Y[1] - Params.X[1]*Params.Y[0] - Params.X[0]*Params.Y[3]; Zi[3] = -Params.X[0]*Params.Y[1]*Params.Z[3] - Params.Y[0]*Params.Z[1]*Params.X[3] - Params.Z[0]*Params.X[1]*Params.Y[3] + Params.X[3]*Params.Y[1]*Params.Z[0] + Params.Z[1]*Params.Y[0]*Params.Z[3] + Params.X[0]*Params.Y[3]*Params.Z[1]; Ai[0] = -Params.Y[0]*Params.Z[1] - Params.Z[0]*Params.Y[2] - Params.Y[1]*Params.Z[2] + Params.Y[2]*Params.Z[1] + Params.Y[1]*Params.Z[0] + Params.Y[0]*Params.Z[2]; Ai[1] = Params.X[0]*Params.Z[1] + Params.Z[0]*Params.X[2] + Params.X[1]*Params.Z[2] - Params.X[1]*Params.Z[1] - Params.X[1]*Params.Z[0] - Params.X[0]*Params.Z[2]; Ai[2] = -Params.X[0]*Params.Y[1] - Params.Y[0]*Params.X[2] - Params.X[1]*Params.Y[2] + Params.X[2]*Params.Y[1] + Params.X[1]*Params.Y[0] + Params.X[0]*Params.Y[2]; Ai[3] = Params.X[0]*Params.Y[1]*Params.Z[2] + Params.Y[0]*Params.Z[1]*Params.X[2] + Params.Z[0]*Params.X[1]*Params.Y[2] - Params.X[2]*Params.Y[1]*Params.Z[0] - Params.X[1]*Params.Y[0]*Params.Z[2] - Params.X[0]*Params.Y[2]*Params.Z[1]; /* Compute the UV conversion parameters */ Matrix.UA = (Params.U[0]*Xi[0] + Params.U[1]*Yi[0] + Params.U[2]*Zi[0] + Params.U[3]*Ai[0]) / Determinant; Matrix.UB = (Params.U[0]*Xi[1] + Params.U[1]*Yi[1] + Params.U[2]*Zi[1] + Params.U[3]*Ai[1]) / Determinant; Matrix.UC = (Params.U[0]*Xi[2] + Params.U[1]*Yi[2] + Params.U[2]*Zi[2] + Params.U[3]*Ai[2]) / Determinant; Matrix.UD = (Params.U[0]*Xi[3] + Params.U[1]*Yi[3] + Params.U[2]*Zi[3] + Params.U[3]*Ai[3]) / Determinant; Matrix.VA = (Params.V[0]*Xi[0] + Params.V[1]*Yi[0] + Params.V[2]*Zi[0] + Params.V[3]*Ai[0]) / Determinant; Matrix.VB = (Params.V[0]*Xi[1] + Params.V[1]*Yi[1] + Params.V[2]*Zi[1] + Params.V[3]*Ai[1]) / Determinant; Matrix.VC = (Params.V[0]*Xi[2] + Params.V[1]*Yi[2] + Params.V[2]*Zi[2] + Params.V[3]*Ai[2]) / Determinant; Matrix.VD = (Params.V[0]*Xi[3] + Params.V[1]*Yi[3] + Params.V[2]*Zi[3] + Params.V[3]*Ai[3]) / Determinant; return (TRUE); } /*=========================================================================== * End of Function l_ComputeDFUVMatrixXYZ1() *=========================================================================*/ /*=========================================================================== * * Function - boolean ComputeDFFaceTextureUVMatrix (Matrix, Face, Object); * * Calculates the transformation parameters to convert the face XYZ coordinates * to texture UV coordinates for the given face, storing in the given matrix. * Returns FALSE on any error. The function computes the A, B...F parameters * for the equations: * U = AX + BY + CZ * V = DX + EY + FZ * *=========================================================================*/ boolean ComputeDFFaceTextureUVMatrix (df3duvmatrix_t& Matrix, const df3dface_t& Face, const CDF3dObject& Object) { DEFINE_FUNCTION("ComputeDFFaceTextureUVMatrix()"); df3dpoint_t* pPoint; df3duvparams_lt Params; boolean Result; /* Ensure valid input */ ASSERT(Face.NumPoints >= 3); /* Initialize the conversion matrix */ Matrix.UA = (float) 1.0; Matrix.UB = (float) 0.0; Matrix.UC = (float) 0.0; Matrix.UD = (float) 0.0; Matrix.VA = (float) 0.0; Matrix.VB = (float) 1.0; Matrix.VC = (float) 0.0; Matrix.UD = (float) 0.0; /* Store the first 3 points of texture coordinates */ Params.U[0] = (float) Face.FaceData[0].TextureU; Params.U[1] = (float) Face.FaceData[1].TextureU + Params.U[0]; Params.U[2] = (float) Face.FaceData[2].TextureU + Params.U[1]; Params.V[0] = (float) Face.FaceData[0].TextureV; Params.V[1] = (float) Face.FaceData[1].TextureV + Params.V[0]; Params.V[2] = (float) Face.FaceData[2].TextureV + Params.V[1]; /* Get and store the 1st point coordinates in face */ pPoint = ((CDF3dObject &)Object).GetFacePoint(Face.FaceData[0].PointOffset); Params.X[0] = (float) pPoint->X; Params.Y[0] = (float) pPoint->Y; Params.Z[0] = (float) pPoint->Z; /* Get and store the 2nd point coordinates in face */ pPoint = ((CDF3dObject &)Object).GetFacePoint(Face.FaceData[1].PointOffset); Params.X[1] = (float) pPoint->X; Params.Y[1] = (float) pPoint->Y; Params.Z[1] = (float) pPoint->Z; /* Get and store the 3rd point coordinates in face */ pPoint = ((CDF3dObject &)Object).GetFacePoint(Face.FaceData[2].PointOffset); Params.X[2] = (float) pPoint->X; Params.Y[2] = (float) pPoint->Y; Params.Z[2] = (float) pPoint->Z; /* get and store the 4th store coordinates, if any */ if (Face.NumPoints > 3) { pPoint = ((CDF3dObject &)Object).GetFacePoint(Face.FaceData[3].PointOffset); Params.X[3] = (float) pPoint->X; Params.Y[3] = (float) pPoint->Y; Params.Z[3] = (float) pPoint->Z; Params.U[3] = (float) Face.FaceData[3].TextureU; Params.V[3] = (float) Face.FaceData[3].TextureV; /* Attempt to use a 4x4 matrix solution if the previous ones failed */ //Result = l_ComputeDFUVMatrixXYZ1(Matrix, Params); //SystemLog.Printf ("\tMatrixXYZ1 = %d", Result); //if (Result) return (TRUE); } else { Params.X[3] = (float) 0.0; Params.Y[3] = (float) 0.0; Params.Z[3] = (float) 0.0; Params.U[3] = (float) 0.0; Params.V[3] = (float) 0.0; } /* Compute the solution using an XY linear equation */ if (Params.X[0] == Params.Z[0] && Params.X[1] == Params.Z[1] && Params.X[2] == Params.Z[2]) { Result = l_ComputeDFUVMatrixXY(Matrix, Params); } /* Compute the solution using an XZ linear equation */ else if (Params.Y[0] == Params.Y[1] && Params.Y[1] == Params.Y[2]) { Result = l_ComputeDFUVMatrixXZ(Matrix, Params); } /* Compute the solution using an XY linear equation */ else if (Params.Z[0] == Params.Z[1] && Params.Z[1] == Params.Z[2]) { Result = l_ComputeDFUVMatrixXY(Matrix, Params); } /* Compute the solution using an YZ linear equation */ else if (Params.X[0] == Params.X[1] && Params.X[1] == Params.X[2]) { Result = l_ComputeDFUVMatrixYZ(Matrix, Params); } /* Compute the solution using an XYZ linear equation */ else { Result = l_ComputeDFUVMatrixXYZ(Matrix, Params); } /* On failure try different solutions */ if (!Result) { Result = l_ComputeDFUVMatrixXYZ(Matrix, Params); if (!Result) Result = l_ComputeDFUVMatrixXY(Matrix, Params); if (!Result) Result = l_ComputeDFUVMatrixXZ(Matrix, Params); if (!Result) Result = l_ComputeDFUVMatrixYZ(Matrix, Params); } /* Attempt to use a 4x4 matrix solution if the previous ones failed */ /* if (!Result) { Result = l_ComputeDFUVMatrixXYZ1(Matrix, Params); #if defined(_DEBUG) SystemLog.Printf ("\tMatrixXYZ1 = %d", Result); #endif } //*/ #if defined(_DEBUG) //SystemLog.Printf ("\tMatrixU = %f, %f, %f", Matrix.UA, Matrix.UB, Matrix.UC); //SystemLog.Printf ("\tMatrixV = %f, %f, %f", Matrix.VA, Matrix.VB, Matrix.VC); if (!Result) { SystemLog.Printf ("\tNumPoints = %d, Texture = %d", Face.NumPoints, Face.TextureIndex); SystemLog.Printf ("\t%6g, %6g, %6g = %6g, %6g", Params.X[0], Params.Y[0], Params.Z[0], Params.U[0], Params.V[0]); SystemLog.Printf ("\t%6g, %6g, %6g = %6g, %6g", Params.X[1], Params.Y[1], Params.Z[1], Params.U[1], Params.V[1]); SystemLog.Printf ("\t%6g, %6g, %6g = %6g, %6g", Params.X[2], Params.Y[2], Params.Z[2], Params.U[2], Params.V[2]); SystemLog.Printf ("\t%6g, %6g, %6g = %6g, %6g", Params.X[3], Params.Y[3], Params.Z[3], Params.U[3], Params.V[3]); } #endif return (Result); } /*=========================================================================== * End of Function ComputeDFFaceTextureUVMatrix() *=========================================================================*/ /*=========================================================================== * * Function - char* CreateDF3DSMaterialName (TextureIndex, ImageIndex); * * Creates a stadard material name from the given texture indices. Returns * a valid static string which is overwritten on subsequent calls. * *=========================================================================*/ char* CreateDF3DSMaterialName (const int TextureIndex, const int ImageIndex) { static char s_MatName[64]; sprintf (s_MatName, "DF%03d_%03d", TextureIndex, ImageIndex); return (s_MatName); } /*=========================================================================== * End of Function CreateDF3DSMaterialName() *=========================================================================*/ /*=========================================================================== * * Function - char* CreateDF3DSTextureName (TextureIndex, ImageIndex); * * Creates a standard texture name from the given texture indices. Returns * a valid static string which is overwritten on subsequent calls. The * texture name should conform to the standard 8.3 DOS filename format. * *=========================================================================*/ char* CreateDF3DSTextureName (const int TextureIndex, const int ImageIndex) { static char s_TextureName[64]; sprintf (s_TextureName, "df%03d%03d.bmp", TextureIndex, ImageIndex); return (s_TextureName); } /*=========================================================================== * End of Function CreateDF3DSTextureName() *=========================================================================*/ /*=========================================================================== * * Function - int l_ExportDFMaterialTo3DS (DFFace, pData); * * Export the material for the given face to the 3DS file (contained in the * callback data pointer). Only outputs textures not previously output by * checking the face tag. Returns a negative value on any error. Used * as a callback function for the CDF3dObject::ForEachFace() method. * *=========================================================================*/ int l_ExportDFMaterialTo3DS (df3dface_t& DFFace, void* pData) { DEFINE_FUNCTION("l_ExportDFMaterialTo3DS()"); df3dexport3ds_t* pCallbackData = (df3dexport3ds_t *) pData; boolean Result; char* pMatName; char* pTextureName; /* Ignore any tagged faces */ if (DFFace.Tag != 0) return (0); /* Create the material and texture names */ pMatName = CreateDF3DSMaterialName(DFFace.TextureIndex, DFFace.SubImageIndex); pTextureName = CreateDF3DSTextureName (DFFace.TextureIndex, DFFace.SubImageIndex); /* Check for the special case of a solid color texture */ if (IsDFTextureSolidColor(DFFace.TextureIndex)) { rgbpalraw_t RawColor = GetDFTextureSolidColor(DFFace.TextureIndex, DFFace.SubImageIndex); Result = pCallbackData->pFile3DS->OutputMatEntry(pMatName, ConvertRawRGBPal(RawColor)); } /* Export a textured material */ else { Result = pCallbackData->pFile3DS->OutputMatEntry(pMatName, pTextureName); } /* Tag the face and all faces with the same texture to ensure * that we don't duplicate materials */ ((CDF3dObject *)pCallbackData->pObject)->TagFaceTexture(DFFace.TextureIndex, DFFace.SubImageIndex); if (!Result) return (-1); return (0); } /*=========================================================================== * End of Function l_ExportDFMaterialTo3DS() *=========================================================================*/ /*=========================================================================== * * Function - int l_ExportDFMaterialGroupTo3DS (DFFace, pData); * * Callback functionm for the CDF3dObject::ForEachFace() method. Outputs * the material face groups to the 3DS file. Returns a negative value * on any error. * *=========================================================================*/ int l_ExportDFMaterialGroupTo3DS (const df3dface_t& DFFace, void* pData) { DEFINE_FUNCTION("l_ExportDFMaterialGroupTo3DS()"); df3dexport3ds_t* pCallbackData = (df3dexport3ds_t *) pData; df3dface_t* pFace; boolean Result; char* pMatName; short FaceGroupCount; int Count; int SubFaceIndex; long FaceIndex; long FaceCount; long CountOffset; long SaveOffset; /* Ignore any tagged faces as they have already been processed */ if (DFFace.Tag != 0) return (0); /* Get the number of faces in the group and material name */ Count = pCallbackData->pObject->TagFaceTexture(DFFace.TextureIndex, DFFace.SubImageIndex); pMatName = CreateDF3DSMaterialName(DFFace.TextureIndex, DFFace.SubImageIndex); FaceCount = 0; FaceGroupCount = 0; /* Output the material group chunk header */ Result = pCallbackData->pFile3DS->StartMatGroupChunk(pMatName, Count); CountOffset = pCallbackData->pFile3DS->Tell() - 2; if (!Result) return (-1); /* Output the array of face indices */ for (FaceIndex = 0; FaceIndex < pCallbackData->pObject->GetNumFaces(); FaceIndex++) { pFace = ((CDF3dObject *) pCallbackData->pObject)->GetFace(FaceIndex); /* Output only the faces with the same texture indices */ if (pFace->TextureIndex == DFFace.TextureIndex && pFace->SubImageIndex == DFFace.SubImageIndex) { /* Output all sub-faces in the DF face (triangle fan) */ for (SubFaceIndex = 0; SubFaceIndex < pFace->NumPoints - 2; SubFaceIndex++) { Result &= pCallbackData->pFile3DS->WriteShort(FaceCount + SubFaceIndex); FaceGroupCount++; } } FaceCount += pFace->NumPoints - 2; } /* Update the face array count */ SaveOffset = pCallbackData->pFile3DS->Tell(); Result &= pCallbackData->pFile3DS->Seek(CountOffset, SEEK_SET); Result &= pCallbackData->pFile3DS->WriteShort(FaceGroupCount); Result &= pCallbackData->pFile3DS->Seek(SaveOffset, SEEK_SET); /* End the current material group chunk */ Result &= pCallbackData->pFile3DS->EndMatGroupChunk(); if (!Result) return (-1); return (0); } /*=========================================================================== * End of Function l_ExportDFMaterialGroupTo3DS() *=========================================================================*/ /*=========================================================================== * * Function - int l_ExportDFTexVertTo3DS (DFFace, pData); * * Outputs one texture vertex to the 3DS file. Returns negative on any error. * Used as a callback for the CDF3dObject::ForEachFaceC() method. * *=========================================================================*/ int l_ExportDFTexVertTo3DS (const df3dface_t& DFFace, void* pData) { DEFINE_FUNCTION("l_ExportDFTexVertTo3DS()"); df3dexport3ds_t* pCallbackData = (df3dexport3ds_t *) pData; df3duvmatrix_t UVMatrix; df3dpoint_t* pPoint; boolean Result; int FaceIndex; float X, Y; float U, V; int Width; int Height; int ReturnValue = 0; /* Get the texture width/height and ensure they are valid */ Width = GetDFTextureWidth(DFFace.TextureIndex, DFFace.SubImageIndex); Height = GetDFTextureHeight(DFFace.TextureIndex, DFFace.SubImageIndex); if (Width <= 0) Width = 64; if (Height <= 0) Height = 64; /* Compute the XYZ-UV conversion matrix for the face if required */ if (DFFace.TextureIndex >= 2 && DFFace.NumPoints > 4) { Result = ComputeDFFaceTextureUVMatrix(UVMatrix, DFFace, *pCallbackData->pObject); if (!Result) ReturnValue = 1; } /* Output all the texture points in the face */ for (FaceIndex = 0; FaceIndex < DFFace.NumPoints; FaceIndex++) { pPoint = ((CDF3dObject *) pCallbackData->pObject)->GetFacePoint(DFFace.FaceData[FaceIndex].PointOffset); ASSERT(pPoint != NULL); pCallbackData->PointIndex++; /* Convert DF XYZ coordinates to standard texture UV */ if (DFFace.TextureIndex <= 1) { X = 0; Y = 0; } else if (FaceIndex > 3) { X = UVMatrix.UA * (float) pPoint->X + UVMatrix.UB * (float) pPoint->Y + UVMatrix.UC * (float) pPoint->Z + UVMatrix.UD; Y = UVMatrix.VA * (float) pPoint->X + UVMatrix.VB * (float) pPoint->Y + UVMatrix.VC * (float) pPoint->Z + UVMatrix.VD; } else if (FaceIndex == 0) { X = (float) DFFace.FaceData[0].TextureU; Y = (float) DFFace.FaceData[0].TextureV; } else if (FaceIndex == 1) { X = (float) DFFace.FaceData[0].TextureU + DFFace.FaceData[1].TextureU; Y = (float) DFFace.FaceData[0].TextureV + DFFace.FaceData[1].TextureV; } else if (FaceIndex == 2) { X = (float) DFFace.FaceData[0].TextureU + DFFace.FaceData[1].TextureU + DFFace.FaceData[2].TextureU; Y = (float) DFFace.FaceData[0].TextureV + DFFace.FaceData[1].TextureV + DFFace.FaceData[2].TextureV; } else if (FaceIndex == 3) { X = (float) DFFace.FaceData[3].TextureU; Y = (float) DFFace.FaceData[3].TextureV; } else { X = 0; Y = 0; } /* Convert from DF to standard UV coordinats */ U = (float) (X / 16.0 / (float) Width); V = (float) (Y / 16.0 / (float) Height); /*SystemLog.Printf ("\t\t%02d: XYZ(%ld, %ld, %ld), UV(%f, %f), DfUV(%d, %d), 3DSUV(%f, %f)", FaceIndex, pPoint->X, pPoint->Y, pPoint->Z, X, Y, DFFace.FaceData[FaceIndex].TextureU, DFFace.FaceData[FaceIndex].TextureV, U, V); //*/ /* Output the texture vertex */ Result = pCallbackData->pFile3DS->WriteTexVert(U, V); if (!Result) return (-1); } return (ReturnValue); } /*=========================================================================== * End of Function l_ExportDFTexVertTo3DS() *=========================================================================*/ /*=========================================================================== * * Function - int ExportDFMaterialGroupsTo3DS (File3DS, DF3dObject); * * Creates the material groups in the 3DS file in the face array chunk after * the main face array (0x4120). Each group of faces with the same material * has a 0x4130 chunk created with the material name and the list of face * indices. Returns a negative value on any error. * *=========================================================================*/ int ExportDFMaterialGroupsTo3DS (C3dsFile& File3DS, const CDF3dObject& DF3dObject) { //DEFINE_FUNCTION("ExportDFMaterialGroupsTo3DS()"); df3dexport3ds_t CallbackData; int Result; /* Initialize the object and callback data */ DF3dObject.ClearFaceTags(); CallbackData.ObjectVersion = 0; CallbackData.pFile3DS = &File3DS; CallbackData.pMeshMatrix = NULL; CallbackData.pObject = (CDF3dObject *) &DF3dObject; CallbackData.PointIndex = 0; /* Output all the material groups */ Result = DF3dObject.ForEachFaceC(l_ExportDFMaterialGroupTo3DS, (void*) &CallbackData); return (Result); } /*=========================================================================== * End of Function ExportDFMaterialGroupsTo3DS() *=========================================================================*/ /*=========================================================================== * * Function - boolean ExportDFMaterialsTo3DS (File3DS, DF3dObject); * * Export the material section of the 3DS file, creating all materials * required to display the given object, both textured and solid colors. * Returns FALSE on any error. * *=========================================================================*/ boolean ExportDFMaterialsTo3DS (C3dsFile& File3DS, const CDF3dObject& DF3dObject) { DEFINE_FUNCTION("ExportDFMaterialsTo3DS()"); df3dexport3ds_t CallbackData; int Result; /* Initialize the callback data and 3D object */ CallbackData.pFile3DS = &File3DS; CallbackData.pObject = (CDF3dObject *) &DF3dObject; CallbackData.pMeshMatrix = NULL; CallbackData.PointIndex = 0; CallbackData.ObjectVersion = 0; DF3dObject.ClearFaceTags(); /* Output all materials required by the object */ Result = ((CDF3dObject&)DF3dObject).ForEachFace(l_ExportDFMaterialTo3DS, (void *) &CallbackData); if (Result < 0) return (FALSE); return (TRUE); } /*=========================================================================== * End of Function ExportDFMaterialsTo3DS() *=========================================================================*/