// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // File : WOWvx.cpp // Purpose : The class that controls a 3D display (CWOWvx) // Path : // Created : 17.6.7 // Author : Phil Palmer (http://www.programmerart.org) // Info : // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #include "Global.h" // PP(2.3.7): A header that will be included by most source files #include "Main.h" // PP(2.3.7): Main stuff, such as the CNoctambuleApp class #include "WOWvx.h" // PP(17.6.7): The class that controls a 3D display (CWOWvx) #include "RenderTarget.h" // PP(3.3.7): Render target wrapper class (CRenderTarget) #include "renderables.h" // PP(3.3.7): Material Management classes for EffectStateManager 'StateManager' Sample #include "Util.h" // PP(3.3.7): Miscellaneous handy stuff #include "LockableTexture.h"// PP(13.9.7): Lockable texture resource class (CLockableTexture) // PP(6.5.8): TEMP! #include "Player.h" // PP(6.5.8): The player class (CPlayer) // ***********************> defines <*********************** // ***********************> todo <*********************** // ***********************> functions <*********************** // PP(9.3.7): MOVEME static void DrawWOWvxHeader(void) { D3DSURFACE_DESC dtdsdRT; PDIRECT3DSURFACE9 pSurfRT; HRESULT hr; // Acquire output render target width and height DEVICE->GetRenderTarget(0, &pSurfRT); pSurfRT->GetDesc(&dtdsdRT); pSurfRT->Release(); // Ensure that we're directly mapping texels to pixels by offset by 0.5 // For more info see the DirectX doc page titled "Directly Mapping Texels to Pixels" /* FLOAT fWidth5 = (FLOAT)(dtdsdRT.Width/2) - 0.5f; FLOAT fHeight5 = (FLOAT)dtdsdRT.Height - 0.5f; /*/ FLOAT fWidth5 = (FLOAT)512 - 0.5f; FLOAT fHeight5 = (FLOAT)1 - 0.5f; //*/ // Draw the quad ScreenVertex svQuad[4]; svQuad[0].p = D3DXVECTOR4(-0.5f, -0.5f, 0.5f, 1.0f); svQuad[1].p = D3DXVECTOR4(fWidth5, -0.5f, 0.5f, 1.0f); svQuad[2].p = D3DXVECTOR4(-0.5f, fHeight5, 0.5f, 1.0f); svQuad[3].p = D3DXVECTOR4(fWidth5, fHeight5, 0.5f, 1.0f); svQuad[0].t = D3DXVECTOR2(0, 0); svQuad[1].t = D3DXVECTOR2(1, 0); svQuad[2].t = D3DXVECTOR2(0, 1); svQuad[3].t = D3DXVECTOR2(1, 1); DEVICE->SetRenderState( D3DRS_LIGHTING, FALSE ); DEVICE->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); DEVICE->SetFVF(ScreenVertex::FVF); V( DEVICE->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, svQuad, sizeof(ScreenVertex)) ); DEVICE->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); } // ***********************> methods <*********************** // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Function : CWOWvx::CWOWvx // Purpose : constructor // Parameter : [void] // Returns : [] // Info : // Author : PP(17.6.7) // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CWOWvx::CWOWvx(void) { this->flags.allFlags = 0; this->flags.codeDirty = 1; this->flags.textureDirty = 1; this->pHeaderTexture = NEW CLockableTexture("WOWvx", 512,1); memset(this->headerCode, 0, WOWVX_NUM_BYTES_IN_HEADER_CODE); } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Function : CWOWvx::~CWOWvx // Purpose : destructor // Parameter : [void] // Returns : [] // Info : // Author : PP(17.6.7) // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CWOWvx::~CWOWvx(void) { // PP(13.9.7): SAFE_DELETE(this->pHeaderTexture); } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Function : CWOWvx::ApplyOptions // Purpose : Apply options // Parameter : [void] // Returns : [void] // Info : // Author : PP(18.9.7) // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void CWOWvx::ApplyOptions(void) { // PP(18.9.7): generate the header texture this->GenerateHeaderCode(); this->flags.codeDirty = false; // PP(18.9.7): need to update the texture before drawing this->flags.textureDirty = true; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Function : CWOWvx::Render // Purpose : render the 3D display effect // Parameter : [void] // Returns : [] // Info : // Author : PP(17.6.7) // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void CWOWvx::Render(void) { HRESULT hr; ID3DXEffect* pEffect = g_game.pShaderEffects[ESHADEREFFECT_WOWVX]->GetPointer(); if( this->flags.textureDirty ) { assert( !this->flags.codeDirty ); this->GenerateHeaderTexture(); this->flags.textureDirty = false; } V( pEffect->SetTexture("position_Tex", g_game.pRenderTargets[ERENDERTARGET_POSITION].pTexture) ); const VEC3* pVec3 = g_viewInfo.pMainViewpoint; D3DXVECTOR4 vec4 = D3DXVECTOR4(pVec3->x, pVec3->y, pVec3->z, 1.f); V( pEffect->SetVector("cMainViewpoint", &vec4) ); pVec3 = g_viewInfo.pPosition; vec4 = D3DXVECTOR4(pVec3->x, pVec3->y, pVec3->z, 1.f); V( pEffect->SetVector("vp", &vec4) ); pVec3 = g_viewInfo.pForeVec; vec4 = D3DXVECTOR4(pVec3->x, pVec3->y, pVec3->z, 1.f); V( pEffect->SetVector("cViewVec", &vec4) ); V( pEffect->SetFloat("cNearDist", g_game.options.stereoscopy.WOWvx.nearDist) ); V( pEffect->SetFloat("cFarDist", g_game.options.stereoscopy.WOWvx.farDist) ); V( pEffect->Begin( NULL, 0 ) ); V( pEffect->BeginPass(0) ); UtilDrawHalfScreenQuad( 0.0f, 0.0f, 1.0f, 1.0f, EHALFSCREENQUADPOSITION_RIGHT ); V( pEffect->EndPass() ); // HEADER... V( pEffect->SetTexture("header_Tex", this->pHeaderTexture->GetPointer()) ); /* V( DEVICE->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT ) ); V( DEVICE->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT ) ); V( DEVICE->SetSamplerState( 1, D3DSAMP_MAGFILTER, D3DTEXF_POINT ) ); V( DEVICE->SetSamplerState( 1, D3DSAMP_MINFILTER, D3DTEXF_POINT ) ); V( DEVICE->SetSamplerState( 2, D3DSAMP_MAGFILTER, D3DTEXF_POINT ) ); V( DEVICE->SetSamplerState( 2, D3DSAMP_MINFILTER, D3DTEXF_POINT ) ); */ V( pEffect->BeginPass(1) ); DrawWOWvxHeader(); V( pEffect->EndPass() ); // v16 BANNER... if( g_game.options.debug.drawBanner && PLAYER->attractMode ) { V( pEffect->SetTexture("banner_Tex", g_game.pTextures[ETEXTURE_BANNER]->GetPointer()) ); V( pEffect->BeginPass(2) ); UtilDrawBannerQuad(); V( pEffect->EndPass() ); } V( pEffect->End() ); } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Function : CWOWvx::GenerateHeaderCode // Purpose : Generate the header code // Parameter : [void] // Returns : [void] // Info : // Author : PP(18.9.7) // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void CWOWvx::GenerateHeaderCode(void) { UCHAR* pCodeByte; UINT edc; // PP(14.9.7): GENERATE THE HEADER CODE... pCodeByte = this->headerCode; // PP(14.9.7): Header_ID *pCodeByte = 0xF1; pCodeByte++; // PP(14.9.7): Hdr_Content_type *pCodeByte = (UCHAR) g_game.options.stereoscopy.WOWvx.contentType; pCodeByte++; // PP(14.9.7): Hdr_Factor *pCodeByte = g_game.options.stereoscopy.WOWvx.factor; pCodeByte++; // PP(14.9.7): Hdr_Offset_CC *pCodeByte = g_game.options.stereoscopy.WOWvx.offset; pCodeByte++; // PP(14.9.7): (leftmost 2 bits) Hdr_Factor_select, Hdr_Offset_CC_select // PP(14.9.7): (remaining 6 bits) Reserved - set to 0 *pCodeByte = (UCHAR(g_game.options.stereoscopy.WOWvx.factorSelect) << 7) |(UCHAR(g_game.options.stereoscopy.WOWvx.factorSelect) << 6); pCodeByte++; // PP(14.9.7): Reserved - set to 0 *pCodeByte = 0; pCodeByte++; // PP(14.9.7): EDC edc = UtilCRC( (char*)this->headerCode, WOWVX_NUM_BYTES_IN_HEADER_CODE-sizeof(edc) ); // PP(18.9.7): need to reverse thee EDC bits for some reason for(int i=0; i<4; i++) *(pCodeByte++) = *( ((UCHAR*)&edc) + 4-1-i ); // PP(14.9.7): check the code length is correct assert(pCodeByte-this->headerCode == WOWVX_NUM_BYTES_IN_HEADER_CODE); } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Function : CWOWvx::GenerateHeaderTexture // Purpose : Generate the header texture // Parameter : [void] // Returns : [void] // Info : **** DON'T CALL THIS EVERY FRAME!!!! **** // Author : PP(13.9.7) // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void CWOWvx::GenerateHeaderTexture(void) { D3DLOCKED_RECT lockedRect; UCHAR* pTextureByte; UCHAR* pCodeByte; int codeBitIndex; int codeBytesRemaining; // PP(14.9.7): WRITE THE HEADER CODE TO THE TEXTURE... this->pHeaderTexture->Lock(&lockedRect); pCodeByte = this->headerCode; pTextureByte = (UCHAR*)lockedRect.pBits; codeBitIndex = 7;// PP(14.9.7): most significant bit codeBytesRemaining = WOWVX_NUM_BYTES_IN_HEADER_CODE; for(int textureByteIndex = 0; textureByteIndex < lockedRect.Pitch; textureByteIndex += 4*2) { if( codeBytesRemaining == 0 ) { *(pTextureByte++) = 0;// b *(pTextureByte++) = 0;// g *(pTextureByte++) = 0;// r *(pTextureByte++) = 0;// a *(pTextureByte++) = 0;// b *(pTextureByte++) = 0;// g *(pTextureByte++) = 0;// r *(pTextureByte++) = 0;// a continue; } // PP(14.9.7): write code to even-numbered pixels *(pTextureByte++) = ((*pCodeByte) & (1<headerCode == WOWVX_NUM_BYTES_IN_HEADER_CODE); this->pHeaderTexture->Unlock(); }