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

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


BEGIN_MESSAGE_MAP(WrapsWin, RMWin)
	//{{AFX_MSG_MAP(WrapsWin)
	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[]="swirl.x";

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

BOOL WrapsWin::CreateScene()
{
    //-------- ÑÅÒÊÈ È ÒÅÊÑÒÓÐÛ --------
    if (LoadMeshes()==FALSE)
        return FALSE;
    if (LoadWrapsTexture()==FALSE)
        return FALSE;

    OnWrapsReset();

    //--------- ÑÂÅÒ ----------
    LPDIRECT3DRMFRAME lightframe;
    LPDIRECT3DRMLIGHT light;
    d3drm->CreateLightRGB(D3DRMLIGHT_AMBIENT,
            D3DVALUE(1),D3DVALUE(1), D3DVALUE(1),
            &light);
    d3drm->CreateFrame( scene, &lightframe );
    lightframe->AddLight( light );
    lightframe->Release();
    lightframe=0;
    light->Release();
    light=0;

    //---------- ÊÀÌÅÐÀ ------------
    d3drm->CreateFrame( scene, &camera );
    camera->SetPosition(scene,
            D3DVALUE(0.0), D3DVALUE(0.0), D3DVALUE(-50));
    d3drm->CreateViewport( device, camera, 0, 0,
            device->GetWidth(), device->GetHeight(),
            &viewport );

    return TRUE;
}

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

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

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

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

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

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

BOOL WrapsWin::LoadMeshes()
{
    HRESULT r;

    const D3DVALUE meshscale=D3DVALUE(13);
    const D3DVALUE meshspacing=D3DVALUE(15);

    D3DRMLOADRESOURCE resinfo;
    resinfo.hModule=NULL;
    resinfo.lpName=MAKEINTRESOURCE( IDR_BOXMESH );
    resinfo.lpType="MESH";
    d3drm->CreateMeshBuilder( &box );
    r=box->Load( &resinfo, NULL, D3DRMLOAD_FROMRESOURCE, NULL, NULL);
    if (r!=D3DRM_OK)
    {
        TRACE("failed to load internal box mesh\n");
        return FALSE;
    }
    box->SetPerspective(TRUE);
    ScaleMesh( box, meshscale-D3DVALUE(2) );

    LPDIRECT3DRMFRAME boxframe;
    d3drm->CreateFrame( scene, &boxframe );
    boxframe->SetPosition(scene,
            -meshspacing, D3DVALUE(0), D3DVALUE(0) );
    boxframe->SetRotation( scene,
            D3DVALUE(0), D3DVALUE(1), D3DVALUE(1),
            D3DVALUE(.1) );
    boxframe->AddVisual( box );

    resinfo.hModule=NULL;
    resinfo.lpName=MAKEINTRESOURCE( IDR_CYLMESH );
    resinfo.lpType="MESH";

    d3drm->CreateMeshBuilder( &cyl );
    cyl->Load( &resinfo, NULL, D3DRMLOAD_FROMRESOURCE, NULL, NULL );
    if (r!=D3DRM_OK)
    {
        TRACE("failed to load internal cylinder mesh\n");
        return FALSE;
    }
    cyl->SetPerspective( TRUE );
    ScaleMesh( cyl, meshscale );

    LPDIRECT3DRMFRAME cylframe;
    d3drm->CreateFrame( scene, &cylframe );
    cylframe->SetRotation( scene,
            D3DVALUE(0), D3DVALUE(1), D3DVALUE(1),
            D3DVALUE(.1) );
    cylframe->AddVisual( cyl );

    resinfo.hModule=NULL;
    resinfo.lpName=MAKEINTRESOURCE( IDR_SPHEREMESH );
    resinfo.lpType="MESH";

    d3drm->CreateMeshBuilder( &sphere );
    sphere->Load( &resinfo, NULL, D3DRMLOAD_FROMRESOURCE, NULL, NULL);
    if (r!=D3DRM_OK)
    {
        TRACE("failed to load internal sphere mesh\n");
        return FALSE;
    }
    sphere->SetPerspective( TRUE );
    ScaleMesh( sphere, meshscale );

    LPDIRECT3DRMFRAME sphereframe;
    d3drm->CreateFrame( scene, &sphereframe );
    sphereframe->SetPosition( scene,
            D3DVALUE(meshspacing), D3DVALUE(0), D3DVALUE(0) );
    sphereframe->SetRotation( scene,
            D3DVALUE(0), D3DVALUE(1), D3DVALUE(1),
            D3DVALUE(.1) );
    sphereframe->AddVisual( sphere );

    return TRUE;
}


BOOL WrapsWin::LoadWrapsTexture()
{
    HRSRC texture_id = FindResource( NULL, MAKEINTRESOURCE(
        IDR_JADETEXTURE), "TEXTURE" );
    LPDIRECT3DRMTEXTURE texture;
    d3drm->LoadTextureFromResource( texture_id, &texture );
    box->SetTexture( texture );
    cyl->SetTexture( texture );
    sphere->SetTexture( texture );
    texture->Release();
    texture=0;
    return TRUE;
}

void WrapsWin::OnWrapsReset()
{
    boxwraptype=D3DRMWRAP_FLAT;
    cylwraptype=D3DRMWRAP_CYLINDER;
    spherewraptype=D3DRMWRAP_SPHERE;

    ApplyWraps();
}

void WrapsWin::ApplyWraps()
{
    if ( boxwraptype==D3DRMWRAP_FLAT )
        ApplyFlat( box );
    else if ( boxwraptype==D3DRMWRAP_CYLINDER )
        ApplyCylinder( box );
    else
        ApplySphere( box );

    if ( cylwraptype==D3DRMWRAP_FLAT )
        ApplyFlat( cyl );
    else if ( cylwraptype==D3DRMWRAP_CYLINDER )
        ApplyCylinder( cyl );
    else
        ApplySphere( cyl );

    if ( spherewraptype==D3DRMWRAP_FLAT )
        ApplyFlat( sphere );
    else if ( spherewraptype==D3DRMWRAP_CYLINDER )
        ApplyCylinder( sphere );
    else
        ApplySphere( sphere );
}

void WrapsWin::ApplyFlat( LPDIRECT3DRMMESHBUILDER meshbuilder )
{
    D3DRMBOX box;
    meshbuilder->GetBox( &box );
    D3DVALUE width=box.max.x-box.min.x;
    D3DVALUE height=box.max.y-box.min.y;

    LPDIRECT3DRMWRAP wrap;
    d3drm->CreateWrap( D3DRMWRAP_FLAT, NULL,
            D3DVALUE(0.0), D3DVALUE(0.0), D3DVALUE(0.0), // wrap origin
            D3DVALUE(0.0), D3DVALUE(0.0), D3DVALUE(1.0), // z axis
            D3DVALUE(0.0), D3DVALUE(1.0), D3DVALUE(0.0), // y axis
            D3DVALUE(0.5), D3DVALUE(0.5),               // texture origin
            D3DDivide(1,width), D3DDivide(1,height),    // texture scale
            &wrap );
    wrap->Apply( meshbuilder );
    wrap->Release();
    wrap=0;
}

void WrapsWin::ApplyCylinder( LPDIRECT3DRMMESHBUILDER meshbuilder )
{
    D3DRMBOX box;
    meshbuilder->GetBox( &box );
    D3DVALUE width=box.max.x-box.min.x;
    D3DVALUE height=box.max.y-box.min.y;

    LPDIRECT3DRMWRAP wrap;
    d3drm->CreateWrap( D3DRMWRAP_CYLINDER, NULL,
            D3DVALUE(0.0), D3DVALUE(0.0), D3DVALUE(0.0), // wrap origin
            D3DVALUE(0.0), D3DVALUE(0.0), D3DVALUE(1.0), // z axis
            D3DVALUE(0.0), D3DVALUE(1.0), D3DVALUE(0.0), // y axis
            D3DVALUE(0.5), D3DVALUE(0.5),               // texture origin
            D3DDivide(1,width), D3DDivide(1,height),    // texture scale
            &wrap );
    wrap->Apply( meshbuilder );
    wrap->Release();
    wrap=0;
}

void WrapsWin::ApplySphere( LPDIRECT3DRMMESHBUILDER meshbuilder )
{
    D3DRMBOX box;
    meshbuilder->GetBox( &box );
    D3DVALUE width=box.max.x-box.min.x;
    D3DVALUE height=box.max.y-box.min.y;

    LPDIRECT3DRMWRAP wrap;
    d3drm->CreateWrap( D3DRMWRAP_SPHERE, NULL,
            D3DVALUE(0.0), D3DVALUE(0.0), D3DVALUE(0.0), // wrap origin
            D3DVALUE(0.0), D3DVALUE(0.0), D3DVALUE(1.0), // z axis
            D3DVALUE(0.0), D3DVALUE(1.0), D3DVALUE(0.0), // y axis
            D3DVALUE(0.5), D3DVALUE(0.5),               // texture origin
            D3DDivide(1,width), D3DDivide(1,height),    // texture scale
            &wrap );
    wrap->Apply( meshbuilder );
    wrap->Release();
    wrap=0;
}

void WrapsWin::OnWrapsFlat()
{
    boxwraptype=D3DRMWRAP_FLAT;
    cylwraptype=D3DRMWRAP_FLAT;
    spherewraptype=D3DRMWRAP_FLAT;

    ApplyWraps();
}


void WrapsWin::OnWrapsCylinder()
{
    boxwraptype=D3DRMWRAP_CYLINDER;
    cylwraptype=D3DRMWRAP_CYLINDER;
    spherewraptype=D3DRMWRAP_CYLINDER;

    ApplyWraps();
}


void WrapsWin::OnWrapsSphere()
{
    boxwraptype=D3DRMWRAP_SPHERE;
    cylwraptype=D3DRMWRAP_SPHERE;
    spherewraptype=D3DRMWRAP_SPHERE;

    ApplyWraps();
}
