#ifndef _3DS_H
#define _3DS_H

/*
Modifications by CJP:
Included main.h file here
*/

#include <iostream>
#include <cstdio>
#include <cstdlib>
//#include <GL/gl.h>                                      // Header File For The OpenGL32 Library
//#include <GL/glu.h>                                     // Header File For The GLu32 Library

# include <string>
# include <vector>
using namespace std;

typedef unsigned char BYTE;

//////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** ////////////////////

// This file includes all of the model structures that are needed to load
// in a .3DS file.  If you intend to do animation you will need to add on
// to this.  These structures only support the information that is needed
// to load the objects in the scene and their associative materials.

#define MAX_TEXTURES 100                                // The maximum amount of textures to load

// This is our 3D point class.  This will be used to store the vertices of our model.
class CVector3
{
public:
    float x, y, z;
};

// This is our 2D point class.  This will be used to store the UV coordinates.
class CVector2
{
public:
    float x, y;
};

// This is our face structure.  This is is used for indexing into the vertex
// and texture coordinate arrays.  From this information we know which vertices
// from our vertex array go to which face, along with the correct texture coordinates.
struct tFace
{
    int vertIndex[3];           // indicies for the verts that make up this triangle
    int coordIndex[3];          // indicies for the tex coords to texture this face
};

// This holds the information for a material.  It may be a texture map of a color.
// Some of these are not used, but I left them because you will want to eventually
// read in the UV tile ratio and the UV tile offset for some models.
struct tMaterialInfo
{
    char  strName[255];         // The texture name
    char  strFile[255];         // The texture file name (If this is set it's a texture map)
    BYTE  color[3];             // The color of the object (R, G, B)
    int   texureId;             // the texture ID
    float uTile;                // u tiling of texture  (Currently not used)
    float vTile;                // v tiling of texture  (Currently not used)
    float uOffset;              // u offset of texture  (Currently not used)
    float vOffset;              // v offset of texture  (Currently not used)
} ;

// This holds all the information for our model/scene.
// You should eventually turn into a robust class that
// has loading/drawing/querying functions like:
// LoadModel(...); DrawObject(...); DrawModel(...); DestroyModel(...);
struct t3DObject
{
    int  numOfVerts;            // The number of verts in the model
    int  numOfFaces;            // The number of faces in the model
    int  numTexVertex;          // The number of texture coordinates
    int  materialID;            // The texture ID to use, which is the index into our texture array
    bool bHasTexture;           // This is TRUE if there is a texture map for this object
    char strName[255];          // The name of the object
    CVector3  *pVerts;          // The object's vertices
    CVector3  *pNormals;        // The object's normals
    CVector2  *pTexVerts;       // The texture's UV coordinates
    tFace *pFaces;              // The faces information of the object

    //CJP additions:
    CVector3 objectCenter;      // The center of the object
    CVector3 Xaxis, Yaxis, Zaxis; //The rotation matrix
};

// This holds our model information.  This should also turn into a robust class.
// We use STL's (Standard Template Library) vector class to ease our link list burdens. :)
struct t3DModel
{
    int numOfObjects;                   // The number of objects in the model
    int numOfMaterials;                 // The number of materials for the model
    vector<tMaterialInfo> pMaterials;   // The list of material information (Textures and colors)
    vector<t3DObject> pObject;          // The object list for our model
};

/*
End of modifications by CJP
*/




//>------ Primary Chunk, at the beginning of each file
#define PRIMARY       0x4D4D

//>------ Main Chunks
#define OBJECTINFO    0x3D3D                // This gives the version of the mesh and is found right before the material and object information
#define VERSION3DS    0x0002                // This gives the version of the .3ds file
#define EDITKEYFRAME  0xB000                // This is the header for all of the key frame info

//>------ sub defines of OBJECTINFO
#define MATERIAL      0xAFFF                // This stored the texture info
#define OBJECT        0x4000                // This stores the faces, vertices, etc...

//>------ sub defines of MATERIAL
#define MATNAME       0xA000                // This holds the material name
#define MATDIFFUSE    0xA020                // This holds the color of the object/material
#define MATMAP        0xA200                // This is a header for a new material
#define MATMAPFILE    0xA300                // This holds the file name of the texture

#define OBJECT_MESH   0x4100                // This lets us know that we are reading a new object

//>------ sub defines of OBJECT_MESH
#define OBJECT_VERTICES     0x4110          // The objects vertices
#define OBJECT_FACES        0x4120          // The objects faces
#define OBJECT_MATERIAL     0x4130          // This is found if the object has a material, either texture map or color
#define OBJECT_UV           0x4140          // The UV texture coordinates

//CJP addition:
#define OBJECT_LOCAL        0x4160          // Coordinate axes of the object


// Here is our structure for our 3DS indicies (since .3DS stores 4 unsigned shorts)
struct tIndices {                           

    unsigned short a, b, c, bVisible;       // This will hold point1, 2, and 3 index's into the vertex array plus a visible flag
};

// This holds the chunk info
struct tChunk
{
    unsigned short int ID;                  // The chunk's ID       
    unsigned int length;                    // The length of the chunk
    unsigned int bytesRead;                 // The amount of bytes read within that chunk
};

// This class handles all of the loading code
class CLoad3DS
{
public:
    CLoad3DS();                             // This inits the data members

    // This is the function that you call to load the 3DS
    bool Import3DS(t3DModel *pModel, const char *strFileName);

private:
    // This reads in a string and saves it in the char array passed in
    int GetString(char *);

    // This reads the next chunk
    void ReadChunk(tChunk *);

    // This reads the next large chunk
    void ProcessNextChunk(t3DModel *pModel, tChunk *);

    // This reads the object chunks
    void ProcessNextObjectChunk(t3DModel *pModel, t3DObject *pObject, tChunk *);

    // This reads the material chunks
    void ProcessNextMaterialChunk(t3DModel *pModel, tChunk *);

    // This reads the RGB value for the object's color
    void ReadColorChunk(tMaterialInfo *pMaterial, tChunk *pChunk);

    // This reads the objects vertices
    void ReadVertices(t3DObject *pObject, tChunk *);

    // This reads the objects face information
    void ReadVertexIndices(t3DObject *pObject, tChunk *);

    // This reads the texture coodinates of the object
    void ReadUVCoordinates(t3DObject *pObject, tChunk *);

    //CJP addition
    // This reads the local coordinate system of the object
    void ReadLocalAxes(t3DObject *pObject, tChunk *);

    // This reads in the material name assigned to the object and sets the materialID
    void ReadObjectMaterial(t3DModel *pModel, t3DObject *pObject, tChunk *pPreviousChunk);
    
    // This computes the vertex normals for the object (used for lighting)
    void ComputeNormals(t3DModel *pModel);

    // This frees memory and closes the file
    void CleanUp();
    
    // The file pointer
    FILE *m_FilePointer;
    
    // These are used through the loading process to hold the chunk information
    tChunk *m_CurrentChunk;
    tChunk *m_TempChunk;
};


#endif


/////////////////////////////////////////////////////////////////////////////////
//
// * QUICK NOTES * 
// 
// This file is created in the hopes that you can just plug it into your code
// easily.  You will probably want to query more chunks though for animation, etc..
//
// 
// Ben Humphrey (DigiBen)
// Game Programmer
// DigiBen@GameTutorials.com
// Co-Web Host of www.GameTutorials.com
//
//
