Direct-X学习笔记--封装一个网格模型类

Direct-X学习笔记--X模型导入 一.介绍 经历了之前手写立方体的痛苦过程,终于到了网格模型这一步。我们做游戏的时候肯定不能只用立方体呀,想要复杂的人物模型肯定是需要美工同学们使用专业的工具才能创建出来的,这些模型文件中定义好了网格模型的形状以及材质纹理等信息,我们所要做的只是读取这个文件,然后就可以根据文件中的信息创建复杂的模型啦!然而说白了,这些东东DX已经为我们定义好了,我们背一背API就行啦! 创建这些模型一般用3DM 阅读详情

之前学习了网格模型的导入,绘制,了解了X文件等相关知识,但是,那样绘制比较麻烦,而且绘制一个模型需要好多代码,完全是面向过程的思维,这次,学习一下怎么把网格模型的导入以及绘制等功能封装在一个类中。顺便加深一下对World Transform的理解。感觉自己的3D思维还是没有培养起来,想绘制一个对象,绘制出来和想象中的位置相差甚远。


一.复习一下网格模型相关知识

网格模型就是一个我们在美术工具中制作好的资源,通过一些API接口我们可以将美术童鞋做好的模型很方便的导入程序中。我们只需要了解怎样从文件中创建网格模型和怎么绘制网格模型就行啦!

这次我们跟上一次程序差不多,都是从文件中读取网格文件信息,然后根据读取的信息加载材质纹理,只不过加了一个网格的优化,以及将网格加载和绘制封装在一个类中。


二.优化网格

我们通常使用OptimizeInplace函数来优化一下网格内容,去除一些无用的顶点等信息,这样我们就可以在绘制使用时更加流畅了。
OptimizeInplace函数参数如下,这个函数是直接在原来的Mesh上进行优化的。还有一个Optimize函数,是将优化后的Mesh又输出到另一个Mesh指针所指向的位置中。
HRESULT OptimizeInplace(
  [in]   DWORD Flags,//参数,按照例子中的写即可
  [in]   const DWORD *pAdjacencyIn,//优化前网格邻接信息数组的指针
  [out]  DWORD *pAdjacencyOut,//优化后网格邻接信息数组的指针
  [out]  DWORD *pFaceRemap,<//null即可
  [out]  LPD3DXBUFFER *ppVertexRemap//null即可
);

三.Mesh类的设计

面向对象万岁!来来来,封装一个类!
之前我们绘制一个Mesh需要两个函数,一堆全局变量,这次,我们将其封装在一个类中。

头文件:
/*!
 * \file Mesh.h
 *
 * \author puppet_master
 * \date 七月 2015
 *网格模型类:负责导入模型以及绘制模型
 * 
 */
#ifndef __MESH_H_
#define __MESH_H_
#pragma once
#include "stdafx.h"

class CMesh
{
public:
	CMesh(LPDIRECT3DDEVICE9 pDevice);
	~CMesh(void);
	
	//创建网格对象
	void CreateMesh(LPSTR filename);
	//绘制网格对象
	void DrawMesh(const D3DXMATRIXA16& matWorld);

private:

	LPDIRECT3DDEVICE9 m_pDevice;		    //D3D设备指针
	LPD3DXMESH m_pMesh;						//网格对象
	LPDIRECT3DTEXTURE9* m_pTextures;		//网格纹理信息
	D3DMATERIAL9* m_pMaterials;				//网格材质信息
	DWORD m_dwNumMtrls;						//网格材质数目
};


#endif // !__MESH_H_


cpp文件:
#include "stdafx.h"
#include "Mesh.h"


CMesh::CMesh(LPDIRECT3DDEVICE9 pDevice) : m_pDevice(pDevice)
{

}


CMesh::~CMesh(void)
{
	//释放相关资源
	SAFE_DELETE_ARRAY(m_pMaterials);

	if (m_pTextures)
	{
		for (int i = 0; i < m_dwNumMtrls; i++)
		{
			SAFE_RELEASE(m_pTextures[i]);
		}
		SAFE_DELETE_ARRAY(m_pTextures);
	}

	SAFE_RELEASE(m_pMesh);
}

void CMesh::CreateMesh(LPSTR filename)
{
	LPD3DXBUFFER pAdjBuffer = NULL;
	LPD3DXBUFFER pMtrlBuffer = NULL;

	D3DXLoadMeshFromX(filename, D3DXMESH_MANAGED, m_pDevice, &pAdjBuffer, &pMtrlBuffer, NULL, &m_dwNumMtrls, &m_pMesh);

	//读取材质和纹理数据
	D3DXMATERIAL *pMtrl = (D3DXMATERIAL*)pMtrlBuffer->GetBufferPointer();

	m_pMaterials = new D3DMATERIAL9[m_dwNumMtrls];
	m_pTextures = new LPDIRECT3DTEXTURE9[m_dwNumMtrls];

	for (int i = 0; i < m_dwNumMtrls; i++)
	{
		m_pMaterials[i] = pMtrl[i].MatD3D;
		m_pMaterials[i].Ambient = m_pMaterials[i].Diffuse;

		m_pTextures[i] = NULL;
		D3DXCreateTextureFromFileA(m_pDevice, pMtrl[i].pTextureFilename, &m_pTextures[i]);
	}

	//优化网格模型
	m_pMesh->OptimizeInplace(D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT| D3DXMESHOPT_STRIPREORDER, (DWORD*)pAdjBuffer->GetBufferPointer(), NULL, NULL, NULL);

	SAFE_RELEASE(pAdjBuffer);
	SAFE_RELEASE(pMtrlBuffer);
}

void CMesh::DrawMesh(const D3DXMATRIXA16& matWorld)
{
	m_pDevice->SetTransform(D3DTS_WORLD, &matWorld);
	m_pDevice->SetRenderState(D3DRS_LIGHTING, false);

	for (int i = 0; i < m_dwNumMtrls; i++)
	{
		m_pDevice->SetMaterial(&m_pMaterials[i]);
		m_pDevice->SetTexture(0, m_pTextures[i]);
		m_pMesh->DrawSubset(i);
	}
}


四.实际运用一下

这里仅贴出了main函数文件的代码:
// D3DDemo.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "D3DDemo.h"
#include "DirectInput.h"
#include "Camera.h"
#include "Terrain.h"
#include "Mesh.h"

#define MAX_LOADSTRING 100


// 全局变量:
HINSTANCE hInst;								// 当前实例
TCHAR szTitle[MAX_LOADSTRING];					// 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING];			// 主窗口类名

// 此代码模块中包含的函数的前向声明:
HWND                g_hWnd;
ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);

//---------改造3D窗口需要的内容------------
LPDIRECT3D9 g_pD3D = NULL;				//D3D接口指针
LPDIRECT3DDEVICE9 g_pDevice = NULL;		//D3D设备指针
CDirectInput* g_pDirectInput = NULL;	//控制指针
CCamera*      g_pCamera      = NULL;    //摄像机指针
CTerrain*     g_pTerrian     = NULL;	//地形类指针
CMesh*        g_pMesh1       = NULL;	//网格对象指针1
CMesh*        g_pMesh2       = NULL;	//网格对象指针2
CMesh*	      g_pMesh3       = NULL;	//网格对象指针3



LPDIRECT3DTEXTURE9  g_pGroundTexture = NULL;	//地面纹理
D3DXMATRIX g_matWorld;							//世界矩阵

//------------绘制图形步骤1.定义灵活顶点格式
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_TEX1)//坐标为经过变换的屏幕坐标,顶点的颜色

//------------绘制图形步骤2.根据上面定义的顶点格式,创建一个顶点的结构体
struct stVertex
{
	float _x, _y, _z;		//位置坐标
	float _u, _v;			//纹理坐标

	stVertex(float x, float y, float z, float u, float v) : _x(x), _y(y), _z(z), _u(u), _v(v){}
	stVertex(){}
};

//----------绘制图形步骤3.声明一个顶点缓冲区指针&一个索引缓冲区指针
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL;
LPDIRECT3DINDEXBUFFER9 g_pIB = NULL;




void onCreatD3D()
{
	g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
	if (!g_pD3D)
		return;

	//检测硬件设备能力的方法
	/*D3DCAPS9 caps;
	ZeroMemory(&caps, sizeof(caps));
	g_pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);*/

	//获得相关信息,屏幕大小,像素点属性
	D3DDISPLAYMODE d3ddm;
	ZeroMemory(&d3ddm, sizeof(d3ddm));

	g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);


	//设置全屏模式
	D3DPRESENT_PARAMETERS d3dpp;
	ZeroMemory(&d3dpp, sizeof(d3dpp));
	/*d3dpp.Windowed = false;
	d3dpp.BackBufferWidth = d3ddm.Width;
	d3dpp.BackBufferHeight = d3ddm.Height;*/

	d3dpp.Windowed = true;
	d3dpp.BackBufferFormat = d3ddm.Format;
	d3dpp.BackBufferCount = 1;

	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;//交换后原缓冲区数据丢弃

	//是否开启自动深度模板缓冲
	d3dpp.EnableAutoDepthStencil = true;
	//当前自动深度模板缓冲的格式
	d3dpp.AutoDepthStencilFormat = D3DFMT_D16;//每个像素点有16位的存储空间,存储离摄像机的距离
	

	g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pDevice);

	if (!g_pDevice)
		return;

	//设置渲染状态,设置启用深度值
	g_pDevice->SetRenderState(D3DRS_ZENABLE, true);

	//设置渲染状态,关闭灯光
	g_pDevice->SetRenderState(D3DRS_LIGHTING, false);

	//设置渲染状态,裁剪模式
	g_pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);

	//g_pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE) ;

}

void CreateMesh()
{
	g_pMesh1 = new CMesh(g_pDevice);
	g_pMesh1->CreateMesh("miki.X");

	g_pMesh2 = new CMesh(g_pDevice);
	g_pMesh2->CreateMesh("Demon.X");

	g_pMesh3 = new CMesh(g_pDevice);
	g_pMesh3->CreateMesh("dragon.X");
}

void CreateCamera()
{
	g_pCamera = new CCamera(g_pDevice);
	g_pCamera->SetCameraPosition(&D3DXVECTOR3(0.0f, 0.0f, -500.0f));
	g_pCamera->SetTargetPosition(&D3DXVECTOR3(0.0f, 0.0f, 0.0f));
	g_pCamera->SetViewMatrix();
	g_pCamera->SetProjectionMartix();
}

void onInit()
{
	//初始化D3D
	onCreatD3D();

	//初始化顶点缓冲区
	initVB();

	//创建Mesh模型
	CreateMesh();

	//创建摄像机
	CreateCamera();

	//创建地形
	CreateTerrain();
	
}



void onDestroy()
{
	SAFE_DELETE(g_pDirectInput);
	SAFE_DELETE(g_pCamera);
	SAFE_DELETE(g_pTerrian);
	SAFE_RELEASE(g_pDevice);
}

void onLogic(float fElapsedTime)
{
	//使用DirectInput类读取数据
	g_pDirectInput->GetInput();

	// 沿摄像机各分量移动视角
	if (g_pDirectInput->IsKeyDown(DIK_A))  g_pCamera->MoveAlongRightVec(-10.0f);
	if (g_pDirectInput->IsKeyDown(DIK_D))  g_pCamera->MoveAlongRightVec( 10.0f);
	if (g_pDirectInput->IsKeyDown(DIK_W)) g_pCamera->MoveAlongLookVec( 10.0f);
	if (g_pDirectInput->IsKeyDown(DIK_S))  g_pCamera->MoveAlongLookVec(-10.0f);
	if (g_pDirectInput->IsKeyDown(DIK_I))  g_pCamera->MoveAlongUpVec( 10.0f);
	if (g_pDirectInput->IsKeyDown(DIK_K))  g_pCamera->MoveAlongUpVec(-10.0f);

	//沿摄像机各分量旋转视角
	if (g_pDirectInput->IsKeyDown(DIK_LEFT))  g_pCamera->RotationUpVec(-0.003f);
	if (g_pDirectInput->IsKeyDown(DIK_RIGHT))  g_pCamera->RotationUpVec( 0.003f);
	if (g_pDirectInput->IsKeyDown(DIK_UP))  g_pCamera->RotationRightVec(-0.003f);
	if (g_pDirectInput->IsKeyDown(DIK_DOWN))  g_pCamera->RotationRightVec( 0.003f);
	if (g_pDirectInput->IsKeyDown(DIK_J)) g_pCamera->RotationLookVec(-0.001f);
	if (g_pDirectInput->IsKeyDown(DIK_L)) g_pCamera->RotationLookVec( 0.001f);

	//鼠标控制右向量和上向量的旋转
	//g_pCamera->RotationUpVec(g_pDirectInput->MouseDX()* 0.001f);
	//g_pCamera->RotationRightVec(g_pDirectInput->MouseDY() * 0.001f);

	//鼠标滚轮控制观察点收缩操作
	static FLOAT fPosZ=0.0f;
	fPosZ += g_pDirectInput->MouseDZ()*3.0f;

	//计算并设置取景变换矩阵
	D3DXMATRIX matView;
	g_pCamera->CalculateViewMatrix(&matView);
	g_pDevice->SetTransform(D3DTS_VIEW, &matView);

	//把正确的世界变换矩阵存到g_matWorld中
	D3DXMatrixTranslation(&g_matWorld, 0.0f, 0.0f, fPosZ);

}

void onRender(float fElasedTime)
{
	//前两个参数是0和NULL时,清空整个游戏窗口的内容(清的是后台)
	//第三个是清除的对象:前面表示清除颜色缓冲区,后面表示清除深度缓冲区,D3DCLEAR_STENCIL清空模板缓冲区
	g_pDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,100,100), 1.0f, 0);

	g_pDevice->BeginScene();

	D3DXMATRIX matWorld1, matWorld2, matWorld3;  
	D3DXMatrixTranslation(&matWorld1, 0.0f, 100.0f, 0.0f);  
	D3DXMatrixTranslation(&matWorld2, 300.0f, 0.0f, 0.0f);
	D3DXMatrixTranslation(&matWorld3, 0.0f, 0.0f, 0.0f);
	g_pMesh1->DrawMesh(matWorld1);
	g_pMesh2->DrawMesh(matWorld2);
	g_pMesh3->DrawMesh(matWorld3);

	g_pDevice->EndScene();


	g_pDevice->Present(NULL, NULL, NULL, NULL);
}


int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPTSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

 	// TODO: 在此放置代码。
	MSG msg;
	HACCEL hAccelTable;

	// 初始化全局字符串
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_D3DDEMO, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

	// 执行应用程序初始化:
	if (!InitInstance (hInstance, nCmdShow))
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_D3DDEMO));

	

	ZeroMemory(&msg, sizeof(msg));
	while (msg.message != WM_QUIT)
	{
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else
		{
			static DWORD dwTime = timeGetTime();
			DWORD dwCurrentTime = timeGetTime();
			DWORD dwElapsedTime = dwCurrentTime - dwTime;
			float fElapsedTime = dwElapsedTime * 0.001f;

			//------------渲染和逻辑部分代码----------
			onLogic(fElapsedTime);
			onRender(fElapsedTime);
			//-----------------------------------------
			if (dwElapsedTime < 1000 / 60)
			{
				Sleep(1000/ 60 - dwElapsedTime);
			}
			dwTime = dwCurrentTime;
		}
	}

	onDestroy();
	return (int) msg.wParam;
}



//
//  函数: MyRegisterClass()
//
//  目的: 注册窗口类。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX);

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_D3DDEMO));
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= MAKEINTRESOURCE(IDC_D3DDEMO);
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

	return RegisterClassEx(&wcex);
}

//
//   函数: InitInstance(HINSTANCE, int)
//
//   目的: 保存实例句柄并创建主窗口
//
//   注释:
//
//        在此函数中,我们在全局变量中保存实例句柄并
//        创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{

   hInst = hInstance; // 将实例句柄存储在全局变量中

   g_hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!g_hWnd)
   {
      return FALSE;
   }

  //初始化DirectInput类
   g_pDirectInput = new CDirectInput();
   g_pDirectInput->Init(g_hWnd, hInst, DISCL_FOREGROUND|DISCL_NONEXCLUSIVE, DISCL_FOREGROUND|DISCL_NONEXCLUSIVE);

   SetMenu(g_hWnd, NULL);
   ShowWindow(g_hWnd, nCmdShow);
   UpdateWindow(g_hWnd);

   onInit();

   return TRUE;
}

//
//  函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的: 处理主窗口的消息。
//
//  WM_COMMAND	- 处理应用程序菜单
//  WM_PAINT	- 绘制主窗口
//  WM_DESTROY	- 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND g_hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_KEYDOWN:
		if (wParam == VK_ESCAPE)
			PostQuitMessage(0);
		break;
	case WM_CLOSE:
		DestroyWindow(g_hWnd);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(g_hWnd, message, wParam, lParam);
	}
	return 0;
}

好了,其实这次主要是来巩固一下WorldTransform的,感觉学习D3D一小段时间了,还是没有形成3D的思维。

好吧,又从浅墨大大那里偷的资源。。。


龙骑士美少女:

凶神恶煞的东东:


摄像机观察(0,0,0),位置在(0, 0, -500),龙在(0, 0, 0),即摄像机观察点,而初音的模型在(0, 100, 0)处,即在龙上面,而红色怪物在(500, 0, 0)处,即在龙的右侧。



Direct-X学习笔记--地形 地形系统,在游戏中肯定少不了滴。终于要开始学习这个东东啦!地形看起来非常神奇,绵延的山峦,横看成岭侧成峰,远近高低各不同,这么复杂的地形到底我们到底要怎么写呢?说实话不学这个之前我真的完全想不到地形的实现方法。 一.简介 三维地形系统在很多地方都有应用,不论是游戏还是模拟系统中,地形都是必不可少的元素之一。说到地图,我们最容易想到的就是一个二维数组,根据数组元素的不同,绘制出不同的图形 阅读详情

相关推荐

Direct-X学习笔记--骨骼动画

学了几个月DX了,终于到了骨骼动画这一步了,好激动!之前导入过一些静态的模型,还是挺帅的。不过不能动,实在是太遗憾了。今天学习了骨骼动画,终于让偶的模型动起来啦!!! 一.简介 说到动画,其实本人又想起了最早开始写小游戏的时候从网上找的那些关键帧素材,设置一个定时器,或者根据游戏循环,不断切换图片,就形成了动态的效果。不过这样实在是太麻烦了,需要美术一张一张的画图或者用PS调整。到了3D时代,

puppet_master的专栏 2537

Direct3D学习手记十一:网格二【从.x文件中加载网格】

上篇我们介绍了自己创建网格的方法,此次我们介绍从.x文件中加载3D模型的方法 .x文件: .x文件是一种存储3D模型数据的一种文本文件,其存储格式有两种:文本方式和二进制方式, 其中文本方式易于查看,.x文件有其特定的格式 .x文件中存储了顶点数据,材质信息和纹理贴图信息等待,可以通过特定的方式读取其中的内容。 从.x文件中加载网格: HRESULT D3DXLoadMeshFromX( LP...

szmtjs10的博客 354

Direct-X学习笔记--深度缓存

今天来学习一下深度测试,不过这个东东貌似暂时就是了解一下原理啦,因为DX默认是打开深度测试的,即我们不需要额外进行设置就可以使用深度测试的功能,不过这个还是有必要了解一下,一是对DX的流程更加了解,二是我们可以手动设置深度测试的参数以及函数,达到一些自己想要实现的效果。 一.简介 三维的世界中,有各种物体,而这些物体难免会有遮挡,而且同一个物体不同部分也会有遮挡的关系,要想表现出来更加

puppet_master的专栏 3163

[Direct2D开发] 绘制网格

转载请注明出处:http://www.cnblogs.com/Ray1024 一、引言 最近在使用Direct2D进行绘制工作中,需要实现使用Direct2D绘制网格的功能。在网上查了很多资料,终于实现了,把方法贴到这里供大家参考。 二、绘制网格 2.1API接口 首先介绍一下绘制网格中使用到的重要接口ID2D1BitmapRenderTarget,它继承自ID2D1Ren...

weixin_30329623的博客 246

Direct-X学习笔记--三维摄像机

一.介绍 哇!到了传说中的3D摄像机啦! 之前我们写的东东,都是观察点不动,通过世界变换让东西动,今天,通过三维摄像机我们就可以改变我们的观察点,观察方向,随意在三维空间中驰骋。之前我们所设定的视角都是通过D3DXMatrixLookAtLH这个函数,通过几个设定好的向量,将视角初始化的,而在程序真正运行时,视角就不再改变了,而这次,我们要实时的生成视角变换矩阵,实时的改变我们的视角,我们所谓

puppet_master的专栏 3291

Direct-X学习笔记--光照&材质&DX自带几何体绘制

DX中自带几何体的绘制: 为了方便,DX为我们提供了几种自带的几何体,我们就不需要定义成吨的顶点来绘制一个图形了。 常用的有几种,立方体,茶壶,柱体,球面体。 HRESULT D3DXCreateTeapot( __in LPDIRECT3DDEVICE9 pDevice, __out LPD3DXMESH *ppMesh, __out LPD3DXBUFFER *

puppet_master的专栏 2387

【Visual C++】游戏开发笔记四十四 浅墨DirectX教程十二 网格模型和X文件使用面面观

本系列文章由zhmxy555(毛星云)编写,转载请注明出处。  文章链接: http://blog.youkuaiyun.com/zhmxy555/article/details/8586540作者:毛星云(浅墨)    邮箱: happylifemxy@163.com  在本篇文章中,我们一起详细探索了Direct3D网格相关的知识,对当前两款主流的三维建模软件(3DS Max和Maya)进行了介绍,了解了

【浅墨的游戏编程Blog】毛星云(浅墨)的专栏 4万+

【控件功能】我来做练习-第49课-Direct2D drawing example

Direct2D drawing example

大龙软件工作室 1036

【Visual C++】游戏开发五十一 浅墨DirectX教程十九 网格模型进阶之路

本系列文章由zhmxy555(毛星云)编写,转载请注明出处。   文章链接: http://blog.youkuaiyun.com/zhmxy555/article/details/8770426 作者:毛星云(浅墨)    邮箱: happylifemxy@163.com  最近几个星期,不停地收到大家的评论和邮件,大家都说希望浅墨早点讲骨骼动画。本来按浅墨拟定的写作计划是把骨骼动画放到很后面,因为骨骼动画

【浅墨的游戏编程Blog】毛星云(浅墨)的专栏 2万+

Direct3D 写的浏览.x模型

浏览D3D模型工具,仅支持 把.x文件拖拉至窗口即可浏览 -A tool of View D3D Modal, suport only drag the Modal into the windows, that s all.

CANoe软件之离线报文回放与分析实战

本文详细介绍了如何使用CANoe软件进行离线报文回放与分析,帮助工程师将现场故障数据转化为可反复研究的实验室资源。通过实战步骤,指导如何搭建分析工程、加载DBC文件解码信号,并利用Trace和Graphics窗口进行深度数据筛选与图形化分析,从而高效定位汽车电子故障,是提升诊断效率的关键技能。

weixin_29227585的博客 528

Direct2D中的2D显示

Dx11中的2D显示抛弃了Dx8和Dx9中的 ID3DxSprite 绘制精灵,也出乎意料的(出乎我的意料 :) )没有采用顶点方式而是返璞归真走向了表面。现在的Direct2D更像是GDI了~~~  DX11上Direct2D的第一个例题就是绘制一个笔刷~~这在原来是不可能实现的;原来的ID3DxSprite 只能够绘制基于纹理的格式,比如我们要做一个效果,当选中一个Button的时候,这个Bu

Augusdi的专栏 4109

模拟IC设计笔记:拆解一个经典的时钟占空比校正(DCC)电路模块,从理论到SPICE仿真

本文深入解析了时钟占空比校正(DCC)电路在模拟IC设计中的关键作用,特别是在高速ADC应用中。通过晶体管级拆解,详细介绍了基于电荷泵和积分器的模拟反馈型DCC电路设计,包括占空比检测、误差放大与校正执行单元的实现。文章还提供了SPICE仿真验证方法,确保电路在100MHz时钟下的稳定性和性能。

weixin_33725722的博客 424

【游戏程序设计】Direct 3D X文件模型导入

运行结果: 源代码: XFileModelClass.h: //============================================================================= //一个封装了X文件载入与渲染功能的头文件 //============================================================...

辣条不爱辣的博客 1005

河道水位标尺识别预警 yolov7

河道水位标尺识别预警系统通过python+yolov7网络模型技术,河道水位标尺识别预警算法对河道水位标尺进行实时监测,当河道水位出现异常情况时,河道水位标尺识别预警算法将自动发出警报提示后台管理人员及时采取措施。YOLO系列算法是一类典型的one-stage目标检测算法,其利用anchor box将分类与目标定位的回归问题结合起来,从而做到了高效、灵活和泛化性能好,所以在工业界也十分受欢迎。Yolo模型采用预定义预测区域的方法来完成目标检测,具体而言是将原始图像划分为 7x7=49 个网格(grid),每

燧机科技的博客 2302

信捷CODESYS平台伺服电机转矩控制模式应用与切换

信捷CODESYS二次开发软件:XS Studio 在运动控制中的转矩控制案例

weixin_64614866的博客 1万+

骨骼3d direct 绘制

D3D中网格模型的运用 在最底层的层次中,Direct3D并不使用网格模型,而只是使用多边形。D3DX增强了 Direct3D系统的功能性,添加了一系列负责处理网格模型的容器和进行渲染的对象。.X文件是微软公司所开发的,高度通用的三维模型存储格式。它是模板驱动并完全可扩展,这就意味着可以使用它来满足文件存储的所有需求。一个.X文件,正如它的文件扩展名所表明的,是非常通用的。它可以是基于文本的,以便更容易进行编辑;或者是基于二进制的,这样可以使文件更小,并且更容易地进行保护以便不被窥视。整个.X文...

dps game 454

双极性步进电机驱动技术:从H桥电路到精准控制

本文深入解析了双极性步进电机驱动技术的核心,从H桥电路的基础原理讲起,阐述了其作为实现电机正反转和精准控制的关键。文章详细介绍了H桥的工作模式、防共态导通设计,并对比了L298N、DRV8825及TMC2209等主流集成驱动芯片的选型。进一步探讨了通过微步进与电流矢量控制实现平滑、静音运行的高级技术,并提供了基于STM32的实战代码与避坑指南,帮助开发者从理论到实践全面掌握精准运动控制。

tea88的博客 593

D3D中网格模型的运用

点击下载源码和资源 在最底层的层次中,Direct3D并不使用网格模型,而只是使用多边形。D3DX增强了 Direct3D系统的功能性,添加了一系列负责处理网格模型的容器和进行渲染的对象。.X文件是微软公司所开发的,高度通用的三维模型存储格式。它是模板驱动并完全可扩展,这就意味着可以使用...

chubaisheng8627的博客 218

YOLOv11涨点改进| Kimi团队 2026 |独家创新首发、注意力改进篇|爆火AttnRes残差自注意力模块,含多种创新改进,借助残差思想,缓解细节信息在传播过程中被稀释,促进YOLOv11涨点

🔥本文提出AttnRes残差自注意力模块,通过深度维度的注意力加权机制替代传统固定残差累加方式,使YOLOv11网络能自适应选择更有价值的历史层特征进行聚合。该方法缓解了浅层细节信息在深层传播过程中被稀释的问题,有效融合浅层纹理与深层语义特征,提升小目标、密集目标和复杂场景的检测能力。AttnRes还改善了深层网络的梯度分布与训练稳定性,增强模型收敛质量和泛化能力。实验表明,该模块能以较小计算开销显著提升YOLOv11的特征表达能力、检测精度和整体鲁棒性。文中详细介绍了模块结构、实现原理、优势特点

Ai缝合怪、助力小伙伴高效发论文 125

异步处理优化:多线程线程池与消息队列的选择与应用

本文讨论了两种常见的异步处理方式:多线程线程池和消息队列(MQ)。通过将非核心逻辑异步化,可以提升系统的性能和响应速度。多线程线程池适用于本地并发任务,适合需要快速响应的场景,但无法处理跨服务任务。消息队列则适用于分布式系统,能够解耦服务并保证任务的可靠性和顺序性,适合处理高并发和高可靠性要求的任务。文章提供了实际代码示例,帮助开发者根据业务需求选择合适的异步处理方式。

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 170万+

[Direct2D]DX11中的2D显示

Dx11中的2D显示抛弃了Dx8和Dx9中的 ID3DxSprite 绘制精灵,也出乎意料的(出乎我的意料 :) )没有采用顶点方式而是返璞归真走向了表面。现在的Direct2D更像是GDI了~~~DX11上Direct2D的第一个例题就是绘制一个笔刷~~这在原来是不可能实现的;原来的ID3DxSprite 只能够绘制基于纹理的格式,比如我们要做一个效果,当选中一个Button的时候,这个Button边界线会高亮显示,这在原来必须依靠制作这样的纹理来实现,现在不同了,你可以定义一个线条笔刷,给他个范围,画一

我是一只夜行的猫仔 5509

TVBox源总失效?不如自己搭建一个!告别不稳定!手把手教你自建TVBox源,全网资源尽掌握!

🚀 TVBox源总失效?别慌!手把手教你自建TVBox源,打造一个稳定、海量、无广告的影视宝库!从此告别片荒,尽享丝滑观影体验!

XiaoqiangClub的博客 5440

别只盯着S参数!HFSS求解器(Direct/Iterative/Domain)选对了吗?性能提升秘籍

本文深度解析HFSS中Direct、Iterative和Domain三大求解器的性能差异与适用场景,帮助工程师优化仿真效率。通过对比内存占用、计算时间和精度控制,提供针对电大尺寸天线、精密滤波器和多物理场耦合问题的黄金组合策略,并揭示常见误区与硬件配置建议,助力提升Solution Setup设置的科学性。

weixin_30736301的博客 427

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

上一篇: 编译时和运行时的关系
下一篇: Direct-X学习笔记--地形
puppet_master
puppet_master 领域专家: C/C++技术领域 领域专家: C/C++技术领域
博客等级 码龄12年 2695粉丝 161原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值