如何在 XNA 中访问模型的脸部?
我正在为使用 Microsoft XNA 框架版本 4.0 编写的游戏进行碰撞检测。当内容框架加载模型后尝试访问模型本身时,我可以访问“ModelMesh”列表,并且每个模型都有一个 MeshPart 列表,但这些部件似乎只有诊断数据,例如顶点数量。我完全不知道模型的实际面部数据发生了什么。
我正在尝试实现球体扫描/平面碰撞 - 也就是说,我有一个移动的球,我想在球移动时测试与多边形的碰撞。我需要一种方法来定义要测试的所有多边形,对我来说将碰撞图定义为简化的网格是有意义的,我与实际图形对象并行设计以用于碰撞,但我完全不知道我很困惑,一旦 XNA 的内容管道加载了该信息,我该如何访问该信息。
也许这里有一些见解?我一整天都在搜索谷歌,但我找不到任何可能有帮助的东西,尽管我可能使用了错误的搜索词......
I'm working on collision detection for a game written using the Microsoft XNA framework version 4.0. When trying to access the model itself once it's been loaded by the content framework, I can access a list of "ModelMesh"es, and for each one a list of MeshParts, but the parts only seem to have diagnostic data like the number of vertices. I'm completely stumped as to what's happened to the actual face data for the model.
I'm trying to implement sphere-sweep/plane collision-- that is, I have a ball moving and I'd like to test collision with a polygon as the ball moves. I need a way to define all the polygons to test with, and it just makes sense to me to define a collision map as a simplified mesh that I design in parallel with my actual graphics object to use for the colliding, but I'm completely baffled as to how I'm supposed to access that info once XNA's content pipeline has loaded it.
Some insight here perhaps? I've been combing Google all day and I'm unable to locate anything that might help, although it's possible that I'm using the wrong search terms...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
内置的 XNA FBX/模型内容导入器和处理器处理“面”的方式与几乎所有建模程序相同 - 作为顶点和索引列表。 (顺便说一句,您的 GPU 本身也支持此方案,并且现代游戏出于性能原因依赖它。)
例如,考虑一个简单的两个三角形四边形。顶点可能是:
或者,
要以“面”形式表示,您需要一个相当于
三角形 1(左上)的数据列表:(0,0,0),(1,0,0), (0,1,0) = (v0,v1,v3)
三角形 2(右下):(1,0,0),(1,1,0),(0,1,0) = (v1, v2,v3)
需要六个顶点记录。
使用 XNA 原生结构,Vector3 具有三个元素,每个元素都是单精度浮点数(4 字节),因此每个元素为 3*4=12 字节,而您需要其中 6 个元素,即 72 字节。
或者,您可以使用索引。除了四个顶点之外,您还可以存储索引列表:
可以使用短整型(16 位整数)来存储索引。那么,让我们检查一下差异:
没有索引:两个面 * 3 个顶点 * 3 个分量 (xyz) * 每个 4 字节 = 2*3*3*4=72 字节。
索引:
顶点:4 个顶点 * 每个组件 3 个组件 * 每个组件 4 个字节 = 48 字节,
索引(每个三角形 3 个短路):6 个索引 * 每个组件 2 个字节 = 12 字节。
48 + 12 = 60,略小于非索引模型的 72 字节。
除非您考虑包含 100,000 多个三角形的整个关卡,否则这 12 个字节可能看起来并不多。此时,您会看到 1.2MB 的差异。尽管您的显卡可能有大约 2+GB 内存,但在主机 RAM 和 GPU RAM 之间来回移动数据的成本很高。
那么,如何获取这些数据呢?
查看 Model.Meshes[].MeshParts[].VertexBuffer.GetData() 和
Model.Meshes[].MeshParts[].IndexBuffer.GetData()
。您可以使用这些方法来提取顶点和索引,然后交叉引用两者来获取三角形列表。您不能直接访问
VertexBuffer
和IndexBuffer
的元素,因为它们存储在 GPU 的 RAM 中 - 允许随机元素访问会将性能拖至接近负值此外,请查看
GraphicsDevice.DrawIndexedPrimitives()
方法。如果需要的话,我可以稍后发布一些示例代码。
The built-in XNA FBX/model content importer and processor handle "faces" the same way that just about every modeling program out there does - as lists of vertices and indices. (As a side note, your GPU also natively supports this scheme, and modern games rely upon it for performance reasons.)
For instance, consider a simple, two-triangle quad. The vertices might be:
or,
To represent this in "face" form, you'd need a list of data equivalent to
triangle 1 (upper-left): (0,0,0),(1,0,0),(0,1,0) = (v0,v1,v3)
triangle 2 (lower-right): (1,0,0),(1,1,0),(0,1,0) = (v1,v2,v3)
which requires six vertex records.
Using XNA-native structures, a Vector3 has three elements, each of which are single-precision floats (4 bytes), so that's 3*4=12 bytes each, and you need six of them, so that 72 bytes.
Or, you can use indexing. In addition to the four vertices, you store a list of indices:
Indices can be stored using shorts (16-bit integers). So, let's examine the difference:
No indices: two faces * 3 vertices*3 components (xyz) * 4 bytes each = 2*3*3*4=72 bytes.
Indexed:
vertices: 4 vertices * 3 components each * 4 bytes per component = 48 bytes,
indices (3 shorts per triangle): 6 indices * 2 bytes each = 12 bytes.
48 + 12 = 60, which is slightly less than 72 bytes for the non-indexed model.
That 12 bytes might not seem like a lot until you consider an entire level with 100,000+ triangles. At that point, you're looking at a 1.2MB difference. Although your graphics card may about 2+GB of memory, moving that data back and forth between host RAM and GPU RAM is expensive.
So, how do you get that data?
Look at
Model.Meshes[].MeshParts[].VertexBuffer.GetData()
andModel.Meshes[].MeshParts[].IndexBuffer.GetData()
. You can use those methods to extract the vertices and indexes, then cross-reference the two to get the triangle list.You can't just directly access the elements of
VertexBuffer
andIndexBuffer
because they are stored in the GPU's RAM - allowing random element access would drag performance to near-negative velocity.Also, have a look at the
GraphicsDevice.DrawIndexedPrimitives()
method.I can post some example code later if necessary.