// *** OpenGTA3 ***
// 3D engine related stuff

enum RwRenderState {
    rwRENDERSTATENARENDERSTATE = 0,

    rwRENDERSTATETEXTURERASTER = 1,
        /**<Raster used for texturing (normally used in immediate mode). 
         *  The value is a pointer to an \ref RwRaster.
         * Default: NULL.
         */
    rwRENDERSTATETEXTUREADDRESS = 2,
        /**<\ref RwTextureAddressMode: wrap,clamp, mirror or border.
         * Default: rwTEXTUREADDRESSWRAP.
         */
    rwRENDERSTATETEXTUREADDRESSU = 3,
        /**<\ref RwTextureAddressMode in u only.
         * Default: rwTEXTUREADDRESSWRAP.
         */
    rwRENDERSTATETEXTUREADDRESSV = 4,
        /**<\ref RwTextureAddressMode in v only.
         * Default: rwTEXTUREADDRESSWRAP.
         */
    rwRENDERSTATETEXTUREPERSPECTIVE = 5,
        /**<Perspective correction on/off (always enabled on many platforms).
         */
    rwRENDERSTATEZTESTENABLE = 6,
        /**<Z-buffer test on/off.
         * Default: TRUE.
         */
    rwRENDERSTATESHADEMODE = 7,
        /**<\ref RwShadeMode: flat or gouraud shading.
         * Default: rwSHADEMODEGOURAUD.
         */
    rwRENDERSTATEZWRITEENABLE = 8,
        /**<Z-buffer write on/off.
         * Default: TRUE.
         */
    rwRENDERSTATETEXTUREFILTER = 9,
        /**<\ref RwTextureFilterMode: point sample, bilinear, trilinear, etc.
         * Default: rwFILTERLINEAR.
         */
    rwRENDERSTATESRCBLEND = 10,
        /**<\ref RwBlendFunction used to modulate the source pixel color
         *  when blending to the frame buffer.
         * Default: rwBLENDSRCALPHA.
         */
    rwRENDERSTATEDESTBLEND = 11,
        /**<\ref RwBlendFunction used to modulate the destination pixel
         *  color in the frame buffer when blending. The resulting pixel
         *  color is given by the formula 
         *  (SRCBLEND * srcColor + DESTBLEND * destColor) for each RGB
         *  component. For a particular platform, not all combinations
         *  of blend function are allowed (see platform specific
         *  restrictions).
         * Default: rwBLENDINVSRCALPHA.
         */
    rwRENDERSTATEVERTEXALPHAENABLE = 12,
        /**<Alpha blending on/off (always enabled on some platforms). 
         *  This is normally used in immediate mode to enable alpha blending 
         *  when vertex colors or texture rasters have transparency. Retained
         *  mode pipelines will usually set this state based on material colors 
         *  and textures.
         * Default: FALSE.
         */
    rwRENDERSTATEBORDERCOLOR = 13,
        /**<Border color for \ref RwTextureAddressMode 
         *  \ref rwTEXTUREADDRESSBORDER. The value should be a packed 
         *  RwUInt32 in a platform specific format. The macro 
         *  RWRGBALONG(r, g, b, a) may be used to construct this using 
         *  8-bit color components.
         * Default: RWRGBALONG(0, 0, 0, 0).
         */
    rwRENDERSTATEFOGENABLE = 14,
        /**<Fogging on/off (all polygons will be fogged).  
         * Default: FALSE.
         */
    rwRENDERSTATEFOGCOLOR = 15,
        /**<Color used for fogging. The value should be a packed RwUInt32 
         *  in a platform specific format. The macro RWRGBALONG(r, g, b, a)
         *  may be used to construct this using 8-bit color components. 
         * Default: RWRGBALONG(0, 0, 0, 0).
         */
    rwRENDERSTATEFOGTYPE = 16,
        /**<\ref RwFogType, the type of fogging to use. 
         * Default: rwFOGTYPELINEAR.
         */
    rwRENDERSTATEFOGDENSITY = 17,
        /**<Fog density for \ref RwFogType of 
         *  \ref rwFOGTYPEEXPONENTIAL or \ref rwFOGTYPEEXPONENTIAL2. 
         *  The value should be a pointer to an RwReal in the 
         *  range 0 to 1.  
         * Default: 1.
         */
    rwRENDERSTATECULLMODE = 20,
        /**<\ref RwCullMode, for selecting front/back face culling, or
         *  no culling.
         * Default: rwCULLMODECULLBACK.
         */
    rwRENDERSTATESTENCILENABLE = 21,
        /**<Stenciling on/off.
         *  <i> Supported on Xbox, D3D8, D3D9, and OpenGL only. </i>
         * Default: FALSE.
         */
    rwRENDERSTATESTENCILFAIL = 22,
        /**<\ref RwStencilOperation used when the stencil test passes.
         *  <i> Supported on Xbox, D3D8, D3D9, and OpenGL only. </i>
         * Default: rwSTENCILOPERATIONKEEP.
         */
    rwRENDERSTATESTENCILZFAIL = 23,
        /**<\ref RwStencilOperation used when the stencil test passes and 
         *  the depth test (z-test) fails. 
         *  <i> Supported on Xbox, D3D8, D3D9, and OpenGL only. </i>
         * Default: rwSTENCILOPERATIONKEEP.
         */
    rwRENDERSTATESTENCILPASS = 24,
        /**<\ref RwStencilOperation used when both the stencil and the depth 
         *  (z) tests pass. 
         *  <i> Supported on Xbox, D3D8, D3D9, and OpenGL only. </i>
         * Default: rwSTENCILOPERATIONKEEP.
         */
    rwRENDERSTATESTENCILFUNCTION = 25,
        /**<\ref RwStencilFunction for the stencil test. 
         *  <i> Supported on Xbox, D3D8, D3D9, and OpenGL only. </i>
         * Default: rwSTENCILFUNCTIONALWAYS.
         */
    rwRENDERSTATESTENCILFUNCTIONREF = 26,
        /**<Integer reference value for the stencil test. 
         *  <i> Supported on Xbox, D3D8, D3D9, and OpenGL only. </i>
         * Default: 0.
         */
    rwRENDERSTATESTENCILFUNCTIONMASK = 27,
        /**<Mask applied to the reference value and each stencil buffer 
         *  entry to determine the significant bits for the stencil test. 
         *  <i> Supported on Xbox, D3D8, D3D9, and OpenGL only. </i>
         * Default: 0xffffffff.
         */
    rwRENDERSTATESTENCILFUNCTIONWRITEMASK = 28,
        /**<Write mask applied to values written into the stencil buffer. 
         *  <i> Supported on Xbox, D3D8, D3D9, and OpenGL only. </i>
         * Default: 0xffffffff.
         */
    rwRENDERSTATEALPHATESTFUNCTION = 29,
        /**<\ref RwAlphaTestFunction for the alpha test. When a pixel fails,
         * neither the frame buffer nor the Z-buffer are updated.
         * Default: rwALPHATESTFUNCTIONGREATER (GameCube, Xbox, D3D8, D3D9
         * and OpenGL). The default PS2 behaviour is to always update the
         * frame buffer and update the Z-buffer only if a greater than or
         * equal test passes.
         */
    rwRENDERSTATEALPHATESTFUNCTIONREF = 30,
        /**<Integer reference value for the alpha test. 
         *  <i> Range is 0 to 255, mapped to the platform's actual range </i>
         * Default: 128 (PS2) 0 (GameCube, Xbox, D3D8, D3D9 and OpenGL).
         */

    rwRENDERSTATEFORCEENUMSIZEINT = 0x7FFFFFFF
};

enum RwPrimitiveType
{
    rwPRIMTYPENAPRIMTYPE = 0,   /**<Invalid primative type */
    rwPRIMTYPELINELIST = 1,     /**<Unconnected line segments, each line is specified by
                                 * both its start and end index, independently of other lines
                                 * (for example, 3 segments specified as 0-1, 2-3, 4-5) */
    rwPRIMTYPEPOLYLINE = 2,     /**<Connected line segments, each line's start index
                                 * (except the first) is specified by the index of the end of
                                 * the previous segment (for example, 3 segments specified as
                                 * 0-1, 1-2, 2-3) */
    rwPRIMTYPETRILIST = 3,      /**<Unconnected triangles: each triangle is specified by
                                 * three indices, independently of other triangles (for example,
                                 * 3 triangles specified as 0-1-2, 3-4-5, 6-7-8) */
    rwPRIMTYPETRISTRIP = 4,     /**<Connected triangles sharing an edge with, at most, one
                                 * other forming a series (for example, 3 triangles specified
                                 * as 0-2-1, 1-2-3-, 2-4-3) */
    rwPRIMTYPETRIFAN = 5 ,      /**<Connected triangles sharing an edge with, at most,
                                 * two others forming a fan (for example, 3 triangles specified
                                 * as 0-2-1, 0-3-2, 0-4-3) */
    rwPRIMTYPEPOINTLIST = 6,    /**<Points 1, 2, 3, etc. This is not
                                 * supported by the default RenderWare
                                 * immediate or retained-mode pipelines
                                 * (except on PlayStation 2), it is intended
                                 * for use by user-created pipelines */
    rwPRIMITIVETYPEFORCEENUMSIZEINT = 0x7FFFFFFF
};

#pragma pack(push, 1)

struct rwMemoryFunctions {
	void *(*rwmalloc)(size_t size, DWORD hint);
	void  (*rwfree)(void *mem);
	void *(*rwrealloc)(void *mem, size_t newSize, DWORD hint);
	void *(*rwcalloc)(size_t numObj, size_t sizeObj, DWORD hint);
};

// Эта структура постепенно заменит RwEngineInstance
// По мере проработки, из нее уйдет работа с строками и файлами
// Все функции, которые работают с ней, переместятся в методы
struct CEngine {
	BYTE	_fill1[0x10];
	// RwDevice begins here
	float	gammaCorrection;	// 010
	DWORD	fpSystem;	// 014
	float	zBufferNear;	// 018
	float	zBufferFar;	// 01C
	void	(__cdecl * renderStateSet)(RwRenderState state, DWORD param);	// 020
	void * _renderStateGet;	// 024
	void * _im2DRenderLine;	// 028
	void * _im2DRenderTriangle;	// 02C
	void	(__cdecl * im2DRenderPrimitive) (RwPrimitiveType type, void * vertices, int count);	// 030
	void * im2DRenderIndexedPrimitive; // 034
	void * _im3DRenderLine; // 038
	void * _im3DRenderTriangle; // 03C
	void * _im3DRenderPrimitive;	// 040
	void * _im3DRenderIndexedPrimitive; // 044
	// RwDevice ends here
	DWORD	_f48;
	DWORD	_f4C;
	DWORD	_f50;
	DWORD	_f54;
	DWORD	_f58;
	DWORD	_f5C;
	void * _getImageFromRaster;	// 060
	void * _setRasterFromImage;	// 064
	DWORD	_f68;
	void * _findRasterFormat;	// 06C
	DWORD	_f70;
	DWORD	_f74;
	DWORD	_f78;
	DWORD	_f7C;
	DWORD	_f80;
	DWORD	_f84;
	DWORD	_f88;
	DWORD	_f8C;
	DWORD	_f90;
	DWORD	_f94;
	DWORD	_f98;
	DWORD	_f9C;
	DWORD	_fA0;
	DWORD	_fA4;
	DWORD	_fA8;
	DWORD	_fAC;
	DWORD	_fB0;
	DWORD	_fB4;
	DWORD	_fB8;
	DWORD	_fBC;
	DWORD	_fC0;
	// RwFileFunctions begins here	TODO: от них нужно избавиться как только это будет возможно
	DWORD	_fC4;
	FILE	(__cdecl *rwfopen) (char * name, char * mode);	// 0C8
	void	(__cdecl *rwfclose) (FILE * file);	// 0CC
	void * _rwfread;	// 0D0
	void * _rwfwrite;	// 0D4
	void * _rwfgets;	// 0D8
	void *	_fDC;
	void * _rwfeof;		// 0E0
	void * _rwfseek;	// 0E4
	void *	_fE8;		
	void * _rwftell;	// 0EC
	// RwFileFunctions ends here
	// RwStringFunctions begins here	TODO: от них нужно избавиться как только это будет возможно
	void * _rwsprintf;	// 0F0
	void * _rwvsprintf;	// 0F4
	void * _rwstrcpy;	// 0F8
	void * _rwstrncpy;	// 0FC
	void * _rwstrcat;	// 100
	void * _rwstrncat;	// 104
	void * _rwstrrchr;	// 108
	void * _rwstrchr;	// 10C
	void * _rwstrstr;	// 110
	void * _rwstrcmp;	// 114
	void * _rwstrncmp;	// 118
	void * _rwstricmp;	// 11C
	void * _rwstrlen;	// 120
	void * _rwstrupr;	// 124
	void * _rwstrlwr;	// 128
	void * _rwstrtok;	// 12C
	void * _rwsscanf;	// 130
	// RwStringFunctions ends here
	rwMemoryFunctions mem;
	void *	(__cdecl * alloc) (void * list, int hint);	// 144
	void	(__cdecl * free) (void * list, void * ptr);	// 148
	DWORD	metrics;	// 14C
	DWORD	engineStatus;	// 150 TODO: bool
	DWORD	resArenaSize;	// 154

	// инициализация. Возвращает false, если произошла ошибка
	bool	init (DWORD _resArenaSize);	//	TODO: а параметр-то нужен?
};
#pragma pack(pop)

extern CEngine ** engine;

#define RENDERSTATESET(s,p) (*engine)->renderStateSet(s, (p))
#define RENDERPRIMITIVE(prim,v,n) (*engine)->im2DRenderPrimitive (prim, (v), (n));

struct RwLLLink {
    RwLLLink *next;
    RwLLLink *prev;
};

// ############################################################################
//	memory allocation
typedef void (*cbaCallback)(void * mem, void * param);

class CBlockAllocator {
public:
	CBlockAllocator (DWORD entrySize, DWORD entriesPerBlock, DWORD preallocateBlocks = 1, DWORD alignment = 4);
	~CBlockAllocator ();

	BYTE * allocateEntry ();
	void freeEntry (BYTE * ptr);
	void forAllUsed (cbaCallback cb, void * param);
	
	int purge ();	// free all empty blocks
	static int purgeAll ();	// free all empty blocks for all allocators

protected:
	struct BlockHead {
		BlockHead * next;		// pointer to the next block (NULL for last block)
		DWORD	allocated;		// number of allocated entries in block
		DWORD	usageMap[1];	// bitmap of the used entries	
	};

	bool	allocateBlock ();	// выделить новый блок и вставить его в начало списка
	void	freeBlock (BlockHead * prevBlock);	// освободить блок, следующий за указанным. Если параметром передан NULL - освободить первый блок

	DWORD entrySize;
	DWORD entriesPerBlock;
	DWORD alignment;
	DWORD blockHeadSize;		// real size of block head
	DWORD flags;				// 2 - release blocks as possible
	BlockHead *		blocks;
	CBlockAllocator * link;		// pointer to the next allocator in chain
};
// ############################################################################
//	streams
// TODO: сделать класс RwStream. 
//	для каждого из возможных типов должен наследоваться свой класс

enum RwStreamType {
    rwNASTREAM = 0,     /**0 - <Invalid stream type */
    rwSTREAMFILE,       /**1 - <File */
    rwSTREAMFILENAME,   /**2 - <File name */
    rwSTREAMMEMORY,     /**3 - <Memory*/
    rwSTREAMCUSTOM		/**4 - <Custom */
};

enum RwStreamAccessType {
    rwNASTREAMACCESS = 0,   /**0 - <Invalid stream access */
    rwSTREAMREAD,           /**1 - <Read */
    rwSTREAMWRITE,          /**2 - <Write */
    rwSTREAMAPPEND			/**3 - <Append */
};

struct RwStream {
	RwStreamType		type;
	RwStreamAccessType	accessType;
	int					position;
	union {
		struct {
			int		position;
			int		size;
			BYTE *	block;
		} memory;
		struct {
			void * file;
		} file;
		struct {
			DWORD	_custom[5];
		} custom;
	};
	bool	owned;
};

// data paramter for RwStreamOpen/rwSTREAMMEMORY
struct RwMemory {
	BYTE *	start;
	DWORD	length;
};

struct RwChunkHeaderInfo {
    DWORD	type;      /**< chunk ID - see \ref RwStreamFindChunk */
    DWORD	length;    /**< length of the chunk data in bytes */
    DWORD	version;   /**< version of the chunk data. See \ref RwEngineGetVersion. */
    DWORD	buildNum;  /**< build number of the RenderWare libraries previously used to stream out the data */
    bool	isComplex;   /**< Internal Use */
};

extern void * _rwStreamModuleOpen (void * object, int offset, int size);	// >> 7EC780 (XREF: rwEngineInit)
extern void * _rwStreamModuleClose (void * object, int offset, int size);	// >> 7EC7E0 (XREF: rwEngineInit)
extern RwStream * RwStreamOpen (RwStreamType type, RwStreamAccessType accessType, void * data);	// >> 7ECEF0 (XREF: 23)
extern RwStream * RwStreamWrite (RwStream * stream, void * buffer, DWORD length); // >> 7ECB30 (76) -- unsupported
extern DWORD RwStreamRead(RwStream * stream, void *buffer, DWORD length); // >> 7EC9D0 (164)
extern RwStream * RwStreamSkip (RwStream * stream, DWORD offset); // >> 7ECD00 (23)
extern bool RwStreamClose (RwStream * stream, void * data);	// >> 7ECE20 (52)
extern RwStream * _rwStreamInitialize (RwStream * stream, bool rwOwned, RwStreamType type, RwStreamAccessType accessType, void * data); // >> 7EC810 (3)
bool _rwStreamReadChunkHeader (RwStream * stream, DWORD * type, DWORD * length, DWORD * version, DWORD * build); // >> 7ED0F0 (7)
extern RwStream * _rwStreamReadData (RwStream * stream, void * data, DWORD bytes);
#define RwStreamReadInt32(s,d,b) _rwStreamReadData (s,d,b)	// >> 7ED540 (58)
#define RwStreamReadReal(s,d,b) _rwStreamReadData (s,d,b)	// >> 7ED4F0 (16)
extern RwStream * RwStreamReadChunkHeaderInfo (RwStream * stream, RwChunkHeaderInfo * info); // 7ED590 (1)
extern bool RwStreamFindChunk (RwStream * stream, DWORD type, DWORD * outLength, DWORD * outVersion); // 7ED2D0 (92)

extern int _rwStringStreamGetSize (char * str); // >> 80A470 (6)
extern char * _rwStringStreamFindAndRead(char *string, RwStream * stream); // >> 80A510 (3);


// plugin callbacks
struct RwStream;	// forward declaration, TODO: remove/redefine as soon, as RwStream rewritten; 
typedef RwStream *(*pluginWriteCB)	(RwStream *stream, int binaryLength, const void *object, int offsetInObject, int sizeInObject);
typedef RwStream *(*pluginReadCB)	(RwStream *stream, int binaryLength, void *object, int offsetInObject, int sizeInObject);
typedef int (*pluginGetSizeCB)(const void *object, int offsetInObject, int sizeInObject);
typedef bool (*pluginAlwaysCB)(void *object, int offsetInObject, int sizeInObject);
typedef bool (*pluginRightsCB)(void *object, int offsetInObject, int sizeInObject, int extraData);
typedef void *(*pluginConstructCB)(void *object, int offsetInObject, int sizeInObject);
typedef void *(*pluginDestructCB)(void *object, int offsetInObject, int sizeInObject);
typedef void *(*pluginCopyCB)(void *dstObject, const void *srcObject, int offsetInObject, int sizeInObject);
typedef void *(*pluginErrStrCB)(void *);

// ############################################################################
// # rasters and textures
#pragma pack(push, 1)
struct RwRaster {
    RwRaster *	parent;		// Top level raster if a sub raster 
    BYTE *		cpPixels;	// Pixel pointer when locked 
    BYTE *		palette;	// Raster palette 
	int			width;
	int			height;
	int			depth;
	int			stide;		// Lines bytes of raster 
	short		nOffsetX;
	short		nOffsetY;
	BYTE		cType;
	BYTE		cFlags;
	BYTE		privateFlags;
	BYTE		cFormat;
	BYTE *		originalPixels;
	int			originalWidth;
	int			originalHeight;
	int			originalStride;
};

struct RwTexDictionary;

#define rwTEXTUREBASENAMELENGTH     32

struct RwTexture {
    RwRaster *	raster;		// pointer to RwRaster with data 
    RwTexDictionary    *dict;		// Dictionary this texture is in 
    RwLLLink    lInDictionary;	// List of textures in this dictionary 

    char		name[rwTEXTUREBASENAMELENGTH];  // Name of the texture 
    char		mask[rwTEXTUREBASENAMELENGTH];  // Name of the textures mask 

    // 31 [xxxxxxxx xxxxxxxx vvvvuuuu ffffffff] 0 
    DWORD		filterAddressing;	// Filtering & addressing mode flags 
    int			refCount;			// Reference count, surprisingly enough 
};
#pragma pack (pop)

// ############################################################################
// # pipeline
enum rxEmbeddedPacketState {
    rxPKST_PACKETLESS = 0, // Packet not created 
    rxPKST_UNUSED     = 1, // Packet created and then destroyed 
    rxPKST_INUSE      = 2, // Packet created but not yet destroyed and fetched but not yet dispatched 
    rxPKST_PENDING    = 3  // Packet created but not destroyed and dispatched but not yet fetched 
};


struct RxPipelineNode;
struct RxPipelineRequiresCluster;
struct RxPacket;


struct RxPipeline {
    bool	locked;			// Flags whether the pipeline is locked for editing 
    DWORD	numNodes;		// Node count 
    RxPipelineNode      *nodes;                 // Topologically sorted array of pipeline nodes 
    DWORD	packetNumClusterSlots; // Number of slots allocated for clusters 
    rxEmbeddedPacketState      embeddedPacketState;   // The state of this pipeline's embedded packet 
    RxPacket                  *embeddedPacket;        // This pipeline's embedded packet 

    DWORD	numInputRequirements;  // Input requirements count 
    RxPipelineRequiresCluster *inputRequirements;     // Input requirements array 

    void *	superBlock;     // Internally used block of memory 
    DWORD	superBlockSize;	// Internally used block of memory 

    DWORD	entryPoint;		// The index of the node which is the entry point of this pipeline 
    DWORD	pluginId;		// If required, the Id of the plugin owning this pipeline, or 0 
    DWORD	pluginData;		// Rights callback extra data 
};

extern void * _rwRenderPipelineOpen (void * object, int offset, int size);	// >> 807C40 (1)
extern void * _rwRenderPipelineClose (void * object, int offset, int size);	// >> 807C60 (1)
extern RxPipeline * RxPipelineExecute(RxPipeline  * pipeline, void * data, bool heapReset); // >> 805710 (7)
extern RxPipeline * RxPipelineCreate (); // >> 8057B0 (11)
extern void RxPipelineDestroy (RxPipeline * pipe); // 805820 (22)
// ############################################################################
//	Atomics
#pragma pack(push, 1)
struct RwObject {
	BYTE	type;
	BYTE	subType;
	BYTE	flags;              
	BYTE	privateFlags;       
    void   *parent;                                   
};

struct RwSphere {
    D3DVECTOR	center;   /**< Sphere center */
    float		radius;  /**< Sphere radius */
};

struct RwObjectHasFrame;
struct RwResEntry;
struct RpGeometry;
struct RpClump;
struct RpAtomic;
struct RpMaterial;
struct RwTexCoords;
struct RpMeshHeader;

#define rwMAXTEXTURECOORDS 8

typedef RwObjectHasFrame * (*RwObjectHasFrameSyncFunction)(RwObjectHasFrame *object);
typedef RpAtomic   *(*RpAtomicCallBackRender) (RpAtomic * atomic);

struct RwObjectHasFrame	{
    RwObject                     object;
    RwLLLink                     lFrame;
    RwObjectHasFrameSyncFunction sync;
};

struct RpInterpolator {
	DWORD	flags; 
	WORD	startMorphTarget; 
	WORD	endMorphTarget; 
	float	time; 
	float	recipTime; 
	float	position; 
};

struct RpMorphTarget {
    RpGeometry *	parentGeom; 
    RwSphere		boundingSphere;
	D3DVECTOR *		verts;
	D3DVECTOR *		normals;
};

struct RwSurfaceProperties {
	float	ambient;	// ambient reflection coefficient 
    float	specular;	// specular reflection coefficient 
    float	diffuse;	// reflection coefficient 
};

struct RpMaterial {
    RwTexture *	texture;
    DWORD		color;		// TODO: RGBA
    RxPipeline  *pipeline; 
    RwSurfaceProperties surfaceProps; /**< surfaceProps */
    short		refCount;          /* C.f. rwsdk/world/bageomet.h:RpGeometry */
	short		pad;
};

struct RpMaterialList {
    RpMaterial **	materials;
    int				numMaterials;
    int				space;
};

struct RpTriangle {
    WORD	vertIndex[3]; 
    WORD	matIndex;   
};

struct RpGeometry {
    RwObject            object;     /* Generic type */
    DWORD				flags;      /* Geometry flags */
    WORD				lockedSinceLastInst; /* What has been locked since we last instanced - for re-instancing */
    short				refCount;   /* Reference count (for keeping track of atomics referencing geometry) */
    int					numTriangles; /* Quantity of various things (polys, verts and morph targets) */
    int					numVertices;
    int					numMorphTargets;
    int					numTexCoordSets;
    RpMaterialList      matList;
    RpTriangle  *		triangles;  /* The triangles */
    DWORD *				preLitLum;	// TODO: RGBA *
    RwTexCoords *		texCoords[rwMAXTEXTURECOORDS]; /* Texture coordinates */
    RpMeshHeader       *mesh;   /* The mesh - groups polys of the same material */
    RwResEntry         *repEntry;       /* Information for an instance */
    RpMorphTarget      *morphTarget;    /* The Morph Target */
};


struct RpAtomic	{
    RwObjectHasFrame    object;
    RwResEntry         *repEntry;	// Information for an instance
    RpGeometry         *geometry;	// Triangles making the object
    RwSphere            boundingSphere;		// Interpolated bounding sphere (in object space and world space)
    RwSphere            worldBoundingSphere;
    RpClump            *clump;		// Connections to other atomics
    RwLLLink            inClumpLink;
    RpAtomicCallBackRender renderCallBack;	// callbacks
    RpInterpolator      interpolator;		// Interpolation animation pointer
    WORD				renderFrame;		// Counter for checks of "render has occurred already"
    WORD				pad;
	RwLLLink			llWorldSectorsInAtomic;	// Connections to sectors
    RxPipeline         *pipeline;	// The Atomic object pipeline for this Atomic
};

struct RpClump {
    RwObject            object;
	RwLLLink			atomicList;
    RwLLLink			lightList;
    RwLLLink			cameraList;
    RwLLLink            inWorldLink;
    ///RpClumpCallBack     callback;
	void *				callback;
};

struct RwMatrix {
	D3DVECTOR	right;
	DWORD		flags;
	D3DVECTOR	top;
	DWORD		_pad1;
	D3DVECTOR	at;
	DWORD		_pad2;
	D3DVECTOR	pos;
	DWORD		_pad3;
};

struct RtQuat {
	D3DVECTOR	imag;
	float		real;
};

struct RwFrame {
    RwObject    object;
    RwLLLink    inDirtyListLink;
    RwMatrix    modelling;
    RwMatrix    ltm;
	RwLLLink	objectList; // List of objects connected to a frame 
    
	RwFrame *	child;
    RwFrame *	next;
    RwFrame *	root;   // Root of the tree 
};

struct RpHAnimNodeInfo;
struct RtAnimInterpolator;
struct RtAnimInterpolatorInfo;

struct RtAnimAnimation {
    RtAnimInterpolatorInfo *	interpInfo;
    int		numFrames;            
    int		flags;
    float	duration;
    void *	pFrames;
    void *	customData;
};

struct RpHAnimHierarchy	{
	int						flags;
    int						numNodes;      
    RwMatrix *				pMatrixArray;			// Pointer to node matrices
    void *					pMatrixArrayUnaligned;	// Pointer to memory used for node matrices from which the aligned pMatrixArray is allocated 
    RpHAnimNodeInfo *		pNodeInfo;		// Array of node information (push/pop flags etc) 
    RwFrame *				parentFrame;    // Pointer to the Root RwFrame of the hierarchy this RpHAnimHierarchy represents 
    RpHAnimHierarchy *		parentHierarchy;                      
    int						rootParentOffset;   
    RtAnimInterpolator *	currentAnim;    
};

struct RwMatrixWeights {
    float	w0;		// The first matrix weight.  
    float	w1;		// The second matrix weight. 
    float	w2;		// The third matrix weight.  
    float	w3;		// The fourth matrix weight. 
};

#pragma pack(pop)
// ############################################################################


// # rpanisot
// # baclump
// # bageomet
// # bamateri
// # bamatlist
// # wrldpipe
// # baworld
// # baworobj
// # balight
// # d3d9vertexdeclaration
// # d3dlights
// # d3dpipe
// # nodeD3D9AtomicAllInOne
// # d3dusage
// # bamesh
// # bameshop
// # bapipew
// # nodeD3D9WorldSectorAllInOne
// # d3d9vertexshader
// # basector
// # babinwor
// # native
// # rphanim
// # stdkey
// # rpskin
// # skind3d9
// # skind3dplain
// # bsplit
// # skind3d9pipesshared
// # rpuvanim
// # ???
// # rtanim
// # rtbmp
// # rtdict
// # rtquat
// # bastream
// # babinary
// # bavector
// # bacamera
// # baim3d
// # baframe
// # bamatrix
// # badevice
// # batextur
// # d3d9vertexbuffer
// # d3d9device
// # baraster
// # d3d2drend
// # d3drendst
// # d3dconvrt
// # baimage
// # baimras
// # babintex
// # batypehf
// # p2core
// # p2define
// # babinfrm
// # bapipe
// # baresour
// # batkreg
// # baerr
// # batkbin
// # babincam
// # babbox
// ???????????
// # baresamp