#define STRICT

// Includes standard Windows
#include <windows.h>
#include <windowsx.h>
#include <time.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <stdio.h>

// Includes D3D
#define  D3D_OVERLOADS
#include <ddraw.h>
#include <d3d.h>
#include <d3dx.h>

// Includes utilitaires D3D
#include "d3dmath.h"
#include "d3dutil.h"
#include "D3DEnum.h"

// Ids Resources
//#include "resource.h"

// Constantes
#include "const.h"

// Types
#include "types.h"

// Variables globales projet
#include "vars.h"

// Prototypes fonctions autres modules
#include "proto.h"

// Macros
#include "macros.h"

// Variables locales au module

//***************************** R E G L A G E S  P A R A M E T R E S  D 3 D ****
void vSetD3DState(void)
{
#ifndef NO3D
	// Régler le z-buffering.
    lpd3dDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, dZBuf);

	lpd3dDevice->SetRenderState(D3DRENDERSTATE_FILLMODE, dFillMode);

	lpd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, bAlpha);
	lpd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCCOLOR); 
	lpd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_SRCCOLOR);

	// Définir les 3 matrices du pipeline D3D
	lpd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matWorld );
    lpd3dDevice->SetTransform( D3DTRANSFORMSTATE_PROJECTION, &matProj );
    lpd3dDevice->SetTransform( D3DTRANSFORMSTATE_VIEW, &matView );

	lpd3dDevice->SetRenderState(D3DRENDERSTATE_CULLMODE , dCull);

    lpd3dDevice->SetRenderState( D3DRENDERSTATE_AMBIENT, cAmbient );
	lpd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, TRUE );
	lpd3dDevice->SetRenderState( D3DRENDERSTATE_SPECULARENABLE, bSpecular);
	lpd3dDevice->SetRenderState( D3DRENDERSTATE_ANTIALIAS, bAntialias ? D3DANTIALIAS_SORTINDEPENDENT : D3DANTIALIAS_NONE);
#endif
}

HRESULT hrInitWorld( LPDIRECT3DDEVICE7 pd3dDevice )
{
	D3DMATRIX mIdentity;

	D3DUtil_SetIdentityMatrix(mIdentity);
	
	// World matrix
	matWorld = mIdentity;

	// View matrix (position et orientation de la caméra)
	D3DUtil_SetViewMatrix(matView,
						  Observer,	// From
                          Target,	// To
						  D3DVECTOR(0.f, 0.f, 0.f));

	// Projection matrix
	matProj = mIdentity;
	matProj._m._11 =  2.0f;
	matProj._m._22 =  2.0f;
	matProj._m._34 =  1.0f;
	matProj._m._43 = -1.0f;
	matProj._m._44 =  0.0f;

	// Mettre à jour les variables d'état du pipe D3D
	vSetD3DState();
	return S_OK;
}

HRESULT hrRender( LPDIRECT3DDEVICE7 pd3dDevice )
{
#ifndef NO3D
    // Clear the viewport to back color
	// Clear the z-buffer (if present) as well with far clipping plane : z > 10
    pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|(dZBuf == D3DZB_TRUE ? D3DCLEAR_ZBUFFER : 0),
		               cBack, 10.0f, 0L );

    // Begin scene
    if( FAILED( pd3dDevice->BeginScene() ) )
		return E_FAIL;
	
	for (register int iTriangle = 0 ; iTriangle <= iTriaLastUsed ; iTriangle++)
	{
		if (Triangles[iTriangle].bEnabled == FALSE) continue;
		if (Triangles[iTriangle].bHidden == TRUE) continue;

	    pd3dDevice->SetMaterial(&(Materials[Triangles[iTriangle].iMtrl].mtrl));

		// Draw base objects triangles
		pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, D3DFVF_VERTEX,
			Triangles[iTriangle].pSommets, dCull == D3DCULL_NONE ? 3 : 6, NULL );
	}

	for (register int iObject = 0 ; iObject <= iObjtLastUsed ; iObject++)
	{
		if (Objects[iObject].bEnabled == FALSE) continue;
		if (Objects[iObject].bHidden == TRUE) continue;

	    pd3dDevice->SetMaterial( &Objects[iObject].mtrl );

		// Draw d3d simpleshape objects
		Objects[iObject].pShape -> Draw();
	}

    // End scene.
    pd3dDevice->EndScene();
#endif
    return S_OK;
}
