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

BEGIN_MESSAGE_MAP(MorphWin, RMWin)
	//{{AFX_MSG_MAP(MorphPlayWin)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

char morphmeshname[7][3]={"a","b","c","d","e","f","g",};

BOOL MorphWin::LoadMorphSequence( const CString& filename )
{
    CString windowtext;
    GetWindowText( windowtext );

    CString txt="Loading: " + filename;
    SetWindowText( txt );

    BOOL ret=FALSE;
    if (LoadMeshes( filename ))
        if (CreateAnimations())
            ret=PrepareMorphVertices();

//    SetWindowText( windowtext );

    return ret;
}


BOOL MorphWin::LoadMeshes( const CString& filename )
{
    for (DWORD i=0;i<nummorphtargets;i++)
        delete [] morphmeshdata[i];
    nummorphtargets=0;

    if (morphmesh)
    {
        morphmesh->Release();
        morphmesh=0;
    }

    BOOL load_ok=TRUE;
    for (i=0;i<MAXMORPHTARGETS && load_ok;i++)
    {
        CString msg;
        HRESULT r;
        LPDIRECT3DRMMESHBUILDER builder;
        d3drm->CreateMeshBuilder( &builder );

        r=builder->Load( (void*)(LPCTSTR)filename,
                (void*)morphmeshname[i],
                D3DRMLOAD_FROMFILE | D3DRMLOAD_BYNAME, NULL, NULL );
        load_ok=r==D3DRM_OK;
        if (r==D3DRMERR_FILENOTFOUND)
        {
            TRACE("file not found\n");
            CString msg=filename + ": file not found";
            AfxMessageBox( msg );
            morphing=FALSE;
        }
        if (!load_ok)
            goto nomoremeshes;

        D3DVALUE scale;
        if (i==0)
            scale=ScaleMesh( builder, D3DVALUE(25) );
        else
            builder->Scale( scale, scale, scale );

        builder->SetQuality( D3DRMRENDER_FLAT );

        LPDIRECT3DRMMESH mesh;
        builder->CreateMesh( &mesh );

        unsigned vcount, fcount;
        DWORD ds;
        mesh->GetGroup( 0, &vcount, &fcount, 0, &ds, 0);

        if (i==0)
            nummorphvertices=vcount;
        else if(vcount!=nummorphvertices && load_ok)
        {
            TRACE("invalid vertex count\n");
            AfxMessageBox("Invalid vertex count");
            morphing=FALSE;
            return FALSE;
        }

        morphmeshdata[i]=new D3DRMVERTEX[nummorphvertices];
        r=mesh->GetVertices( 0, 0, nummorphvertices, morphmeshdata[i] );
        if (r!=D3DRM_OK)
            TRACE("mesh->GetVertices() failed\n");

        msg.Format("Mesh %d - %d vertices, %d faces",
                i+1, vcount, fcount );
        SetWindowText( msg );

        if (i==0)
            morphmesh=mesh;
        else
        {
            mesh->Release();
            mesh=0;
        }

        nomoremeshes:

        builder->Release();
        builder=0;

    }
    nummorphtargets=i-1;
    morphing=TRUE;

    return TRUE;
}


BOOL MorphWin::CreateAnimations()
{
    static int vertexcount;
    ReleaseAnimations( vertexcount );
    vertexcount=nummorphvertices;

    posanimation=new LPDIRECT3DRMANIMATION[nummorphvertices];
    posframe=new LPDIRECT3DRMFRAME[nummorphvertices];

    normanimation=new LPDIRECT3DRMANIMATION[nummorphvertices];
    normframe=new LPDIRECT3DRMFRAME[nummorphvertices];

    for (DWORD vert=0; vert<nummorphvertices; vert++)
    {
        d3drm->CreateAnimation( &posanimation[vert] );
        posanimation[vert]->SetOptions( D3DRMANIMATION_LINEARPOSITION |
                D3DRMANIMATION_POSITION );
        d3drm->CreateFrame( scene, &posframe[vert] );
        posanimation[vert]->SetFrame( posframe[vert] );
        d3drm->CreateAnimation( &normanimation[vert] );
        normanimation[vert]->SetOptions( D3DRMANIMATION_LINEARPOSITION |
                D3DRMANIMATION_POSITION );
        d3drm->CreateFrame( scene, &normframe[vert] );
        normanimation[vert]->SetFrame( normframe[vert] );
    }
    return TRUE;
}

BOOL MorphWin::PrepareMorphVertices()
{
    if (morphvertex)
    {
        delete [] morphvertex;
        morphvertex=0;
    }

    morphvertex=new D3DRMVERTEX[nummorphvertices];

    return TRUE;
}


BOOL MorphWin::AddMorphKey( DWORD target, D3DVALUE time )
{
    if (target<0 || target>nummorphtargets)
        return FALSE;

    for (DWORD i=0;i<nummorphvertices;i++)
    {
        D3DVECTOR& pos=morphmeshdata[target][i].position;
        posanimation[i]->AddPositionKey( time,
                pos.x, pos.y, pos.z );

        D3DVECTOR& norm=morphmeshdata[target][i].normal;
        normanimation[i]->AddPositionKey( time,
                norm.x, norm.y, norm.z );
    }
    return TRUE;
}

BOOL MorphWin::SetMorphTime( D3DVALUE time )
{
    for (DWORD v=0; v<nummorphvertices; v++)
    {
        posanimation[v]->SetTime( time );
        D3DVECTOR pos;
        posframe[v]->GetPosition( scene, &pos );
        morphvertex[v].position=pos;

        normanimation[v]->SetTime( time );
        D3DVECTOR norm;
        normframe[v]->GetPosition( scene, &norm );
        morphvertex[v].normal=norm;
    }
    morphmesh->SetVertices( 0, 0, nummorphvertices, morphvertex );

    return TRUE;
}


void MorphWin::OnDestroy()
{
}

BOOL MorphWin::ReleaseAnimations(int count)
{
return TRUE;
}

MorphWin::MorphWin()
{
}
