buildPolyDetail() 傳入的是contours,先對過長的邊進行插值,通過”int nn = 1 + (int)floorf(d/sampleDist);“ 進行判斷需要劃分多少段,這個過程也對點的y軸進行了設置。然後按原來的方向順序將點的下標放到hull中,形成一個精細化的三維的contours(hull)。
然後進行triangulatehull過程。
再然後,對整個contours進行均勻的網狀的劃分,找出其中的網的所有交點,這些交點與contours的邊的距離(在xz平面上)大於 “-sampleDist/2”
然後循環進行 (每次從採樣點中選取 與 上次deluanay劃分計算出的mesh 距離最大的點 ,放入到verts中,然後又將所有verts中的點進行deluanay劃分)的操作。最後一次的deluanay劃分出來的tris就是buildPolyDetail所求。
getHeightData() ,基本上註釋說得很明確。
while (head*3 < queue.size()) //在上面先求出滿足要求的頂點,再基於這些頂點用廣度優先算法一圈一圈的向外擴展,按這樣的方式對獲取所有有效頂點的高度,並保存到hp.data中
triangulateHull 創建修長的三角形網格,主要代碼如下
tris.push(hull[start]);
tris.push(hull[left]);
tris.push(hull[right]);
tris.push(0);
// Triangulate the polygon by moving left or right,
// depending on which triangle has shorter perimeter.
// This heuristic was chose emprically, since it seems
// handle tesselated straight edges well.
while (next(left, nhull) != right)
{
// Check to see if se should advance left or right.
int nleft = next(left, nhull);
int nright = prev(right, nhull);
const float* cvleft = &verts[hull[left]*3];
const float* nvleft = &verts[hull[nleft]*3];
const float* cvright = &verts[hull[right]*3];
const float* nvright = &verts[hull[nright]*3];
const float dleft = vdist2(cvleft, nvleft) + vdist2(nvleft, cvright);
const float dright = vdist2(cvright, nvright) + vdist2(cvleft, nvright);
if (dleft < dright)
{
tris.push(hull[left]);
tris.push(hull[nleft]);
tris.push(hull[right]);
tris.push(0);
left = nleft;
}
else
{
tris.push(hull[left]);
tris.push(hull[nright]);
tris.push(hull[right]);
tris.push(0);
right = nright;
}
}
每次找最左右未取到的相對更短邊與上一步新加的邊組成新的三角形,根據這個邏輯,結果類似這樣:(實際點是三維的,在y軸是不共面的)
這裏使用triangulateHull而不使用delaunayhull原因如下:
// Tessellate the base mesh.
// We're using the triangulateHull instead of delaunayHull as it tends to
// create a bit better triangulation for long thin triangles when there
// are no internal points.
delaunayHull()//對poly進行德洛內三角劃分,得出poly的三角行和頂點,存放到tris和verts中。首先將最外圍的一圈點鏈接起來,再對所有點進行三角劃分,將信息存放到edge中。最後再edge中的信息放到tris中
裏面主要理解的是edges。 一條邊,由四個變量組成,起點,終點,邊的左邊三角形面id,邊的右邊三角形面id。默認面id爲EV_UNDEF或者EV_HULL(邊界的edges)。組裝點edge的時候採用逆時針方向進行組裝的,所以初始的時候的hull邊界的left爲EV_HULL。而right正是將要 求取 的,設置爲EV_UNDEF。
int currentEdge = 0;
while (currentEdge < nedges)
{
if (edges[currentEdge*4+2] == EV_UNDEF)
completeFacet(ctx, pts, npts, &edges[0], nedges, maxEdges, nfaces, currentEdge);
//找出一個三角形 ,對nedges會做修改 ,nfaces 會增1,並將face id存放到相關的edge中(edge[2],edge[3])。
if (edges[currentEdge*4+3] == EV_UNDEF)
completeFacet(ctx, pts, npts, &edges[0], nedges, maxEdges, nfaces, currentEdge);
currentEdge++;
}
completeFacet,採用的方法是 計算該邊與所有其他點的最小外接圓。
rcBuildPolyMeshDetail,將上面的rcBuildPolyMesh 計算出來的poly 信息存放到 rcPolyMeshDetail中。逐個poly的進行buildpolydetail計算。
dmesh,meshes存放submesh,實際是存放poly信息。
dmesh.nmeshes = mesh.npolys; //num sub mesh
dmesh.nverts = 0; //dmesh總的頂點數
dmesh.ntris = 0;//dmesh總的triangle數
dmesh.meshes = (unsigned int*)rcAlloc(sizeof(unsigned int)*dmesh.nmeshes*4, RC_ALLOC_PERM);
for (int i = 0; i < mesh.npolys; ++i){
。。。。
dmesh.meshes[i*4+0] = (unsigned int)dmesh.nverts;//存放poly的vert在dmesh->verts中的存放的起點位置
dmesh.meshes[i*4+1] = (unsigned int)nverts;//存放這個poly的verts數量
dmesh.meshes[i*4+2] = (unsigned int)dmesh.ntris;//存放poly的triangle在dmesh->tris中存放的起點位置
dmesh.meshes[i*4+3] = (unsigned int)ntris;//存放這個poly triangle數量
。。。。