NSDT工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - AI模型在线查看 - Three.js虚拟轴心开发包 - 3D模型在线减面 - STL模型在线切割 - 3D道路快速建模
如果程序员可以将艺术家的作品转化为实时 3D 环境,游戏就会好得多。 对于许多程序员来说,3D Studio MAX 是预计算和实时 3d 场景的首选工具。 而且,在笔者看来,Microsoft 的 DirectX API 是 Windows 平台上最高效的游戏 API
本文介绍了如何创建 3DS MAX 插件以将艺术家的作品导出到你的实时 3D 引擎中。 我的说明将带你了解 MAX 和 Direct3D API。 虽然不需要任何经验,但你应该熟悉 Visual C++、Windows、Direct3D(使用立即模式的绘图基元)以及计算机图形基础知识。
我将从 MAX 的 API 开始,介绍如何使用它来创建新插件。 有了这些知识,我们就可以使用 Visual C++ 实现插件的项目了。 对于真正具体的东西,例如网格和材质导出,你将不得不等待下一篇文章。
1、3DS MAX插件开发介绍
3DS MAX 主要处理有关 3d 对象实现的网格。 面片和 NURBS 也得到管理,但由于强大的几何管线使得将它们转换为网格成为可能,所以这应该不是问题。 基于 NURBS 的对象的导出会使实时 3D 变得非常困难和不合适。 这种灵活性是 3DS MAX 成为游戏开发标准的原因。 如果你已经拥有第二个版本,您将享受与第一个版本相比的性能。 在第二个版本中进行了许多更改,因此两个版本之间的插件不兼容。 绕过这种不兼容性只需要重新编译和可能的一些更改。 因此,考虑到这一点,无论你拥有哪个 MAX SDK 版本,本文中介绍的技术都将起作用。
2、我需要什么?
在软件方面,你需要 Microsoft Visual C++。 虽然 4.0 版本足以为第一个版本的 3DS MAX 创建插件,但如果你使用 MAX2 SDK,将迫切需要 5.0 版本。 至于 API,你当然需要 MAX 的 SDK 和 DirectX 5 版本。
虽然 CPU 速度在硬件方面并不是非常重要,因为它不会影响编译/测试时间,但我强烈建议你至少使用 64 Mb RAM。 如果你拥有的更少,MAX、Visual C++ 和你的项目将无法留在内存中。 发生这种情况时,编译时间将乘以 5,加载 MAX 至少需要 20 秒。 不用说,这可能会让人抓狂。
如果你的插件项目位于已经包含 3d 游戏引擎等项目的工作区内,128 Mb RAM 就足够了。
MAX SDK 为开发人员提供了创建多种插件的可能性,从程序对象到视频后期处理。 一个名为“文件导出”的插件类型特别令人感兴趣。 然而,这不是我推荐的类型。 导出插件用于导出整个 MAX 场景,无需与用户进行任何交互,在我们目前的情况下,这不是我们想要的。 实用程序插件更灵活,以防你想要选择要导出的场景组件以及导出方式。
3、3DS MAX理念
作为 MAX 插件开发人员,你必须了解 MAX 的内部结构。 本文的其余部分将向你介绍基本概念,例如几何管道、场景节点的操作、微积分实现和插件的接口。 如果你喜欢面向对象编程,你会喜欢 MAX 的 API:一切都是根据 OOP 哲学制作的,你会发现几乎所有你能想到的东西(网格、面、点、矩阵……)的类。
4、节点操作
什么是节点? 在 MAX 中,节点是对象的视觉表示(这里,术语“对象”表示 3D 对象、光线、相机、形状等)。 节点相互链接以形成层次结构。 这个层级的根节点是 MAX 场景。 要实现 MAX 导出器插件,熟悉节点的操作很重要,因为它们是你转换的起点。
我们可以用节点做什么? 从 MAX 的类 INode 创建和控制节点。 我不打算详细介绍这个类,MAX 的帮助文件会比我做的更好,但我只会评论一些对我们的导出器有用的东西。
节点的主要功能是引用与其关联的对象。 可以在给定时间在世界中评估此对象的状态(其在视口中的表示)。 有关详细信息,请参阅几何管道。 评估此对象后,您可以检索其所有特定数据,稍后我们将看到如何执行此操作。
关于层次结构……从一个节点,您可以使用 INode::GetParentNode()
、 INode::NumberOfChildren
和 INode::GetChildNode()
方法获取其父节点、其子节点的数量和特定子节点。 要扫描整个场景,您只需获取根节点(使用插件接口的函数),然后使用下面给出的函数。
可以检索其他属性,如节点的变换矩阵(变换矩阵由位置、方向和比例因子组成)、对象的变换矩阵、它的引用和它的名称。
现在了解了节点的基本工作原理,让我们解释一下对象如何借助几何管道工作。
5、几何管线
这是MAX最根本的理念和创新。 如果你已经使用过 3D Studio/DOS,就会知道如何创建网格。 你可以首先使用 2D 造型器创建许多 2D 形状,然后使用 3D 放样器基于这些形状创建 3D 对象。 要对其应用修改(顶点置换、布尔运算、映射等),你可以使用 3D 编辑器。 每次对 2D 形状或 3D 对象进行修改时,先前的状态都会丢失,因为修改会直接应用于构成 2D 形状或 3D 对象的实体(面、顶点、2d 样条)。
MAX 使用另一种方法来创建几何组件,称为“程序方法”。 每个节点都包含一个节点管道。 在此管道的开头是基础对象。 每次对节点应用修改时,你使用的修改器都会在节点管道中引用,并带有设置的参数。 然后,几何管道评估节点的管道以创建节点对象的世界空间状态。 这个世界空间状态就是你可以在 MAX 的视口中看到的。
好吧,让我们来看看模型是什么“顶级”。 不要指望一个很好的,我只是一个程序员!
该模型可以分两步制作:创建一个球体并在其上应用锥度。
创建球体时,还会创建一个新节点并将其插入到 MAX 场景中。 节点引用的对象是节点的基础对象(球体)。 由于它是一个程序对象,球体对象在这个阶段不是由面和顶点构成的。 根据你指定的参数,可以将该对象生成为网格。
下图1是该阶段节点及其World Space State的几何管线表示。
在第二步中,在我们的节点上应用了 Taper Modifier,你可以在上图 中看到结果(我还指定了一个纹理贴图)。 该节点现在指向我们所说的“派生对象”。 此派生对象是几何管道解释节点管道的结果。
派生对象之后是锥度修改器,最后是我们的基础对象:球体。
假设对对象应用弯曲。 此修改器将出现在派生对象之后和锥化之前的管道中。 在 MAX 的修改器栈的帮助下,你可以更改想要的任何修改器(甚至是基础对象)的参数。 你还可以在 Stack 中的任意位置移除或插入修饰符。 任何时候对象的世界空间状态都将被重组:这是几何管道的工作。
可以使用 INode::EvalWorldState()
方法评估节点的世界空间状态对象。 该方法返回一个 ObjecState 类的 C++ 对象。 从该对象中,你可以检索由几何管道评估的对象。 评估的对象也是从 Object 类派生的类的 C++ 对象。 MAX 实现了许多派生自 Object 类的类。
在本系列的后面,我们将看到如下类:
- TriObject:定义由三角形构成的网格对象
- CameraObject:定义自由或目标相机
- LightObject:定义泛光灯、平行光、目标聚光灯或自由聚光灯
6、一点计算
MAX 的 API 提供了一组类和函数,使矩阵、点和四元数的使用更加容易。 由于点的操作并不是真正的大挑战,因此我不打算概述 Point3 类。 谈论四元数超出了本文的范围,因为它们主要用于处理动画。 所以只解释矩阵的基本原理。 开始了。
7、变换矩阵
转换矩阵用于从一个给定的坐标系切换到另一个坐标系; 例如,将对象顶点的坐标从本地坐标系转移到世界空间坐标系。 变换矩阵也用于定位场景中的节点。 这些矩阵提供的变换是:平移、旋转和缩放。 这样的矩阵可以通过 MAX 的 Matrix3 类创建和使用。
在 MAX 中,矩阵有 4 行 3 列。 通常,3D 矩阵是 4x4 而不是 4x3。 MAX 也是如此,但由于此类矩阵的最后一列始终为 [0 0 0 1],因此它由处理它的类和函数隐式管理。
max使用的坐标系是右手坐标系,从轴的正方向看是逆时针的,如下图所示。
现在让我们看看身份、平移、旋转和缩放是如何编码的。 单位矩阵具有在向量/矩阵或矩阵/矩阵乘法期间保持向量或矩阵不变的属性。 它的编码如下:
可以通过将 1 传递给 Matrix3 类的构造函数或调用方法 Matrix3::IdentityMatrix()
来将矩阵初始化为恒等式。
平移以这种方式存储在矩阵中:
可以使用 Matrix3::SetTrans()
设置平移,使用 Matrix3::GetTrans()
检索,使用 Matrix3::NoTrans()
设置为空。
围绕三个轴旋转的矩阵如下所示。 旋转的角度始终以弧度表示。
X旋转:
Y旋转:
Z 旋转:
这些矩阵可以使用全局函数 RotateXMatrix()
、 RotateYMatrix()
、 RotateZMatrix()
创建。 可以使用 Matrix3 的方法 Matrix3::RotateX()
、 Matrix3::RotateY()
、 Matrix3::RotateZ()
执行围绕一个特定轴的增量旋转。
还提供了 Matrix3 类的方法来创建 Yaw/Pitch/Roll 角度矩阵(使用欧拉角规则): Matrix3::RotateYPRMatrix()
。
比例因子编码如下:
比例因子可以使用 Matrix3::SetScale()
设置,或使用 Matrix3::NoScale()
重置为 1。
在本文的最后一部分,我们将简要了解插件如何访问 MAX 功能。
8、插件接口
插件的接口是在插件初始化期间检索到的 C++ 接口。 术语接口表示 C++ 对象仅包含方法。 插件接口用于提供 MAX 提供给插件的 API。 从它提供的 API 列表中,以下内容与我们的导出器有关。
9、命令面板
由于我们将使用的插件类型是 Utility Plugin,因此我们必须设计一个对话框,该对话框将在插件初始化期间出现在 Utility Plugin 的 Pan 中。 该对话框将以 Rollup Page 的形式出现。 插件接口的方法将用于添加和删除此汇总页面对话框。
节点相关方法:通过使用这个 API 的函数,我们可以访问场景的根节点,从它的名字访问一个节点。
节点选取:提供调用MAX交互节点选择对话框的函数。 用于选择我们要导出的节点。
标准 MAX 对话框:可以使用此 API 调用 Track View Pick Dialog、Material Browse Dialog。
原文链接:From 3D Studio MAX to Direct 3D: Introduction to Plugin Development
bBimAnt翻译整理,转载请标明出处