/*=========================================================================== * * File: DF3DObj.H * Author: Dave Humphrey (uesp@m0use.net) * Created On: Wednesday, June 20, 2001 * * Defines the CDF3dObject class for handling a 3D object file. * *=========================================================================*/ #ifndef __DF3DOBJ_H #define __DF3DOBJ_H /*=========================================================================== * * Begin Required Include Files * *=========================================================================*/ #include "uesp/dagger/common/dfcommon.h" #include "common/dl_str.h" /*=========================================================================== * End of Required Include Files *=========================================================================*/ /*=========================================================================== * * Begin Definitions * *=========================================================================*/ /* Code limited number of points per faces */ #define DF3D_FACE_MAXPOINTS 32 /* Record sizes */ #define DF3D_FACE_RECORDSIZE 8 #define DF3D_DATA2_RECORDSIZE 18 /* Version values */ #define DF3D_VERSION_25 25 #define DF3D_VERSION_26 26 #define DF3D_VERSION_27 27 #define DF3D_VERSION_UNKNOWN 0 /*=========================================================================== * End of Definitions *=========================================================================*/ #pragma pack(push, 1) /*=========================================================================== * * Begin Type Definitions * *=========================================================================*/ /* Basic Daggerfall point type */ typedef struct { long X; long Y; long Z; } df3dpoint_t; /* Unknown section data1 record type */ typedef struct { unsigned char Unknown[24]; } df3ddata1_t; /* Unknown section data2 record subtype */ typedef struct { byte Unknown[6]; } df3ddata2_subrecord_t; /* Unknown section data2 record type */ typedef struct { long Unknown1; long Unknown2; long Unknown3; long Unknown4; short NumSubRecords; df3ddata2_subrecord_t* pSubRecords; } df3ddata2_t; /*=========================================================================== * End of Type Definitions *=========================================================================*/ /*=========================================================================== * * Begin 3D Object Header Structure * * Each object has this fixed length header. * *=========================================================================*/ typedef struct { char Version[4]; /* Object version string "v2.7" */ long NumPoints; /* Number of points in object */ long NumFaces; /* Number of face in object */ long Unknown1; long NullValue1; /* Always 0 */ long NullValue2; /* Always 0 */ long Data1Offset; /* Offset to Data1 section from start of file */ long Data2Offset; /* Offset to Data2 section from start of file */ long NumData2; /* Number of Data2 records */ short Unknown2; short Unknown3; long NullValue3; /* Always 0 */ long NullValue4; /* Always 0 */ long PointOffset; /* Offset to point data from start of file */ long NormalOffset; /* Offset to normal data from start of file */ long Unknown4; long FaceOffset; /* Offset to face data from start of file */ } df3dheader_t; /*=========================================================================== * End of 3D Object Header Structure *=========================================================================*/ /*=========================================================================== * * Begin 3D Object Face Point Data * * The data structure for each point making up a face/plane. * *=========================================================================*/ typedef struct { long PointOffset; /* Indicates point data to use (3D object version dependant) */ short TextureU; /* Texture coordinates */ short TextureV; } df3dfacedata_t; /*=========================================================================== * End of 3D Object Face Point DAta *=========================================================================*/ /*=========================================================================== * * Begin 3D Object Plane Record Structure * * Each plane/face in the 3D Object has this data structure. The structure * is a bit field. * *=========================================================================*/ typedef struct { byte NumPoints; /* Number of points making up the face */ byte Unknown1; ushort SubImageIndex : 7; /* Indicate the texture image to use */ ushort TextureIndex : 9; long Unknown2; /* The data for each point in the face */ df3dfacedata_t FaceData[DF3D_FACE_MAXPOINTS]; short Tag; /* Used for custom user data. Must be after the face data so it doesn't affect the reading and writing of the face. */ } df3dface_t; /*=========================================================================== * End of 3D Object Plane Record Structure *=========================================================================*/ /*=========================================================================== * * Begin Callback Function Types * *=========================================================================*/ /* ForEachPoint() callback function type */ typedef int (* PFNDF3D_FOREACHPOINT) ( df3dpoint_t& DFPoint, void* pCallbackData); typedef int (* PFNDF3D_FOREACHPOINTC) (const df3dpoint_t& DFPoint, void* pCallbackData); /* ForEachFace() callback function type */ typedef int (* PFNDF3D_FOREACHFACE) ( df3dface_t& DFFace, void* pCallbackData); typedef int (* PFNDF3D_FOREACHFACEC) (const df3dface_t& DFFace, void* pCallbackData); /*=========================================================================== * End of Callback Function Types *=========================================================================*/ /* Re-enable default structure alignment */ #pragma pack(pop) /*=========================================================================== * * Begin Class CDF3dObject Definition * * Handles a single Daggerfall 3D object file, either in a single file or * contained within a BSA file. * *=========================================================================*/ class CDF3dObject { /*---------- Begin Private Class Members ----------------------*/ private: df3dheader_t m_Header; /* The fixed length 3D object header */ df3dpoint_t* m_pPoints; /* Array of points */ df3dface_t* m_pFaces; /* Array of faces */ df3dpoint_t* m_pNormals; /* Array of normals? */ df3ddata1_t* m_pData1; /* Array of unknown data1 records */ df3ddata2_t* m_pData2; /* Array of unknown data2 records */ int m_Version; /* Shortcut to object verison */ long m_FileSize; /* Used when loading the file */ long m_StartOffset; /*---------- Begin Protected Class Methods --------------------*/ protected: /* Helper functions to load object sections */ boolean ReadHeader (FILE *pFileHandle); boolean ReadPoints (FILE *pFileHandle); boolean ReadFaces (FILE *pFileHandle); boolean ReadNormals (FILE *pFileHandle); boolean ReadData1 (FILE *pFileHandle); boolean ReadData2 (FILE *pFileHandle); /*---------- Begin Public Class Methods -----------------------*/ public: /* Class Constructors/Destructors */ CDF3dObject(); virtual ~CDF3dObject() { Destroy(); } virtual void Destroy (void); /* Reset the tags for each face */ void ClearFaceTags (void) const; /* Perform a custom operation for each object element */ int ForEachFace (PFNDF3D_FOREACHFACE fnCallBack, void* pCallbackData); int ForEachPoint (PFNDF3D_FOREACHPOINT fnCallBack, void* pCallbackData); int ForEachFaceC (PFNDF3D_FOREACHFACEC fnCallBack, void* pCallbackData) const; int ForEachPointC (PFNDF3D_FOREACHPOINTC fnCallBack, void* pCallbackData) const; /* Get header information */ long GetNumPoints (void) const; long GetNumFaces (void) const; long GetNumData2 (void) const; long GetPointOffset (void) const; long GetFaceOffset (void) const; long GetNormalOffset (void) const; long GetData1Offset (void) const; long GetData2Offset (void) const; char* GetVersion (void) const; int GetVersionNum (void) const; long GetMaxY (void) const; long GetMinY (void) const; /* Access face array */ df3dface_t* GetFace (const long FaceIndex); /* Get a point from a face point offset */ df3dpoint_t* GetFacePoint (const long PointOffset); long GetFacePointIndex (const long PointOffset); df3dpoint_t* GetPointData (void) const; /* Check version information */ boolean IsVersion (const char* pString) const; boolean IsVersion (const int Version) const; /* Read object from file stream */ boolean Read (FILE* pFileHandle); /* Set class members */ void SetFileSize (const long Size); /* Tag all faces with the given texture */ int TagFaceTexture (const int TextureIndex, const int ImageIndex) const; }; /*=========================================================================== * End of Class CDF3dObject Definition *=========================================================================*/ /*=========================================================================== * * Begin CDF3dObject Inline Methods * *=========================================================================*/ /* Get header information */ inline long CDF3dObject::GetNumFaces (void) const { return (m_Header.NumFaces); } inline long CDF3dObject::GetNumPoints (void) const { return (m_Header.NumPoints); } inline long CDF3dObject::GetNumData2 (void) const { return (m_Header.NumData2); } inline long CDF3dObject::GetPointOffset (void) const { return (m_Header.PointOffset); } inline long CDF3dObject::GetFaceOffset (void) const { return (m_Header.FaceOffset); } inline long CDF3dObject::GetNormalOffset (void) const { return (m_Header.NormalOffset); } inline long CDF3dObject::GetData1Offset (void) const { return (m_Header.Data1Offset); } inline long CDF3dObject::GetData2Offset (void) const { return (m_Header.Data2Offset); } inline char* CDF3dObject::GetVersion (void) const { return (char*)(m_Header.Version); } inline int CDF3dObject::GetVersionNum (void) const { return (m_Version); } /* Return a face from the object */ inline df3dface_t* CDF3dObject::GetFace (const long FaceIndex) { IASSERT(FaceIndex >= 0 && FaceIndex < GetNumFaces()); return &(m_pFaces[FaceIndex]); } /* Return a point object from a face point offset */ inline df3dpoint_t* CDF3dObject::GetFacePoint (const long PointOffset) { return &(m_pPoints[GetFacePointIndex(PointOffset)]); } /* Return a point index from a face point offset */ inline long CDF3dObject::GetFacePointIndex (const long PointOffset) { long PointIndex; /* Special case for 2.5 version objects */ if (m_Version == DF3D_VERSION_25) PointIndex = PointOffset / 4; else PointIndex = PointOffset / 12; /* Ensure a valid point index */ IASSERT(PointIndex >= 0 && PointIndex < GetNumPoints()); return (PointIndex); } /* Return a the point data array */ inline df3dpoint_t* CDF3dObject::GetPointData (void) const { return (m_pPoints); } /* Check version information */ inline boolean CDF3dObject::IsVersion (const char* pString) const { return (strnicmp(m_Header.Version, pString, 4) == 0 ? TRUE : FALSE); } inline boolean CDF3dObject::IsVersion (const int Version) const { return (m_Version == Version ? TRUE : FALSE); } /* Set class members */ inline void CDF3dObject::SetFileSize (const long Size) { m_FileSize = Size; } /*=========================================================================== * End of CDF3dObject Inline Methods *=========================================================================*/ /*=========================================================================== * * Begin Inline Functions * *=========================================================================*/ /* Returns the divisor needed to convert a face data point offset * into a point index. */ inline const int GetDF3dFacePointOffsetDivisor (const int& Version) { /* Special case for 2.5 version objects */ if (Version == DF3D_VERSION_25) return (4); return (12); } /* Get a point index from an face point offset. Does not verify the * point index returned or the input data. */ inline const int GetDF3dFacePointIndex (const df3dfacedata_t& FaceData, const int& Version) { return (FaceData.PointOffset / GetDF3dFacePointOffsetDivisor(Version)); } /*=========================================================================== * End of Inline Functions *=========================================================================*/ #endif /*=========================================================================== * End of File Df3dobj.H *=========================================================================*/