WPF-3D圓柱體透視

猝不及防發表於2021-04-21

3D圓柱體透視效果

總效果

原理:

3D面+面在攝像機方向上的2D投影點的集合

3D面效果

2D線:

畫線時需要注意兩個點:

1 在圓柱體上下兩個圓之間有兩條豎著的稜邊代表圓柱體邊緣

2 被遮蓋的圓面後半面顯示為虛線

1 如何確定兩條稜邊的位置

我們需要確定上下兩個圓面最左邊和最右邊的點。

隨著攝像機的移動,上面的左右兩個點和下面的左右兩個點也隨之變化

點的變化和Y軸無關,所以我們可以把它看作是個2維關係。

其中直線是攝像機位置視角與面中心的連線,兩個紅點則是這個面最左邊的點和最右邊的點。

即問題轉變為:求一條過圓心的點直線的垂線與圓的交點。

即:

			Point3D cameraRealPosition = transform.Transform(carema.Position);
            Point caremaRealPoint = new Point(cameraRealPosition.X, cameraRealPosition.Z);
            var l1 = caremaRealPoint.X - center.X;
            var l2 = caremaRealPoint.Y - center.Y;
            var l3 = Math.Sqrt(l1 * l1 + l2 * l2);
            var sinb = l2 / l3;
            var cosb = l1 / l3;
            var x1 = r * sinb + center.X;
            var y1 = -r * cosb + center.Y;
            var x2 = -r * sinb + center.X;
            var y2 = r * cosb + center.Y;

此時我們求出一個面的點(x1,y1)(x2,y2)

在三維中,y是z軸,則點為

    		    new Point3D(x1, pointTopCenter.Y, y1)
                new Point3D(x2, pointTopCenter.Y, y2)
                new Point3D(x1, pointBottomCenter.Y, y1)
                new Point3D(x2, pointBottomCenter.Y, y2)

上下點連線則為圓柱體的側邊。

2 如何確定虛線位置。

2.1分離實線點和虛線點

我們可以發現虛線與實線是以(x1,y1)(x2,y2)分離的。

由於線是以投影點的集合組合而成。

我們可以根據每個點在(x1,y1)-(x2,y2)這條直線的左邊還是右邊把這個集合分成兩部分。

根據向量叉乘來判斷在左邊還是右邊。

 bool IsPointOnLineLeftOrRight(Point a, Point b, Point p)
        {
            Vector pa = new Vector(a.X - p.X, a.Y - p.Y);
            Vector pb = new Vector(b.X - p.X, b.Y - p.Y);
            return Vector.CrossProduct(pa, pb) < 0;
        }

其中ab為分別為x1y1左邊兩個點。

2.2確定上面存在虛線還是下面存在虛線

思路:從四個集合中選取位置相同四個點,通過和攝像機的距離比較來判斷哪個集合是虛線集合

1 通過上下面相同位置的點F1,F2的距離,判斷是上面存在被遮蓋的面還是下面存在被遮蓋的面。

如圖:

DistanceF2ToCamera>DistanceF1ToCamera

則虛線應該在下邊這個圓上。

2.3 確定面左邊集合是虛線還是右邊集合

同樣DistanceF3ToCamera>DistanceF4ToCamera

所以F3所在的集合是虛線點集

由此就可以判斷虛線點集了。

3 點集的順序一致性。

我們畫的是開放的半圓,在畫2D半圓線的時候,我們需要保證從左邊第一個點開始畫,畫到最右邊的點,

如果是從中間開始畫,那麼就會是個封閉的半圓了。

開放的半圓:

封閉的半圓:

所以我們要保證點集的順序是從左到右的:

正常視角:

那我們存在兩種情況:

若以A為起點,則按順序有三個點集:A1,B,A2

點集A=A2+A1

點集B=B

若以A為起點,則按順序有三個點集:A1,B,A2

點集A=A2+A1

點集B=B

兩種情況統一:

我們需要注意的是A=A2+A1

兩個集合新增的時候順序要變一下。

相關文章