使用 rayTraceP
进行光线追踪时,我可以找到射线与图相交的点。
> rayTraceP (p2 (0, 0)) (r2 (1, 0)) ((p2 (1,-1) ~~ p2 (1,1))
Just (p2 (1.0, 0.0))
我想用它不仅可以找到“碰撞点”,还可以找到碰撞时间和该点表面的法向矢量。
-- A Collision has a time, a contact point, and a normal vector.
-- The normal vector is perpendicular to the surface at the contact
-- point.
data Collision v n = Collision n (Point v n) (v n)
deriving (Show)
给定射线的起点和沿射线的速度矢量,我可以使用rayTraceP
找到接触点end
:
end <- rayTraceP start vel dia
我可以使用 start
和 end
之间的距离找到碰撞时间:
time = distance start end / norm vel
但我一直在寻找法线向量。我正在这个函数中工作:
rayTraceC :: (Metric v, OrderedField n)
=> Point v n -> v n -> QDiagram B v n Any -> Maybe (Collision v n)
-- Takes a starting position for the ray, a velocity vector for the
-- ray, and a diagram to trace the ray to. If the ray intersects with
-- the diagram, it returns a Collision containing:
-- * The amount of time it takes for a point along the ray going at
-- the given velocity to intersect with the diagram.
-- * The point at which it intersects with the diagram.
-- * The normal vector to the surface at that point (which will be
-- perpendicular to the surface there).
-- If the ray does not intersect with the diagram, it returns Nothing.
rayTraceC start vel dia =
do
end <- rayTraceP start vel dia
let time = distance start end / norm vel
-- This is where I'm getting stuck.
-- How do I find the normal vector?
let normalV = ???
return (Collision time end normalV)
我想要它做什么的一些例子:
> -- colliding straight on:
> rayTraceC (p2 (0, 0)) (r2 (1, 0)) (p2 (1,-1) ~~ p2 (1,1))
Just (Collision 1 (p2 (1, 0)) (r2 (-1, 0)))
> -- colliding from a diagonal:
> rayTraceC (p2 (0, 0)) (r2 (1, 1)) (p2 (1,0) ~~ p2 (1,2))
Just (Collision 1 (p2 (1, 1)) (r2 (-1, 0))
> -- colliding onto a diagonal:
> rayTraceC (p2 (0, 0)) (r2 (1, 0)) (p2 (0,-1) ~~ p2 (2,1))
Just (Collision 1 (p2 (1, 0)) (r2 (-√2/2, √2/2)))
> -- no collision
> rayTraceC (p2 (0, 0)) (r2 (1, 0)) (p2 (1,1) ~~ p2 (1,2))
Nothing
除了法向量之外,这些示例中的所有内容都是正确的。
我查看了 Diagrams.Trace 的文档和 Diagrams.Core.Trace ,但也许我找错了地方。
最佳答案
一般来说没有办法做到这一点;这取决于你到底击中了什么。有一个模块Diagrams.Tangent用于计算轨迹的切线,但要计算给定点的切线,您必须知道其相对于轨迹的参数;目前我们缺少的一件事是一种从给定点转换为给定段/踪迹/路径上最近点的参数的方法(它已经在待办事项列表上有一段时间了)。
梦想更大,也许痕迹本身应该返回更多信息——不仅是参数告诉您击中的光线有多远,还包括有关您击中的内容的信息(从中可以更轻松地执行诸如计算法向量)。
您正在计算哪些事物的痕迹?可能有一种方法可以利用您的用例的特定细节,以一种不太糟糕的方式获得您想要的法线。
关于haskell - 光线追踪并找到交点处表面的法向量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52028449/