/*=========================================================================== * * File: Df_3DSExp.CPP * Author: Dave Humphrey (uesp@m0use.net) * Created On: Friday, March 22, 2002 * * Implementation of 3DS specific export functions for DF 3D objects. * *=========================================================================*/ /* Include Files */ #include "df3dexpo.h" #include "bsa/df3dutil.h" /*=========================================================================== * * Begin Local Variable Definitions * *=========================================================================*/ DEFINE_FILE(); /*=========================================================================== * End of Local Variable Definitions *=========================================================================*/ /*=========================================================================== * * Function - int l_ExportDF3dFaceTo3DS (DFFace, pCallbackData); * * Local function used as a callback function for the CDF3dObject::ForEachFace() * method. Outputs one face to the current position in the file stream * contained in the callback data pointer. Returns 0 on success. * * The faces are output as triangle fans, based on the first point in the * face. This is because Daggerfall stores its faces as non-triangular * elements (except for planes with 3 points of course) while the 3DS * format stores its faces solely as triangular elements. The face is * output in such a way that it displays correctly as a single polygon in * 3DS and not a collection of triangular faces (in general anyways). * * This version of the face export function should be paired with the * l_ExportDF3dPointTo3DS() function. These two function keep the DF method * of using the same point for several faces where faces intersect. This * method cannot be used if materials are to be export to the 3DS file * as UV texture coordinates cannot be specified for all the faces. * *=========================================================================*/ int l_ExportDF3dFaceTo3DS (const df3dface_t& DFFace, void* pData) { //DEFINE_FUNCTION("l_ExportDF3dFaceTo3DS()"); df3dexport3ds_t* pCallbackData = (df3dexport3ds_t *) pData; int OffsetDivisor; boolean Result; long PointIndex; short Point1; short Point2; short Point3; /* Ignore if no points in face to export */ if (DFFace.NumPoints <= 0) return (0); /* Initialize variables */ OffsetDivisor = GetDF3dFacePointOffsetDivisor(pCallbackData->ObjectVersion); /* Output the first sub-triangle in face */ Point1 = (short) DFFace.FaceData[0].PointOffset / OffsetDivisor; Point2 = (short) DFFace.FaceData[1].PointOffset / OffsetDivisor; Point3 = (short) DFFace.FaceData[2].PointOffset / OffsetDivisor; Result = pCallbackData->pFile3DS->WriteFace(Point1, Point2, Point3, 6); if (!Result) return (-1); /* Output remaining sub-triangles in the face */ for (PointIndex = 2; PointIndex < DFFace.NumPoints-1; PointIndex++) { Point2 = (short) DFFace.FaceData[PointIndex ].PointOffset / OffsetDivisor; Point3 = (short) DFFace.FaceData[PointIndex+1].PointOffset / OffsetDivisor; Result = pCallbackData->pFile3DS->WriteFace(Point1, Point2, Point3, 2); if (!Result) return (-1); } return (0); } /*=========================================================================== * End of Function l_ExportDF3dFaceTo3DS() *=========================================================================*/ /*=========================================================================== * * Function - int l_ExportDF3dFaceTo3DS2 (DFFace, pCallbackData); * * Local function used as a callback function for the CDF3dObject::ForEachFace() * method. Outputs one face to the current position in the file stream * contained in the callback data pointer. Returns 0 on success. Uses * and updates the PointIndex data member of the callback data. * * The faces are output as triangle fans, based on the first point in the * face. This is because Daggerfall stores its faces as non-triangular * elements (except for planes with 3 points of course) while the 3DS * format stores its faces solely as triangular elements. The face is * output in such a way that it displays correctly as a single polygon in * 3DS and not a collection of triangular faces (in general anyways). * * This version of the face export function should be paired with the * l_ExportDF3dPointTo3DS2() function. These two functions use multiple points * where faces intersect (instead of a single point). This method must be * used if materials are to be export to the 3DS file as mulitple UV texture * coordinates are required for each point on the face. * *=========================================================================*/ int l_ExportDF3dFaceTo3DS2 (const df3dface_t& DFFace, void* pData) { //DEFINE_FUNCTION("l_ExportDF3dFaceTo3DS2()"); df3dexport3ds_t* pCallbackData = (df3dexport3ds_t *) pData; boolean Result; short PointIndex; short Point1; short Point2; short Point3; /* Ignore if no points in face to export */ if (DFFace.NumPoints <= 0) return (0); /* Output the first sub-triangle in face */ Point1 = (short) pCallbackData->PointIndex; Point2 = (short) pCallbackData->PointIndex + 1; Point3 = (short) pCallbackData->PointIndex + 2; Result = pCallbackData->pFile3DS->WriteFace(Point1, Point2, Point3, 6); if (!Result) return (-1); /* Output remaining sub-triangles in the face */ for (PointIndex = 2; PointIndex < DFFace.NumPoints-1; PointIndex++) { Point2 = (short) (pCallbackData->PointIndex + PointIndex); Point3 = (short) pCallbackData->PointIndex + PointIndex + 1; Result = pCallbackData->pFile3DS->WriteFace(Point1, Point2, Point3, 2); if (!Result) return (-1); } /* Increase the total point count for the next face output */ pCallbackData->PointIndex += DFFace.NumPoints; return (0); } /*=========================================================================== * End of Function l_ExportDF3dFaceTo3DS2() *=========================================================================*/ /*=========================================================================== * * Function - int l_ExportDF3dPointTo3DS (DFPoint, pCallbackData); * * Local function used as a callback function for the CDF3dObject::ForEachPoint() * method. Outputs one point to the current position in the file stream * contained in the callback data pointer. Returns 0 on success. * * NOTE: Y-Z coordinates swapped, Z coordinate negated. Points scaled down * by DF3D_3DS_FACTOR. * * This version of the points export function should be paired with the * l_ExportDF3dFaceTo3DS() function. These two function keep the DF method * of using the same point for several faces where faces intersect. This * method cannot be used if materials are to be export to the 3DS file * as UV texture coordinates cannot be specified for all the faces. * *=========================================================================*/ int l_ExportDF3dPointTo3DS (const df3dpoint_t& DFPoint, void* pData) { //DEFINE_FUNCTION("l_ExportDF3dPointTo3DS()"); df3dexport3ds_t* pCallbackData = (df3dexport3ds_t *) pData; boolean Result; float X, Y, Z; /* Get the base point coordinates */ X = (float) DFPoint.X / DF3D_3DS_FACTOR; Z = (float) -DFPoint.Y / DF3D_3DS_FACTOR; Y = (float) DFPoint.Z / DF3D_3DS_FACTOR; /* Transform the point if required and output */ if (pCallbackData->pMeshMatrix != NULL) { const float* pMeshMatrix = pCallbackData->pMeshMatrix; float X1, Y1, Z1; X1 = pMeshMatrix[0]*X + pMeshMatrix[3]*Y + pMeshMatrix[6]*Z + pMeshMatrix[9]; Y1 = pMeshMatrix[1]*X + pMeshMatrix[4]*Y + pMeshMatrix[7]*Z + pMeshMatrix[10]; Z1 = pMeshMatrix[2]*X + pMeshMatrix[5]*Y + pMeshMatrix[8]*Z + pMeshMatrix[11]; Result = pCallbackData->pFile3DS->WritePoint(X1, Y1, Z1); } else { Result = pCallbackData->pFile3DS->WritePoint(X, Y, Z); } return (Result ? 0 : -1); } /*=========================================================================== * End of Function l_ExportDF3dPointTo3DS() *=========================================================================*/ /*=========================================================================== * * Function - int l_ExportDF3dPointTo3DS2 (DFFace, pCallbackData); * * Local function used as a callback function for the CDF3dObject::ForEachFace() * method. Outputs all the points in the face to the current position in the * file stream contained in the callback data pointer. Returns 0 on success. * * NOTE: Point Y-Z coordinates swapped, Z coordinate negated. Points scaled * down by DF3D_3DS_FACTOR. * * This version of the point export function should be paired with the * l_ExportDF3dFaceTo3DS2() function. These two functions use multiple points * where faces intersect (instead of a single point). This method must be * used if materials are to be export to the 3DS file as mulitple UV texture * coordinates are required for each point on the face. * *=========================================================================*/ int l_ExportDF3dPointTo3DS2 (const df3dface_t& DFFace, void* pData) { //DEFINE_FUNCTION("l_ExportDF3dPointTo3DS2()"); df3dexport3ds_t* pCallbackData = (df3dexport3ds_t *) pData; df3dpoint_t* pPoint; CDF3dObject* pDFObject = ((CDF3dObject * )(pCallbackData->pObject)); int Result; int PointIndex; /* Create a unique point for each point on the face */ for (PointIndex = 0; PointIndex < DFFace.NumPoints; PointIndex++) { pPoint = pDFObject->GetFacePoint(DFFace.FaceData[PointIndex].PointOffset); Result = l_ExportDF3dPointTo3DS(*pPoint, pData); if (Result < 0) return (-1); } return (0); } /*=========================================================================== * End of Function l_ExportDF3dPointTo3DS2() *=========================================================================*/ /*=========================================================================== * * Function - * boolean ExportDF3dObjectTo3DS (File3DS, DF3dObject, pMeshMatrix, pName); * * Exports the given Daggerfall 3D object to a single trimesh chunk in the * 3DS file. Returns FALSE on any error. The optional mesh matrix * gives the 3x4 sized transformation matrix to use for transforming each * point. If the given name string is not NULL, that name is used for the * 3DS object name. Otherwise a default unique name is generated. * *=========================================================================*/ boolean ExportDF3dObjectTo3DS (C3dsFile& File3DS, const CDF3dObject& DF3dObject, const float* pMeshMatrix, const char* pName) { DEFINE_FUNCTION("ExportDF3dObjectTo3DS()"); df3dexport3ds_t CallbackData; static long s_ObjectIndex = 1; char NameBuffer[64]; boolean Result; int iResult; /* Setup the callback data structure */ CallbackData.pFile3DS = &File3DS; CallbackData.pMeshMatrix = pMeshMatrix; CallbackData.ObjectVersion = DF3dObject.GetVersionNum(); CallbackData.pObject = &DF3dObject; CallbackData.PointIndex = 0; /* Create the object name if required */ if (pName == NULL) { snprintf (NameBuffer, 63, "df3d%03d", s_ObjectIndex); pName = NameBuffer; s_ObjectIndex++; } /* Start the object-trimesh chunks */ Result = File3DS.StartObjectChunk(pName); Result &= File3DS.StartTrimeshChunk(); Result &= File3DS.StartPointChunk(); if (!Result) return (FALSE); /* Output the point data */ iResult = DF3dObject.ForEachFaceC(l_ExportDF3dPointTo3DS2, &CallbackData); if (iResult != 0) return (FALSE); Result = File3DS.EndPointChunk(); if (!Result) return (FALSE); /* Output the texture vertices chunk */ Result = File3DS.StartTexVertChunk(); CallbackData.PointIndex = 0; iResult = DF3dObject.ForEachFaceC(l_ExportDFTexVertTo3DS, &CallbackData); Result &= File3DS.EndTexVertChunk(CallbackData.PointIndex); if (iResult < 0 || !Result) return (FALSE); CallbackData.PointIndex = 0; /* Start the mesh matrix and face chunks */ Result = File3DS.WriteMeshMatrix(); Result &= File3DS.StartFaceChunk(); if (!Result) return (FALSE); /* Output the face data */ iResult = DF3dObject.ForEachFaceC(l_ExportDF3dFaceTo3DS2, &CallbackData); if (iResult != 0) return (FALSE); /* Output the face material grouping */ iResult = ExportDFMaterialGroupsTo3DS(File3DS, DF3dObject); if (iResult != 0) return (FALSE); /* End outtputing the 3DS object chunks */ Result = File3DS.EndFaceChunk(); Result &= File3DS.EndTrimeshChunk(); Result &= File3DS.EndObjectChunk(); return (Result); } /*=========================================================================== * End of Function ExportDF3dObjectTo3DS() *=========================================================================*/