Direct3D网格(一)

2023-10-10 01:20
文章标签 网格 direct3d

本文主要是介绍Direct3D网格(一),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

创建网格

我们可以用D3DXCreateMeshFVF函数创建一个"空"网格对象 ,空网格对象是指我们指定了网格的面片总数和顶点总数,然后由该函数为顶点缓存索引缓存属性缓存分配大小合适的内存,之后即可手工填入网格数据。

HRESULT WINAPI D3DXCreateMeshFVF(DWORD NumFaces,DWORD NumVertices,DWORD Options,DWORD FVF,LPDIRECT3DDEVICE9 pD3DDevice,LPD3DXMESH* ppMesh
);

NumFaces:网格将具有的面片总数,该值必须大于0

NumVertices:网格将具有的顶点总数,该值必须大于0

Options:创建网格时所使用的创建标记,枚举D3DXMESH,一些常用的标记如下
D3DXMESH_32BIT  网格将使用32位索引
D3DXMESH_MANAGED  网格数据将被存储于托管内存池中
D3DXMESH_WEITEONLY  指定网格数据为只读

FVF:存储在该网格中的顶点的灵活顶点格式

pDevice:设备指针

ppMesh:所创建的网格对象的指针

也可以用函数D3DXCreateMesh函数来创建空网格,在该函数中并未指定FVF,而是用一个D3DVERTEXELEMENT9类型的结构数组来描述顶点数据的布局方式。

HRESULT WINAPI D3DXCreateMesh(DWORD NumFaces,DWORD NumVertices,DWORD Options,CONST D3DVERTEXELEMENT9 *pDeclaration,LPDIRECT3DDEVICE9 pD3DDevice,LPD3DXMESH* ppMesh
);HRESULT WINAPI D3DXDeclaratorFromFVF(DWORD FVF,D3DVERTEXELEMENT9 pDeclarator[MAX_FVF_DECL_SIZE]
);

ID3DXBaseMesh获取几何信息接口

//获取
HRESULT ID3DXMesh::GetVertexBuffer(LPDIRECT3DVERTEXBUFFER9* ppVB);			//获取顶点缓存(用于存储网格顶点)
HRESULT ID3DXMesh::GetIndexBuffer(LPDIRECT3DINDEXBUFFER9* ppIB);			//获得索引缓存(决定顶点应以何种组合方式构成网格的三角形单元)
//锁定缓存,进行读写操作,注意这些方法锁定的是整个顶点缓存或索引缓存
//Flags参数描述了如何进行锁定,函数返回是ppData参返回指向被锁定的内存的指针的地址
HRESULT ID3DXMesh::LockVertexBuffer(DWORD Flags, BYTE** ppData);
HRESULT ID3DXMesh::LockIndexBuffer(DWORD Flags, BYTE** ppData);
//解锁
HRESULT ID3DXMesh::UnlockVertexBuffer();
HRESULT ID3DXMesh::UnlockIndexBuffer();
//获取几何信息的其他接口
DWORD GetFVF();					//返回描述顶点格式的DWORD
DWORD GetNumVertices();			//返回顶点缓存中的顶点个数
DWORD GetNumBytesPerVertex();	//返回每个顶点所占的字节数
DWORD GetNumFaces();			//返回网格中(三角形)面片的个数
DWORD GetOptions();             //返回网格的标记组合

子集和属性缓存

一个网格由一个或多个子集组成,一个子集是网格中一组可用相同属性进行绘制的三角形单元,这里属性是指材质、纹理和绘制状态

为了区分不同子集,我们为每个子集指定一个唯一的非负整数值,该值可为DWORD类型所能容纳的任何非负整数,网格中的每个三角形单元都被赋予了一个属性ID,该ID指定了该三角形单元所属的子集

这些三角形单元的属性ID被存储在网格的属性缓存中,该属性缓存实际上是一个DWORD类型的数组,由于每个面片在属性缓存中都有对应项,所以属性缓存中元素的个数与网格中面片的个数完全相等,而且属性缓存中那些项与在索引缓存中定义的三角形单元是一一对应 的,即属性缓存中的第i项对应于索引缓存中的第i个三角形,三角形单元i是有索引缓存中如下3个索引定义的。

A=i\cdot 3      B=i\cdot 3+1     C=i\cdot 3+2

属性缓存的锁定与解锁
ID3DXMesh::LockAttributeBuffer(DWORD Flags, DWORD** ppData);
ID3DXMesh::UnlockAttributeBuffer();

绘制

ID3DXMesh接口提供了方法DrawSubset用于绘制三角形单元,参数AttribId为指定的某个子集,若要绘制整个网格,必须绘制该网格的所有子集,比较方便的方法为将各子集的属性ID依次指定为0,1,2...n-1,n为子集的总数,每个子集都有一个对应的材质和纹理数组,这样通过索引i就可找到对应的材质和纹理。

ID3DXMesh::DrawSubset(DWORD AttribId);for (int i = 0; i < numSubsets; ++i)
{Device->SetMaterial(mtrls[i]);Device->SetTexture(0, textures[i]);Mesh->DrawSubset(i);
}

网格优化

为了更高效的绘制一个网格,我们可对该网格中的顶点和索引进行重组,这个重组的过程称为网格优化OptimizeInplace

HRESULT ID3DXMesh::OptimizeInplace(DWORD Flags,CONST DWORD* pAdjacencyIn,DWORD* pAdjacencyOut,DWORD* pFaceRemap,LPD3DXBUFFER *ppVertexRemap
);

Flags:优化选项标记,通知该方法所要实施的优化方案
D3DXMESHOPT_COMPACT  从网格中移除那些无用顶点和索引
D3DXMESHOPT_ATTSORT  依据属性对各三角形单元进行排序,并生成一个属性表,这样可使DrawSubset获得更高的绘制效率
D3DXMESHOPT_VERTEXCACHE  提高顶点高速缓存的命中率
D3DXMESHOPT_STRIPORDER  对索引进行重组,以使三角形单元条带尽可能的长
D3DXMESHOPT_IGNOREVERTS  仅对索引进行优化,忽略顶点
标记D3DXMESHOPT_VERTEXCACHE和D3DXMESHOPT_STRIPORDER不允许被被同时使用

pAdjacencyIn:指向未经优化的网格的邻接数组的指针

pAdjacencyOut:指向一个DWORD类型数组的指针,该数组被填充了经优化后的网格的邻接信息,该数组的维数必须为GetNumFaces()*3(每个三角形单元有3个边,所有邻接信息倍数为3倍),如果不需要该信息,可将参数赋为0

pFaceRemap:指向一个DWORD类型数组的指针,该数组填充了网格面片的重绘信息,该数组的维数应为GetNumFaces(),当对一个网格面实施优化后,其面片在索引缓存中可能发生了移动,该面片重绘信息表明了原始面片所被移动到的新位置,即pFaceRemap中的第i项保存了表示第i个原始面片被移动到哪里的面片索引,如果不需要该信息可将该参数赋为0

ppVertexRemap:指向ID3DXMesh对象指针的地址,该对象中保存了顶点的重绘信息,该缓存所包含的顶点数应为GetNumVertices(),当网格面经过优化之后,其顶点在索引缓存中的位置可能发生变动,顶点重绘信息表明了原始顶点移动到的新位置,即ppVertexRemap中的第i项保存了表示第i个原始顶点被移动到哪里的顶点索引,如果不需要该值,将该参数赋为0

DWORD adjacencyInfo[Mesh->GetNumFaces() * 3];
Mesh->GenerateAdjacency(0.0f, adjacencyInfo);
DWORD optimizedAdjacencyInfo[Mesh->GetNumFaces() * 3];
Mesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_COMPACT | D3DXMESHOPT_VERTEXCACHE, adjacencyInfo, optimizedAdjacencyInfo, 0, 0);

OptimizeInplace功能类似的另一个方法是Optimize该方法将输出调用该方法的网格对象优化后的版本,但是网格对象本身不会发生改变

HRESULT ID3DXMesh::Optimize(DWORD Flags,CONST DWORD* pAdjacencyIn,DWORD* pAdjacencyOut,DWORD* pFaceRemap,LPD3DXBUFFER *ppVertexRemap,LPD3DXMESH* ppOptMesh
);

属性表

如果一个网格对象在优化处理时使用了D3DXMESHOPT_ATTRSORT标记,则构成该网格的三角形面片就会依据其属性进行排序,这样属于特定子集的三角形面片就会被保存在顶点缓存或索引缓存中的一个连续存储空间

除了可对面片进行排序外,D3DXMESHOPT_ATTRSORT优化选项还将创建一个属性表,该属性表是一个D3DXATTRIBUTERANGE类型的结构数组,属性表中每一项都对应于网格的一个子集,并指定了该子集中面片的几何信息被存储在顶点缓存或索引缓存的哪一个存储块中。

typedef struct _D3DXATTRIBUTERANGE
{DWORD AttribId;DWORD FaceStart;DWORD FaceCount;DWORD VertexStart;DWORD VertexCount;
} D3DXATTRIBUTERANGE;

AttribId:子集的Id
FaceStart:一个大小为FaceStart*3的偏移量,表明了该子集的三角形单元在索引缓存中的起始位置
FaceCount:该子集中面片(三角形单元)的总数
VertexStart:一个表明了与子集相关的顶点在顶点缓存中起始位置的偏移量
VertexCount:该子集中的顶点总数

属性表的访问与设置

可以使用GetAttributeTable方法来访问一个网格面的属性表,该方法完成了俩项工作:返回属性表中的属性个数和属性数据填充D3DXATTRIBUTERANGE类型的结构数组。要想获取属性表中的元素个数,可将方法第一个参数取为0

HRESULT ID3DXMesh::GetAttributeTable(D3DXATTRIBUTERANGE *pAttribTable,DWORD* pAttribTableSize
);DWORD numSubsets=0;
Mesh->GetAttributeTable(0,&numSubsets);//一旦得到了属性表中的元素个数,就可以用属性数据填充结构数组
D3DXATTRIBUTERANGE table = new D3DXATTRIBUTERANGE[numSubSets];
Mesh->GetAttributeTable(table,&numSubsets);

可以使用SetAttributeTable对属性表进行设置

D3DXATTRIBUTERANGE attributeTable[12];
//填充该数组结构....//设定属性表共有12个子集
Mesh->SetAttributeTable(attributeTable,12);

邻接信息

对于某些网格运算(如网格优化),需要知道对任意给定三角形面片,哪些面片与其邻接,这些邻接信息都存储在网格的邻接数组中。邻接数组的类型为DWORD,其每一项都包含了一个标识网格中某个三角形面片的索引,如果邻接数组中某一项等于ULONG MAX=4294967295,则表明网格中某一特定边没有邻接面片,我们也可将该项赋为-1来表示此种情形。

邻接数组的维数必须为GetNumFaces()*3,网格中每个三角形面片都有3个可能的邻接面片,可用GenerateAdjacency函数来输出邻接信息。

HRESULT ID3DXMesh::GenerateAdjacency(FLOAT Epsilon,DWORD* pAdjacency
);DWORD adjacencyInfo[Mesh->GetNumFaces()*3];
Mesh->GenerateAdjacency(0.001f,adjacencyInfo);

fEpsilon:一个很小的正数值,指定了在某种距离度量下,俩个点接近到何种程度方可认为这俩点为同一点,例如俩点间距离小于该值,认为俩点为同一点
pAdjacency:指向一个DWORD类型的数组的指针,该数组中存储了邻接信息

克隆

有时需要生成网格数据的一个副本可用CloneMeshFVF方式来实现,该方法允许目标网格采用与原网格不同的创建选项和灵活顶点格式。

HRESULT ID3DXMesh::CloneMeshFVF(DWORD Options,DWORD FVF, LPDIRECT3DDEVICE9 pD3DDevice, LPD3DXMESH* ppCloneMesh
);ID3DXMesh* clone = 0;
Mesh->CloneMeshFVF(Mesh->GetOptions(), D3DFVF_XYZ | D3DFVF_NORMAL, Device, &clone);

Options:创建某网格副本时的创建标记或标记组合,枚举D3DXMESH
D3DXMESH_32BIT  网格将使用32位索引
D3DXMESH_MANAGED  网格数据将被存储于托管内存池中
D3DXMESH_WRITEONLY 指定网格数据为只读
D3DXMESH_DYNAMIC  网格缓存将使用动态内存

FVF:所要创建的克隆网格的灵活顶点格式

pDevice:设备指针

ppCloneMesh:输出所创建的克隆网格

这篇关于Direct3D网格(一)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/176939

相关文章

”CSS 网格“二维布局系统(补充)——WEB开发系列32

CSS 网格布局是一种二维布局系统,用于网页设计。通过使用网格,你可以将内容以行和列的形式进行排列。此外,网格布局还能够简便地实现一些复杂的布局结构。 一、什么是网格布局? CSS网格布局是一种二维布局系统,它允许我们创建复杂的网页布局,既可以处理行也可以处理列。与传统的布局方法不同,网格布局将网页分成多个可控的区域,这些区域可以任意排列、对齐和调整大小。网格布局使得创建灵活且响应

css——网格布局

名词解释 div{$}*9+tab键,快捷生成   记首字母gtc  网格布局:display: grid;        grid-template-columns: 100px 100px 100px;        grid-template-rows: 100px 100px 100px; (父元素) <!DOCTYPE html><html lang="en"

Data Mesh,数据网格的道与术

周末的时候,看到有群友讨论关于 Data Mesh 的话题。这个名词我在2020年初的时候听到过一次,当时感觉就是一个概念,看的糊里糊涂,没有当回事。最近突然又被推上了话题风口,所以静下心来看了一下相关的论文和介绍。 在讨论 Data Mesh 之前,首先要给大家介绍一下 Service Mesh。 Service Mesh 公认的定义,是用以处理服务与服务之间通信的专用基础设施层。更本质的理

图像数据到网格数据-3——Cuberille算法

前言   这是本博客网格生成算法系列的第三篇,第一篇里面介绍了最为流行的MarchingCubes算法,第二篇中使用新三角形表来对MC算法进行了简化改进,形成了SMC算法。而这篇将介绍一种新的不同与MC算法思路的新网格生成算法,叫做Cuberille法,这种算法的思想相比MC算法要简单,更加易于实现。   体素立方体模型   根据第一篇的介绍,我们知道MC算法的基本模型是把组成三

哈希表的应用-浅析顶点聚簇网格简化算法的实现

前言   本篇接顶点去重那一篇,继续使用哈希表来实现网格算法。这次介绍的是一种比较简单的网格简化算法,叫做顶点聚簇。   网格简化   为了介绍这个算法,首先说明一下网格简化算法。随着计算机绘图在现代科技领域中的广泛应用, 计算机图形在现代制造业中发挥着重要的作用。计算机图形学中对模型的要求更加精密, 也更加复杂, 生成的面片数也更加庞大, 庞大的数据量必然对计算机的计算能力提出

图像数据到网格数据-2——改进的SMC算法

概要   本篇接上一篇继续介绍网格生成算法,同时不少内容继承自上篇。上篇介绍了经典的三维图像网格生成算法MarchingCubes,并且基于其思想和三角形表实现了对样例数据的网格构建。本篇继续探讨网格生成算法,并且在MC的基础上进行进一步的简化和改进,形成Simple Marching Cubes(简称SMC算法)。本篇主要介绍SMC算法的思路以及与MC算法的对比。同时也介绍如何在MC三角形

ActiViz实战:使用Actor2D画一个二维网格

文章目录 一、效果预览二、交互三、C#源码示例 一、效果预览 二、交互 1、能实现等比缩放 2、不允许平移和旋转 3、能够与三维坐标大小匹配 三、C#源码示例 private void AddCudeAxes2D(){double scale =

【Rust光年纪】极致性能体验:数据管道实现、虚拟化列表和网格布局美化完全攻略

优秀开源库大揭秘:内存分析、数据处理、页面滚动监测、图片延迟加载全指南 前言 在当今的软件开发环境中,存在着各种各样的库和工具,它们为开发人员提供了丰富的功能和技术支持。本文将介绍几个与内存分析、数据处理、页面滚动状态监测、图片延迟加载、虚拟化长列表和网格布局美化相关的优秀库,帮助开发人员更好地理解和利用这些工具。 欢迎订阅专栏:Rust光年纪 文章目录 优秀开源库大揭秘:内

【三维重建】三角网格中轴骨架线提取

三维网格中轴线提取 方法介绍实现提取 三维网格中轴线提取是计算机图形学和三维建模领域中的一个重要技术,它对于理解三维形状的拓扑结构和几何特性具有重要意义。 方法介绍 以下是几种常见的三维网格中轴线提取方法: 基于距离变换的方法 基本原理:首先计算三维网格中每个点到网格边界的距离,形成距离场。然后,根据距离场的分布,通过细化算法提取中轴线。这种方法的核心在于距离变换和细化操作

裁减网格纸(贪心)

题目描述 度度熊有一张网格纸,但是纸上有一些点过的点,每个点都在网格点上,若把网格看成一个坐标轴平行于网格线的坐标系的话,每个点可以用一对整数x,y来表示。度度熊必须沿着网格线画一个正方形,使所有点在正方形的内部或者边界。然后把这个正方形剪下来。问剪掉正方形的最小面积是多少。 输入描述: 第一行一个数n(2≤n≤1000)表示点数,接下来每行一对整数xi,yi(-1e9<=xi,yi<=1e