public IEnumerable<PatchDescriptor> GetPatches(TerrainTile tile, Frustum f, Vector3 eyeWorld) { // create root node var root = new QuadTreeNode(tile); return root.GetPatches(eyeWorld,f); }
private void DebugRenderFrustum(Frustum f) { lineBuffer.SetColour(new Vector4(1f, 1f, 1f, 1f)); lineBuffer.MoveTo(f.NearTopLeftCorner.Xyz.TopDown()); lineBuffer.LineTo(f.NearTopRightCorner.Xyz.TopDown()); lineBuffer.LineTo(f.FarTopRightCorner.Xyz.TopDown()); lineBuffer.LineTo(f.FarTopLeftCorner.Xyz.TopDown()); lineBuffer.LineTo(f.NearTopLeftCorner.Xyz.TopDown()); lineBuffer.SetColour(new Vector4(1f, 1f, 1f, .5f)); lineBuffer.MoveTo(f.NearBottomLeftCorner.Xyz.TopDown()); lineBuffer.LineTo(f.NearBottomRightCorner.Xyz.TopDown()); lineBuffer.LineTo(f.FarBottomRightCorner.Xyz.TopDown()); lineBuffer.LineTo(f.FarBottomLeftCorner.Xyz.TopDown()); lineBuffer.LineTo(f.NearBottomLeftCorner.Xyz.TopDown()); lineBuffer.SetColour(new Vector4(1f, 0f, 0f, 1f)); lineBuffer.MoveTo(f.NearTopLeftCorner.Xyz.TopDown()); lineBuffer.LineTo(f.FarTopLeftCorner.Xyz.TopDown()); lineBuffer.LineTo(f.FarBottomLeftCorner.Xyz.TopDown()); lineBuffer.LineTo(f.NearBottomLeftCorner.Xyz.TopDown()); lineBuffer.LineTo(f.NearTopLeftCorner.Xyz.TopDown()); lineBuffer.SetColour(new Vector4(0f, 1f, 0f, 1f)); lineBuffer.MoveTo(f.NearTopRightCorner.Xyz.TopDown()); lineBuffer.LineTo(f.FarTopRightCorner.Xyz.TopDown()); lineBuffer.LineTo(f.FarBottomRightCorner.Xyz.TopDown()); lineBuffer.LineTo(f.NearBottomRightCorner.Xyz.TopDown()); lineBuffer.LineTo(f.NearTopRightCorner.Xyz.TopDown()); }
public IEnumerable<PatchDescriptor> GetPatches(Vector3 eye, Frustum f) { bool childFrustumCheck = true; // frustum cull if (checkFrustum) { var clipresult = f.TestBox(this.vertex); if (clipresult == Frustum.ObjectClipResult.TotallyOutside) { yield break; } if (clipresult == Frustum.ObjectClipResult.TotallyInside) { childFrustumCheck = false; } } // get eye y-difference (0 within min/max height) //float eyeY = U.Max(U.Max(eye.Y - MaxHeight, 0f), U.Max(MinHeight - eye.Y, 0f)); float eyeYdiff = 0f; if (eye.Y > MaxHeight) { eyeYdiff = eye.Y - MaxHeight; } else if (eye.Y < MinHeight) { eyeYdiff = MinHeight - eye.Y; } eyeYdiff *= eyeYdiff; int i = 0; distance[i++] = (float)Math.Sqrt((eye.X - vertex[i].X).Sqr() + eyeYdiff + (eye.Z - vertex[i].Z).Sqr()); distance[i++] = (float)Math.Sqrt((eye.X - vertex[i].X).Sqr() + eyeYdiff + (eye.Z - vertex[i].Z).Sqr()); distance[i++] = (float)Math.Sqrt((eye.X - vertex[i].X).Sqr() + eyeYdiff + (eye.Z - vertex[i].Z).Sqr()); distance[i++] = (float)Math.Sqrt((eye.X - vertex[i].X).Sqr() + eyeYdiff + (eye.Z - vertex[i].Z).Sqr()); distance[i++] = U.DistanceToSquare( vertex[(int)Corner.BottomNearLeft].X, vertex[(int)Corner.BottomNearLeft].Z, vertex[(int)Corner.BottomFarRight].X, vertex[(int)Corner.BottomFarRight].Z, eye.X, eye.Z, eyeYdiff); for (i = 0; i < 5; i++) { lod[i] = GetLOD(distance[i], depth); } int patchLOD = lod.Max(); int LODDiff = patchLOD - lod.Min(); float patchDistance = distance.Min(); // recusion limit, or not enough lod difference if (depth > MaxDepth || LODDiff <= MaxLODDiff) { yield return new PatchDescriptor { Tile = this.tile, TileModelMatrix = this.tile.ModelMatrix, TileSize = tileSize, MeshSize = GetMeshSize(tileSize, patchLOD), //Offset = (vertex[(int)Corner.BottomNearLeft].Xz - TileOffset.Xz) / (float)this.tile.Width, Scale = (float)tileSize / (float)tile.Width, Offset = this.Offset, Distance = patchDistance, LOD = patchLOD }; } else { // recurse var BottomNearCentre = vertex[(int)Corner.BottomNearLeft]; BottomNearCentre.X = BottomCentre.X; var BottomCentreLeft = vertex[(int)Corner.BottomNearLeft]; BottomCentreLeft.Z = BottomCentre.Z; var BottomFarCentre = vertex[(int)Corner.BottomFarLeft]; BottomFarCentre.X = BottomCentre.X; var BottomCentreRight = vertex[(int)Corner.BottomNearRight]; BottomCentreRight.Z = BottomCentre.Z; var TopNearCentre = vertex[(int)Corner.TopNearLeft]; TopNearCentre.X = TopCentre.X; var TopCentreLeft = vertex[(int)Corner.TopNearLeft]; TopCentreLeft.Z = TopCentre.Z; var TopFarCentre = vertex[(int)Corner.TopFarLeft]; TopFarCentre.X = TopCentre.X; var TopCentreRight = vertex[(int)Corner.TopNearRight]; TopCentreRight.Z = TopCentre.Z; float offsetfactor = 1.0f/(1 << (depth+1)); // near left quadrant foreach (var pd in new QuadTreeNode(this, tile, tileSize >> 1, depth + 1, childFrustumCheck, Offset, vertex[(int)Corner.BottomNearLeft], BottomNearCentre, BottomCentreLeft, BottomCentre, vertex[(int)Corner.TopNearLeft], TopNearCentre, TopCentreLeft, TopCentre ).GetPatches(eye, f)) { yield return pd; } // near right quadrant foreach (var pd in new QuadTreeNode(this, tile, tileSize >> 1, depth + 1, childFrustumCheck, Offset + new Vector2(offsetfactor, 0f), BottomNearCentre, vertex[(int)Corner.BottomNearRight], BottomCentre, BottomCentreRight, TopNearCentre, vertex[(int)Corner.TopNearRight], TopCentre, TopCentreRight ).GetPatches(eye, f)) { yield return pd; } // far left quadrant foreach (var pd in new QuadTreeNode(this, tile, tileSize >> 1, depth + 1, childFrustumCheck, Offset + new Vector2(0f, offsetfactor), BottomCentreLeft, BottomCentre, vertex[(int)Corner.BottomFarLeft], BottomFarCentre, TopCentreLeft, TopCentre, vertex[(int)Corner.TopFarLeft], TopFarCentre ).GetPatches(eye, f)) { yield return pd; } // far right quadrant foreach (var pd in new QuadTreeNode(this, tile, tileSize >> 1, depth + 1, childFrustumCheck, Offset + new Vector2(offsetfactor, offsetfactor), BottomCentre, BottomCentreRight, BottomFarCentre, vertex[(int)Corner.BottomFarRight], TopCentre, TopCentreRight, TopFarCentre, vertex[(int)Corner.TopFarRight] ).GetPatches(eye, f)) { yield return pd; } } }