当前位置: 首页 > news >正文

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网格(一)

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

C语言打印菱形

一、运行结果图 二、源代码 # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff1b;int line 0;int i 0;int j 0;//获取变量值&#xff1b;scanf("%d", &line);//循环打印上半部分&#xff1b;for (i 0; i <…...

ElasticSearch搜索引擎:数据的写入流程

一、ElasticSearch 写数据的总体流程&#xff1a; &#xff08;1&#xff09;ES 客户端选择一个节点 node 发送请求过去&#xff0c;这个节点就是协调节点 coordinating node &#xff08;2&#xff09;协调节点对 document 进行路由&#xff0c;通过 hash 算法计算出数据应该…...

python3 调用 另外一个python脚本

3种python调用其他脚本脚本的方法_python 调用python脚本_linjingyg的博客-CSDN博客 Python之系统交互(调用系统命令)subprocess_subprocess.getoutput(cmd) 参数格式不正确-CSDN博客 subprocess.call()只能返回状态码。subprocess.getoutput(cmd)只能输出命令结果。 str(py…...

【13】c++设计模式——>简单工厂模式

工厂模式的定义 c中的工厂模式是一种创建型设计模式&#xff0c;它提供一种创建对象的接口&#xff0c;但具体创建的对象类型可以在运行时决定&#xff0c;这样可以将对象的创建与使用代码分离&#xff0c;提高代码的灵活性和可维护性。 在c中实现工厂模式&#xff0c;通常会定…...

系统架构设计:2 论软件设计方法及其应用

目录 一 软件设计方法 1结构化设计 2信息工程 3面向对象设计 4原型设计...

基于Winform的UDP通信

1、文件结构 2、UdpReceiver.cs using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading.Tasks;namespace UDPTest.Udp {public class UdpStateEventArgs : EventArgs…...

掌握 BERT:自然语言处理 (NLP) 从初级到高级的综合指南(1)

简介 BERT&#xff08;来自 Transformers 的双向编码器表示&#xff09;是 Google 开发的革命性自然语言处理 (NLP) 模型。它改变了语言理解任务的格局&#xff0c;使机器能够理解语言的上下文和细微差别。在本文[1]中&#xff0c;我们将带您踏上从 BERT 基础知识到高级概念的旅…...

Linux Ftrace介绍

文章目录 一、简介二、内核函数调用跟踪参考链接&#xff1a; 一、简介 Ftrace 是 Linux 官方提供的跟踪工具&#xff0c;在 Linux 2.6.27 版本中引入。Ftrace 可在不引入任何前端工具的情况下使用&#xff0c;让其可以适合在任何系统环境中使用。 Ftrace 可用来快速排查以下相…...

Go语言进阶------>init()函数

Init()包初始化 执行优先级 Init()函数的执行优先级比main()函数的执行优先级要高,也就是说程序会优先执行Init()函数之后再执行main()函数. 代码如下 package mainimport "fmt"func init() {fmt.Println("执行了Init()函数") }func main() {fmt.Println…...

云计算:常用微服务框架

目录 一、理论 1.Java微服务框架 2.Go微服务框架 3.Python微服务框架 4.Node.js微服务框架 5..Net微服务框架 一、理论 1.Java微服务框架 Spring Cloud&#xff1a;最早最成熟&#xff0c;Java开源微服务框架方案 SpringBoot&#xff1a;全新框架&#xff0c;设计目的是…...

jmeter添加断言(详细图解)

先创建一个线程组&#xff0c;再创建一个http请求。 为了方便观察&#xff0c;我们添加两个监听器&#xff0c;察看结果树和断言结果。 添加断言&#xff1a;响应断言&#xff0c;响应断言也是比较常用的一个断言 设置响应断言&#xff1a;正常情况下响应代码是200。选择响应代…...

few shot object detection via feature reweight笔记

摘要部分 few shot很多用的都是faster R-CNN为基础&#xff0c;本文用的是one-stage 结构。 用了一个meta feature learner和reweighting模块。 和其他的few shot一样&#xff0c;先学习base数据集&#xff0c;再推广到novel数据集。 feature learner会从base数据集中提取meta…...

工会排队模式:电商新营销模式吸引消费者,提升销售!

随着电商行业的繁荣发展&#xff0c;私域流量已经成为了电商平台争夺消费者和促进销售的重要手段。工会排队模式正是在这种背景下应运而生的一种创新性的电商营销模式。这种模式通过奖金池的资金来为消费者和商家提供返现和排队奖励&#xff0c;构建了一个实现消费者和商家共赢…...

定档通知2024中国(北京)国际红外技术及设备展览会

时间&#xff1a;2024年7月14-16日 地点&#xff1a;北京国家会议中心 ◆展会背景background&#xff1a; 各有关红外企业厂商&#xff1a;2024年7月14&#xff5e;16日&#xff0c;2024中国国际红外技术及设…...

自助建站系统,一建建站系统api版,自动建站

安装推荐php7.2或7.2以下都行 可使用虚拟主机或者服务器进行搭建。 分站进入网站后台 域名/admin 初始账号123456qq.com密码123456 找到后台的网站设置 将主站域名及你在主站的通信secretId和通信secretKey填进去。 即可正常使用 通信secretId和通信secretKey在主站的【账号…...

算法框架-LLM-1-Prompt设计(一)

原文&#xff1a;算法框架-LLM-1-Prompt设计&#xff08;一&#xff09; - 知乎 目录 收起 1 prompt-engineering-for-developers 1.1 Prompt Engineering 1.1.1 提示原则 1. openai的环境 2. 两个基本原则 3. 示例 eg.1 eg.2 结构化输出 eg.3 模型检验 eg.4 提供示…...

一个rar压缩包如何分成三个?

一个rar压缩包体积太大了&#xff0c;想要将压缩包分为三个&#xff0c;该如何做到&#xff1f;其实很简单&#xff0c;方法就在我们经常使用的WinRAR当中。 我们先将压缩包内的文件解压出来&#xff0c;然后查看一下&#xff0c;然后打开WinRAR软件&#xff0c;找到文件&…...

批量获取拼多多商品详情数据,拼多多商品详情API接口

批量获取拼多多商品详情数据可以采用以下方式&#xff1a; 使用拼多多开放平台API接口。 拼多多开放平台提供了API接口&#xff0c;可以通过API接口获取拼多多平台上的商品信息&#xff0c;使用API接口需要进行权限申请和认证&#xff0c;操作较为复杂。 使用第三方工具。 市面…...

Redis Cluster Gossip Protocol: 目录

术语说明 server&#xff1a;当前的节点 cluster&#xff1a;每个节点的内存中都有一个集群信息结构&#xff0c;里面包含了集群中各个节点的状态信息&#xff08;包括server自己&#xff09; myself&#xff1a;当前节点在cluster中的实体 node&#xff1a;cluster节点字典中…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈

在日常iOS开发过程中&#xff0c;性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期&#xff0c;开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发&#xff0c;但背后往往隐藏着系统资源调度不当…...