topical media & game development
hush-src-multi-GamePlayer-archive-CustomMixer.cpp / cpp
//------------------------------------------------------------------------------
// File: CustomMixer.cpp
//
// Desc: DirectShow sample code - MultiVMR9 GamePlayer
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
include <stdafx.h>
include <hall.h>
include <CustomMixer.h>
include "MultiVMR9_i.c"
include <scene/find.h>
CComPtr<IDirect3DTexture9> gCaptureTexture;
extern machine* GM;
// world matrix (combined projection and view)
D3DXMATRIX g_matWorld(
-0.681917f, -0.094384f, -0.725303f, 0.f,
-0.727560f, 0.189257f, 0.659417f, 0.f,
0.075027f, 0.977377f, -0.197721f, 0.f,
-318.524170f, -210.488570f, 81.793221f, 1.f
);
const D3DCOLOR g_colorPale = D3DCOLOR_RGBA( 0xFD, 0xBB, 0x40, 0x30 );
const D3DCOLOR g_colorGold = D3DCOLOR_RGBA( 0xFD, 0xBB, 0x40, 0xC0 );
// start position of the left top corner of the first movie screen
const float g_fXStart = -370.f;
const float g_fYStart = -1900.f;
const float g_fZStart = 610.f;
const float g_fMovieSlotWidth = 600.f; // width of the movie screen
const float g_fMovieSlotHeight = 450.f; // height of the movie screen
const float g_fFrameWidth = 5.f; // width of the frame for the movie screen
const float g_fDelta = 100.f; // distance between movies
const float g_fDarknessRange[] = {-2000.f, -1500.f, 1500.f, 2000.f};
const float g_fSpeed = 0.19f; // gait speed
****************************Public*Routine******************************\
CGameMixer
constructor
\*************************************************************************
CGameMixer::CGameMixer(LPUNKNOWN pUnk, HRESULT *phr)
: CUnknown(NAME("GameMixer Control for MultiVMR9"), pUnk)
, m_bInitialized( FALSE )
, m_pOwner( NULL )
, m_fSpeed( g_fSpeed )
, m_dwPrevTick( NULL )
, m_pFont( NULL )
, m_Left( 0)
, m_bAnimate( TRUE )
, m_pActiveMovie( NULL)
, m_pHall( NULL )
, m_pCharacter( NULL )
{
float fAspect;
int i;
m_matWorld = g_matWorld;
D3DXVECTOR3 vEye( 0, 0, -700.f );
D3DXVECTOR3 vAt( 0, 0, 0 );
D3DXVECTOR3 vUp( 0, 1, 0 );
m_pFont = new CD3DFont( _T("Trebuchet MS"), 12, D3DFONT_BOLD );
D3DXMatrixLookAtLH( &m_matView, &vEye, &vAt, &vUp);
fAspect = 4.f / 3.f;
D3DXMatrixPerspectiveFovLH( &m_matProj,
D3DX_PI/4.f, // FOV
4.f/3.f, // aspect ratio: always 4:3
10.f, // nearest plane
100000.f); // far plane
D3DVECTOR vecStart;
vecStart.x = g_fXStart;
vecStart.y = g_fYStart;
vecStart.z = g_fZStart;
for( i=0; i<8; i++)
{
m_Frames[i].Calculate(i, vecStart, NULL);
}
m_pHall = new CHall();
if( !m_pHall )
{
*phr = E_OUTOFMEMORY;
}
m_pCharacter = new CCharacter();
if( !m_pCharacter )
{
*phr = E_OUTOFMEMORY;
}
}
****************************Public*Routine******************************\
~CMultiVMR9MixerControl
destructor
\*************************************************************************
CGameMixer::~CGameMixer()
{
CAutoLock Lock(&m_ObjectLock);
Clean_();
}
/////////////////// IUnknown ///////////////////////////////////
****************************Public*Routine******************************\
CreateInstance
\*************************************************************************
CUnknown* CGameMixer::CreateInstance(LPUNKNOWN pUnk, HRESULT *phr)
{
return new CGameMixer(pUnk, phr);
}
****************************Public*Routine******************************\
NonDelegatingQueryInterface
\*************************************************************************
STDMETHODIMP
CGameMixer::NonDelegatingQueryInterface(
REFIID riid,
void ** ppv)
{
HRESULT hr = E_NOINTERFACE;
*ppv = NULL;
if (riid == IID_IMultiVMR9MixerControl)
{
hr = GetInterface((IMultiVMR9MixerControl *)this, ppv);
}
else
{
hr = CUnknown::NonDelegatingQueryInterface(riid,ppv);
}
return hr;
}
/////////////////// IMultiVMR9MixerControl /////////////////////////
****************************Public*Routine******************************\
Compose
\*************************************************************************
STDMETHODIMP
CGameMixer::Compose(
void* lpParam)
{
HRESULT hr = S_OK;
DWORD t = reinterpret_cast<DWORD>(lpParam);
LONG dt;
float dy;
if( 0L == m_dwPrevTick )
{
m_dwPrevTick = t;
return S_OK;
}
dt = t - m_dwPrevTick;
m_dwPrevTick = t;
CAutoLock Lock(&m_ObjectLock);
try
{
CHECK_HR(
( !m_bInitialized ) ? VFW_E_WRONG_STATE : S_OK,
DbgMsg("CGameMixer::Compose: mixer was not initialized!"));
if( m_bAnimate )
{
if( m_pHall )
{
// compose the hall
CHECK_HR(
hr = m_pHall->Compose( t ),
DbgMsg("CGameMixer::Compose: failed to compose the hall, hr = 0x%08x",hr));
}
if( m_pCharacter )
{
// compose the figure
CHECK_HR(
hr = m_pCharacter->Compose( t ),
DbgMsg("CGameMixer::Compose: failed to compose the character, hr = 0x%08x",hr));
}
// compose frames
dy = m_fSpeed * dt;
// check if we have to flip "left"
if( m_Frames[m_Left].m_S[1].Pos.y +dy > g_fDarknessRange[3])
{
m_Frames[m_Left].FlipToEnd( 8 );
m_Left++;
if( 8 == m_Left )
{
m_Left = 0;
}
}
// update coordinates for "left"
m_Frames[m_Left].MoveY( dy );
}// if animate
}// try
catch( HRESULT hr1 )
{
hr = hr1;
}
return hr;
}
****************************Public*Routine******************************\
BeginDeviceLoss
\*************************************************************************
STDMETHODIMP CGameMixer::BeginDeviceLoss( void )
{
HRESULT hr = S_OK;
HWND hwndVideo = NULL;
if( m_pHall )
{
delete m_pHall;
m_pHall = NULL;
}
if( m_pCharacter )
{
delete m_pCharacter;
m_pCharacter = NULL;
}
m_bInitialized = FALSE;
return S_OK;
}
****************************Public*Routine******************************\
EndDeviceLoss
\*************************************************************************
STDMETHODIMP CGameMixer::EndDeviceLoss( IDirect3DDevice9* pDevice )
{
HRESULT hr = S_OK;
if( !pDevice )
return E_POINTER;
if( m_pHall )
{
delete m_pHall;
m_pHall = NULL;
}
m_pHall = new CHall();
if( !m_pHall )
return E_OUTOFMEMORY;
if( m_pCharacter )
{
delete m_pCharacter;
m_pCharacter = NULL;
}
m_pCharacter = new CCharacter();
if( !m_pCharacter )
return E_OUTOFMEMORY;
m_bInitialized = FALSE;
hr = Initialize( pDevice );
return hr;
}
****************************Public*Routine******************************\
Compose
\*************************************************************************
STDMETHODIMP
CGameMixer::Render(
IDirect3DDevice9* pDevice,
void *lpParam )
{
HRESULT hr = S_OK;
list<CMovie*>::iterator start, end, it;
CMovie* pMovie = NULL;
int FrameRate100 = 0;
int FrameRateAvg100 = 0;
TCHAR achFrameRate[MAX_PATH];
CComPtr<IMultiVMR9Wizard> pWizard;
CComPtr<IDirect3DTexture9> pTexture;
if( !pDevice )
{
return E_POINTER;
}
CAutoLock Lock(&m_ObjectLock);
try
{
// error if not initialized
CHECK_HR(
m_bInitialized ? S_OK : VFW_E_WRONG_STATE,
DbgMsg("CGameMixer::Render: mixer was not initialized!"));
CHECK_HR(
m_pOwner ? S_OK : E_UNEXPECTED,
DbgMsg("CGameMixer::Render: mixer is initialized, but has no Render engine owner!"));
CHECK_HR(
hr = m_pOwner->GetWizardOwner( &(pWizard.p) ),
DbgMsg("CGameMixer::Render: mixer has owner, but has no parent wizard!"));
if( m_bAnimate )
{
// make sure we are in the right world
CHECK_HR(
hr = pDevice->SetTransform( D3DTS_WORLD, &m_matWorld ),
DbgMsg("CGameMixer::Render: failed to set the world transform, hr = 0x%08x", hr));
if( m_pCharacter )
{
// render the figure
CHECK_HR(
hr = m_pCharacter->Render( pDevice ),
DbgMsg("CGameMixer::Render: failed to render the character, hr = 0x%08x", hr));
}
// make sure we are in the right world
CHECK_HR(
hr = pDevice->SetTransform( D3DTS_WORLD, &m_matWorld ),
DbgMsg("CGameMixer::Render: failed to set the world transform, hr = 0x%08x", hr));
if( m_pHall )
{
// render the hall
CHECK_HR(
hr = m_pHall->Render( pDevice ),
DbgMsg("CGameMixer::Render: failed to render the hall, hr = 0x%08x", hr));
}
// restore device objects for movies
CHECK_HR(
hr = RestoreDeviceObjects( pDevice ),
DbgMsg("CGameMixer::Render: failed in RestoreDeviceObjects, hr = 0x%08x", hr));
// render all the movies
start = m_listMovies.begin();
end = m_listMovies.end();
if( false == m_listMovies.empty() )
{
int Index;
D3DVECTOR vecStart;
vecStart.x = g_fXStart;
vecStart.z = g_fZStart;
it = start;
for( int i=0; i<8; i++)
{
pMovie = (CMovie*)(*it);
CHECK_HR(
pMovie ? S_OK : E_UNEXPECTED,
DbgMsg("CGameMixer::Render: FATAL, list contains NULL movies"));
CHECK_HR(
hr = pWizard->GetTexture( pMovie->m_dwID, &pTexture ),
DbgMsg("CGameMixer::Render: failed to get the texture for movie \%ld, hr = 0x%08x", pMovie->m_dwID, hr));
Index = i - m_Left;
if( Index < 0 )
{
Index += 8;
}
vecStart.y = m_Frames[m_Left].m_S[0].Pos.y;
CHECK_HR(
hr = m_Frames[i].Calculate( Index, vecStart, pMovie),
DbgMsg("CGameMixer::Render: failed to recalculate coordinates for frame \%d, movie \%ld, hr = 0x%08x", i, pMovie->m_dwID, hr));
CHECK_HR(
hr = m_Frames[i].Render( pDevice, pTexture),
DbgMsg("CGameMixer::Render: failed to render movie \%ld, hr = 0x%08x", pMovie->m_dwID, hr));
it++;
if( it == end )
{
it = start;
}
pTexture = NULL;
}
}// if list is not empty
}// if animate
else // draw selected movie
{
if( m_pActiveMovie )
{
D3DXMATRIX matPlainWorld;
D3DXMatrixIdentity( &matPlainWorld );
pDevice->SetTransform( D3DTS_WORLD, &matPlainWorld);
// restore device objects for movies
CHECK_HR(
hr = RestoreDeviceObjects( pDevice ),
DbgMsg("CGameMixer::Render: failed in RestoreDeviceObjects, hr = 0x%08x", hr));
CHECK_HR(
hr = pWizard->GetTexture( m_pActiveMovie->m_dwID, &pTexture ),
DbgMsg("CGameMixer::Render: failed to get the texture for active movie \%ld, hr = 0x%08x", m_pActiveMovie->m_dwID, hr));
CHECK_HR(
hr = m_ActiveMovieFrame.CalculateInFocus( m_pActiveMovie ),
DbgMsg("CGameMixer::Render: hr = 0x%08x", hr));
CHECK_HR(
hr = m_ActiveMovieFrame.Render( pDevice, pTexture),
DbgMsg("CGameMixer::Render: failed to render 'active' movie \%ld, hr = 0x%08x", m_pActiveMovie->m_dwID, hr));
pDevice->SetTransform( D3DTS_WORLD, &m_matWorld );
}// if active movie
}
hr = m_pOwner->GetFrameRate( &FrameRate100 );
hr = m_pOwner->GetFrameRateAvg( &FrameRateAvg100 );
_stprintf( achFrameRate, TEXT("FPS: %6.2f\t (average %6.2f fps)"), (float)FrameRate100/100.f, (float)FrameRateAvg100/100.f);
if( m_pFont )
{
m_pFont->DrawText( 20, 570, D3DCOLOR_ARGB(180,133,197,235), achFrameRate );
}
}
catch( HRESULT hr1 )
{
if( hr1 == D3DERR_DEVICELOST && m_pOwner )
{
hr = m_pOwner->ProcessLostDevice();
}
else
{
hr = hr1;
}
}
return hr;
}
****************************Public*Routine******************************\
AddVideoSource
\*************************************************************************
STDMETHODIMP
CGameMixer::AddVideoSource(
DWORD_PTR dwID,
LONG lImageWidth,
LONG lImageHeight,
LONG lTextureWidth,
LONG lTextureHeight)
{
HRESULT hr = S_OK;
CMovie *pMovie = NULL;
float dy = 0.f;
CAutoLock Lock(&m_ObjectLock);
try
{
pMovie = new CMovie( dwID,
lImageWidth,
lImageHeight,
lTextureWidth,
lTextureHeight);
CHECK_HR(
pMovie ? S_OK: E_OUTOFMEMORY,
DbgMsg("CGameMixer::AddVideoSource: failed to create new CMovieFrame object"));
m_listMovies.push_back( pMovie );
}
catch( HRESULT hr1 )
{
hr = hr1;
}
return hr;
}
****************************Public*Routine******************************\
DeleteVideoSource
\*************************************************************************
STDMETHODIMP
CGameMixer::DeleteVideoSource(
DWORD_PTR dwID)
{
HRESULT hr = S_OK;
list<CMovie*>::iterator start, end, it;
CMovie* pMovie = NULL;
CMovie* pMovieRequested = NULL;
start = m_listMovies.begin();
end = m_listMovies.end();
CAutoLock Lock(&m_ObjectLock);
try
{
for( it=start; it!=end; it++)
{
pMovie = (CMovie*)(*it);
CHECK_HR(
pMovie? S_OK : E_UNEXPECTED,
DbgMsg("CGameMixer::DeleteVideoSource: FATAL, list contains NULL movies!"));
if( dwID == pMovie->m_dwID )
{
pMovieRequested = pMovie;
break;
}
}
CHECK_HR(
pMovieRequested ? S_OK : VFW_E_NOT_FOUND,
DbgMsg("CGameMixer::DeleteVideoSource: requested movie ID = 0x%08x was not found in the list", dwID));
// if movie found, delete it from the list
m_listMovies.remove( pMovieRequested );
delete pMovieRequested;
pMovieRequested = NULL;
}
catch(HRESULT hr1)
{
hr = hr1;
}
return hr;
}
****************************Public*Routine******************************\
SetRenderEngineOwner
\*************************************************************************
STDMETHODIMP
CGameMixer::SetRenderEngineOwner(
IMultiVMR9RenderEngine* pRenderEngine)
{
HRESULT hr = S_OK;
CAutoLock Lock(&m_ObjectLock);
try
{
RELEASE( m_pOwner );
if( pRenderEngine )
{
m_pOwner = pRenderEngine;
m_pOwner->AddRef();
}
}
catch( HRESULT hr1)
{
hr = hr1;
}
return hr;
}
****************************Public*Routine******************************\
GetRenderEngineOwner
\*************************************************************************
STDMETHODIMP
CGameMixer::GetRenderEngineOwner(
IMultiVMR9RenderEngine** ppRenderEngine)
{
if( !ppRenderEngine )
{
return E_POINTER;
}
if( !m_pOwner )
{
return VFW_E_NOT_FOUND;
}
*ppRenderEngine = m_pOwner;
(*ppRenderEngine)->AddRef();
return S_OK;
}
****************************Public*Routine*****************************\
Initialize
\*************************************************************************
STDMETHODIMP
CGameMixer::Initialize(
IDirect3DDevice9 *pDevice)
{
HRESULT hr = S_OK;
TCHAR achMessage[MAX_PATH];
CAutoLock Lock(&m_ObjectLock);
achMessage[0] = TEXT('\0');
if( m_bInitialized )
{
return VFW_E_WRONG_STATE;
}
if( !pDevice )
{
return E_POINTER;
}
try
{
CHECK_HR(
hr = m_pFont->InitDeviceObjects( pDevice ),
DbgMsg("CGameMixer::Initialize: failed to initialize font, hr = 0x%08x", hr));
CHECK_HR(
hr = m_pFont->RestoreDeviceObjects(),
DbgMsg("CGameMixer::Initialize: failed to RestoreDeviceObjects for the font, hr = 0x%08x", hr));
if( m_pHall )
{
CHECK_HR(
hr = m_pHall->Initialize( pDevice ),
DbgMsg("CGameMixer::Initialize: failed to initialize the hall, hr = 0x%08x", hr));
m_pHall->SetSpeed( g_fSpeed );
}
if( m_pCharacter )
{
CHECK_HR(
hr = m_pCharacter->Initialize( pDevice ),
DbgMsg("CGameMixer::Initialize: failed to initialize the character, hr = 0x%08x", hr));
}
CHECK_HR(
hr = pDevice->SetTransform( D3DTS_VIEW, &m_matView ),
DbgMsg("CGameMixer::Initialize: failed to set the view matrix, hr = 0x%08x", hr));
CHECK_HR(
hr = pDevice->SetTransform( D3DTS_PROJECTION, &m_matProj ),
DbgMsg("CGameMixer::Initialize: failed to set the projection matrix, hr = 0x%08x", hr));
m_bInitialized = TRUE;
}
catch( HRESULT hr1 )
{
hr = hr1;
}
return hr;
}
****************************Public*Routine******************************\
RestoreDeviceObjects
\*************************************************************************
HRESULT CGameMixer::RestoreDeviceObjects( IDirect3DDevice9 *pDevice )
{
HRESULT hr = S_OK;
if( !pDevice )
{
return E_POINTER;
}
try
{
CHECK_HR(
hr = pDevice->SetRenderState( D3DRS_AMBIENT, 0x00FFFFFF ),
DbgMsg("CGameMixer::RestoreDeviceObjects: failed to set render state D3DRS_AMBIENT/0xFFFFFFFF, hr = 0x%08x",hr));
CHECK_HR(
hr = pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE),
DbgMsg("CGameMixer::RestoreDeviceObjects: failed to set render state D3DRS_CULLMODE/D3DCULL_NONE, hr = 0x%08x",hr));
CHECK_HR(
hr = pDevice->SetRenderState(D3DRS_ZENABLE, TRUE),
DbgMsg("CGameMixer::RestoreDeviceObjects: failed to set render state D3DRS_ZENABLE/FALSE, hr = 0x%08x",hr));
CHECK_HR(
hr = pDevice->SetSamplerState(0, D3DSAMP_ADDRESSU ,D3DTADDRESS_CLAMP),
DbgMsg("CGameMixer::RestoreDeviceObjects: failed to set sampler state D3DSAMP_ADDRESSU/D3DTADDRESS_CLAMP, hr = 0x%08x",hr));
CHECK_HR(
hr = pDevice->SetSamplerState(0, D3DSAMP_ADDRESSV ,D3DTADDRESS_CLAMP),
DbgMsg("CGameMixer::RestoreDeviceObjects: failed to set sampler state D3DSAMP_ADDRESSV/D3DTADDRESS_CLAMP, hr = 0x%08x",hr));
}
catch(HRESULT hr1)
{
hr = hr1;
}
return hr;
}
****************************Public*Routine******************************\
SetWorldMatrix
\*************************************************************************
HRESULT CGameMixer::SetWorldMatrix( D3DXMATRIX& M )
{
m_matWorld = M;
return S_OK;
}
****************************Public*Routine******************************\
Animate
\*************************************************************************
HRESULT CGameMixer::Animate( BOOL bAnimate)
{
DWORD_PTR dwID = NULL;
int nIndex = 0;
float dY_min;
float dY_cur;
m_bAnimate = bAnimate;
if( m_bAnimate == FALSE )
{
// do not stop if movie list is empty
if( m_listMovies.empty())
{
m_bAnimate = TRUE;
return S_FALSE;
}
// select movie that is closest to the center
nIndex = 0;
dY_min = (m_Frames[0].m_S[0].Pos.y + m_Frames[0].m_S[1].Pos.y) / 2.f;
if( dY_min < 0.f )
{
dY_min = - dY_min;
}
for( int i=1; i<8; i++)
{
dY_cur = (m_Frames[i].m_S[0].Pos.y + m_Frames[i].m_S[1].Pos.y) / 2.f;
if( dY_cur < 0.f )
{
dY_cur = - dY_cur;
}
if( dY_cur < dY_min )
{
dY_min = dY_cur;
nIndex = i;
}
}// for
dwID = m_Frames[nIndex].m_dwID;
// try to find this movie in the list
list<CMovie*>::iterator start, end, it;
m_pActiveMovie = NULL;
start = m_listMovies.begin();
end = m_listMovies.end();
for( it=start; it!=end; it++)
{
if( (*it)->m_dwID == dwID )
{
m_pActiveMovie = (*it);
break;
}
}
if( !m_pActiveMovie )
{
m_bAnimate = TRUE;
return S_FALSE;
}
return S_OK;
}
m_pActiveMovie = NULL;
return S_OK;
}
//////////////////////// CMovie ///////////////////////////////
****************************Public*Routine******************************\
CMovie
\*************************************************************************
CGameMixer::CMovie::CMovie(
DWORD_PTR dwID,
LONG lImageWidth,
LONG lImageHeight,
LONG lTextureWidth,
LONG lTextureHeight)
: m_dwID( dwID)
{
float w;
float h;
float ar; // aspect ratio
m_fU = 1.f;//( lTextureWidth ) ? (float)lImageWidth/(float)lTextureWidth : 1.f;
m_fV = 1.f;//( lTextureHeight ) ? (float)lImageHeight/(float)lTextureHeight : 1.f;
ar = (float)lImageWidth / (float)lImageHeight;
// try to fit movie withing the width
w = g_fMovieSlotWidth;
h = (float)w / ar;
if( h > g_fMovieSlotHeight )
{
h = g_fMovieSlotHeight;
w = h * ar;
}
m_fY = (g_fMovieSlotWidth - w)/2.f;
m_fZ = (g_fMovieSlotHeight -h)/2.f;
}
//////////////////////// CFrame ///////////////////////////////
****************************Public*Routine******************************\
CFrame
constructor
\*************************************************************************
CGameMixer::CFrame::CFrame( )
{
int i;
for( i=0; i<4; i++)
{
m_V[i].color = D3DCOLOR_ARGB( 0xCC, 0xFF, 0xFF, 0xFF );
}
for( i=0; i<10; i++)
{
m_F[i].color = g_colorPale;
}
}
****************************Public*Routine******************************\
Calculate
calculates position of the movie screen in the "walking girl" scene
\*************************************************************************
HRESULT CGameMixer::CFrame::Calculate( int n,
D3DVECTOR& v0,
CGameMixer::CMovie* pMovie )
{
HRESULT hr = S_OK;
int j;
if( n<0 || n>8 )
return E_FAIL;
float fYShift = -(g_fMovieSlotWidth + g_fDelta) * n;
float fCenter;
float c, l, t, r, b, a;
D3DCOLOR colorFrame;
float x0 = v0.x;
float y0 = v0.y;
float z0 = v0.z;
float fy = 0.f;
float fz = 0.f;
float fU = 0.f;
float fV = 0.f;
if( pMovie )
{
fy = pMovie->m_fY;
fz = pMovie->m_fZ;
fU = pMovie->m_fU;
fV = pMovie->m_fV;
}
m_S[0].Pos.x = x0;
m_S[0].Pos.y = y0 + fYShift;
m_S[0].Pos.z = z0;
m_V[0].Pos.x = m_S[0].Pos.x;
m_V[0].Pos.y = m_S[0].Pos.y - fy;
m_V[0].Pos.z = m_S[0].Pos.z - fz;
m_S[1].Pos.x = x0;
m_S[1].Pos.y = y0 + fYShift - g_fMovieSlotWidth;
m_S[1].Pos.z = z0;
m_V[1].Pos.x = m_S[1].Pos.x;
m_V[1].Pos.y = m_S[1].Pos.y + fy;
m_V[1].Pos.z = m_S[1].Pos.z - fz;
m_S[2].Pos.x = x0;
m_S[2].Pos.y = y0 + fYShift;
m_S[2].Pos.z = z0 - g_fMovieSlotHeight;
m_V[2].Pos.x = m_S[2].Pos.x;
m_V[2].Pos.y = m_S[2].Pos.y - fy;
m_V[2].Pos.z = m_S[2].Pos.z + fz;
m_S[3].Pos.x = x0;
m_S[3].Pos.y = y0 + fYShift - g_fMovieSlotWidth;
m_S[3].Pos.z = z0 - g_fMovieSlotHeight;
m_V[3].Pos.x = m_S[3].Pos.x;
m_V[3].Pos.y = m_S[3].Pos.y + fy;
m_V[3].Pos.z = m_S[3].Pos.z + fz;
m_V[0].tu = 0.f; m_V[0].tv = 0.f;
m_V[1].tu = fU; m_V[1].tv = 0.f;
m_V[2].tu = 0.f; m_V[2].tv = fV;
m_V[3].tu = fU; m_V[3].tv = fV;
// calculate frame
c = m_V[0].Pos.x;
a = g_fFrameWidth;
l = m_V[0].Pos.y;
r = m_V[1].Pos.y;
t = m_V[0].Pos.z;
b = m_V[2].Pos.z;
m_F[0].Pos.x = c; m_F[0].Pos.y = l+a; m_F[0].Pos.z = t+a;
m_F[1].Pos.x = c; m_F[1].Pos.y = l; m_F[1].Pos.z = t;
m_F[2].Pos.x = c; m_F[2].Pos.y = r-a; m_F[2].Pos.z = t+a;
m_F[3].Pos.x = c; m_F[3].Pos.y = r; m_F[3].Pos.z = t;
m_F[4].Pos.x = c; m_F[4].Pos.y = r-a; m_F[4].Pos.z = b-a;
m_F[5].Pos.x = c; m_F[5].Pos.y = r; m_F[5].Pos.z = b;
m_F[6].Pos.x = c; m_F[6].Pos.y = l+a; m_F[6].Pos.z = b-a;
m_F[7].Pos.x = c; m_F[7].Pos.y = l; m_F[7].Pos.z = b;
m_F[8].Pos.x = c; m_F[8].Pos.y = l+a; m_F[8].Pos.z = t+a;
m_F[9].Pos.x = c; m_F[9].Pos.y = l; m_F[9].Pos.z = t;
fCenter = (m_V[0].Pos.y + m_V[1].Pos.y)/2.f;
if( fCenter > -350.f && fCenter < 350.f)
{
colorFrame = g_colorGold;
}
else
{
colorFrame = g_colorPale;
}
for( j=0; j<10; j++)
{
m_F[j].color = colorFrame;
}
m_dwID = pMovie? pMovie->m_dwID : NULL;
return S_OK;
}
****************************Public*Routine******************************\
CalculateInFocus
calculates position of the movie screen in the "in-focus" scene
\*************************************************************************
HRESULT CGameMixer::CFrame::CalculateInFocus(CGameMixer::CMovie* pMovie)
{
HRESULT hr = S_OK;
int i;
if( !pMovie )
return E_POINTER;
float left = -380.f + pMovie->m_fY/600.f*760.f;
float right = 380.f - pMovie->m_fY/600.f*760.f;
float top = 285.f - pMovie->m_fZ/450.f*570.f;
float bottom = -285.f + pMovie->m_fZ/450.f*570.f;
m_V[0].Pos.x = left; m_V[0].Pos.y = top; m_V[0].Pos.z = 0.f;
m_V[1].Pos.x = right; m_V[1].Pos.y = top; m_V[1].Pos.z = 0.f;
m_V[2].Pos.x = left; m_V[2].Pos.y = bottom; m_V[2].Pos.z = 0.f;
m_V[3].Pos.x = right; m_V[3].Pos.y = bottom; m_V[3].Pos.z = 0.f;
m_V[0].tu = 0.f; m_V[0].tv = 0.f;
m_V[1].tu = pMovie->m_fU; m_V[1].tv = 0.f;
m_V[2].tu = 0.f; m_V[2].tv = pMovie->m_fV;
m_V[3].tu = pMovie->m_fU; m_V[3].tv = pMovie->m_fV;
for( i=0; i<4; i++)
{
m_V[i].color = D3DCOLOR_RGBA( 0xFF, 0xFF, 0xFF, 0xFF);
}
float c = 0.f;
float a = g_fFrameWidth;
float l = m_V[0].Pos.x;
float r = m_V[1].Pos.x;
float t = m_V[0].Pos.y;
float b = m_V[2].Pos.y;
m_F[0].Pos.x = l-a; m_F[0].Pos.y = t+a; m_F[0].Pos.z = c;
m_F[1].Pos.x = l; m_F[1].Pos.y = t; m_F[1].Pos.z = c;
m_F[2].Pos.x = r+a; m_F[2].Pos.y = t+a; m_F[2].Pos.z = c;
m_F[3].Pos.x = r; m_F[3].Pos.y = t; m_F[3].Pos.z = c;
m_F[4].Pos.x = r+a; m_F[4].Pos.y = b-a; m_F[4].Pos.z = c;
m_F[5].Pos.x = r; m_F[5].Pos.y = b; m_F[5].Pos.z = c;
m_F[6].Pos.x = l-a; m_F[6].Pos.y = b-a; m_F[6].Pos.z = c;
m_F[7].Pos.x = l; m_F[7].Pos.y = b; m_F[7].Pos.z = c;
m_F[8].Pos.x = l-a; m_F[8].Pos.y = t+a; m_F[8].Pos.z = c;
m_F[9].Pos.x = l; m_F[9].Pos.y = t; m_F[9].Pos.z = c;
for( i=0; i<10; i++)
{
m_F[i].color = g_colorGold;
}
return hr;
}
****************************Public*Routine******************************\
Render
\*************************************************************************
HRESULT CGameMixer::CFrame::Render(
IDirect3DDevice9* pDevice,
IDirect3DTexture9* pTexture)
{
HRESULT hr = S_OK;
if( !pDevice || !pTexture)
{
return E_POINTER;
}
try
{
CHECK_HR(
hr = pDevice->SetTexture(0, pTexture),
DbgMsg("CFrame::Render: failed in SetTexture, hr = 0x%08x",hr));
CHECK_HR(
hr = pDevice->SetFVF( g_FVFMixer ),
DbgMsg("CFrame::Render: failed to set FVF, hr = 0x%08x",hr));
CHECK_HR(
hr = pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1),
DbgMsg("CFrame::Render: failed to set texture stage state D3DTSS_ALPHAOP/D3DTOP_MODULATE, hr = 0x%08x",hr));
CHECK_HR(
hr = pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE),
DbgMsg("CFrame::Render: failed to set texture stage state D3DTSS_ALPHAARG1/D3DTA_TEXTURE, hr = 0x%08x",hr));
CHECK_HR(
hr = pDevice->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP,
2,
(LPVOID)(m_V),
sizeof(m_V[0])),
DbgMsg("CFrame::Render: failed in DrawPrimitiveUP, hr = 0x%08x", hr));
CHECK_HR(
hr = pDevice->SetTexture(0, NULL),
DbgMsg("CFrame::Render: failed in SetTexture(NULL), hr = 0x%08x",hr));
// draw frame around the movie
CHECK_HR(
hr = pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1),
DbgMsg("CFrame::Render: failed to set texture stage state D3DTSS_ALPHAOP/D3DTOP_MODULATE, hr = 0x%08x",hr));
CHECK_HR(
hr = pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE),
DbgMsg("CFrame::Render: failed to set texture stage state D3DTSS_ALPHAARG1/D3DTA_TEXTURE, hr = 0x%08x",hr));
CHECK_HR(
hr = pDevice->SetFVF( g_FVFframe ),
DbgMsg("CFrame::Render: failed to set FVFhr = 0x%08x",hr));
CHECK_HR(
hr = pDevice->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP,
8,
(LPVOID)(m_F),
sizeof(m_F[0])),
DbgMsg("CFrame::Render: failed in DrawPrimitiveUP for the frame, hr = 0x%08x", hr));
}
catch( HRESULT hr1 )
{
hr = hr1;
}
return hr;
}
****************************Public*Routine******************************\
FlipToEnd
\*************************************************************************
void CGameMixer::CFrame::FlipToEnd( int N)
{
float Shift = -( g_fMovieSlotWidth + g_fDelta ) * N;
MoveY( Shift);
}
****************************Public*Routine******************************\
MoveY
\*************************************************************************
void CGameMixer::CFrame::MoveY( float Shift )
{
int i;
for( i=0; i<4; i++)
{
//m_V[i].Pos.y += Shift;
m_S[i].Pos.y += Shift;
}
/*
for( i=0; i<10; i++)
{
m_F[i].Pos.y += Shift;
}
*/
}
/////////////////////// PRIVATE DOMAIN /////////////////////////////
****************************Private*Routine*****************************\
Clean_
\*************************************************************************
void CGameMixer::Clean_()
{
RELEASE(m_pOwner);
// clean the list
list<CMovie*>::iterator start, end, it;
CMovie *pMovie = NULL;
start = m_listMovies.begin();
end = m_listMovies.end();
for( it=start; it!=end; it++)
{
pMovie = (CMovie*)(*it);
if( pMovie )
{
delete pMovie;
pMovie = NULL;
}
}
m_listMovies.clear();
if( m_pFont )
{
m_pFont->InvalidateDeviceObjects();
m_pFont->DeleteDeviceObjects();
delete m_pFont;
m_pFont = NULL;
}
if( m_pHall )
{
delete m_pHall;
m_pHall = NULL;
}
if( m_pCharacter )
{
delete m_pCharacter;
m_pCharacter = NULL;
}
}
(C) Æliens
20/2/2008
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.