/*===========================================================================
 *
 * File:	File3ds.H
 * Author:	Dave Humphrey (uesp@m0use.net)
 * Created On:	Friday, June 22, 2001
 *
 * Implements the C3dsFile class for handling 3DS files.
 *
 *=========================================================================*/
#ifndef __FILE3DS_H
#define __FILE3DS_H


/*===========================================================================
 *
 * Begin Required Include Files
 *
 *=========================================================================*/
  #include "common/file/genfile.h"
  #include "images/rgbpal.h"
/*===========================================================================
 *		End of Required Include Files
 *=========================================================================*/


/*===========================================================================
 *
 * Begin Definitions
 *
 *=========================================================================*/

	/* Flags for the 3DS chunk types */
  #define CHUNK3DS_FLAG_SIMPLECONTAINER 1

	/* Size of the chunk stack in elements */
  #define CHUNK3DS_STACK_SIZE 64

	/* Chunk IDs */
  #define CHUNK3DS_ID_NULL		((ushort)0x0000)
  #define CHUNK3DS_ID_3DSVERSION	((ushort)0x0002)
  #define CHUNK3DS_ID_COLOR24		((ushort)0x0011)
  #define CHUNK3DS_ID_INT_PERCENTAGE	((ushort)0x0030)
  #define CHUNK3DS_ID_MAIN		((ushort)0x4D4D)
  #define CHUNK3DS_ID_EDIT		((ushort)0x3D3D)
  #define CHUNK3DS_ID_EDITVERSION	((ushort)0x3D3E)
  #define CHUNK3DS_ID_MASTERSCALE	((ushort)0x0100)
  #define CHUNK3DS_ID_NAMEDOBJECT	((ushort)0x4000)
  #define CHUNK3DS_ID_TRIMESH		((ushort)0x4100)
  #define CHUNK3DS_ID_POINTARRAY	((ushort)0x4110)
  #define CHUNK3DS_ID_FACEARRAY		((ushort)0x4120)
  #define CHUNK3DS_ID_MATGROUP		((ushort)0x4130)
  #define CHUNK3DS_ID_TEX_VERTS		((ushort)0x4140)
  #define CHUNK3DS_ID_SMOOTHGROUP	((ushort)0x4150)
  #define CHUNK3DS_ID_MESHMATRIX	((ushort)0x4160)
  #define CHUNK3DS_MAT_ENTRY		((ushort)0xAFFF)
  #define CHUNK3DS_MAT_NAME		((ushort)0xA000)
  #define CHUNK3DS_MAT_AMBIENT		((ushort)0xA010)
  #define CHUNK3DS_MAT_DIFFUSE		((ushort)0xA020)
  #define CHUNK3DS_MAT_SPECULAR		((ushort)0xA030)
  #define CHUNK3DS_MAT_SHININESS	((ushort)0xA040)
  #define CHUNK3DS_MAT_SHIN2PCT		((ushort)0xA041)
  #define CHUNK3DS_MAT_TRANSPARENCY	((ushort)0xA050)
  #define CHUNK3DS_MAT_XPFALL		((ushort)0xA052)
  #define CHUNK3DS_MAT_REFBLUR		((ushort)0xA053)
  #define CHUNK3DS_MAT_SHADING		((ushort)0xA100)
  #define CHUNK3DS_MAT_SELF_ILPCT	((ushort)0xA084)
  #define CHUNK3DS_MAT_XPFALLIN		((ushort)0xA08A)
  #define CHUNK3DS_MAT_WIRESIZE		((ushort)0xA087)
  #define CHUNK3DS_MAT_TEXMAP		((ushort)0xA200)
  #define CHUNK3DS_MAT_MAPNAME		((ushort)0xA300)
  #define CHUNK3DS_MAT_MAP_TILING	((ushort)0xA351)
  #define CHUNK3DS_MAT_MAP_TEXBLUR	((ushort)0xA353)
  #define CHUNK3DS_MAT_ENTRY		((ushort)0xAFFF)
  #define CHUNK3DS_ID_LAST		((ushort)0xFFFF)

/*===========================================================================
 *		End of Definitions
 *=========================================================================*/


/*===========================================================================
 *
 * Begin Type Definitions
 *
 *=========================================================================*/

	/* Holds information on the chunk types */
  typedef struct {
    ushort ID;
    int    Flags;
    char*  pName;
   } chunk3ds_t;

	/* Chunk stack record type */
  typedef struct {
    ushort ID;
    long   Offset;
   } chunk3dsstack_t;

/*===========================================================================
 *		End of Type Definitions
 *=========================================================================*/


/*===========================================================================
 *
 * Begin Class C3dsFile Definition
 *
 * Handles simple Input/Output of 3DS type files.
 *
 *=========================================================================*/
class C3dsFile : public CGenFile {

  /*---------- Begin Private Class Members ----------------------*/
private:
  long m_MainChunkOffset;	/* Keeps track of the chunk starting offsets */
  long m_EditChunkOffset;
  long m_ObjectChunkOffset;
  long m_TrimeshChunkOffset;
  long m_PointChunkOffset;
  long m_FaceChunkOffset;

  long m_MainChunkSize;		/* Keeps track of the chunk sizes */
  long m_EditChunkSize;
  long m_ObjectChunkSize;
  long m_TrimeshChunkSize;
  long m_PointChunkSize;
  long m_FaceChunkSize;

  short m_NumFaces;
  short m_NumPoints;


  chunk3dsstack_t m_ChunkStack[CHUNK3DS_STACK_SIZE];
  int		  m_ChunkStackSize;


  /*---------- Begin Protected Class Methods --------------------*/
protected:

	/* Helper function to dump chunks recursively */
  boolean DumpChunk      (FILE* pFileHandle);
  boolean DumpMeshMatrix (FILE* pFileHandle);

	/* Helper input functions */
  boolean ReadName (char* pBuffer);

	/* Chunk stack manipulation */
  boolean PushChunkStack (const ushort ID);
  boolean PopChunkStack  (const ushort ID);
  boolean PopChunkStack  (const ushort ID, const short Value);


  /*---------- Begin Public Class Methods -----------------------*/
public:

	/* Class Constructors/Destructors */
  //C3dsFile();
  //virtual ~C3dsFile() { Destroy(); }
  //virtual void Destroy (void);

	/* Create a translation mesh matrix */
  static void CreateMeshMatrix (float* pMeshMatrix, const float XPos,   const float YPos,   const float ZPos, 
				      	     const float XScale, const float YScale, const float ZScale, 
					     const float XAngle, const float YAngle, const float ZAngle);

	/* Dump the chunks found in the 3DS file */
  boolean DumpContents (FILE* pFileHandle);

	/* End writing major chunk sections */
  boolean EndMainChunk      (void);
  boolean EndEditChunk      (void);
  boolean EndObjectChunk    (void);
  boolean EndTrimeshChunk   (void);
  boolean EndFaceChunk      (void);
  boolean EndPointChunk     (void);
  boolean EndChunk	    (const ushort ID);
  boolean EndMatGroupChunk  (void);
  boolean EndTexVertChunk   (const short Count);

	/* Attempts to find a chunk info structure */
  static char*       GetChunkName (const ushort ChunkID);
  static int         GetChunkFlag (const ushort ChunkID);
  static chunk3ds_t* FindChunk    (const ushort ChunkID);

	/* Start writing major chunk sections */
  boolean StartMainChunk     (void);
  boolean StartEditChunk     (void);
  boolean StartObjectChunk   (const char* pName);
  boolean StartTrimeshChunk  (void);
  boolean StartFaceChunk     (void);
  boolean StartPointChunk    (void);
  boolean StartChunk	     (const ushort ID);
  boolean StartMatGroupChunk (const char* pMatName, const short Count);
  boolean StartTexVertChunk  (void);

	/* Output a standard material section */
  boolean OutputMatEntry (const char* pMatName, const char* pTextureName);
  boolean OutputMatEntry (const char* pMatName, const rgbpal_t& PalEntry);
  
	/* Write trimesh elements */
  boolean WriteFace       (const short Point1, const short Point2, const short Point3, const short Flags = 0);
  boolean WritePoint      (const float X, const float Y, const float Z);
  boolean WriteMeshMatrix (const float* pMeshMatrix = NULL);

	/* Standard output methods */
  boolean WriteCharColor  (const ushort ChunkID, const byte Red, const byte Green, const byte Blue);
  boolean WriteIntPercent (const ushort ChunkID, const short Percentage); 
  boolean WriteIntPercent (const short Percentage); 
  boolean WriteChunkShort (const ushort ChunkID, const short Value);
  boolean WriteChunkFloat (const ushort ChunkID, const float Value);
  boolean WriteString     (const ushort ChunkID, const char* pString);
  boolean WriteTexVert    (const float X, const float Y);

 };
/*===========================================================================
 *		End of Class C3dsFile Definition
 *=========================================================================*/


/*===========================================================================
 *
 * Begin C3dsFile Inline Methods
 *
 *=========================================================================*/

	/* End outputting chunk sections */
inline boolean C3dsFile::EndTexVertChunk  (const short Count) { return PopChunkStack(CHUNK3DS_ID_TEX_VERTS, Count); }
inline boolean C3dsFile::EndEditChunk     (void) { return PopChunkStack(CHUNK3DS_ID_EDIT); }
inline boolean C3dsFile::EndFaceChunk     (void) { return PopChunkStack(CHUNK3DS_ID_FACEARRAY, m_NumFaces); }
inline boolean C3dsFile::EndMainChunk     (void) { return PopChunkStack(CHUNK3DS_ID_MAIN); }
inline boolean C3dsFile::EndMatGroupChunk (void) { return PopChunkStack(CHUNK3DS_ID_MATGROUP); }
inline boolean C3dsFile::EndObjectChunk   (void) { return PopChunkStack(CHUNK3DS_ID_NAMEDOBJECT); }
inline boolean C3dsFile::EndPointChunk    (void) { return PopChunkStack(CHUNK3DS_ID_POINTARRAY, m_NumPoints); }
inline boolean C3dsFile::EndTrimeshChunk  (void) { return PopChunkStack(CHUNK3DS_ID_TRIMESH); }

	/* Start/end arbitrary chunks */
inline boolean C3dsFile::EndChunk   (const ushort ID) { return PopChunkStack(ID); }
inline boolean C3dsFile::StartChunk (const ushort ID) { return PushChunkStack(ID); }

/*===========================================================================
 *		End of C3dsFile Inline Methods
 *=========================================================================*/


#endif
/*===========================================================================
 *		End of File File3ds.H
 *=========================================================================*/