#include <AfxWin.h>
#include <AfxExt.h>
#define INITGUID
#include <ddraw.h>
#include <d3d.h>
#include <d3drm.h>
#include <d3drmwin.h>
#include "ShadowWin.h"
#include "resource.h"

#pragma comment (lib,"ddraw.lib")
#pragma comment (lib,"d3drm.lib")


BEGIN_MESSAGE_MAP(ShadowWin, RMWin)
	//{{AFX_MSG_MAP(ShadowWin)
	ON_COMMAND(ID_RENDER_WIREFRAME, OnRenderWireframe)
	ON_COMMAND(ID_RENDER_FLAT, OnRenderFlat)
	ON_COMMAND(ID_RENDER_GOURAUD, OnRenderGouraud)
	ON_UPDATE_COMMAND_UI(ID_RENDER_FLAT, OnUpdateRenderFlat)
	ON_UPDATE_COMMAND_UI(ID_RENDER_GOURAUD, OnUpdateRenderGouraud)
	ON_UPDATE_COMMAND_UI(ID_RENDER_WIREFRAME, OnUpdateRenderWireframe)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

char meshname_cube[]="D:\\mssdk\\samples\\Multimedia\\D3DRM\\media\\ncube.x";
char meshname_sphere[]="D:\\mssdk\\samples\\Multimedia\\D3DRM\\media\\tiger.x";

ShadowWin::ShadowWin()
{
	floorbuilder=0;
}

BOOL ShadowWin::CreateScene()
{
	HRESULT r;

	// ------- MESH --------
	d3drm->CreateMeshBuilder( &floorbuilder );
	r=floorbuilder->Load( meshname_cube, NULL, D3DRMLOAD_FROMFILE, NULL, NULL );
	if (r!=D3DRM_OK)
	{
		CString msg;
		msg.Format( "Failed to load file '%s'\n", meshname_cube );
		AfxMessageBox( msg );
		return FALSE;
	}
	floorbuilder->Scale( D3DVALUE(10), D3DVALUE(.05), D3DVALUE(10) );
	floorbuilder->SetPerspective( TRUE );
	floorbuilder->SetQuality( D3DRMRENDER_FLAT );

	//ScaleMesh( meshbuilder, D3DVALUE(25) );

	//------------ FLOOR TEXTURE ÒÅÊÑÒÓÐÀ ÏÎËÀ --------------
	LPDIRECT3DRMTEXTURE texture;
	HRSRC texture_id = FindResource( NULL,
        MAKEINTRESOURCE(IDR_FLOORTEXTURE), "TEXTURE" );
	d3drm->LoadTextureFromResource( texture_id, &texture );
	floorbuilder->SetTexture( texture );
	texture->Release();
	texture=0;

	//------------ FLOOR WRAP ÏÎÊÐÛÒÈÅ ÏÎËÀ ------------
	D3DRMBOX box;
	floorbuilder->GetBox( &box );
	D3DVALUE w=box.max.x-box.min.x;
	D3DVALUE h=box.max.z-box.min.z;

	LPDIRECT3DRMWRAP wrap;
	d3drm->CreateWrap( D3DRMWRAP_FLAT, NULL,
        D3DVALUE(0.0), D3DVALUE(0.0), D3DVALUE(0.0), // wrap origin
        D3DVALUE(0.0), D3DVALUE(1.0), D3DVALUE(0.0), // wrap z axis
        D3DVALUE(0.0), D3DVALUE(0.0), D3DVALUE(1.0), // wrap y axis
        D3DVALUE(.5) ,D3DVALUE(0.5),                 // texture origin
        D3DDivide(1,w), D3DDivide(1,h),              // texture scale
        &wrap );
	wrap->Apply( floorbuilder );
	wrap->Release();
	wrap=0;

	//------------- FLOOR FRAME ÔÐÅÉÌ ÏÎËÀ ----------
	LPDIRECT3DRMFRAME floorframe;
	d3drm->CreateFrame( scene, &floorframe );
	floorframe->AddVisual( floorbuilder );
	floorframe->Release();
	floorframe=0;


	// ------- MESH --------
	d3drm->CreateMeshBuilder( &forkbuilder );
	r=forkbuilder->Load( meshname_sphere, NULL, D3DRMLOAD_FROMFILE, NULL, NULL );
	if (r!=D3DRM_OK)
	{
		CString msg;
		msg.Format( "Failed to load file '%s'\n", meshname_sphere );
		AfxMessageBox( msg );
		return FALSE;
	}
	forkbuilder->SetQuality( D3DRMRENDER_FLAT );
	//forkbuilder->SetColorRGB(D3DVALUE(0.0), D3DVALUE(1.0), D3DVALUE(0.0) );
	ScaleMesh( forkbuilder, D3DVALUE(10) );

	//--------------- FORK FRAME ÔÐÅÉÌ ÂÈËÊÈ ----------
	LPDIRECT3DRMFRAME forkframe;
	d3drm->CreateFrame( scene, &forkframe );
	forkframe->SetRotation( scene,
        D3DVALUE(1), D3DVALUE(1), D3DVALUE(1),
        D3DVALUE(0.4) );
	forkframe->SetPosition( scene,
        D3DVALUE(0), D3DVALUE(6), D3DVALUE(0) );
	forkframe->AddVisual( forkbuilder );
	forkframe->AddMoveCallback( AdjustSpin, NULL );

	// ---------AMBIENT LIGHT--------
	LPDIRECT3DRMLIGHT alight;
	d3drm->CreateLightRGB( D3DRMLIGHT_AMBIENT,
			D3DVALUE(1.00), D3DVALUE(1.00), D3DVALUE(1.00), 
			&alight);

	scene->AddLight( alight );
	alight->Release();
	alight=0;

	// ---------DIRECTIONAL LIGHT--------
	LPDIRECT3DRMLIGHT dlight;
	d3drm->CreateLightRGB( D3DRMLIGHT_POINT,
			D3DVALUE(1.00), D3DVALUE(1.00), D3DVALUE(1.00), 
			&dlight);

	LPDIRECT3DRMFRAME dlightframe;
	d3drm->CreateFrame( scene, &dlightframe );
	dlightframe->AddLight( dlight );
	dlightframe->SetPosition( scene,
        D3DVALUE(0), D3DVALUE(30), D3DVALUE(0) );
	dlightframe->Release();
	dlightframe=0;

//-------------- SHADOW ÒÅÍÜ ----------
	LPDIRECT3DRMVISUAL shadow;
	d3drm->CreateShadow( forkbuilder, dlight,
        D3DVALUE(0), box.max.y+D3DVALUE(0.1), D3DVALUE(0),
        D3DVALUE(0), box.max.y+D3DVALUE(1.0), D3DVALUE(0),
        (LPDIRECT3DRMVISUAL*)&shadow );
	forkframe->AddVisual( shadow );

	shadow->Release();
	shadow=0;
	forkframe->Release();
	forkframe=0;
	dlight->Release();
	dlight=0;

	//------ CAMERA-----------
	d3drm->CreateFrame( scene, &camera );
	camera->SetPosition( scene,
        D3DVALUE(0.0), D3DVALUE(25.0), D3DVALUE(-20.0) );
	camera->SetOrientation( scene,
        D3DVALUE(0), D3DVALUE(-25), D3DVALUE(20),
        D3DVALUE(.1), D3DVALUE(1), D3DVALUE(0) );
	d3drm->CreateViewport( device, camera,
        0, 0,
        device->GetWidth(), device->GetHeight(),
        &viewport );
	return TRUE;
}

void ShadowWin::OnRenderWireframe() 
{
	if (floorbuilder)
		floorbuilder->SetQuality( D3DRMRENDER_WIREFRAME );
	if (forkbuilder)
		forkbuilder->SetQuality( D3DRMRENDER_WIREFRAME );
}

void ShadowWin::OnRenderFlat() 
{
	if (floorbuilder)
		floorbuilder->SetQuality( D3DRMRENDER_FLAT );
	if (forkbuilder)
		forkbuilder->SetQuality( D3DRMRENDER_FLAT );
}

void ShadowWin::OnRenderGouraud() 
{
	if (floorbuilder)
		floorbuilder->SetQuality( D3DRMRENDER_GOURAUD );
	if (forkbuilder)
		forkbuilder->SetQuality( D3DRMRENDER_GOURAUD );
}

void ShadowWin::OnUpdateRenderWireframe(CCmdUI* pCmdUI) 
{
	if (floorbuilder)
	{
		D3DRMRENDERQUALITY meshquality = floorbuilder->GetQuality();
		pCmdUI->SetCheck( meshquality==D3DRMRENDER_WIREFRAME );
	}
}

void ShadowWin::OnUpdateRenderFlat(CCmdUI* pCmdUI) 
{
	if (floorbuilder)
	{
		D3DRMRENDERQUALITY meshquality = floorbuilder->GetQuality();
		pCmdUI->SetCheck( meshquality==D3DRMRENDER_FLAT );
	}
}

void ShadowWin::OnUpdateRenderGouraud(CCmdUI* pCmdUI) 
{
	if (floorbuilder)
	{
		D3DRMRENDERQUALITY meshquality = floorbuilder->GetQuality();
		pCmdUI->SetCheck( meshquality==D3DRMRENDER_GOURAUD );
	}
}


void ShadowWin::AdjustSpin(LPDIRECT3DRMFRAME frame, void*, D3DVALUE)
{
static UINT delay;
    if (++delay<11)
        return;
    delay=0;

    LPDIRECT3DRMFRAME scene;
    frame->GetScene( &scene );

    D3DVECTOR spinvect;
    D3DRMVectorRandom( &spinvect );
    D3DVALUE spin=D3DDivide( rand()%100+1, 200 );
    frame->SetRotation( scene,
            spinvect.x, spinvect.y, spinvect.z,
            spin );
}
