最近因为项目要做显示一个三维模型,所以研究了下如何在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
运行程序
文章来源:https://www.toymoban.com/news/detail-731809.html
PS:
如遇“托管调试助手 “LoaderLock”报错“Message=托管调试助手 “LoaderLock”:“正尝试在 OS 加载程序锁内执行托管代码。不要尝试在 DllMain 或映像初始化函数内运行托管代码,这样做会导致应用程序挂起。””,可以快捷键Ctrl+Alt+E,改动Managed Debuggin Assistants->LoaderLock 的选中状态去掉。文章来源地址https://www.toymoban.com/news/detail-731809.html
到了这里,关于C#使用DirectX SDK 加载.x三维模型的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!