/* -----------------------------------------------------------------------------

   PicoModel Library

   Copyright (c) 2002, Randy Reddig & seaw0lf
   All rights reserved.

   Redistribution and use in source and binary forms, with or without modification,
   are permitted provided that the following conditions are met:

   Redistributions of source code must retain the above copyright notice, this list
   of conditions and the following disclaimer.

   Redistributions in binary form must reproduce the above copyright notice, this
   list of conditions and the following disclaimer in the documentation and/or
   other materials provided with the distribution.

   Neither the names of the copyright holders nor the names of its contributors may
   be used to endorse or promote products derived from this software without
   specific prior written permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
   ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
   ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

   ----------------------------------------------------------------------------- */



/* marker */
#ifndef PICOMODEL_H
#define PICOMODEL_H

#ifdef __cplusplus
extern "C"
{
#endif

#include <stddef.h>



/* version */
#define PICOMODEL_VERSION       "0.8.20"


/* constants */
#define PICO_GROW_SHADERS       16
#define PICO_GROW_SURFACES      16
#define PICO_GROW_VERTEXES      1024
#define PICO_GROW_INDEXES       1024
#define PICO_GROW_ARRAYS        8
#define PICO_GROW_FACES         256
#define PICO_MAX_SPECIAL        8
#define PICO_MAX_DEFAULT_EXTS   4       /* max default extensions per module */


/* types */
typedef unsigned char picoByte_t;
typedef float picoVec_t;
typedef float picoVec2_t[ 2 ];
typedef float picoVec3_t[ 3 ];
typedef float picoVec4_t[ 4 ];
typedef picoByte_t picoColor_t[ 4 ];
typedef int picoIndex_t;

typedef enum
{
	PICO_BAD,
	PICO_TRIANGLES,
	PICO_PATCH
}
picoSurfaceType_t;

typedef enum
{
	PICO_NORMAL,
	PICO_VERBOSE,
	PICO_WARNING,
	PICO_ERROR,
	PICO_FATAL
}
picoPrintLevel_t;

typedef struct picoSurface_s picoSurface_t;
typedef struct picoShader_s picoShader_t;
typedef struct picoModel_s picoModel_t;
typedef struct picoModule_s picoModule_t;

struct picoSurface_s
{
	void                        *data;

	picoModel_t                 *model;     /* owner model */

	picoSurfaceType_t type;
	char                        *name;      /* sea: surface name */
	picoShader_t                *shader;    /* ydnar: changed to ptr */

	int numVertexes, maxVertexes;
	picoVec3_t                  *xyz;
	picoVec3_t                  *normal;
	picoIndex_t                 *smoothingGroup;

	int numSTArrays, maxSTArrays;
	picoVec2_t                  **st;

	int numColorArrays, maxColorArrays;
	picoColor_t                 **color;

	int numIndexes, maxIndexes;
	picoIndex_t                 *index;

	int numFaceNormals, maxFaceNormals;
	picoVec3_t                  *faceNormal;

	int special[ PICO_MAX_SPECIAL ];
};


/* seaw0lf */
struct picoShader_s
{
	picoModel_t                 *model;         /* owner model */

	char                        *name;          /* shader name */
	char                        *mapName;       /* shader file name (name of diffuse texturemap) */
	picoColor_t ambientColor;                   /* ambient color of mesh (rgba) */
	picoColor_t diffuseColor;                   /* diffuse color of mesh (rgba) */
	picoColor_t specularColor;                  /* specular color of mesh (rgba) */
	float transparency;                         /* transparency (0..1; 1 = 100% transparent) */
	float shininess;                            /* shininess (0..128; 128 = 100% shiny) */
};

struct picoModel_s
{
	void                        *data;
	char                        *name;          /* model name */
	char                        *fileName;      /* sea: model file name */
	int frameNum;                               /* sea: renamed to frameNum */
	int numFrames;                              /* sea: number of frames */
	picoVec3_t mins;
	picoVec3_t maxs;

	int numShaders, maxShaders;
	picoShader_t                **shader;

	int numSurfaces, maxSurfaces;
	picoSurface_t               **surface;

	const picoModule_t          *module;        /* sea */
};


/* seaw0lf */
/* return codes used by the validation callbacks; pmv is short */
/* for 'pico module validation'. everything >PICO_PMV_OK means */
/* that there was an error. */
enum
{
	PICO_PMV_OK,            /* file valid */
	PICO_PMV_ERROR,         /* file not valid */
	PICO_PMV_ERROR_IDENT,   /* unknown file magic (aka ident) */
	PICO_PMV_ERROR_VERSION, /* unsupported file version */
	PICO_PMV_ERROR_SIZE,    /* file size error */
	PICO_PMV_ERROR_MEMORY,  /* out of memory error */
};

/* convenience (makes it easy to add new params to the callbacks) */
#define PM_PARAMS_CANLOAD \
	const char *fileName, const void *buffer, int bufSize

#define PM_PARAMS_LOAD \
	const char *fileName, int frameNum, const void *buffer, int bufSize

#define PM_PARAMS_CANSAVE \
	void

#define PM_PARAMS_SAVE \
	const char *fileName, picoModel_t * model

/* pico file format module structure */
struct picoModule_s
{
	char                    *version;                               /* internal module version (e.g. '1.5-b2') */

	char                    *displayName;                           /* string used to display in guis, etc. */
	char                    *authorName;                            /* author name (eg. 'My Real Name') */
	char                    *copyright;                             /* copyright year and holder (eg. '2002 My Company') */

	char                    *defaultExts[ PICO_MAX_DEFAULT_EXTS ];  /* default file extensions used by this file type */
	int ( *canload )( PM_PARAMS_CANLOAD );                          /* checks whether module can load given file (returns PMVR_*) */
	picoModel_t             *( *load )( PM_PARAMS_LOAD );             /* parses model file data */
	int ( *cansave )( PM_PARAMS_CANSAVE );                          /* checks whether module can save (returns 1 or 0 and might spit out a message) */
	int ( *save )( PM_PARAMS_SAVE );                                /* saves a pico model in module's native model format */
};



/* general functions */
int                         PicoInit( void );
void                        PicoShutdown( void );
int                         PicoError( void );

void                        PicoSetMallocFunc( void *( *func )( size_t ) );
void                        PicoSetFreeFunc( void ( *func )( void* ) );
void                        PicoSetLoadFileFunc( void ( *func )( const char*, unsigned char**, int* ) );
void                        PicoSetFreeFileFunc( void ( *func )( void* ) );
void                        PicoSetPrintFunc( void ( *func )( int, const char* ) );

const picoModule_t          **PicoModuleList( int *numModules );

picoModel_t                 *PicoLoadModel( const char *name, int frameNum );

typedef size_t ( *PicoInputStreamReadFunc )( void* inputStream, unsigned char* buffer, size_t length );
picoModel_t* PicoModuleLoadModelStream( const picoModule_t* module, void* inputStream, PicoInputStreamReadFunc inputStreamRead, size_t streamLength, int frameNum, const char *fileName );

/* model functions */
picoModel_t                 *PicoNewModel( void );
void                        PicoFreeModel( picoModel_t *model );
int                         PicoAdjustModel( picoModel_t *model, int numShaders, int numSurfaces );


/* shader functions */
picoShader_t                *PicoNewShader( picoModel_t *model );
void                        PicoFreeShader( picoShader_t *shader );
picoShader_t                *PicoFindShader( picoModel_t *model, char *name, int caseSensitive );


/* surface functions */
picoSurface_t               *PicoNewSurface( picoModel_t *model );
void                        PicoFreeSurface( picoSurface_t *surface );
picoSurface_t               *PicoFindSurface( picoModel_t *model, char *name, int caseSensitive );
int                         PicoAdjustSurface( picoSurface_t *surface, int numVertexes, int numSTArrays, int numColorArrays, int numIndexes, int numFaceNormals );


/* setter functions */
void                        PicoSetModelName( picoModel_t *model, const char *name );
void                        PicoSetModelFileName( picoModel_t *model, const char *fileName );
void                        PicoSetModelFrameNum( picoModel_t *model, int frameNum );
void                        PicoSetModelNumFrames( picoModel_t *model, int numFrames );
void                        PicoSetModelData( picoModel_t *model, void *data );

void                        PicoSetShaderName( picoShader_t *shader, char *name );
void                        PicoSetShaderMapName( picoShader_t *shader, char *mapName );
void                        PicoSetShaderAmbientColor( picoShader_t *shader, picoColor_t color );
void                        PicoSetShaderDiffuseColor( picoShader_t *shader, picoColor_t color );
void                        PicoSetShaderSpecularColor( picoShader_t *shader, picoColor_t color );
void                        PicoSetShaderTransparency( picoShader_t *shader, float value );
void                        PicoSetShaderShininess( picoShader_t *shader, float value );

void                        PicoSetSurfaceData( picoSurface_t *surface, void *data );
void                        PicoSetSurfaceType( picoSurface_t *surface, picoSurfaceType_t type );
void                        PicoSetSurfaceName( picoSurface_t *surface, const char *name );
void                        PicoSetSurfaceShader( picoSurface_t *surface, picoShader_t *shader );
void                        PicoSetSurfaceXYZ( picoSurface_t *surface, int num, picoVec3_t xyz );
void                        PicoSetSurfaceNormal( picoSurface_t *surface, int num, picoVec3_t normal );
void                        PicoSetSurfaceST( picoSurface_t *surface, int array, int num, picoVec2_t st );
void                        PicoSetSurfaceColor( picoSurface_t *surface, int array, int num, const picoColor_t color );
void                        PicoSetSurfaceIndex( picoSurface_t *surface, int num, picoIndex_t index );
void                        PicoSetSurfaceIndexes( picoSurface_t *surface, int num, picoIndex_t *index, int count );
void                        PicoSetFaceNormal( picoSurface_t *surface, int num, picoVec3_t normal );
void                        PicoSetSurfaceSpecial( picoSurface_t *surface, int num, int special );
void                        PicoSetSurfaceSmoothingGroup( picoSurface_t *surface, int num, picoIndex_t smoothingGroup );


/* getter functions */
char                        *PicoGetModelName( picoModel_t *model );
char                        *PicoGetModelFileName( picoModel_t *model );
int                         PicoGetModelFrameNum( picoModel_t *model );
int                         PicoGetModelNumFrames( picoModel_t *model );
void                        *PicoGetModelData( picoModel_t *model );
int                         PicoGetModelNumShaders( picoModel_t *model );
picoShader_t                *PicoGetModelShader( picoModel_t *model, int num ); /* sea */
int                         PicoGetModelNumSurfaces( picoModel_t *model );
picoSurface_t               *PicoGetModelSurface( picoModel_t *model, int num );
int                         PicoGetModelTotalVertexes( picoModel_t *model );
int                         PicoGetModelTotalIndexes( picoModel_t *model );

char                        *PicoGetShaderName( picoShader_t *shader );
char                        *PicoGetShaderMapName( picoShader_t *shader );
picoByte_t                  *PicoGetShaderAmbientColor( picoShader_t *shader );
picoByte_t                  *PicoGetShaderDiffuseColor( picoShader_t *shader );
picoByte_t                  *PicoGetShaderSpecularColor( picoShader_t *shader );
float                       PicoGetShaderTransparency( picoShader_t *shader );
float                       PicoGetShaderShininess( picoShader_t *shader );

void                        *PicoGetSurfaceData( picoSurface_t *surface );
char                        *PicoGetSurfaceName( picoSurface_t *surface );      /* sea */
picoSurfaceType_t           PicoGetSurfaceType( picoSurface_t *surface );
char                        *PicoGetSurfaceName( picoSurface_t *surface );
picoShader_t                *PicoGetSurfaceShader( picoSurface_t *surface );    /* sea */

int                         PicoGetSurfaceNumVertexes( picoSurface_t *surface );
picoVec_t                   *PicoGetSurfaceXYZ( picoSurface_t *surface, int num );
picoVec_t                   *PicoGetSurfaceNormal( picoSurface_t *surface, int num );
picoVec_t                   *PicoGetSurfaceST( picoSurface_t *surface, int array, int num );
picoByte_t                  *PicoGetSurfaceColor( picoSurface_t *surface, int array, int num );
int                         PicoGetSurfaceNumIndexes( picoSurface_t *surface );
picoIndex_t                 PicoGetSurfaceIndex( picoSurface_t *surface, int num );
picoIndex_t                 *PicoGetSurfaceIndexes( picoSurface_t *surface, int num );
picoVec_t                   *PicoGetFaceNormal( picoSurface_t *surface, int num );
int                         PicoGetSurfaceSpecial( picoSurface_t *surface, int num );


/* hashtable related functions */
typedef struct picoVertexCombinationData_s
{
	picoVec3_t xyz, normal;
	picoVec2_t st;
	picoColor_t color;
} picoVertexCombinationData_t;

typedef struct picoVertexCombinationHash_s
{
	picoVertexCombinationData_t vcd;
	picoIndex_t index;

	void                        *data;

	struct picoVertexCombinationHash_s  *next;
} picoVertexCombinationHash_t;

int                         PicoGetHashTableSize( void );
unsigned int                PicoVertexCoordGenerateHash( picoVec3_t xyz );
picoVertexCombinationHash_t **PicoNewVertexCombinationHashTable( void );
void                        PicoFreeVertexCombinationHashTable( picoVertexCombinationHash_t **hashTable );
picoVertexCombinationHash_t *PicoFindVertexCombinationInHashTable( picoVertexCombinationHash_t **hashTable, picoVec3_t xyz, picoVec3_t normal, picoVec3_t st, picoColor_t color );
picoVertexCombinationHash_t *PicoAddVertexCombinationToHashTable( picoVertexCombinationHash_t **hashTable, picoVec3_t xyz, picoVec3_t normal, picoVec3_t st, picoColor_t color, picoIndex_t index );

/* specialized functions */
int                         PicoFindSurfaceVertexNum( picoSurface_t *surface, picoVec3_t xyz, picoVec3_t normal, int numSTs, picoVec2_t *st, int numColors, const picoColor_t *color, picoIndex_t smoothingGroup );
void                        PicoFixSurfaceNormals( picoSurface_t *surface );
int                         PicoRemapModel( picoModel_t *model, char *remapFile );


void PicoAddTriangleToModel( picoModel_t *model, picoVec3_t** xyz, picoVec3_t** normals, int numSTs, picoVec2_t **st, int numColors, const picoColor_t **colors, picoShader_t* shader, const char *name, picoIndex_t* smoothingGroup );

/* end marker */
#ifdef __cplusplus
}
#endif

#endif
