英吋 XNA

XNA – HeightmapCollision 高度計算修正

嗯…
即使在Creators Club還是會有不正確的地方哪…
這張是說明文件裡面的圖…


範例裡面高度的算法是先計算X方向和Z方向的比例,也就是正規化(Normalize)。
接著用X方向的比例求AB兩點的值。

以AB為線切成類似下圖的橫切面,最終高度就會落在線上。
接著再用AB兩點和Z方向的線性比例算出最終高度。

這方法看起來簡單又快速,可是卻有很大的機會讓物體放在不正確的高度。

現在將四個點分別叫做A(左上)、B(右上)、C(左下)和 D(右下)。
依照TerrainProcessor裡面產生地形的頂點順序,可將這個正方型分成上半部(ABC)和下半部(ADC)
倘若將B點的高度拉高,只會影響上和右兩個邊,可以在3ds Max裡面拉拉看。
簡單來說,若是我們要求的點落在上半部的三角面上,那麼高度的計算就不該會用到左和下兩邊。

後來跑去問老師,得知其他相關書籍也都是要先確認落在哪個三角面再去計算的。
判斷在哪個三角面很簡單~

這是  Beginning XNA 2.0 Game Programming: From Novice to Professional  裡面的圖


接下來改寫範例計算高度的部分~

首先,算出正規化後的X和Z值

 float xNormalized = (positionOnHeightmap.X % terrainScale) / terrainScale;
 float zNormalized = (positionOnHeightmap.Z % terrainScale) / terrainScale;

準備一些變數,方便辨識

 float resultHeight;                                      // 最後要回傳的值
 float xDistance, zDistance;                      // 記錄X和Z的高度差
 float RT = heights[left + 1, top];                // 左上角的高度
 float LT = heights[left, top];                       // 右上角得高度
 float RB = heights[left + 1, top + 1];         // 右下角的高度
 float LB = heights[left, top + 1];                // 左下角的高度

接著,判斷落在哪個三角面

 if (xNormalized > zNormalized)
 {
     // 如果 X > Y,就落在上半部
     // 計算 [左上] 到 [右上] 的高度距離
     xDistance = RT LT;

     // 計算 [右上] 到 [右下] 的高度距離
     zDistance = RB RT;
 }
 else
 {
     // 不然就落在下半部
     // 計算 [左下] 到 [右下] 的高度距離
     xDistance = RB LB;

     // 計算 [左上] 到 [左下] 的高度距離
     zDistance = LB LT;
 }

最後,計算結果

 // 一樣使用線性插值計算高度
 resultHeight
= LT + xDistance * xNormalized + zDistance * zNormalized;

 // 回傳結果
 return resultHeight;

這樣一來,就可以踩得更準確了!


最後,今天才赫然發現…
請注意範例使用的HeightMap的BMP圖,它的尺寸是257*257,而不是下意識會使用的256*256
因為在一開始產生地形頂點時,長寬除以 2,因為是 0 ~ 255,所以會有 0.5 的小誤差出現…
在此之前,還一直為那 0.5 的差距喬來喬去的…

–End

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Google photo

您的留言將使用 Google 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.