5

给定两个向量AB,它们形成线段L = AB。此外,给定一个由其左、右、下、上、近和远平面定义的视锥F。

我如何剪辑L反对F

也就是说,测试一个交叉点以及该交叉点在 L 上的哪个位置?(请记住,如果一条线段在拐角处与两侧相交,则它可以与平截头体有多个交点。)

如果可能,请提供代码示例(首选 C++ 或 Python)。

4

3 回答 3

4

我现在不想为此编写代码,但如果我正确理解“截锥体”,以下应该可以工作。

  1. 与所有给定平面相交线
  2. 如果你有两个路口,你就完成了。
  3. 如果您只有一个交点,请计算前平面并相交。
  4. 如果您仍然只有一个交点,请计算背板并相交。

但我可能完全误解了。在这种情况下,请详细说明:)

于 2008-09-16T22:21:31.997 回答
1

除了上面所说的下士 Touchy 所说的,您还需要知道如何将线段与平面相交。在该页面的描述中, u 表示您的线的参数定义中的参数。首先,使用描述的 2 种方法之一计算 u。如果 u 的值在 0.0 到 1.0 的范围内,则平面会剪裁线段上某处的线。将 u 插回您的直线方程可以为您提供该交点发生的点。

另一种方法是找到每个点到平面的有向距离。如果一个点的距离为正而另一个为负,则它们位于平面的相对两侧。然后,您知道哪个点在您的截锥体之外(基于您的平面法线指向的方式)。使用这种方法,通过基于有向距离的比率进行线性插值,可以更快地找到交点。例如,如果一个点的距离是 +12 而另一个是 -12,那么您知道平面将线段切成两半,并且您的 u 参数是 0.5。

希望这可以帮助。

于 2008-09-18T07:17:40.607 回答
1

首先从您的视图矩阵中提取平面

然后使用您的点将向量和最小值/最大值定义为 (0, 1),然后遍历平面并将它们与线段相交,更新最小值/最大值,如果min > max.

这是一个纯 Python 函数的示例,没有外部依赖。

def clip_segment_v3_plane_n(p1, p2, planes):
    """
    - p1, p2: pair of 3d vectors defining a line segment.
    - planes: a sequence of (4 floats): `(x, y, z, d)`.

    Returns 2 vector triplets (the clipped segment)
    or (None, None) then segment is entirely outside.
    """
    dp = sub_v3v3(p2, p1)

    p1_fac = 0.0
    p2_fac = 1.0

    for p in planes:
        div = dot_v3v3(p, dp)
        if div != 0.0:
            t = -plane_point_side_v3(p, p1)
            if div > 0.0:  # clip p1 lower bounds
                if t >= div:
                    return None, None
                if t > 0.0:
                    fac = (t / div)
                    if fac > p1_fac:
                        p1_fac = fac
                        if p1_fac > p2_fac:
                            return None, None
            elif div < 0.0:  # clip p2 upper bounds
                if t > 0.0:
                    return None, None
                if t > div:
                    fac = (t / div)
                    if fac < p2_fac:
                        p2_fac = fac
                        if p1_fac > p2_fac:
                            return None, None

    p1_clip = add_v3v3(p1, mul_v3_fl(dp, p1_fac))
    p2_clip = add_v3v3(p1, mul_v3_fl(dp, p2_fac))

    return p1_clip, p2_clip


# inline math library
def add_v3v3(v0, v1):
    return (
        v0[0] + v1[0],
        v0[1] + v1[1],
        v0[2] + v1[2],
        )

def sub_v3v3(v0, v1):
    return (
        v0[0] - v1[0],
        v0[1] - v1[1],
        v0[2] - v1[2],
        )

def dot_v3v3(v0, v1):
    return (
        (v0[0] * v1[0]) +
        (v0[1] * v1[1]) +
        (v0[2] * v1[2])
        )

def mul_v3_fl(v0, f):
    return (
        v0[0] * f,
        v0[1] * f,
        v0[2] * f,
        )

def plane_point_side_v3(p, v):
    return dot_v3v3(p, v) + p[3]
于 2016-01-23T06:50:55.453 回答