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

📄 shader_keyframelinear.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
字号:
/*********************************************************************NVMH2****
Path:  E:\devrel\NV_SDK_4\DX8\NVEffectsBrowser\Effects\Keyframe
File:  shader_KeyframeLinear.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_KeyframeLinear.h"
#include "shader_KeyframeHermite.h"
#include "nvinc.h"
#include "MouseUI.h"
#include "KeyframeCommon.h"
#include "Constants.h"

#include <mmsystem.h>

using namespace std;

DECLARE_EFFECT_MAIN()

extern "C"
{

__declspec(dllexport) unsigned int GetNumEffects() { return 2; }

__declspec(dllexport) EBEffect* CreateEffect(unsigned int EffectNum)
{	
	switch(EffectNum)
	{
		case 0:
			return new CShaderKeyframeLinear();
			break;
		case 1:
			return new CShaderKeyframeHermite();
			break;
		default:
			return NULL;
	}
}

}


CShaderKeyframeLinear::CShaderKeyframeLinear()
	: m_pVertexBuffers(NULL),
	m_pIndexBuffer(NULL),
	m_pTexture(NULL),
	m_dwCurrentShader(0),
	m_pUI(NULL),
	m_frame0(0),
	m_frame1(1),
	m_bWireframe(false)
{
	m_strEffectLocation = "Vertex Shaders\\Animation";
	m_strEffectName = "Linear Keyframe Interpolation";
	m_strEffectVertexShader = GetFilePath("KeyframeLinear.nvv");
	m_strEffectPixelShader = "";
	
	m_md2Model = NULL;
}

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

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

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


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

void CShaderKeyframeLinear::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, 150.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 CShaderKeyframeLinear::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 CShaderKeyframeLinear::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 CShaderKeyframeLinear::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);

	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_END());

	hr = LoadAndCreateShader(GetFilePath("KeyframeLinear.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_pD3DDev->SetStreamSource(0, m_pVertexBuffers[0], sizeof(KeyframeVertex));
	m_pD3DDev->SetStreamSource(1, m_pVertexBuffers[1], sizeof(KeyframeVertex));
	
	m_baseTime = timeGetTime();

	return S_OK;
}

HRESULT CShaderKeyframeLinear::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 CShaderKeyframeLinear::Start()
{
	return S_OK;
}

void CShaderKeyframeLinear::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 CShaderKeyframeLinear::MouseMove(HWND hWnd, int x, int y)
{
	m_pUI->OnMouseMove(x, y);
	return;
}

void CShaderKeyframeLinear::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 CShaderKeyframeLinear::Tick(EBTimer* pTimer)
{
	HRESULT hr = S_OK;

	SetMatricesBasedOnInput();

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

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

		m_baseTime = timeGetTime();
		timeElapsed = 0;
	}
	
	//set blend factor
	float fTimeDelta = (float)timeElapsed / PERIOD;
	D3DXVECTOR4 blendFactor(fTimeDelta, 1.0f - fTimeDelta, 0.0f, 0.0f);
	m_pD3DDev->SetVertexShaderConstant(CV_BLEND_FACTORS, blendFactor, 1);

	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->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 CShaderKeyframeLinear::ConfirmDevice(D3DCAPS8* pCaps, DWORD dwBehavior, D3DFORMAT Format)
{
	return S_OK;
}

⌨️ 快捷键说明

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