3

我有相机类,它处理相机行为。其中的字段是对目标的 Cube 类的引用(Cube 只是对象之一,但为了简单起见,我不会提及其他)。为了计算 View 矩阵,我需要相机的位置和目标的位置,所以我可以向我的程序解释:“相机放在这里,从这里看这个立方体”。如果立方体碰巧四处移动,相机的视角也会自动改变。

到目前为止,一切都很好:有一个 Camera 类依赖于 Cube 类,还有一个 Cube 类不依赖任何东西(在这个例子中)。

当我需要绘制一个立方体或其他任何东西时,我遇到了一个问题——为了绘制一些东西,在所需的值中,它是相机的视图矩阵;这就是我刚刚在第一段中计算的那个。本质上,这意味着当我开始在屏幕上绘制东西时,Cube 类也变得依赖于 Camera 类,并且它们现在相互依赖。这意味着我要么:

  1. 需要将Camera类的View矩阵字段设为静态,这样我就可以直接从Cube类中访问了。
  2. 需要在 Cube 类中创建一个方法(例如 SetView),然后我可以从 Camera 类中调用该方法(因为我已经有它的引用)。
  3. 需要将视图矩阵保持在外部范围内。
  4. 需要做一个双向依赖。

但是,我不喜欢其中任何一个:

  1. 有更多的摄像机可以处理多个视图(目前屏幕上有 3 个)并且可能更多(或更少)。
  2. 这使得代码稍微(有时,也许,非常)不可读——例如,当我绘制立方体时,视图矩阵的来源不是很清楚,你只是有点使用它,不要回头。
  3. 我会从相机类访问外部范围,或者外部范围将访问相机,我不喜欢这样,因为外部范围仅用于处理执行机制。
  4. 我喜欢将我的引用字段保持为“只读”,因为它目前在这个系统中无处不在——引用是在构造函数中设置的,并且仅用于从引用的类中获取数据。

而且,如果我没有说清楚,让我重复一下,有多个 Camera 对象,以及多个 Cube 对象;而任何相机可能会或可能不依赖于任何立方体,但通常至少有一个相机依赖于立方体。

任何建议,将不胜感激 :)

4

5 回答 5

2

If your Cube must know how to render itself with respect to a Camera (and therefore must know about the Camera), then it probably doesn't make sense for the Camera to know how to align itself to a Cube. The alignment behavior that's currently in Camera probably belongs in a higher-level class like a CameraDirector that knows about both Cubes and Cameras. This improves class cohesion, as it splits off some of the responsibilities of Camera into a different, tightly-focused CameraDirector class. This lets the Camera focus on its core job and makes it easier to understand and maintain.

于 2010-10-18T15:37:46.037 回答
1

假设您的DrawWorld()例程已经知道Cubes 和Cameras,我会将视图矩阵传递给Cube'sDraw()方法:

foreach (Cube cube in cubes) {
    cube.Draw(..., mainCamera.ViewMatrix, ...);
}

这种方式Cube只“依赖”Matrix而不是Camera。再说一次,也许这违反了上面的规则 3。不过,如果没有看到您的一些代码,我将无法做得更好。

于 2010-10-18T14:07:29.197 回答
1

两个备选方案:

  1. 为彼此不链接但仍包含您要使用的大部分逻辑的 Camera 和 Cube 创建基类。然后,您可以添加对 Cube 的 BaseCamera 引用,您将为其分配一个 Camera 对象,而不是 BaseCamera 对象。(还有一个带有 BaseCube 字段的相机。)这就是多态性的力量。
  2. 定义一个 ICamera 和 ICube 接口。然后,Camera 类将使用 ICube 字段链接到多维数据集,反之亦然。

不过,这两种解决方案都要求您在创建和释放新的相机和立方体对象时要小心。我个人的偏好是使用接口。请记住,ICube 和 ICamera 接口不应相互链接。它们的相关类将链接到另一个接口,但不链接到接口。

于 2010-10-18T14:14:47.590 回答
1

我让每个对象类负责它自己的渲染。

在您的情况下,您必须将图形实例和相对于对象的视点传递给每个渲染方法。

绘图类可以访问所有对象类的实例,并以任何有意义的顺序调用每个对象的绘图方法。您的对象类可能必须有另一个方法来确定与视点的距离,以便您可以按最远到最近的顺序调用绘图方法。

于 2010-10-18T14:34:38.993 回答
0

在做 XNA 时,我遇到了一个类似的问题。

我通过将相机接口添加到我的 Draw 方法接口中来解决它。

它不漂亮,相机到处都是,但效果很好。

真正要得到的是你的更新和绘制循环是分开的。

绘制时,您有一个要绘制的对象列表,并且您的绘制例程有一些相机类传递给它。

以一种方式对您的类进行编码以生成需要渲染的所有对象的列表的替代方法。将此传递给包含相机的渲染器。

关键是要维护一个摄像机列表以及一个可绘制对象列表,尽管所有这些对象也属于描述游戏状态的逻辑模式。

阅读控制反转。这就是我真正描述的一切。

于 2010-10-18T14:17:15.510 回答