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

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


BEGIN_MESSAGE_MAP(MeshPickWin, RMWin)
	//{{AFX_MSG_MAP(MeshPickWin)
	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_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

char meshname[]="D:\\mssdk\\samples\\Multimedia\\D3DRM\\media\\sphere4.x";

DragData MeshPickWin::drag;

MeshPickWin::MeshPickWin()
{
	meshbuilder=0;
}

BOOL MeshPickWin::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(5) );
//    meshbuilder->SetQuality( D3DRMRENDER_FLAT );

    //------ NINE MESHES ÄÅÂßÒÜ ÑÅÒÎÊ----------
    for (int x=0;x<3;x++)
    {
        for (int y=0;y<3;y++)
        {
            LPDIRECT3DRMMESH mesh;
            meshbuilder->CreateMesh( &mesh );
            mesh->SetGroupColorRGB( 0,
				D3DVALUE(x==0?1:(y==0?1:0)),
				D3DVALUE(x==1?1:(y==1?1:0)),
				D3DVALUE(x==2?1:(y==2?1:0)) );
            mesh->SetGroupColorRGB( 1,
				D3DVALUE(x==0?1:(y==0?1:0)),
				D3DVALUE(x==1?1:(y==1?1:0)),
				D3DVALUE(x==2?1:(y==2?1:0)) );

            LPDIRECT3DRMFRAME meshframe;
            d3drm->CreateFrame( scene, &meshframe );
            meshframe->AddVisual( mesh );
            int xoffset=(rand()%3)-1;
            int yoffset=(rand()%3)-1;
            meshframe->SetPosition( scene,
                    D3DVALUE((x-1)*10),//+xoffset),
                    D3DVALUE((y-1)*10),//+yoffset),
                    D3DVALUE(0) );
            meshframe->SetRotation( scene,
                    D3DVALUE(0), D3DVALUE(1), D3DVALUE(0),
                    D3DVALUE(.1) );

            meshframe->Release();
            meshframe=0;
            mesh->Release();
            mesh=0;
        }
    }


    //------- CALLBACK ÊÎÑÂÅÍÍÛÉ ÂÛÇÎÂ--------
    scene->AddMoveCallback( UpdateDrag, NULL );

	// ---------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(1), D3DVALUE(-1), D3DVALUE(1),
			D3DVALUE(1), 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 MeshPickWin::OnRenderWireframe() 
{
	if (meshbuilder)
		meshbuilder->SetQuality( D3DRMRENDER_WIREFRAME );
}

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

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

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

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

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

void MeshPickWin::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
    if (PickMesh( point ))
    {
        ShowCursor( FALSE );
        SetCapture();
    }
    RMWin::OnLButtonDown( nFlags, point );
}

void MeshPickWin::OnLButtonUp(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
    if (drag.frame)
    {
        drag.frame=0;
        ShowCursor( TRUE );
        ReleaseCapture();
    }
    RMWin::OnLButtonUp( nFlags, point );
}


BOOL MeshPickWin::PickMesh( const CPoint& point )
{
    HRESULT r;
    LPDIRECT3DRMPICKEDARRAY pickarray;

    viewport->Pick( point.x, point.y, &pickarray );

    BOOL ret=FALSE;
    DWORD numpicks=pickarray->GetSize();
    if (numpicks>0)
    {
        LPDIRECT3DRMVISUAL visual;
        LPDIRECT3DRMFRAMEARRAY framearray;
        D3DRMPICKDESC pickdesc;

        r=pickarray->GetPick( 0, &visual, &framearray, &pickdesc );
        if (r==D3DRM_OK)
        {
            framearray->GetElement( framearray->GetSize()-1,
                    &drag.frame );
            D3DVECTOR pos;
            drag.frame->GetPosition( 0, &pos );
            drag.origx=pos.x;
            drag.origy=pos.y;
            drag.mousedown.x=point.x;
            drag.mousedown.y=point.y;
            visual->Release();
            framearray->Release();
            ret=TRUE;
        }
    }
    pickarray->Release();
    return ret;
}

void MeshPickWin::UpdateDrag(LPDIRECT3DRMFRAME frame, void*, D3DVALUE)
{
    if (drag.frame)
    {
        int x=GetMouseX();
        int y=GetMouseY();
        D3DVALUE newx=
                -D3DVALUE(drag.mousedown.x-x)*D3DVALUE(.07)+drag.origx;
        D3DVALUE newy=
                D3DVALUE(drag.mousedown.y-y)*D3DVALUE(.07)+drag.origy;
        drag.frame->SetPosition( 0, newx, newy, D3DVALUE(0) );
    }
}
