Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Lua 3d中圆上最近的点。什么';她失踪了?_Lua_Collision Detection_Linear Algebra_Vectormath - Fatal编程技术网

Lua 3d中圆上最近的点。什么';她失踪了?

Lua 3d中圆上最近的点。什么';她失踪了?,lua,collision-detection,linear-algebra,vectormath,Lua,Collision Detection,Linear Algebra,Vectormath,我希望我能解释清楚这一点。我试图在3D中计算圆上最近的点。我找到了以下解决方案: 我的代码如下(用Lua编写)。主要问题是投影Q似乎不正确,或者我不知道如何正确计算它。正如你在纸上看到的,Q应该是点在圆平面上的投影 例如,圆的法线为{0,1,0},其中心位于{3,3,3}。我试图计算离圆最近距离的点(p)位于{6,3,2}。然后,在我的计算中,圆平面上的投影Q是{6,0,2} 为了使算法工作,我似乎必须用平面的位置偏移Q,例如圆心分量在其法线方向上的位置。在这种情况下,y方向的值为3 我可以对

我希望我能解释清楚这一点。我试图在3D中计算圆上最近的点。我找到了以下解决方案:

我的代码如下(用Lua编写)。主要问题是投影Q似乎不正确,或者我不知道如何正确计算它。正如你在纸上看到的,Q应该是点在圆平面上的投影

例如,圆的法线为{0,1,0},其中心位于{3,3,3}。我试图计算离圆最近距离的点(p)位于{6,3,2}。然后,在我的计算中,圆平面上的投影Q是{6,0,2}

为了使算法工作,我似乎必须用平面的位置偏移Q,例如圆心分量在其法线方向上的位置。在这种情况下,y方向的值为3

我可以对正常的{0,1,0}进行破解,因为这很容易,但是一旦圆面对任意位置,我就不知道如何计算它了

我错过了什么?我错在哪里

function calculatePointCircleDistance(p, circleCenter, circleNormal, circleRadius)
local C = circleCenter
local R = circleRadius
local Q = projectVectorOntoPlane(p, circleNormal)

-- I need to do a fix like this in order to get the calculations right
-- This for example only works with circleNormal {0,1,0}
-- Adding the y component of the circle position to the projection Q
Q[2] = C[2]

if vec3.equal(Q, C) == 1 then
    print("point exacly aligned with center circle")
    return vec3.mag(vec3.sub(C, p)), C
end

-- the following is calculating X=C+R (Q−C / |Q−C|)
local QminC = vec3.sub(Q, C)
local tmp = vec3.scale(vec3.div(QminC, vec3.mag(QminC)), R)
local X = vec3.add(C, tmp)

-- return distance as |X-p| as well as point X
return vec3.mag(vec3.sub(X, p)), X
end



function projectVectorOntoPlane(v, normal)
-- U = V - (V dot N)N
local vProjected = vec3.sub(v, vec3.scale(normal, vec3.dot(v, normal)))
return vProjected
end

我认为,你链接到的那份报纸对这次行动有点影响

您的问题是
projectvectornoplane
实际上并没有将向量投影到您想要的平面上。它将向量投影到另一个平面上,该平面与所需平面平行,但通过原点。(然后您试图用
Q[2]=C[2]
来解决这个问题,但这只会让事情变得更糟。)

平面可以由法向量和平面上的某个点定义,因此您可以像这样编写
projectVectorOntoPlane
函数:

-- Project P onto the plane with normal n containing the point O.
function projectVectorOntoPlane(P, n, O)
    return vec3.sub(P, vec3.scale(n, vec3.dot(vec3.sub(P, O), n)))
end
-- Return a point on the circle with center C, unit normal n and radius r
-- that's closest to the point P. (If all points are closest, return any.)
function pointCircleClosest(P, C, n, r)
    -- Translate problem to C-centred coordinates.
    local P = vec3.sub(P, C)

    -- Project P onto the plane containing the circle.
    local Q = vec3.sub(P, vec3.scale(n, vec3.dot(n, P)))

    -- If Q is at the centre, all points on the circle are equally close.
    if vec3.equal(Q, {0,0,0}) then
        Q = perpendicular(n)
    end

    -- Now the nearest point lies on the line through the origin and Q.
    local R = vec3.sub(P, vec3.scale(Q, r / vec3.mag(Q)))

    -- Return to original coordinate system.
    return vec3.add(R, C)
end

-- Return an arbitrary vector that's perpendicular to n.
function perpendicular(n)
    if math.abs(n[1]) < math.abs(n[2]) then
        return vec3.cross(n, {1,0,0})
    else
        return vec3.cross(n, {0,1,0})
    end
end
但是,对于这个问题,最简单的方法是在基于圆心的坐标系中进行计算,因此我建议如下:

-- Project P onto the plane with normal n containing the point O.
function projectVectorOntoPlane(P, n, O)
    return vec3.sub(P, vec3.scale(n, vec3.dot(vec3.sub(P, O), n)))
end
-- Return a point on the circle with center C, unit normal n and radius r
-- that's closest to the point P. (If all points are closest, return any.)
function pointCircleClosest(P, C, n, r)
    -- Translate problem to C-centred coordinates.
    local P = vec3.sub(P, C)

    -- Project P onto the plane containing the circle.
    local Q = vec3.sub(P, vec3.scale(n, vec3.dot(n, P)))

    -- If Q is at the centre, all points on the circle are equally close.
    if vec3.equal(Q, {0,0,0}) then
        Q = perpendicular(n)
    end

    -- Now the nearest point lies on the line through the origin and Q.
    local R = vec3.sub(P, vec3.scale(Q, r / vec3.mag(Q)))

    -- Return to original coordinate system.
    return vec3.add(R, C)
end

-- Return an arbitrary vector that's perpendicular to n.
function perpendicular(n)
    if math.abs(n[1]) < math.abs(n[2]) then
        return vec3.cross(n, {1,0,0})
    else
        return vec3.cross(n, {0,1,0})
    end
end
——返回圆心C、单位法向n和半径r的圆上的点
--最接近点P(如果所有点都最接近,则返回任意点)
函数点CircleClosest(P、C、n、r)
--将问题转换为以C为中心的坐标。
局部P=vec3.sub(P,C)
--将P投影到包含圆的平面上。
局部Q=vec3.sub(P,vec3.scale(n,vec3.dot(n,P)))
--如果Q在中心,则圆上的所有点都相等接近。
如果向量3等于(Q,{0,0,0}),那么
Q=垂直(n)
结束
--现在,最近的点位于通过原点和Q的直线上。
局部R=vec3.sub(P,vec3.scale(Q,R/vec3.mag(Q)))
--返回到原始坐标系。
返回vec3.add(R,C)
结束
--返回一个垂直于n的任意向量。
函数垂直(n)
如果math.abs(n[1])

哦,您可能会发现使用更好的
vec3
类更方便,这样您就可以编写
p-C
而不是繁琐的
vec3.sub(p,C)
等等,这似乎是一个四元数的工作,这是没有乐趣,但发明的原因是,没有任何其他做的把戏时,定向在3空间。非常感谢你!你真的救了我一天。感谢您抽出时间提出一个更优雅、更高效的替代方案。我之所以使用这些vec3类,是因为它们与嵌入Lua代码的环境一起提供。我同意这样做会更好。在这之后,我将发布另一个关于向量数学的问题,也许你可以看一下…更正:localr=vec3.sub(P,vec3.scale(Q,R/vec3.mag(Q)))应该改为localr=vec3.scale(Q,R/vec3.mag(Q))。