Don't fill gaps, don't have gaps!We only perform the displacement if our neighbour has children. Additionally, we tell the neighboring children that share this point, they can now be displaced, as it's guaranteed they haven't been if we're not split yet. Worth noting is the above code becomes one very simple line once you index your mesh, as you don't need to use the magicrelationship to seek out the point on each triangle, you just need to find it for one. for(int i=0; i<3; i++) { //here, even if were not raising the point to the radius+detail, //prepare the texturing, colouring etc as if we were //... if(t>e[i]>bHasChildren()) { n[i].vNormalize(); n[i] *= radius; //and tell neighboring children sharing point they can raise from midpoint int it0=t>e[i]>iSharesEdge(t); int it1=it0+1; if(it1>2)it1=0; int it3=it1+1; if(it3>2)it3=0; t>e[i]>child[it0]>p[it1]=n[i]; t>e[i]>child[it1]>p[it0]=n[i]; t>e[i]>child[3]>p[it3]=n[i]; } } Now we can construct our children and set up our child, parent pointers. t>child[0] = new cLoDTri(t>p[0],n[0],n[2]); t>child[1] = new cLoDTri(n[0],t>p[1],n[1]); t>child[2] = new cLoDTri(n[2],n[1],t>p[2]); t>child[3] = new cLoDTri(n[1],n[2],n[0]); for(int i=0;i<4;i++) t>child[i]>pParent=t; t>child[0]>e[1]=t>child[3]; t>child[1]>e[2]=t>child[3]; t>child[2]>e[0]=t>child[3]; "Neighbour's... Everybody needs good..."We can also set up child[3]'s edge pointers as it simply points to the other children. t>child[3]>SetEdgePointers(t>child[2],t>child[0],t>child[1]); Setting up the other children's edge pointers is slightly less trivial because of the variable orientations of neighboring tris. Rather than use a big switch() setup dealing with the neighbor orientations on a case by case business though, the mathmagical relationship saves us again and makes it trivial (and plenty fast enough for a split operation). for(int i=0; i<3; i++) { if(t>e[i]) //nonclosed surface trap if(t>e[i]>bHasChildren()) { //triangle has children we can point our children too. int j=i+1; if(j>2) j=0; int sharedEdge=t>e[i]>iSharesEdge(t); if(sharedEdge!=1) { int k=sharedEdge+1; if(k>2)k=0; t>child[i]>e[i]=t>e[i]>child[k]; t>child[j]>e[i]=t>e[i]>child[sharedEdge]; t>e[i]>child[sharedEdge]>e[sharedEdge]=t>child[j]; t>e[i]>child[k]>e[sharedEdge]=t>child[i]; } } } the function iSharesEdge is simply defined as: int cLoDTri::iSharesEdge(cLoDTri* t) { for(int i=0;i<3;i++) if(e[i]==t) return i; return 1; } This is fairly intuitive if you stare at the diagram for a little while. All thats left is to put the children into the mesh, and take the parent out. m_llMesh.AddHead(t>child[0]); m_llMesh.AddHead(t>child[1]); m_llMesh.AddHead(t>child[2]); m_llMesh.AddHead(t>child[3]); t>Remove(); m_llParents.AddHead(t); 
