Files
Client/Library/dxx8/samples/Multimedia/DirectShow_WinXP/VMR/VMRXcl/BltAlpha.h
LGram16 e067522598 Initial commit: ROW Client source code
Game client codebase including:
- CharacterActionControl: Character and creature management
- GlobalScript: Network, items, skills, quests, utilities
- RYLClient: Main client application with GUI and event handlers
- Engine: 3D rendering engine (RYLGL)
- MemoryManager: Custom memory allocation
- Library: Third-party dependencies (DirectX, boost, etc.)
- Tools: Development utilities

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 16:24:34 +09:00

977 lines
32 KiB
C++

//----------------------------------------------------------------------------
// File: BltAlpha.h
//
// Desc: DirectShow sample code
// Header file and class description for CAlphaBlt,
// texture surface to be used in PresentImage of the
// customized allocator-presenter
//
// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
#ifndef __INITDDSTRUCT_DEFINED
#define __INITDDSTRUCT_DEFINED
#include <math.h>
#include <d3dxmath.h>
#include "d3dtextr.h"
#include "d3dfont.h"
#include "utils.h"
#include "resrc1.h"
#include "d3dutil.h"
extern struct SceneSettings g_ss;
template <typename T>
__inline void INITDDSTRUCT(T& dd)
{
ZeroMemory(&dd, sizeof(dd));
dd.dwSize = sizeof(dd);
}
#endif
#ifndef __RELEASE_DEFINED
#define __RELEASE_DEFINED
template<typename T>
__inline void RELEASE( T* &p )
{
if( p ) {
p->Release();
p = NULL;
}
}
#endif
#ifndef CHECK_HR
#define CHECK_HR(expr) do { if (FAILED(expr)) __leave; } while(0);
#endif
#define COMPLVERTSIZE 640 // must be divisible by 4!!!
#define pi 3.1415926535f
//----------------------------------------------------------------------------
// CAlphaBlt
//
// Desc: texture surface to be used in PresentImage of the
// customized allocator-presenter
//----------------------------------------------------------------------------
class CAlphaBlt
{
private:
LPDIRECTDRAW7 m_pDD;
LPDIRECT3D7 m_pD3D;
LPDIRECT3DDEVICE7 m_pD3DDevice;
LPDIRECTDRAWSURFACE7 m_lpDDBackBuffer;
LPDIRECTDRAWSURFACE7 m_lpDDMirror;
LPDIRECTDRAWSURFACE7 m_lpDDM32;
LPDIRECTDRAWSURFACE7 m_lpDDM16;
DDSURFACEDESC2 m_ddsdM32;
DDSURFACEDESC2 m_ddsdM16;
bool m_fPowerOf2;
bool m_fSquare;
bool m_bNeedToRestoreMenu;
TextureContainer * m_ptxtrMenu;
CD3DFont * m_pFont;
typedef struct Vertex
{
float x, y, z, rhw;
D3DCOLOR clr;
float tu, tv;
} Vertex;
Vertex pVertices[4]; // primitive for rotating effect
Vertex pVComplex[COMPLVERTSIZE];// primitive for twisting effect
Vertex pVMenu[4]; // primitive for menu effect
//----------------------------------------------------------------------------
// CAlphaBlt::Rotate
//
// Desc: 3D transformation of pVertices that provide rotation around Z and Y
//
// Parameters:
// theta - angle of rotation around Z axis
// thetaY - angle of rotation around Y axis
// pVertices - array of (Vertex*) to be transformed
// nSize - number of vertices
// (cx2, cy2) - center of rotation
//----------------------------------------------------------------------------
void Rotate(float theta, float thetaY,
CAlphaBlt::Vertex * pVertices,
int nSize, float cx2, float cy2)
{
D3DXMATRIX mtrV;
D3DXMATRIX mtrRotZ;
D3DXMATRIX mtrRotY;
D3DXMATRIX mtrPrs;
D3DXMATRIX mtrRes;
float pi2 = 1.57079632675f; // pi/2.
// initialize mtrV
mtrV.m[0][0] = pVertices[0].x - cx2;
mtrV.m[1][0] = pVertices[0].y - cy2;
mtrV.m[2][0] = pVertices[0].z;
mtrV.m[3][0] = 0.f;
mtrV.m[0][1] = pVertices[1].x - cx2;
mtrV.m[1][1] = pVertices[1].y - cy2;
mtrV.m[2][1] = pVertices[1].z;
mtrV.m[3][1] = 0;
mtrV.m[0][2] = pVertices[2].x - cx2;
mtrV.m[1][2] = pVertices[2].y - cy2;
mtrV.m[2][2] = pVertices[2].z;
mtrV.m[3][2] = 0;
mtrV.m[0][3] = pVertices[3].x - cx2;
mtrV.m[1][3] = pVertices[3].y - cy2;
mtrV.m[2][3] = pVertices[3].z;
mtrV.m[3][3] = 0;
D3DXMatrixRotationZ( &mtrRotZ, theta);
D3DXMatrixRotationY( &mtrRotY, thetaY);
D3DXMatrixPerspectiveFov( &mtrPrs, pi2, 1.1f, 0.f, 1.f);
// mtrRotZ * mtrV
D3DXMatrixMultiply( &mtrRes, &mtrRotZ, &mtrV);
// mtrRotY * mtrRotZ * mtrV
D3DXMatrixMultiply( &mtrV, &mtrRotY, &mtrRes);
// mtrPrs * mtrRotY * mtrRotZ * mtrV
D3DXMatrixMultiply( &mtrRes, &mtrPrs, &mtrV);
// here, mtrRes has what we need; copy it back to pVertices
pVertices[0].x = mtrRes.m[0][0] + cx2;
pVertices[1].x = mtrRes.m[0][1] + cx2;
pVertices[2].x = mtrRes.m[0][2] + cx2;
pVertices[3].x = mtrRes.m[0][3] + cx2;
pVertices[0].y = mtrRes.m[1][0] + cy2;
pVertices[1].y = mtrRes.m[1][1] + cy2;
pVertices[2].y = mtrRes.m[1][2] + cy2;
pVertices[3].y = mtrRes.m[1][3] + cy2;
pVertices[0].z = mtrRes.m[2][0];
pVertices[1].z = mtrRes.m[2][1];
pVertices[2].z = mtrRes.m[2][2];
pVertices[3].z = mtrRes.m[2][3];
return;
}
//----------------------------------------------------------------------------
// IsSurfaceBlendable
//
// Checks the DD surface description and the given
// alpha value to determine if this surface is blendable.
//
//----------------------------------------------------------------------------
bool
IsSurfaceBlendable(
DDSURFACEDESC2& ddsd,
BYTE fAlpha
)
{
// Is the surface already a D3D texture ?
if (ddsd.ddsCaps.dwCaps & DDSCAPS_TEXTURE) {
return true;
}
// OK we have to mirror the surface
return false;
}
//----------------------------------------------------------------------------
// MirrorSourceSurface
//
// The mirror surface cab be either 16 or 32 bit RGB depending
// upon the format of the source surface.
//
// Of course it should have the "texture" flag set and should be in VRAM.
// If we can't create the surface then the AlphaBlt should fail
//----------------------------------------------------------------------------
HRESULT MirrorSourceSurface(
LPDIRECTDRAWSURFACE7 lpDDS,
DDSURFACEDESC2& ddsd
)
{
HRESULT hr = DD_OK;
DWORD dwMirrorBitDepth = 0;
DDSURFACEDESC2 ddsdMirror={0};
//
// OK - is it suitable for our needs.
//
// Apply the following rules:
// if ddsd is a FOURCC surface the mirror should be 32 bit
// if ddsd is RGB then the mirror's bit depth should match
// that of ddsd.
//
// Also, the mirror must be large enough to actually hold
// the surface to be blended
//
m_lpDDMirror = NULL;
if (ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC ||
ddsd.ddpfPixelFormat.dwRGBBitCount == 32) {
if (ddsd.dwWidth > m_ddsdM32.dwWidth ||
ddsd.dwHeight > m_ddsdM32.dwHeight) {
RELEASE(m_lpDDM32);
}
if (!m_lpDDM32) {
dwMirrorBitDepth = 32;
}
else {
m_lpDDMirror = m_lpDDM32;
ddsdMirror = m_ddsdM32;
}
}
else if (ddsd.ddpfPixelFormat.dwRGBBitCount == 16) {
if (ddsd.dwWidth > m_ddsdM16.dwWidth ||
ddsd.dwHeight > m_ddsdM16.dwHeight) {
RELEASE(m_lpDDM16);
}
if (!m_lpDDM16) {
dwMirrorBitDepth = 16;
}
else {
m_lpDDMirror = m_lpDDM16;
ddsdMirror = m_ddsdM16;
}
}
else {
// No support for RGB24 or RGB8!
return E_INVALIDARG;
}
if (!m_lpDDMirror) {
INITDDSTRUCT(ddsdMirror);
ddsdMirror.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
ddsdMirror.ddpfPixelFormat.dwFlags = DDPF_RGB;
ddsdMirror.ddpfPixelFormat.dwRGBBitCount = dwMirrorBitDepth;
switch (dwMirrorBitDepth) {
case 16:
ddsdMirror.ddpfPixelFormat.dwRBitMask = 0x0000F800;
ddsdMirror.ddpfPixelFormat.dwGBitMask = 0x000007E0;
ddsdMirror.ddpfPixelFormat.dwBBitMask = 0x0000001F;
break;
case 32:
ddsdMirror.ddpfPixelFormat.dwRBitMask = 0x00FF0000;
ddsdMirror.ddpfPixelFormat.dwGBitMask = 0x0000FF00;
ddsdMirror.ddpfPixelFormat.dwBBitMask = 0x000000FF;
break;
}
ddsdMirror.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE;
ddsdMirror.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
if (m_fPowerOf2) {
for (ddsdMirror.dwWidth = 1;
ddsd.dwWidth > ddsdMirror.dwWidth;
ddsdMirror.dwWidth <<= 1);
for (ddsdMirror.dwHeight = 1;
ddsd.dwHeight > ddsdMirror.dwHeight;
ddsdMirror.dwHeight <<= 1);
}
else {
ddsdMirror.dwWidth = ddsd.dwWidth;
ddsdMirror.dwHeight = ddsd.dwHeight;
}
if (m_fSquare) {
if (ddsdMirror.dwHeight > ddsdMirror.dwWidth) {
ddsdMirror.dwWidth = ddsdMirror.dwHeight;
}
if (ddsdMirror.dwWidth > ddsdMirror.dwHeight) {
ddsdMirror.dwHeight = ddsdMirror.dwWidth;
}
}
__try {
// Attempt to create the surface with theses settings
CHECK_HR(hr = m_pDD->CreateSurface(&ddsdMirror, &m_lpDDMirror, NULL));
INITDDSTRUCT(ddsdMirror);
CHECK_HR(hr = m_lpDDMirror->GetSurfaceDesc(&ddsdMirror));
switch (dwMirrorBitDepth) {
case 16:
m_ddsdM16 = ddsdMirror;
m_lpDDM16 = m_lpDDMirror;
break;
case 32:
m_ddsdM32 = ddsdMirror;
m_lpDDM32 = m_lpDDMirror;
break;
}
} __finally {}
}
if (hr == DD_OK) {
__try {
RECT rc = {0, 0, ddsd.dwWidth, ddsd.dwHeight};
CHECK_HR(hr = m_lpDDMirror->Blt(&rc, lpDDS, &rc, DDBLT_WAIT, NULL));
ddsd = ddsdMirror;
} __finally {}
}
return hr;
}
public:
//----------------------------------------------------------------------------
// Constructor
//----------------------------------------------------------------------------
CAlphaBlt(LPDIRECTDRAWSURFACE7 lpDDSDst, HRESULT* phr) :
m_pDD(NULL),
m_pD3D(NULL),
m_pD3DDevice(NULL),
m_lpDDBackBuffer(NULL),
m_lpDDMirror(NULL),
m_lpDDM32(NULL),
m_lpDDM16(NULL),
m_ptxtrMenu( NULL),
m_pFont(NULL),
m_fPowerOf2(false),
m_fSquare(false),
m_bNeedToRestoreMenu(false)
{
ZeroMemory(&m_ddsdM32, sizeof(m_ddsdM32));
ZeroMemory(&m_ddsdM16, sizeof(m_ddsdM16));
HRESULT hr;
hr = lpDDSDst->GetDDInterface((LPVOID *)&m_pDD);
if (FAILED(hr)) {
m_pDD = NULL;
*phr = hr;
}
if (SUCCEEDED(hr)) {
hr = m_pDD->QueryInterface(IID_IDirect3D7, (LPVOID *)&m_pD3D);
if (FAILED(hr)) {
m_pD3D = NULL;
*phr = hr;
}
}
if (SUCCEEDED(hr)) {
hr = m_pD3D->CreateDevice(IID_IDirect3DHALDevice,
lpDDSDst,
&m_pD3DDevice);
if (FAILED(hr)) {
m_pD3DDevice = NULL;
*phr = hr;
}
else {
m_lpDDBackBuffer = lpDDSDst;
m_lpDDBackBuffer->AddRef();
}
}
if (SUCCEEDED(hr)) {
D3DDEVICEDESC7 ddDesc;
if (DD_OK == m_pD3DDevice->GetCaps(&ddDesc)) {
if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) {
m_fPowerOf2 = true;
}
if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) {
m_fSquare = true;
}
}
else {
*phr = hr;
}
}
// here, so far we have D3Device, let's Restore texture surface
// it actually loads the bitmap from the resource onto a texture surface
m_ptxtrMenu = new TextureContainer(
"IDB_MENU", 0, 0, IDB_MENU);
if( m_ptxtrMenu)
{
hr = m_ptxtrMenu->LoadImageData();
if( m_ptxtrMenu->m_hbmBitmap )
{
BITMAP bm;
GetObject( m_ptxtrMenu->m_hbmBitmap, sizeof(BITMAP), &bm );
m_ptxtrMenu->m_dwWidth = (DWORD)bm.bmWidth;
m_ptxtrMenu->m_dwHeight = (DWORD)bm.bmHeight;
m_ptxtrMenu->m_dwBPP = (DWORD)bm.bmBitsPixel;
}
hr = m_ptxtrMenu->Restore(m_pD3DDevice);
if( FAILED(hr))
{
delete m_ptxtrMenu;
m_ptxtrMenu = NULL;
}
}
// load the font
m_pFont = new CD3DFont( TEXT("Comic Sans MS"),18,0);
if( m_pFont )
{
m_pFont->InitDeviceObjects( m_pDD, m_pD3DDevice);
}
// setup menu primitive
pVMenu[0].x = 0.f;
pVMenu[0].y = 0.f;
pVMenu[0].z = 0.0f;
pVMenu[0].rhw = 2.0f;
pVMenu[0].clr = RGBA_MAKE(0xff, 0xff, 0xff, 0xff);
pVMenu[1].x = 60.f;
pVMenu[1].y = 0.f;
pVMenu[1].z = 0.0f;
pVMenu[1].rhw = 2.0f;
pVMenu[1].clr = RGBA_MAKE(0xff, 0xff, 0xff, 0xff);
pVMenu[2].x = 0.f;
pVMenu[2].y = 480.f;
pVMenu[2].z = 0.0f;
pVMenu[2].rhw = 2.0f;
pVMenu[2].clr = RGBA_MAKE(0xff, 0xff, 0xff, 0xff);
pVMenu[3].x = 60.f;
pVMenu[3].y = 480.f;
pVMenu[3].z = 0.0f;
pVMenu[3].rhw = 2.0f;
pVMenu[3].clr = RGBA_MAKE(0xff, 0xff, 0xff, 0xff);
//
// Setup the SRC info
//
pVMenu[0].tu = 0.f;
pVMenu[0].tv = 0.f;
pVMenu[1].tu = 1.f;
pVMenu[1].tv = 0.f;
pVMenu[2].tu = 0.f;
pVMenu[2].tv = 1.f;
pVMenu[3].tu = 1.f;
pVMenu[3].tv = 1.f;
}
//----------------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------------
~CAlphaBlt()
{
if( m_ptxtrMenu )
{
delete m_ptxtrMenu;
m_ptxtrMenu = NULL;
}
if( m_pFont )
{
delete m_pFont;
m_pFont = NULL;
}
RELEASE(m_lpDDBackBuffer);
RELEASE(m_lpDDM32);
RELEASE(m_lpDDM16);
RELEASE(m_pD3DDevice);
RELEASE(m_pD3D);
RELEASE(m_pDD);
}
//----------------------------------------------------------------------------
// GetMenuTexture
//
// returns pointer to texture's DD surface or NULL otherwise
//----------------------------------------------------------------------------
LPDIRECTDRAWSURFACE7 GetMenuTexture()
{
if( m_ptxtrMenu && m_ptxtrMenu->m_pddsSurface )
{
return (m_ptxtrMenu->m_pddsSurface);
}
return NULL;
}
//----------------------------------------------------------------------------
// SetMenuRestoreFlag
//
// sets m_bNeedToRestoreMenu = true; (called from CMpegMovie::RestoreDDRawSurfaces() )
//----------------------------------------------------------------------------
void SetMenuRestoreFlag()
{
m_bNeedToRestoreMenu = true;
}
//----------------------------------------------------------------------------
// GetFont
//----------------------------------------------------------------------------
CD3DFont * GetFont()
{
return m_pFont;
}
//----------------------------------------------------------------------------
// PrepareVerticesRotate
//
// This is the 'main' transformation function for foration effect.
// It generates rotation angles from 'time' variable that is just
// a static counter of images from CMpegMovie:PresentImage function
//
// Parameters:
// lpDst - destination rectangle
// lpSrc - source rectangle
// alpha - alpha level for the surface
// fWid - width of the surface obtained by CMpegMovie:PresentImage
// fHgt - height of the surface obtained by CMpegMovie:PresentImage
//----------------------------------------------------------------------------
void PrepareVerticesRotate( RECT* lpDst, RECT* lpSrc, BYTE alpha,
float fWid, float fHgt)
{
float RotRadZ = 0.f;
float RotRadY = 0.f;
//
// Setup the DST info
//
pVertices[0].x = (float)lpDst->left;
pVertices[0].y = (float)lpDst->top;
pVertices[0].z = 0.5f;
pVertices[0].rhw = 2.0f;
pVertices[0].clr = RGBA_MAKE(0xff, 0xff, 0xff, alpha);
pVertices[1].x = (float)lpDst->right;
pVertices[1].y = (float)lpDst->top;
pVertices[1].z = 0.5f;
pVertices[1].rhw = 2.0f;
pVertices[1].clr = RGBA_MAKE(0xff, 0xff, 0xff, alpha);
pVertices[2].x = (float)lpDst->left;
pVertices[2].y = (float)lpDst->bottom;
pVertices[2].z = 0.5f;
pVertices[2].rhw = 2.0f;
pVertices[2].clr = RGBA_MAKE(0xff, 0xff, 0xff, alpha);
pVertices[3].x = (float)lpDst->right;
pVertices[3].y = (float)lpDst->bottom;
pVertices[3].z = 0.5f;
pVertices[3].rhw = 2.0f;
pVertices[3].clr = RGBA_MAKE(0xff, 0xff, 0xff, alpha);
//
// Setup the SRC info
//
pVertices[0].tu = ((float)lpSrc->left) / fWid;
pVertices[0].tv = ((float)lpSrc->top) / fHgt;
pVertices[1].tu = ((float)lpSrc->right) / fWid;
pVertices[1].tv = ((float)lpSrc->top) / fHgt;
pVertices[2].tu = ((float)lpSrc->left) / fWid;
pVertices[2].tv = ((float)lpSrc->bottom) / fHgt;
pVertices[3].tu = ((float)lpSrc->right) / fWid;
pVertices[3].tv = ((float)lpSrc->bottom) / fHgt;
// g_ss.nGradZ is an angle in grades, so calculate radians
RotRadZ = (float) (g_ss.nGradZ++) * pi / 180.f;
if( !g_ss.bRotateZ)
{
g_ss.nGradZ--;
}
RotRadY = (float) (g_ss.nGradY++) * pi / 180.f;
if( !g_ss.bRotateY)
{
g_ss.nGradY--;
}
// to avoid stack overflow, limit counters withing 360 grades
if( g_ss.nGradZ > 360)
{
g_ss.nGradZ = 0;
}
if( g_ss.nGradY > 360)
{
g_ss.nGradY = 0;
}
// and finally rotate the primitive pVertices
// NOTE that rotation center is hardcoded for the case
// 640x480 display mode
Rotate(RotRadZ, RotRadY, pVertices, 4, 320.f, 240.f);
}
//----------------------------------------------------------------------------
// PrepareVerticesTwist
//
// This is the 'main' transformation function for "twist" effect.
// It generates transformation parameters 'time' variable that is just
// a static counter of images from CMpegMovie:PresentImage function
//
// Parameters:
// lpDst - destination rectangle
// lpSrc - source rectangle
// alpha - alpha level for the surface
// fWid - width of the surface obtained by CMpegMovie:PresentImage
// fHgt - height of the surface obtained by CMpegMovie:PresentImage
//
// Other: put your own effects here
// The effect I use is as following:
// (a) move picture down to create 'slipping' effect
// (b) srink lower part of the picture (parameter c applied to each verticle
// so that it would look like a wine glass stem (cosine is what we need)
// Shrinking coefficient depends on Y-coordinate of a verticle
// (c) twist lower part of the picture around Y axis, angle depends on
// Y-coordinate of a verticle
//----------------------------------------------------------------------------
void PrepareVerticesTwist( RECT* lpDst, RECT* lpSrc, BYTE alpha,
float fW, float fH)
{
CAlphaBlt::Vertex * V = pVComplex;
float W = (float)(lpDst->right - lpDst->left);
float H = (float)(lpDst->bottom - lpDst->top);
float sW = (float)(lpSrc->right - lpSrc->left)/fW;
float sH = (float)(lpSrc->bottom - lpSrc->top);
float Ht = 480 - H;
float c;
float radY = 0.f;
float radX = pi/4.f;
float x;
double costh;
double sinth;
D3DXMATRIX mtrPrs;
D3DXMATRIX mtrOrg;
D3DXMATRIX mtrRes;
int N = COMPLVERTSIZE/2;
g_ss.nDy = g_ss.nDy + 3;
if( g_ss.nDy > 480 )
{
g_ss.nDy = 0;
}
for( int i=0; i<COMPLVERTSIZE; i=i+2)
{
V[i ].x = (float)(lpDst->left);
V[i+1].x = (float)(lpDst->right);
V[i ].y = V[i+1].y = (float)(i * H/(N-1)) + g_ss.nDy;
V[i ].z = V[i+1].z = 0.5f;
V[i ].rhw = V[i+1].rhw = 2.f;
V[i ].clr = V[i+1].clr = RGBA_MAKE(0xff, 0xff, 0xff, alpha);
V[i ].tu = ((float)lpSrc->left) / fW;
V[i+1].tu = ((float)lpSrc->right) / fW;
V[i ].tv = V[i+1].tv = (float)(lpSrc->top + sH * (float)i/(N-1.f)/2.f)/fH;
if( V[i].y >= H )
{
c = (float)( W * (1. + cos(pi * (480. - V[i].y)/Ht)) / 4.);
//c *= 0.25f;
V[i ].x += c;
V[i+1].x -= c;
radY = pi * ( V[i].y - H ) / 2.f / Ht;
costh = cos(radY);
sinth = sin(radY);
x = V[i].x - 320.f;
V[i].x = (float)(costh * x - sinth * V[i].z) + 320.f;
V[i].z = (float)(sinth * x + costh * V[i].z);
x = V[i+1].x - 320.f;
V[i+1].x = (float)(costh * x - sinth * V[i+1].z) + 320.f;
V[i+1].z = (float)(sinth * x + costh * V[i+1].z);
} // if
}// for i
// now let's implement projection
D3DXMatrixPerspectiveFov( &mtrPrs, pi/2.f, 1.1f, 0.f, 1.f);
for( i=0; i<COMPLVERTSIZE; i = i+4)
{
mtrOrg.m[0][0] = V[i].x;
mtrOrg.m[1][0] = V[i].y;
mtrOrg.m[2][0] = V[i].z;
mtrOrg.m[3][0] = 0.f;
mtrOrg.m[0][1] = V[i+1].x;
mtrOrg.m[1][1] = V[i+1].y;
mtrOrg.m[2][1] = V[i+1].z;
mtrOrg.m[3][1] = 0.f;
mtrOrg.m[0][2] = V[i+2].x;
mtrOrg.m[1][2] = V[i+2].y;
mtrOrg.m[2][2] = V[i+2].z;
mtrOrg.m[3][2] = 0.f;
mtrOrg.m[0][3] = V[i+3].x;
mtrOrg.m[1][3] = V[i+3].y;
mtrOrg.m[2][3] = V[i+3].z;
mtrOrg.m[3][3] = 0.f;
D3DXMatrixMultiply( &mtrRes, &mtrPrs, &mtrOrg);
V[i ].x = mtrRes.m[0][0];
V[i ].y = mtrRes.m[1][0];
V[i ].z = mtrRes.m[2][0];
V[i+1].x = mtrRes.m[0][1];
V[i+1].y = mtrRes.m[1][1];
V[i+1].z = mtrRes.m[2][1];
V[i+2].x = mtrRes.m[0][2];
V[i+2].y = mtrRes.m[1][2];
V[i+2].z = mtrRes.m[2][2];
V[i+3].x = mtrRes.m[0][3];
V[i+3].y = mtrRes.m[1][3];
V[i+3].z = mtrRes.m[2][3];
}// for
return;
}
//----------------------------------------------------------------------------
// AlphaBlt
//
// This function receives LPDIRECTDRAWSURFACE7 from ImagePresenter, calls
// transformation functions to provide visual effects, sets the scene and
// renders primitives
//
// Parameters:
// lpDst -- destination rectangle
// lpDDSSrc -- surface obtained by ImagePresenter
// lpSrc -- source rectangle
// bAlpha -- alpha value for the surface
//----------------------------------------------------------------------------
HRESULT
AlphaBlt(RECT* lpDst,
LPDIRECTDRAWSURFACE7 lpDDSSrc,
RECT* lpSrc,
BYTE bAlpha
)
{
HRESULT hr=S_OK;
DDSURFACEDESC2 ddsd;
int nVertSize = 0;
CAlphaBlt::Vertex * pV = NULL;
__try {
INITDDSTRUCT(ddsd);
CHECK_HR(hr = lpDDSSrc->GetSurfaceDesc(&ddsd));
if (!IsSurfaceBlendable(ddsd, bAlpha)) {
CHECK_HR(hr = MirrorSourceSurface(lpDDSSrc, ddsd));
lpDDSSrc = m_lpDDMirror;
}
float fWid = (float)ddsd.dwWidth;
float fHgt = (float)ddsd.dwHeight;
if( g_ss.bShowTwist )
{
nVertSize = COMPLVERTSIZE;
PrepareVerticesTwist(lpDst, lpSrc, bAlpha, fWid, fHgt);
pV = pVComplex;
}
else
{
nVertSize = 4;
PrepareVerticesRotate(lpDst, lpSrc, bAlpha, fWid, fHgt);
pV = pVertices;
}
BYTE alpha = bAlpha;
m_pD3DDevice->SetTexture(0, lpDDSSrc);
// if menu is defined, set it
m_pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, TRUE);
m_pD3DDevice->SetRenderState(D3DRENDERSTATE_BLENDENABLE, TRUE);
m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_ANISOTROPIC);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_ANISOTROPIC);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTFP_LINEAR);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
//
// Do the alpha BLT
//
CHECK_HR(hr = m_pD3DDevice->BeginScene());
CHECK_HR(hr = m_pD3DDevice->Clear(0,NULL,D3DCLEAR_TARGET,0,0.5,0));
CHECK_HR(hr = m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1,
pV, nVertSize, D3DDP_WAIT));
// now, draw menu over the video
// if user switched modes, menu texture may be lost; then restore
if( m_bNeedToRestoreMenu )
{
DDSURFACEDESC2 ddsd;
ZeroMemory( &ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_ALL;
m_pDD->GetDisplayMode( &ddsd);
// if we try to restore surface in a different display mode, we will fail
// so make the check first
if( ddsd.dwWidth == SCRN_WIDTH &&
ddsd.dwHeight == SCRN_HEIGHT &&
ddsd.ddpfPixelFormat.dwRGBBitCount == SCRN_BITDEPTH )
{
hr = GetMenuTexture()->Restore();
if( FAILED(hr))
{
OutputDebugString("ERROR: Failed to restore menu texture");
}
else
{
// surface restored, but its image lost; reload
if( m_ptxtrMenu)
{
hr = m_ptxtrMenu->LoadImageData();
if( FAILED(hr))
{
OutputDebugString("Failed to load the image from resource\n");
}
if( m_ptxtrMenu->m_hbmBitmap )
{
BITMAP bm;
GetObject( m_ptxtrMenu->m_hbmBitmap, sizeof(BITMAP), &bm );
m_ptxtrMenu->m_dwWidth = (DWORD)bm.bmWidth;
m_ptxtrMenu->m_dwHeight = (DWORD)bm.bmHeight;
m_ptxtrMenu->m_dwBPP = (DWORD)bm.bmBitsPixel;
}
hr = m_ptxtrMenu->Restore(m_pD3DDevice);
if( FAILED(hr))
{
delete m_ptxtrMenu;
m_ptxtrMenu = NULL;
}
}
m_bNeedToRestoreMenu = false;
}
}
else
{
OutputDebugString("Failed to restore menu texture");
}
}
m_pD3DDevice->SetTexture(0, m_ptxtrMenu->m_pddsSurface);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_ANISOTROPIC);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_ANISOTROPIC);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTFP_LINEAR);
//
m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
CHECK_HR(hr = m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1,
pVMenu, 4, D3DDP_WAIT));
m_pD3DDevice->SetTexture(0, NULL);
// and if necessary, draw the dext over the menu
if( g_ss.bShowHelp )
{
HRESULT hr = m_pFont->DrawText((float)g_ss.nXHelp, (float)g_ss.nYHelp,
RGBA_MAKE(0xFF, 0xFF, 0x00, 0xFF),
g_ss.achHelp );
}
if( g_ss.bShowStatistics )
{
m_pFont->DrawText( 420, 0,
RGBA_MAKE(0x00, 0xFF, 0x00, 0xFF),
g_ss.achFPS );
}
CHECK_HR(hr = m_pD3DDevice->EndScene());
} __finally {
m_pD3DDevice->SetTexture(0, NULL);
}
return hr;
}
//----------------------------------------------------------------------------
// TextureSquare
// true if texture is square
//----------------------------------------------------------------------------
bool TextureSquare() {
return m_fSquare;
}
//----------------------------------------------------------------------------
// TexturePower2
// true if texture size is of a power of 2
//----------------------------------------------------------------------------
bool TexturePower2() {
return m_fPowerOf2;
}
};