C#使用DirectX SDK 加载.x三维模型

news2024/10/5 21:15:40

最近因为项目要做显示一个三维模型,所以研究了下如何在Winform中加载并显示三维模型。在Windows平台巨硬公司提供了DirectX SDK用于渲染图形,参考了几篇文章做了个demo记录下,以便日后温习只用。这个SDK涉及到了计算机图形学的一些基础知识,需要掌握一点基础,推荐可以看看OpenGL初学手册。

创建项目

我们开始返回正题,首先使用Visual Studio 2019创建一个Winform项目,然后添加DirectX 三个dll库的引用,路径是:C:\Windows\Microsoft.NET\DirectX for Managed Code\1.0.2902.0, 主要是前3个dll,后面的可用可不用。

添加控件

通过工具箱添加timer和panel控件,panel用于显示三位模型(也可不添加这个,直接用form显示),timer用于实时渲染。

 代码实现
/*--------成员变量声明-----------*/
//设备
private Device device;
//显示参数
private PresentParameters pres;
//保存3D文件
private Mesh mesh;
//渲染材质
private Material[] materials;
private Texture[] textures;


/*--------方法实现-----------*/
public bool InitializeGraphics()
{
    pres = new PresentParameters();
    pres.Windowed = true;
    pres.SwapEffect = SwapEffect.Discard;
    pres.EnableAutoDepthStencil = true;
    pres.AutoDepthStencilFormat = DepthFormat.D16;
    device = new Device(0, DeviceType.Hardware, panel1, CreateFlags.SoftwareVertexProcessing,
      pres);
    device.RenderState.CullMode = Cull.None;
    CreateMesh(@"airplane 2.x");
    //CreateMesh(@"lobby_skybox.x");
    return true;
}
public void CreateMesh(string path)
{
    ExtendedMaterial[] exMaterials;
    mesh = Mesh.FromFile(path, MeshFlags.SystemMemory, device, out exMaterials);
    if (textures != null)
    {
        DisposeTextures();
    }
    textures = new Texture[exMaterials.Length];
    materials = new Material[exMaterials.Length];
    for (int i = 0; i< exMaterials.Length; ++i)
    {
        if (exMaterials[i].TextureFilename != null)
        {
            string texturePath = Path.Combine(Path.GetDirectoryName(path), exMaterials[i].TextureFilename);
            textures[i] = TextureLoader.FromFile(device, texturePath);
        }
        materials[i] = exMaterials[i].Material3D;
        materials[i].Ambient = materials[i].Diffuse;
    }
}
public void DisposeTextures()
{
    if (textures == null)
    {
        return;
    }
    foreach (Texture t in textures)
    {
        if (t != null)
        {
            t.Dispose();
        }
    }
}

public void SetupMatrices()
{
    float yaw = Environment.TickCount / 500.0F;
    float pitch = Environment.TickCount / 500.0F;
    device.Transform.World = Matrix.RotationYawPitchRoll(yaw, pitch, 0);
    device.Transform.View = Matrix.LookAtLH(new Vector3(0, 0, -6), new Vector3(0, 0, 0), new Vector3(0, 1, 0));
    device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 2.0F, 1.0F, 1.0F, 10.0F);
}

public void SetupLights()
{
    device.RenderState.Lighting = true;
    device.Lights[0].Diffuse = Color.White;
    device.Lights[0].Specular = Color.White;
    device.Lights[0].Type = LightType.Directional;
    device.Lights[0].Direction = new Vector3(-1, -1, 3);
    device.Lights[0].Enabled = true;
    device.RenderState.Ambient = Color.FromArgb(0x00, 0x00, 0x00);
}

public void RenderMesh()
{
    for (int i = 0; i< materials.Length; ++i)
    {
        if (textures[i] != null)
        {
            device.SetTexture(0, textures[i]);
        }
        device.Material = materials[i];
        mesh.DrawSubset(i);
    }
}

public void Render()
{
    device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.SkyBlue, 1.0F, 0);
    device.BeginScene();
    SetupMatrices();
    SetupLights();
    RenderMesh();
    device.EndScene();
    device.Present();
}

public void DisposeGraphics()
{
    DisposeTextures();
    device.Dispose();
}
渲染实现

在Form1_Load事件中调用初始化函数,然后在timer的timer1_Tick事件中调用Render函数实时渲染

private void Form1_Load(object sender, EventArgs e)
{
    InitializeGraphics();
}

private void timer1_Tick(object sender, EventArgs e)
{
    Render();
}

 编译程序,编译之前设置32位模式,需要自己新建一个32位的编译模式

准备素材

需要安装为微软的DirectX SDK,链接: https://www.microsoft.com/zh-cn/download/details.aspx?id=6812

到这个路径下C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Samples\Media\Airplane复制三个资源文件到本地的的exe文件目录 RobotSimulator\DirectX3D\bin\x86\Debug

运行程序

PS:

 如遇“托管调试助手 “LoaderLock”报错“Message=托管调试助手 “LoaderLock”:“正尝试在 OS 加载程序锁内执行托管代码。不要尝试在 DllMain 或映像初始化函数内运行托管代码,这样做会导致应用程序挂起。””,可以快捷键Ctrl+Alt+E,改动Managed Debuggin Assistants->LoaderLock 的选中状态去掉。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1015701.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

听GPT 讲Istio源代码--operator

File: istio/istioctl/pkg/waypoint/waypoint.go 在Istio项目中&#xff0c;istio/istioctl/pkg/waypoint/waypoint.go文件是istioctl的源代码之一&#xff0c;用于管理Istio的路由规则。 revision变量用于指定Istio的版本号&#xff0c;例如可以值 v1.2.3。这个版本号用于检索…

openGauss学习笔记-71 openGauss 数据库管理-创建和管理普通表-删除表中数据

文章目录 openGauss学习笔记-71 openGauss 数据库管理-创建和管理普通表-删除表中数据 openGauss学习笔记-71 openGauss 数据库管理-创建和管理普通表-删除表中数据 在使用表的过程中&#xff0c;可能会需要删除已过期的数据&#xff0c;删除数据必须从表中整行的删除。 SQL不…

arcgis拓扑检查实现多个矢量数据之间消除重叠区域

目录 环境介绍&#xff1a; 操作任务&#xff1a; 步骤&#xff1a; 1、数据库和文件结构准备 2、建立拓扑规则 3、一直下一页默认参数后&#xff0c;进行拓扑检查 4、打开TP_CK_Topology&#xff0c;会自动带出拓扑要素&#xff0c;红色区域为拓扑错误的地方&#xff1…

Python 魔法方法

视频版教程 Python3零基础7天入门实战视频教程 Python的魔法方法&#xff0c;也称为特殊方法或双下划线方法&#xff0c;是一种特殊的方法&#xff0c;用于在类中实现一些特殊的功能。这些方法的名称始终以双下划线开头和结尾&#xff0c;例如__init__&#xff0c;repr&#x…

NV040D语音芯片丨助力空气净化器语音功能

空气净化器通过过滤网和电子静电等技术&#xff0c;可以清除室内空气中的有害物质&#xff0c;如灰尘、花粉、细菌、甲醛等&#xff0c;达到净化空气的目标&#xff0c;让人们呼吸到更加清新的空气&#xff0c;保护人体健康。在空气净化器中加入九芯语音芯片的提醒功能&#xf…

jvm 内存模型介绍

一、类加载子系统 1、类加载的过程&#xff1a;装载、链接、初始化&#xff0c;其中&#xff0c;链接又分为验证、准备和解析 装载&#xff1a;加载class文件 验证&#xff1a;确保字节流中包含信息符合当前虚拟机要求 准备&#xff1a;分配内存&#xff0c;设置初始值 解析&a…

Nginx运维知识基础详解

一. nginx简介 1. nginx介绍 nginx是一个HTTP和反向代理服务器&#xff0c;邮件代理服务器&#xff0c;通用的TCP/UDP代理服务器。 反向代理服务器&#xff1a; 作用就是负载均衡 2. 编译安装 #!/bin/bash#新建文件夹存放nginx源码包 mkdir -p /nginx cd /nginx# 下载nginx压…

2023-数仓建设规范指南

一、数据模型架构原则 1. 数仓分层原则 优秀可靠的数仓体系&#xff0c;往往需要清晰的数据分层结构&#xff0c;即要保证数据层的稳定又要屏蔽对下游的影响&#xff0c;并且要避免链路过长。那么问题来了&#xff0c;一直在讲数仓要分层&#xff0c;那数仓分几层最好&#x…

redis--windows配置--redis基础

写在前面&#xff1a; 文章目录 win安装配置密码配置服务服务已经存在 可视化工具运行类型基础类型 帮助文档命令通用命令string命令hashlistsetsortedset win安装 下载地址 然后一路next就可以了。 记得添加到环境变量 配置密码 在目录打开配置文件 搜索requirepass …

任意区域的色彩一致性处理方法

影像任意感兴趣区域的色彩一致性处理方法&#xff0c;主要是针对掩膜后的影像&#xff0c;类似下图&#xff0c;对非背景区域的像素进行处理 其中非黑色部分我们叫待匀色区域。 这种处理 对于wallis 和直方图匹配 很容易实现&#xff0c;但是颜色转移就相对而言 困难点。 颜…

【JavaScript保姆级教程】输出函数和初识变量

文章目录 前言一、输出内容1.1 document.write()函数1.2 console.log()函数查看终端输出信息 1.3 alert()函数 二、变量的使用1.1 变量的声明1.3变量的赋值1.4 变量的声明和赋值 三、输入提示框的使用总结 前言 JavaScript是一种强大的脚本语言&#xff0c;广泛应用于网页开发…

Linux中swap几乎耗尽,但物理内存还有空余的现象

故障现象&#xff1a; 产生此现象的原因&#xff1a; swappiness 配额设置了偏高的值。 还有一个潜在的因素是某个程序因其自身对内存管理的缺陷&#xff0c;形成了zombie进程、且为及时关闭的处理任务还在持续消耗Mem及swap。 解决办法&#xff1a; 调低swappiness 配额值&…

数据库连接工具Chat2DB介绍

1、Chat2DB介绍 Chat2DB 是一款有开源免费的多数据库客户端工具&#xff0c;支持windows、mac本地安装&#xff0c;也支持服务器端部署&#xff0c;web网页访问。和传统的数据库客户端软件Navicat、DBeaver 相比Chat2DB集成了AIGC的能力&#xff0c;能够将自然语言转换为SQL&a…

阿里云 服务器配置端口号阿里云网页开放的一个新端口后,重启防火墙,端口未启动

问题&#xff1a; 阿里云网页开放的一个新端口后&#xff0c;重启防火墙&#xff0c;端口未启动&#xff0c;之前配置的也都停止了。 解决&#xff1a; 原因可能是阿里的服务控制了&#xff0c;只能一个个端口开启了。把新配置新端口也单独启用。 开启80端口指令 firewall-cm…

【AIGC】Stable Diffusion Prompt 每日一练0916

一、前言 1.1 写在前面 本文是一个系列&#xff0c;有点类似随笔&#xff0c;每天一次更新&#xff0c;重点就Stable Diffusion Prompt进行专项训练&#xff0c;本文是第022篇《Stable Diffusion Prompt 每日一练0916》。上一篇《Stable Diffusion Prompt 每日一练0915》 1.…

查询linux系统中的cup和内存占用率?如何能够降低程序的cpu或者内存的占用率?

查询linux系统中的cup和内存占用率?如果查到具体是哪一个进程的cup占用率比较多&#xff0c;你会怎么做&#xff1f;如何能够降低程序的cpu或者内存的占用率? 要查询Linux系统中的CPU和内存占用率&#xff0c;您可以使用top命令&#xff0c;它可以显示系统的总体运行状态和每…

怒刷LeetCode的第1天(Java版)

目录 第一题 题目来源 题目内容 解决方法 方法一&#xff1a;暴力枚举 方法二&#xff1a;哈希表 第二题 题目来源 题目内容 解决方法 方法一&#xff1a;动态规划 第三题 题目来源 题目内容 解决方法 方法一&#xff1a;模拟 第一题 题目来源 两数之和 - 力…

【python爬虫—星巴克产品】

文章目录 需求爬取星巴克产品以及图片&#xff0c;星巴克菜单 python爬虫爬取结果 需求 爬取星巴克产品以及图片&#xff0c;星巴克菜单 网页分析&#xff1a; 首先&#xff0c;需要分析星巴克官方网站的结构&#xff0c;了解菜单栏的位置、布局以及菜单项的标签或类名等信息…

开源AI家庭自动化助手-手机控制家庭智能家居服务

产品简介 将本地控制和隐私放在首位的开源家庭自动化。由全球开发者和 DIY 爱好者社区提供支持。非常适合在 Raspberry Pi 或本地服务器上运行。 功能介绍 1. 控制面板在控制面板&#xff0c;你可以查看家庭的灯光&#xff0c;温度&#xff0c;门铃&#xff0c;音响&#xf…

激光切割机加工过程中产生毛刺的原因及解决方案

激光切割设备在进行工件加工时产生了大量的工件毛刺。很多人认为是设备质量问题&#xff0c;然而事实并非如此。 毛刺是指在金属制品加工过程中遗留在金属表面的超量残渣颗粒。加工的工件出现毛刺&#xff0c;那么即被认为是次品。 当使用激光切割设备加工工件时&#xff0c;如…