⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shader_keyframehermite.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
字号:
/*********************************************************************NVMH2****
Path:  E:\devrel\NV_SDK_4\DX8\NVEffectsBrowser\Effects\Keyframe
File:  shader_KeyframeHermite.cpp

Copyright (C) 1999, 2000 NVIDIA Corporation
This file is provided without support, instruction, or implied warranty of any
kind.  NVIDIA makes no guarantee of its fitness for a particular purpose and is
not liable under any circumstances for any damages or loss whatsoever arising
from the use or inability to use this file or items derived from it.

Comments:


******************************************************************************/


#include "eb_effect.h"
#include "shader_KeyframeHermite.h"
#include "nvinc.h"
#include "MouseUI.h"
#include "KeyframeCommon.h"
#include "Constants.h"

#include <mmsystem.h>

using namespace std;

CShaderKeyframeHermite::CShaderKeyframeHermite()
	: m_pVertexBuffers(NULL),
	m_pIndexBuffer(NULL),
	m_pTexture(NULL),
	m_dwCurrentShader(0),
	m_pUI(NULL),
	m_frame0(0),
	m_frame1(1),
	m_frame2(2),
	m_frame3(3),
	m_bWireframe(false)
{
	m_strEffectLocation = "Vertex Shaders\\Animation";
	m_strEffectName = "Hermite Keyframe Interpolation";
	m_strEffectVertexShader = GetFilePath("KeyframeHermite.nvv");
	m_strEffectPixelShader = "";
	
	m_md2Model = NULL;
}

void CShaderKeyframeHermite::UpdateProperties()
{
	EBEffect::UpdateProperties();

	AddProperty(new EBProperty("Wireframe", OBJECT_MEMBER(m_bWireframe), EBTYPE_BOOL_PROP));

	m_pVertexShaderEnum->AddEnumerant(new EBEnumValue(m_pVertexShaderEnum, "Keyframing", GetFilePath("KeyframeHermite.nvv"), EBTYPE_STRING_PROP));
}


CShaderKeyframeHermite::~CShaderKeyframeHermite()
{
	Free();	
}

void CShaderKeyframeHermite::SetupMatrices(const Extents& e)
{
	float dx = e.maxX - e.minX;
	float dy = e.maxY - e.minY;
	float dz = e.maxZ - e.minZ;
	
	float midX = (dx / 2) + e.minX;
	float midY = (dy / 2) + e.minY;
	float midZ = (dz / 2) + e.minZ;
	
	float maxExtent = (dx > dy) ? dx : dy;
	maxExtent = (maxExtent > dz) ? maxExtent : dz;
	
	D3DXMATRIX world;
	
	D3DXMatrixIdentity(&world);
	
	D3DXVECTOR3 lookAt;
	D3DXVECTOR3 up;
	D3DXVECTOR3 eye;
	
	eye.x    = midX; eye.y    = midY; eye.z    = e.minZ - (1.5f * maxExtent);
	lookAt.x = midX; lookAt.y = midY; lookAt.z = 0.0f;
	up.x     = 0.0f; up.y     = 1.0f; up.z     = 0.0f;
	
	//set view
	D3DXMatrixLookAtLH(&m_view, &eye, &lookAt, &up);
	
	D3DXMatrixPerspectiveFovLH(&m_proj, D3DXToRadian(60.0f), 1, 1.0f, 500.0f);

	D3DXMATRIX worldViewProj;
	D3DXMatrixMultiply(&worldViewProj, &world, &m_view);
	D3DXMatrixMultiply(&worldViewProj, &worldViewProj, &m_proj);

	D3DXMatrixTranspose(&worldViewProj, &worldViewProj);

	m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &worldViewProj, 4);
}

void CShaderKeyframeHermite::SetMatricesBasedOnInput()
{
	D3DXMATRIX compoundMatrix;
	D3DXMATRIX worldMatrix;

	D3DXMatrixMultiply(&compoundMatrix, &m_pUI->GetRotationMatrix(), &m_pUI->GetTranslationMatrix());
	
	D3DXMatrixTranspose(&worldMatrix, &compoundMatrix);

	m_pD3DDev->SetVertexShaderConstant(CV_WORLD_0, &worldMatrix, 4);

	D3DXMatrixMultiply(&compoundMatrix, &compoundMatrix, &m_view);

	D3DXMatrixMultiply(&compoundMatrix, &compoundMatrix, &m_proj);

	D3DXMatrixTranspose(&compoundMatrix, &compoundMatrix);

	m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &compoundMatrix, 4);
}


void CShaderKeyframeHermite::SetExtents(const KeyframeVertex& vertex, Extents& e)
{
	if(vertex.Position.x > e.maxX)
		e.maxX = vertex.Position.x;
	if(vertex.Position.y > e.maxY)
		e.maxY = vertex.Position.y;
	if(vertex.Position.z > e.maxZ)
		e.maxZ = vertex.Position.z;
	if(vertex.Position.x < e.minX)
		e.minX = vertex.Position.x;
	if(vertex.Position.y < e.minY)
		e.minY = vertex.Position.y;
	if(vertex.Position.z < e.minZ)
		e.minZ = vertex.Position.z;
}


HRESULT CShaderKeyframeHermite::Initialize(LPDIRECT3DDEVICE8 pDev)
{
	HRESULT hr;

	m_pD3DDev = pDev;
	pDev->AddRef();

	//initialize mouse UI
	RECT rect;
	rect.left = rect.top = 0;
	D3DVIEWPORT8 viewport;
	m_pD3DDev->GetViewport(&viewport);
	rect.bottom = viewport.Height;
	rect.right  = viewport.Width;
	m_pUI = new MouseUI((const RECT)rect);

	//we need one stream per keyframe we're blending with
	// spline interpolation requires 4 keyframes to blend between, so we have 4 streams
	vector<DWORD> Declaration;
	Declaration.push_back(D3DVSD_STREAM(0));
	Declaration.push_back(D3DVSD_REG(0, D3DVSDT_FLOAT3));
	Declaration.push_back(D3DVSD_REG(1, D3DVSDT_FLOAT3));
	Declaration.push_back(D3DVSD_REG(2, D3DVSDT_FLOAT2));
	Declaration.push_back(D3DVSD_STREAM(1));
	Declaration.push_back(D3DVSD_REG(3, D3DVSDT_FLOAT3));
	Declaration.push_back(D3DVSD_REG(4, D3DVSDT_FLOAT3));
	Declaration.push_back(D3DVSD_REG(5, D3DVSDT_FLOAT2));
	Declaration.push_back(D3DVSD_STREAM(2));
	Declaration.push_back(D3DVSD_REG(6, D3DVSDT_FLOAT3));
	Declaration.push_back(D3DVSD_REG(7, D3DVSDT_FLOAT3));
	Declaration.push_back(D3DVSD_REG(8, D3DVSDT_FLOAT2));
	Declaration.push_back(D3DVSD_STREAM(3));
	Declaration.push_back(D3DVSD_REG(9, D3DVSDT_FLOAT3));
	Declaration.push_back(D3DVSD_REG(10, D3DVSDT_FLOAT3));
	Declaration.push_back(D3DVSD_REG(11, D3DVSDT_FLOAT2));
	
	Declaration.push_back(D3DVSD_END());

	hr = LoadAndCreateShader(GetFilePath("KeyframeHermite.vso"), &Declaration[0], 0, SHADERTYPE_VERTEX, &m_dwCurrentShader);
	if (FAILED(hr))
		return hr;

    m_md2Model = md2ReadModel(GetFilePath(FILENAME).c_str());

	m_numFrames = m_md2Model->header.numFrames - START_FRAME;
	if(m_numFrames % DISTANCE_BETWEEN_FRAMES != 0)
		m_numFrames = (m_numFrames / DISTANCE_BETWEEN_FRAMES) + 1;
	else
		m_numFrames = (m_numFrames / DISTANCE_BETWEEN_FRAMES);

	m_pVertexBuffers = new LPDIRECT3DVERTEXBUFFER8[m_numFrames];
	
	//extents that define the bounding box of the model
	Extents e;
	e.maxX = e.maxY = e.maxZ = -999999;
	e.minX = e.minY = e.minZ = 999999;

	//NON-INDEXED
	for(int i = 0; i < m_md2Model->header.numFrames; i++)
	{
		if( (i >= START_FRAME) && ((i % DISTANCE_BETWEEN_FRAMES) == 0) )
		{
			int bufferCtr = (i - START_FRAME) / DISTANCE_BETWEEN_FRAMES;

			//create vb for this keyframe
			hr = m_pD3DDev->CreateVertexBuffer( m_md2Model->header.numTriangles * 3 * sizeof(KeyframeVertex), D3DUSAGE_WRITEONLY, 0, 
				D3DPOOL_MANAGED, &m_pVertexBuffers[bufferCtr]);
			if (FAILED(hr))
				return hr;
			
			//lock and load
			KeyframeVertex* pBuff;
			hr = m_pVertexBuffers[bufferCtr]->Lock(0, sizeof(KeyframeVertex) * m_md2Model->header.numTriangles * 3, (BYTE**)&pBuff, 0);
			
			int vertCtr = 0;

			for(int j = 0; j < m_md2Model->header.numTriangles; j++)
			{
				//three vertices per triangle

				//vertex 1
				short currVertIndex = m_md2Model->triangles[j].vertexIndices[0];
				short currTexIndex = m_md2Model->triangles[j].textureIndices[0];
				pBuff[vertCtr].Position.x = m_md2Model->frames[i].vertices[currVertIndex].vertex[0];
				pBuff[vertCtr].Position.y = m_md2Model->frames[i].vertices[currVertIndex].vertex[1];
				pBuff[vertCtr].Position.z = m_md2Model->frames[i].vertices[currVertIndex].vertex[2];
				
				pBuff[vertCtr].Normal.x   = m_md2Model->frames[i].vertices[currVertIndex].normal[0];
				pBuff[vertCtr].Normal.y   = m_md2Model->frames[i].vertices[currVertIndex].normal[1];
				pBuff[vertCtr].Normal.z   = m_md2Model->frames[i].vertices[currVertIndex].normal[2];
				
				pBuff[vertCtr].Texture.x = (float)m_md2Model->texCoords[currTexIndex].s / 255.f;
				pBuff[vertCtr].Texture.y = (float)m_md2Model->texCoords[currTexIndex].t / 255.f;

				//set extents, based on the first frame
				if(i == (START_FRAME + (START_FRAME % DISTANCE_BETWEEN_FRAMES)))
					SetExtents(pBuff[vertCtr], e);

				vertCtr++;
				
				//vertex 2
				currVertIndex = m_md2Model->triangles[j].vertexIndices[1];
				currTexIndex = m_md2Model->triangles[j].textureIndices[1];
				pBuff[vertCtr].Position.x = m_md2Model->frames[i].vertices[currVertIndex].vertex[0];
				pBuff[vertCtr].Position.y = m_md2Model->frames[i].vertices[currVertIndex].vertex[1];
				pBuff[vertCtr].Position.z = m_md2Model->frames[i].vertices[currVertIndex].vertex[2];
				
				pBuff[vertCtr].Normal.x   = m_md2Model->frames[i].vertices[currVertIndex].normal[0];
				pBuff[vertCtr].Normal.y   = m_md2Model->frames[i].vertices[currVertIndex].normal[1];
				pBuff[vertCtr].Normal.z   = m_md2Model->frames[i].vertices[currVertIndex].normal[2];
				
				pBuff[vertCtr].Texture.x = (float)m_md2Model->texCoords[currTexIndex].s / 255.f;
				pBuff[vertCtr].Texture.y = (float)m_md2Model->texCoords[currTexIndex].t / 255.f;

				//set extents, based on the first frame
				if(i == (START_FRAME + (START_FRAME % DISTANCE_BETWEEN_FRAMES)))
					SetExtents(pBuff[vertCtr], e);

				vertCtr++;

				//vertex 3
				currVertIndex = m_md2Model->triangles[j].vertexIndices[2];
				currTexIndex = m_md2Model->triangles[j].textureIndices[2];
				pBuff[vertCtr].Position.x = m_md2Model->frames[i].vertices[currVertIndex].vertex[0];
				pBuff[vertCtr].Position.y = m_md2Model->frames[i].vertices[currVertIndex].vertex[1];
				pBuff[vertCtr].Position.z = m_md2Model->frames[i].vertices[currVertIndex].vertex[2];
				
				pBuff[vertCtr].Normal.x   = m_md2Model->frames[i].vertices[currVertIndex].normal[0];
				pBuff[vertCtr].Normal.y   = m_md2Model->frames[i].vertices[currVertIndex].normal[1];
				pBuff[vertCtr].Normal.z   = m_md2Model->frames[i].vertices[currVertIndex].normal[2];
				
				pBuff[vertCtr].Texture.x = (float)m_md2Model->texCoords[currTexIndex].s / 255.f;
				pBuff[vertCtr].Texture.y = (float)m_md2Model->texCoords[currTexIndex].t / 255.f;
			
				//set extents, based on the first frame
				if(i == (START_FRAME + (START_FRAME % DISTANCE_BETWEEN_FRAMES)))
					SetExtents(pBuff[vertCtr], e);

				vertCtr++;
			}
			m_pVertexBuffers[bufferCtr]->Unlock();
		}
	}
	
	SetupMatrices(e);
	
	//create texture
	hr = D3DXCreateTextureFromFile(m_pD3DDev, GetFilePath(TEXTURE_FILENAME).c_str(), &m_pTexture);
	if(FAILED(hr))
		return hr;

	hr = m_pD3DDev->SetTexture(0, m_pTexture);
	if(FAILED(hr))
		return hr;

	hr = m_pD3DDev->SetVertexShader(m_dwCurrentShader);
	if (FAILED(hr))
		return hr;
	
	m_pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
	m_pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
	m_pD3DDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
	m_pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
	
	D3DXVECTOR4 lightDir(0.0f, 0.0f, -1.0f, 0.0f);
	m_pD3DDev->SetVertexShaderConstant(CV_LIGHT_DIRECTION, &lightDir, 1);

	D3DXVECTOR4 constants(0.0f, 0.5f, 1.0f, -1.0f);
	m_pD3DDev->SetVertexShaderConstant(CV_CONSTANTS, &constants, 1);

	m_baseTime = timeGetTime();

	return S_OK;
}

HRESULT CShaderKeyframeHermite::Free()
{
	if(m_pVertexBuffers)
	{
		for(int i = 0; i < m_numFrames; i++)
		{
			SAFE_RELEASE(m_pVertexBuffers[i]);
		}
	}

	SAFE_DELETE_ARRAY(m_pVertexBuffers);

	SAFE_RELEASE(m_pTexture);

	if (m_pD3DDev)
	{
		if (m_dwCurrentShader)
			m_pD3DDev->DeleteVertexShader(m_dwCurrentShader);
		SAFE_RELEASE(m_pD3DDev);
	}

	SAFE_RELEASE(m_pIndexBuffer);
	
	md2FreeModel(m_md2Model);
	
	m_md2Model = NULL;

	SAFE_DELETE(m_pUI);

	return S_OK;
}

HRESULT CShaderKeyframeHermite::Start()
{
	return S_OK;
}

void CShaderKeyframeHermite::MouseButton(HWND hWnd, eButtonID button, bool bDown, int x, int y)
{
	if(button == MOUSE_LEFTBUTTON)
	{
		if(bDown)
		{
			m_pUI->OnLButtonDown(x, y);
		}
		else
		{
			m_pUI->OnLButtonUp(x, y);
		}
	}
	return;
}

void CShaderKeyframeHermite::MouseMove(HWND hWnd, int x, int y)
{
	m_pUI->OnMouseMove(x, y);
	return;
}

void CShaderKeyframeHermite::Keyboard(DWORD dwKey, UINT nFlags, bool bDown)
{
	if(bDown)
	{
		switch(dwKey)
		{
			case 'W' :
            case 'w' :
            {
                m_bWireframe = !m_bWireframe;
				m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
                break;
            }

            case 'H' :
            case VK_F1 :
            {
		        ::MessageBoxEx( NULL, " Help : F1 - Help \n\n Home - Reset To Defaults \n\n W - Wireframe Toggle \n\n Space\\Pause - Toggle Pause/Resume \n\n Left Button & Mouse - Rotate Object\n\n Shift Left Button & Mouse - Pan Camera \n\n Ctrl Left Button & Mouse - Move Camera In & Out\n\n",
					   "Help", MB_ICONINFORMATION | MB_TASKMODAL, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ) );
                break;
            }

            case VK_HOME :
            case VK_END :
			case VK_NUMPAD7 :
			case VK_NUMPAD1 :
            case '7' :
            case '1' :
            {
                m_pUI->Reset();
                m_bWireframe = false;
				m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
                break;
            }

            default :
            {
                break;
            }
        }
	}
	SetMatricesBasedOnInput();
	return;
}

HRESULT CShaderKeyframeHermite::Tick(EBTimer* pTimer)
{
	HRESULT hr = S_OK;

	SetMatricesBasedOnInput();

	m_pD3DDev->SetRenderState(D3DRS_FILLMODE, (m_bWireframe ? D3DFILL_WIREFRAME : D3DFILL_SOLID));
	
	//advance one keyframe every PERIOD milliseconds
	int timeElapsed = timeGetTime() - m_baseTime;
	if(timeElapsed > PERIOD)
	{
		m_frame0++;
		m_frame1++;
		m_frame2++;
		m_frame3++;

		//clamp
		if(m_frame0 > (m_numFrames - 1))
			m_frame0 = 0;
		if(m_frame1 > (m_numFrames - 1))
			m_frame1 = 0;
		if(m_frame2 > (m_numFrames - 1))
			m_frame2 = 0;
		if(m_frame3 > (m_numFrames - 1))
			m_frame3 = 0;

		m_baseTime = timeGetTime();
		
		//this is set to zero, so the below calculation of fTimeDelta is correct
		timeElapsed = 0;
	}
	
	//set blend factor
	float fTimeDelta = (float)timeElapsed / PERIOD;
	
	//calculate the four hermite blend factors
	float fTimeDeltaSquared = fTimeDelta * fTimeDelta;
	float fTimeDeltaCubed = fTimeDeltaSquared*fTimeDelta;
	D3DXVECTOR4 blendFactor(2*fTimeDeltaCubed - 3*fTimeDeltaSquared + 1, 
		                    0.5f * (fTimeDeltaCubed - 2*fTimeDeltaSquared + fTimeDelta), 
							0.5f * (fTimeDeltaCubed - fTimeDeltaSquared),
							-2*fTimeDeltaCubed + 3*fTimeDeltaSquared);
	m_pD3DDev->SetVertexShaderConstant(CV_BLEND_FACTORS, blendFactor, 1);

	//set all streams (we're blending between four of them
	hr = m_pD3DDev->SetStreamSource(0, m_pVertexBuffers[m_frame0], sizeof(KeyframeVertex));
	if (FAILED(hr))
		return hr;
	
	hr = m_pD3DDev->SetStreamSource(1, m_pVertexBuffers[m_frame1], sizeof(KeyframeVertex));
	if (FAILED(hr))
		return hr;

	hr = m_pD3DDev->SetStreamSource(2, m_pVertexBuffers[m_frame2], sizeof(KeyframeVertex));
	if (FAILED(hr))
		return hr;
	
	hr = m_pD3DDev->SetStreamSource(3, m_pVertexBuffers[m_frame3], sizeof(KeyframeVertex));
	if (FAILED(hr))
		return hr;

	hr = m_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0xAA, 0xAA, 0xAA ), 1.0, 0);

	hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, m_md2Model->header.numTriangles);

	return hr;
}

HRESULT CShaderKeyframeHermite::ConfirmDevice(D3DCAPS8* pCaps, DWORD dwBehavior, D3DFORMAT Format)
{
	return S_OK;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -