0

我正在做一个项目,我必须展示一些建筑物的 3D 模型,并且用户可以选择其中一个。他们可以自由旋转/移动/缩放 3D 模型,但现在我需要限制它们,这样他们就无法在模型下方看到、缩放太多或将模型从屏幕上移开。当前的代码有点神秘,因为我没有编写它,而且编写它的人并没有真正提供帮助,所以我决定重写它。

这是当前的轮换代码:

void Building3DLayer::rotate(float x, float y)
{
    if(!active) return;
    kmMat4 copy, rot;

    x /= 100.f;
    y /= 100.f;

    kmMat4Assign(&copy, &_state.modelview);
    kmMat4RotationY(&rot, x);
    kmMat4Multiply(&_state.modelview, &copy, &rot);

    kmMat4Assign(&copy, &_state.modelview);
    _state.rX += y;
    kmVec3 axis = {copy.mat[0],copy.mat[4],copy.mat[8]};
    kmMat4RotationAxisAngle(&rot, &axis, y);

    kmMat4Multiply(&_state.modelview, &copy, &rot);

    kmMat4Multiply(&_mvp, &_projection, &_state.modelview);
}

我可以用什么来实现这样的目标?我想我可以只使用一个 vec3 作为位置,一个用于旋转,一个浮动作为建筑比例(而不是转换为放大/缩小),但我不知道如何根据缩放来更改限制(如果你靠近它,你可以拖动建筑物比你远离它时所能拖动的更多)。我还阅读了关于轨迹球旋转的文章,它们是否比简单的向量更容易使用(并添加限制)(即使更难编写)?

4

1 回答 1

0

首先,不要更改转换的表示。矩阵是您的方案的理想选择。链接转换时,许多其他选项很难处理。如果您更改现有代码,您应该绝对确定自己在做什么。以前的程序员很可能有他的理由按照他的方式去做。

这个想法

我假设随后使用非常小的参数调用上述方法。然后您可以执行以下操作:

  1. 保存旧的转换
  2. 修改变换
  3. 将修改后的对象投影到屏幕上
  4. 检查结果是否符合您的约束
  5. 如果不是,则将转换恢复为前一个。

如果参数足够小,这应该可以工作。否则,您将不得不将转换分解为更小的步骤。

约束

第一个约束(用户不得查看模型下方)很容易实现。您只需要确定模型是否完全位于 z 近平面的前面。您可以通过计算模型边界球体到平面的有符号距离来近似此值。您也可以使用边界框甚至整个模型来执行此操作(尽管我不建议这样做)。

第二个(用户不得将模型移出屏幕)可以通过类似的方式实现。为此,您将需要视锥体平面。然后有几种方法。我建议始终将模型的中心保持在截锥体内(通过计算到所有平面的符号距离)。通过这种方式,可以将模型部分(但不是全部)移出屏幕,这可能是理想的。如果您不希望这样做,请进行更严格的检查(例如,使用整个包围体)。

于 2013-08-26T17:05:15.830 回答