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

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


BEGIN_MESSAGE_MAP(MolWin, RMWin)
	//{{AFX_MSG_MAP(MolWin)
	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)
	ON_COMMAND(ID_CHILDREN_1, OnChildren1)
	ON_UPDATE_COMMAND_UI(ID_CHILDREN_1, OnUpdateChildren1)
	ON_COMMAND(ID_CHILDREN_2, OnChildren2)
	ON_UPDATE_COMMAND_UI(ID_CHILDREN_2, OnUpdateChildren2)
	ON_COMMAND(ID_CHILDREN_3, OnChildren3)
	ON_UPDATE_COMMAND_UI(ID_CHILDREN_3, OnUpdateChildren3)
	ON_COMMAND(ID_CHILDREN_4, OnChildren4)
	ON_UPDATE_COMMAND_UI(ID_CHILDREN_4, OnUpdateChildren4)
	ON_COMMAND(ID_DEPTH_1, OnDepth1)
	ON_UPDATE_COMMAND_UI(ID_DEPTH_1, OnUpdateDepth1)
	ON_COMMAND(ID_DEPTH_2, OnDepth2)
	ON_UPDATE_COMMAND_UI(ID_DEPTH_2, OnUpdateDepth2)
	ON_COMMAND(ID_DEPTH_3, OnDepth3)
	ON_UPDATE_COMMAND_UI(ID_DEPTH_3, OnUpdateDepth3)
	ON_COMMAND(ID_DEPTH_4, OnDepth4)
	ON_UPDATE_COMMAND_UI(ID_DEPTH_4, OnUpdateDepth4)
	ON_COMMAND(ID_DEPTH_5, OnDepth5)
	ON_UPDATE_COMMAND_UI(ID_DEPTH_5, OnUpdateDepth5)
	ON_COMMAND(ID_DEPTH_6, OnDepth6)
	ON_UPDATE_COMMAND_UI(ID_DEPTH_6, OnUpdateDepth6)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

char meshname[]="D:\\mssdk\\samples\\Multimedia\\D3DRM\\media\\sphere3.x";
D3DCOLOR meshcolor[MAXDEPTH]={
	D3DRGB(0,0,128),D3DRGB(0,255,255),
	D3DRGB(128,128,0),D3DRGB(192,220,192),
	D3DRGB(164,160,164),D3DRGB(231,231,255),};

MolWin::MolWin()
{
	meshbuilder=0;
    curdepth=4;
    numchildren=2;

}

BOOL MolWin::CreateScene()
{
	HRESULT r;
	// ------- MESH --------
	d3drm->CreateMeshBuilder( &meshbuilder );
	r=meshbuilder->Load( meshname, NULL, D3DRMLOAD_FROMFILE, NULL, NULL );
	if (r!=D3DRM_OK)
	{
		CString msg;
		msg.Format( "Failed to load file '%s'\n", meshname );
		AfxMessageBox( msg );
		return FALSE;
	}
//	ScaleMesh( meshbuilder, D3DVALUE(25) );

    for (int i=0;i<MAXDEPTH;i++)
    {
        ScaleMesh( meshbuilder, D3DVALUE(MAXDEPTH-i) );
        D3DCOLOR clr=meshcolor[i];
        D3DVALUE r=D3DRMColorGetRed( clr );
        D3DVALUE g=D3DRMColorGetGreen( clr );
        D3DVALUE b=D3DRMColorGetBlue( clr );
        meshbuilder->SetColorRGB( r, g, b );
        LPDIRECT3DRMMESH m;
        meshbuilder->CreateMesh( &m );
        mesh[i]=m;
    }

    CreateHierarchy();

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

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

	//------ CAMERA-----------
	d3drm->CreateFrame( scene, &camera );
	camera->SetPosition( scene, D3DVALUE(0), D3DVALUE(0), D3DVALUE(-50));
	d3drm->CreateViewport( device, camera, 0, 0,	
			device->GetWidth(), device->GetHeight(), 
			&viewport);

	return TRUE;
}

void MolWin::OnRenderWireframe() 
{
	if (meshbuilder)
		meshbuilder->SetQuality( D3DRMRENDER_WIREFRAME );
}

void MolWin::OnRenderFlat() 
{
	if (meshbuilder)
		meshbuilder->SetQuality( D3DRMRENDER_FLAT );
}

void MolWin::OnRenderGouraud() 
{
	if (meshbuilder)
		meshbuilder->SetQuality( D3DRMRENDER_GOURAUD );
}

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

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

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

void MolWin::OnChildren1() 
{
	// TODO: Add your command handler code here
    numchildren=1;
    CreateHierarchy();
}

void MolWin::OnUpdateChildren1(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
    pCmdUI->SetCheck( numchildren==1 );	
}

void MolWin::OnChildren2() 
{
	// TODO: Add your command handler code here
    numchildren=2;
    CreateHierarchy();
}

void MolWin::OnUpdateChildren2(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
    pCmdUI->SetCheck( numchildren==2 );	
}

void MolWin::OnChildren3() 
{
	// TODO: Add your command handler code here
    numchildren=3;
    CreateHierarchy();
}

void MolWin::OnUpdateChildren3(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
    pCmdUI->SetCheck( numchildren==3 );	
}

void MolWin::OnChildren4() 
{
	// TODO: Add your command handler code here
    numchildren=4;
    CreateHierarchy();	
}

void MolWin::OnUpdateChildren4(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
    pCmdUI->SetCheck( numchildren==4 );	
}

void MolWin::OnDepth1() 
{
	// TODO: Add your command handler code here
    curdepth=1;
    CreateHierarchy();
	
}

void MolWin::OnUpdateDepth1(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
    pCmdUI->SetCheck( curdepth==2 );	
}

void MolWin::OnDepth2() 
{
	// TODO: Add your command handler code here
    curdepth=2;
    CreateHierarchy();
	
}

void MolWin::OnUpdateDepth2(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
    pCmdUI->SetCheck( curdepth==2 );	
}

void MolWin::OnDepth3() 
{
	// TODO: Add your command handler code here
    curdepth=3;
    CreateHierarchy();
	
}

void MolWin::OnUpdateDepth3(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
    pCmdUI->SetCheck( curdepth==3 );	
}

void MolWin::OnDepth4() 
{
	// TODO: Add your command handler code here
    curdepth=4;
    CreateHierarchy();
	
}

void MolWin::OnUpdateDepth4(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
    pCmdUI->SetCheck( curdepth==4 );	
}

void MolWin::OnDepth5() 
{
	// TODO: Add your command handler code here
    curdepth=5;
    CreateHierarchy();
	
}

void MolWin::OnUpdateDepth5(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->SetCheck( curdepth==5 );
}

void MolWin::OnDepth6() 
{
	// TODO: Add your command handler code here
    curdepth=6;
    CreateHierarchy();
	
}

void MolWin::OnUpdateDepth6(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
    pCmdUI->SetCheck( curdepth==6 );	
}

BOOL MolWin::CreateHierarchy()
{
    static LPDIRECT3DRMFRAME mainframe;
    if (mainframe)
    {
        scene->DeleteChild( mainframe );
        mainframe->Release();
    }
    d3drm->CreateFrame( scene, &mainframe );
    for (int i=0;i<numchildren;i++)
        CreateChildren( mainframe, curdepth );

    return TRUE;
}

BOOL MolWin::CreateChildren(LPDIRECT3DRMFRAME frame, int depth)
{
    LPDIRECT3DRMFRAME parent;
    frame->GetParent( &parent );

    D3DVECTOR vector;
    D3DRMVectorRandom( &vector );
    frame->SetRotation( parent,
            vector.x, vector.y, vector.z ,
            D3DVALUE(rand()%100)/D3DVALUE(1000)+D3DVALUE(.1) );
    frame->AddVisual( mesh[curdepth-depth] );
    if (depth>1)
    {
        LPDIRECT3DRMFRAME child;
        d3drm->CreateFrame( frame, &child );

        static int count;
        count++;
        D3DVALUE trans=5.0;//distance[curdepth-depth];
        D3DVALUE smalltrans=trans/D3DVALUE(2);
        D3DVALUE xtrans=(count%2) ? trans : -trans;
        D3DVALUE ytrans=(rand()%2) ? smalltrans : -smalltrans;
        D3DVALUE ztrans=(rand()%2) ? smalltrans : -smalltrans;
        child->SetPosition( frame, xtrans, ytrans, ztrans );

        for (int i=0;i<numchildren;i++)
            CreateChildren( child, depth-1 );
    }
    return TRUE;
}
