簡體   English   中英

三維線段與平面交點

[英]3D Line Segment and Plane Intersection

我正在嘗試實現一個線段和平面相交測試,它將返回true或false,具體取決於它是否與平面相交。 它還將返回線相交的平面上的接觸點,如果線不相交,則如果線段已經是光線,則該函數仍應返回交點。 我使用了Christer Ericson的實時碰撞檢測中的信息和代碼,但我認為我沒有正確實現它。

使用的平面是從三角形的法線和頂點導出的。 找到平面上交點的位置是我想要的,無論它是否位於我用來導出平面的三角形上。

在此輸入圖像描述

該功能的參數如下:

contact = the contact point on the plane, this is what i want calculated
ray = B - A, simply the line from A to B
rayOrigin = A, the origin of the line segement
normal = normal of the plane (normal of a triangle)
coord = a point on the plane (vertice of a triangle)

這是我使用的代碼:

bool linePlaneIntersection(Vector& contact, Vector ray, Vector rayOrigin, Vector normal, Vector coord) {

    // calculate plane
    float d = Dot(normal, coord);

    if (Dot(normal, ray)) {
        return false; // avoid divide by zero
    }

    // Compute the t value for the directed line ray intersecting the plane
    float t = (d - Dot(normal, rayOrigin)) / Dot(normal, ray);

    // scale the ray by t
    Vector newRay = ray * t;

    // calc contact point
    contact = rayOrigin + newRay;

    if (t >= 0.0f && t <= 1.0f) {
        return true; // line intersects plane
    }
    return false; // line does not
}

在我的測試中,它永遠不會真實......任何想法?

我正在回答這個問題,因為當它被要求提供射線交集的c ++示例時,它首先出現在Google上:)

代碼總是返回false,因為您輸入if here:

if (Dot(normal, ray)) {
   return false; // avoid divide by zero
}

如果向量是垂直的,則點積僅為零,這是您要避免的情況(沒有交點),並且非零數字在C中為真。
因此解決方案是否定(!)或做Dot(...)== 0。
在所有其他情況下,將有一個交叉點。

在交點計算上:平面的所有點X都遵循等式

點(N,X)= d

其中N是法線, d可以通過將平面的已知點放在等式中找到。

float d = Dot(normal, coord);

在光線上,線的所有點s可以表示為點p和給出方向D的矢量:

s = p + x * D.

因此,如果我們搜索飛機中的xs ,我們就有了

點(N,s)= d
點(N,p + x * D)= d

點積ab轉置(a)* b
設置轉置(N)Nt

Nt *(p + x * D)= d
Nt * p + Nt * D * x = d (x標量)
x =(d - Nt * p)/(Nt * D)
x =(d - 點(N,p))/點(N,D)

這給了我們:

float x = (d - Dot(normal, rayOrigin)) / Dot(normal, ray);
我們現在可以通過將x放在線方程中來獲得交點

s = p + x * D.

 Vector intersection = rayOrigin + x*ray; 

上面的代碼更新了:
 bool linePlaneIntersection(Vector& contact, Vector ray, Vector rayOrigin, Vector normal, Vector coord) { // get d value float d = Dot(normal, coord); 
if (Dot(normal, ray) == 0) { return false; // No intersection, the line is parallel to the plane }
// Compute the X value for the directed line ray intersecting the plane float x = (d - Dot(normal, rayOrigin)) / Dot(normal, ray);
// output contact point *contact = rayOrigin + normalize(ray)*x; //Make sure your ray vector is normalized return true; }

除了1:
d值是什么意思?
對於兩個矢量ab ,點積實際上返回一個矢量的正交投影的長度,而另一個矢量的另一個矢量。
但是如果a被歸一化(長度= 1),那么Dot(a,b)就是ba的投影長度。 在我們的平面的情況下, d給出了平面在垂直於原點的方向上的所有點的方向距離( a是法線)。 然后,我們可以通過比較法線上的投影長度(點積)來確定點是否在此平面上。

除了2:
如何檢查光線是否與三角形相交? (用於光線追蹤)
為了測試光線是否進入由3個頂點給出的三角形,您首先必須執行此處顯示的內容,得到與三角形形成的平面的交點。
下一步是看這個點是否在三角形中。 這可以使用重心坐標來實現,該重心坐標將平面中的點表示為其中三個點的組合。 請參閱重心坐標並從笛卡爾坐標轉換

我可能錯了,但代碼中有一些看似非常可疑的地方。 首先,請考慮以下這一行:

// calculate plane
float d = Dot(normal, coord);

這里,您的值d對應於平面法線(矢量)和空間點(平面上的點)之間的點積。 這似乎是錯的。 特別是,如果您有任何平面穿過原點並使用原點作為坐標點,您將最終計算

d = Dot(normal, (0, 0, 0)) = 0

並立即返回false。 我不確定你打算在這里做什么,但我很確定這不是你的意思。

代碼中另一個似乎可疑的地方是這一行:

// Compute the t value for the directed line ray intersecting the plane
float t = (d - Dot(normal, rayOrigin)) / Dot(normal, ray);

請注意,您正在計算平面法線向量(矢量)和光線原點(空間中的點)之間的點積。 這看起來很奇怪,因為它意味着根據光線在空間中的起源,您用於光線的縮放因子會發生變化。 我建議再看一下這段代碼,看看這是不是你的意思。

希望這可以幫助!

這對我來說都很好看。 我已經獨立檢查了代數,這對我來說很好。

作為示例測試用例:

A = (0,0,1)
B = (0,0,-1)
coord = (0,0,0)
normal = (0,0,1)

這給出了:

d = Dot( (0,0,1), (0,0,0)) = 0
Dot( (0,0,1), (0,0,-2)) = -2 // so trap for the line being in the plane passes.
t = (0 - Dot( (0,0,1), (0,0,1) ) / Dot( (0,0,1), (0,0,-2)) = ( 0 - 1) / -2 = 1/2
contact = (0,0,1) + 1/2 (0,0,-2) = (0,0,0) // as expected.

因此,考慮到@ templatetypedef的答案之后的校正,我可以看到問題的唯一區域是其他操作之一的實現,無論是Dot()還是Vector運算符。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM