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

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


BEGIN_MESSAGE_MAP(AnimWin, RMWin)
	//{{AFX_MSG_MAP(AnimWin)
	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_ANIMATION_LINEAR, OnAnimationLinear)
	ON_UPDATE_COMMAND_UI(ID_ANIMATION_LINEAR, OnUpdateAnimationLinear)
	ON_COMMAND(ID_ANIMATION_SPLINE, OnAnimationSpline)
	ON_UPDATE_COMMAND_UI(ID_ANIMATION_SPLINE, OnUpdateAnimationSpline)
	ON_COMMAND(ID_SPEED_FAST, OnSpeedFast)
	ON_UPDATE_COMMAND_UI(ID_SPEED_FAST, OnUpdateSpeedFast)
	ON_COMMAND(ID_SPEED_MEDIUM, OnSpeedMedium)
	ON_UPDATE_COMMAND_UI(ID_SPEED_MEDIUM, OnUpdateSpeedMedium)
	ON_COMMAND(ID_SPEED_SLOW, OnSpeedSlow)
	ON_UPDATE_COMMAND_UI(ID_SPEED_SLOW, OnUpdateSpeedSlow)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

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

#define PI 3.14f

D3DVECTOR vect[]=   // rotation vector for each key frame
		    // вектор вращения для каждого ключевого фрейма
{
  { D3DVALUE(1), D3DVALUE(0), D3DVALUE(0) },
  { D3DVALUE(1), D3DVALUE(0), D3DVALUE(0) },
  { D3DVALUE(1), D3DVALUE(0), D3DVALUE(0) },
  { D3DVALUE(1), D3DVALUE(0), D3DVALUE(0) },
  { D3DVALUE(0), D3DVALUE(1), D3DVALUE(0) },
  { D3DVALUE(1), D3DVALUE(0), D3DVALUE(0) },
  { D3DVALUE(0), D3DVALUE(1), D3DVALUE(0) },
  { D3DVALUE(1), D3DVALUE(0), D3DVALUE(0) },
  { D3DVALUE(0), D3DVALUE(1), D3DVALUE(0) },
  { D3DVALUE(1), D3DVALUE(0), D3DVALUE(0) },
  { D3DVALUE(1), D3DVALUE(0), D3DVALUE(0) },
};

const D3DVALUE rot[]= // object rotation at each key frame
		      // объект вращения каждого ключевого фрейма
{
	PI/2,
    PI,
    -(PI/2),
    PI,
    PI/2,
    PI,
    -(PI/2),
    -PI,
    PI/2,
    PI,
    PI/2,
};

#define FARLIM D3DVALUE(45)
#define CLOSELIM D3DVALUE(10)

#define XOUTLIM D3DVALUE(20)
#define YOUTLIM D3DVALUE(20)

const D3DVECTOR trans[]=  // object location for each key frame
				// положение объекта для каждого ключевого фрейма
{
    { D3DVALUE(0), D3DVALUE(0), FARLIM },
    { XOUTLIM,     D3DVALUE(0), CLOSELIM },
    { D3DVALUE(0), D3DVALUE(0), FARLIM },
    { -XOUTLIM,    D3DVALUE(0), CLOSELIM },
    { D3DVALUE(0), D3DVALUE(0), FARLIM },
    { D3DVALUE(0), -YOUTLIM,    CLOSELIM },
    { D3DVALUE(0), D3DVALUE(0), FARLIM },
    { D3DVALUE(0), YOUTLIM,     CLOSELIM },
    { D3DVALUE(0), D3DVALUE(0), FARLIM },
    { D3DVALUE(0), D3DVALUE(0), CLOSELIM-3 },
    { D3DVALUE(0), D3DVALUE(0), FARLIM },
};



const D3DVALUE fastspeed=D3DVALUE(0.026);
const D3DVALUE mediumspeed=D3DVALUE(0.013);
const D3DVALUE slowspeed=D3DVALUE(0.007);

static D3DVALUE speed;

AnimWin::AnimWin()
{
	meshbuilder=0;
	speed=fastspeed;
}

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

    //-------- ANIMATION АНИМАЦИЯ --------
    d3drm->CreateAnimation( &animation );
    for (int i=0; i<11; i++)
    {
        D3DRMQUATERNION    quat;
        D3DRMQuaternionFromRotation( &quat, &vect[i], rot[i] );
        animation->AddRotateKey( D3DVALUE(i), &quat );
        animation->AddPositionKey( D3DVALUE(i),
                trans[i].x, trans[i].y, trans[i].z  );
    }
    OnAnimationLinear();

    //-------- MESH FRAME ФРЕЙМ СЕТКИ ------
    LPDIRECT3DRMFRAME meshframe;
    d3drm->CreateFrame( scene, &meshframe );
    meshframe->AddVisual( meshbuilder );
    meshframe->AddMoveCallback( UpdateScene, animation );
    animation->SetFrame( meshframe );
    meshframe->Release();
    meshframe=0;

	// ---------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_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 AnimWin::OnRenderWireframe() 
{
	if (meshbuilder)
		meshbuilder->SetQuality( D3DRMRENDER_WIREFRAME );
}

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

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

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

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

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

void AnimWin::OnAnimationLinear() 
{
	// TODO: Add your command handler code here
    animation->SetOptions( D3DRMANIMATION_LINEARPOSITION |
            D3DRMANIMATION_CLOSED |
            D3DRMANIMATION_POSITION
			| D3DRMANIMATION_SCALEANDROTATION
			);
}

void AnimWin::OnUpdateAnimationLinear(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
    D3DRMANIMATIONOPTIONS options;
    options = animation->GetOptions();
    pCmdUI->SetCheck( options & D3DRMANIMATION_LINEARPOSITION );
}

void AnimWin::OnAnimationSpline() 
{
	// TODO: Add your command handler code here
    animation->SetOptions( D3DRMANIMATION_SPLINEPOSITION |
            D3DRMANIMATION_CLOSED |
            D3DRMANIMATION_POSITION |
            D3DRMANIMATION_SCALEANDROTATION );
}

void AnimWin::OnUpdateAnimationSpline(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
    D3DRMANIMATIONOPTIONS options;
    options = animation->GetOptions();
    pCmdUI->SetCheck( options & D3DRMANIMATION_SPLINEPOSITION );
}

void AnimWin::OnSpeedFast() 
{
	// TODO: Add your command handler code here
    speed=fastspeed;	
}

void AnimWin::OnUpdateSpeedFast(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
    pCmdUI->SetCheck( speed==fastspeed);
}

void AnimWin::OnSpeedMedium() 
{
	// TODO: Add your command handler code here
    speed=mediumspeed;	
}

void AnimWin::OnUpdateSpeedMedium(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
    pCmdUI->SetCheck( speed==mediumspeed);	
}

void AnimWin::OnSpeedSlow() 
{
	// TODO: Add your command handler code here
    speed=slowspeed;	
}

void AnimWin::OnUpdateSpeedSlow(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
    pCmdUI->SetCheck( speed==slowspeed);	
}

HRESULT AnimWin::LoadTexture(char*, void*,
                               LPDIRECT3DRMTEXTURE* texture)
{
    HRSRC id = FindResource( NULL, MAKEINTRESOURCE(IDR_TEXTURE1),
            "TEXTURE" );
      RMWin::d3drm->LoadTextureFromResource( id, texture );
    return D3DRM_OK;
}

void AnimWin::UpdateScene(LPDIRECT3DRMFRAME, void* p, D3DVALUE)
{
    LPDIRECT3DRMANIMATION animation=(LPDIRECT3DRMANIMATION)p;
    static D3DVALUE time;
    time+=speed;
    animation->SetTime( time );
}
