//
// metaobjects.h
//

#ifndef __METAOBJECTS_H_
#define __METAOBJECTS_H_

#include "ogl_support.h"

#define	MO_COOKIE				0xfeedface		// set at head of every object for validation

#define	SPRITE_SCALE_BASIS_DENOMINATOR	640.0f

		/* OBJECT TYPES */
enum
{
	MO_TYPE_GROUP		= 	'grup',
	MO_TYPE_MESH		=	'mesh',
	MO_TYPE_MATERIAL	=	'matl',
	MO_TYPE_MATRIX		=	'mtrx'
};



		/* META OBJECT HEADER */
		//
		// This structure is always at the head of any metaobject
		//

struct MetaObjectHeader
{
	u_long		cookie;						// this value should always == MO_COOKIE
	long		refCount;					// # times this is referenced
	u_long		type;						// object type
	u_long		subType;					// object sub-type
	void		*data;						// pointer to meta object's specific data	
	
	struct MetaObjectHeader *parentGroup;			// illegal reference to parent group, or nil if no parent
		
	struct MetaObjectHeader *prevNode;			// ptr to previous node in linked list
	struct MetaObjectHeader *nextNode;			// ptr to next node in linked list
};
typedef struct MetaObjectHeader MetaObjectHeader;

typedef	void * MetaObjectPtr;


		/****************/
		/* GROUP OBJECT */
		/****************/
		
#define	MO_MAX_ITEMS_IN_GROUP	70
		
typedef struct
{
	int					numObjectsInGroup;	
	MetaObjectHeader	*groupContents[MO_MAX_ITEMS_IN_GROUP];
}MOGroupData;
		
typedef struct
{
	MetaObjectHeader	objectHeader;
	MOGroupData			objectData;
}MOGroupObject;


		/*******************/
		/* MATERIAL OBJECT */
		/*******************/

typedef struct
{
	OGLSetupOutputType *setupInfo;					// materials are draw context relative, so remember which context we're using now
	
	u_long			flags;	
	OGLColorRGBA	diffuseColor;					// rgba diffuse color
	
	Boolean			hasTexture;			
	u_long			width,height;					// dimensions of texture
	void			*texturePixels;					// ptr to texture pixels
	GLuint			textureName;					// texture name assigned by OpenGL
}MOMaterialData;
		
typedef struct
{
	MetaObjectHeader	objectHeader;
	MOMaterialData		objectData;
}MOMaterialObject;



		/***************/
		/* MESH OBJECT */
		/***************/
		
typedef struct
{
	GLuint vertexIndices[3];
}MOTriangleIndecies;
		
typedef struct
{
	MOMaterialObject 	*material;							// a reference to a material meta object
	
	int					numPoints;							// # vertices in the model
	int					numTriangles;						// # triangls in the model
	OGLPoint3D			*points;							// ptr to array of vertex x,y,z coords
	OGLVector3D			*normals;							// ptr to array of vertex normals
	OGLTextureCoord		*uvs;								// ptr to array of vertex uv's
	OGLColorRGBA_Byte	*colorsByte;						// ptr to array of vertex colors (byte & float versions)
	OGLColorRGBA		*colorsFloat;
	MOTriangleIndecies	*triangles;						// ptr to array of triangle triad indecies
			
	OGLBoundingBox		bBox;
}MOMeshData;
		
typedef struct
{
	MetaObjectHeader	objectHeader;
	MOMeshData			objectData;
}MOMeshObject;



		/*****************/
		/* MATRIX OBJECT */
		/*****************/
		
typedef struct
{
	MetaObjectHeader	objectHeader;
	OGLMatrix4x4		matrix;
}MOMatrixObject;





//-----------------------------

		/* C FUNCTIONS */
		
#ifdef __cplusplus
extern "C" {
#endif

void MO_InitHandler(void);
MetaObjectPtr MO_CreateNewObjectOfType(u_long type, u_long subType, void *data);
MetaObjectPtr MO_GetNewReference(MetaObjectPtr mo);
void MO_AppendToGroup(MOGroupObject *group, MetaObjectPtr newObject);
void MO_AttachToGroupStart(MOGroupObject *group, MetaObjectPtr newObject);
void MO_DrawGeometry_VertexArray(const MOMeshData *data);
void MO_DrawGroup(const MOGroupObject *object, const OGLSetupOutputType *setupInfo);
void MO_DrawObject(const MetaObjectPtr object, const OGLSetupOutputType *setupInfo);
void MO_DrawMaterial(MOMaterialObject *matObj);
void MO_DrawMatrix(const MOMatrixObject *matObj, const OGLSetupOutputType *setupInfo);
void MO_DisposeObjectReference(MetaObjectPtr obj);
void MO_DuplicateVertexArrayData(MOMeshData *inData, MOMeshData *outData);
void MO_DeleteObjectInfo_Geometry_VertexArray(MOMeshData *data);
void MO_DisposeObject_Geometry_VertexArray(MOMeshData *data);
void MO_CalcBoundingBox(MetaObjectPtr object, OGLBoundingBox *bBox);
void MO_VertexArray_OffsetUVs(MetaObjectPtr object, float du, float dv);
void MO_Object_OffsetUVs(MetaObjectPtr object, float du, float dv);
MOMaterialObject *MO_CreateTextureObjectFromBuffer(OGLSetupOutputType *setupInfo, int width, int height, Ptr buffer);

#ifdef __cplusplus
}
#endif


#endif