0

我在 C# 中使用 DirectX 9
我将所有顶点存储在一个列表(不是数组)中,因为我使用动态 LOD 算法,所以所有内容都是按帧计算的,所以我的顶点可能每帧都不同。

一切正常,直到我尝试添加法线和照明。
我发现一旦将顶点添加到列表中,就无法编辑法线,因为它是结构而不是类的列表。所以它只会给出一个错误,比如“无法修改 blablaba 的返回值,因为它不是变量”
例如,如果我尝试这样做,它将不起作用 -

vertices[i].Normal = new Vector3(0, 1, 0);

将顶点放入列表时必须添加法线,但在拥有完整网格之前无法计算法线。

所以我做了一个新的自定义顶点类型,而不是把它变成一个结构,我把它变成了一个类。这也不起作用,因为directx不会接受它,除非它是一个结构......

因此,我尝试使其与数组而不是顶点列表一起使用。这导致每秒少于一帧。我不得不使用 Array.Resize 每帧将数组的大小更改几百次,我猜它不喜欢那样。

你可能在想我应该把最终的列表变成一个数组,然后从那里计算法线。这不起作用,因为顶点不是以任何特定顺序添加的,所以我不知道哪些顶点靠近给定顶点以便能够计算法线。

那么,如何在构建网格后以一种可以给它们法线的方式存储顶点?

4

1 回答 1

1

C# 阻止您编写vertices[i].Normal = new Vector3(0, 1, 0),因为该表达式不会执行您想要的操作。与数组索引器不同,List<T>索引器返回指定元素的副本,并且因为顶点是结构体,所以复制了整个顶点,Normal等等。您将更新顶点的临时副本,而不是列表中的实际顶点。

解决方法是从列表中获取(副本)顶点,对其进行更新,然后将其放回(副本):

var vertex = vertices[i];
vertex.Normal = new Vector3(0, 1, 0); 
vertices[i] = vertex;

不幸的是,没有简单的方法可以避免这种重复复制。

于 2012-01-30T03:40:35.230 回答