public void ClampTo(SgtRectL other) { if (minX < other.minX) { minX = other.minX; } else if (minX > other.maxX) { minX = other.maxX; } if (minY < other.minY) { minY = other.minY; } else if (minY > other.maxY) { minY = other.maxY; } if (maxX < other.minX) { maxX = other.minX; } else if (maxX > other.maxX) { maxX = other.maxX; } if (maxY < other.minY) { maxY = other.minY; } else if (maxY > other.maxY) { maxY = other.maxY; } }
private void WriteNormals(SgtRectL outer, SgtRectL inner) { inner.ClampTo(outer); WriteNormals(outer.minX, inner.maxY, outer.maxX, outer.maxY); // Top WriteNormals(outer.minX, outer.minY, outer.maxX, inner.maxY); // Bottom WriteNormals(outer.minX, inner.minX, inner.minX, inner.maxY); // Left WriteNormals(inner.maxX, inner.minX, inner.maxX, inner.maxY); // Right }
private void WriteIndices(SgtRectL outer, SgtRectL inner, long detail, long size) { SgtHelper.ClearCapacity(indices, 1024); for (var y = outer.minY; y < outer.maxY; y++) { for (var x = outer.minX; x < outer.maxX; x++) { if (x >= inner.minX && x < inner.maxX && y >= inner.minY && y < inner.maxY) { continue; } var aX = x; var aY = y; var bX = x + 1; var bY = y; var cX = x; var cY = y + 1; var dX = x + 1; var dY = y + 1; if (y == outer.minY && y > -detail) { if (x % 2 == 0) { bX -= 1; } else { aX -= 1; } } if (y == outer.maxY - 1 && y < detail - 1) { if (x % 2 == 0) { dX += 1; } else { cX += 1; } } if (x == outer.minX && x > -detail) { if (y % 2 == 0) { cY -= 1; } else { aY -= 1; } } if (x == outer.maxX - 1 && x < detail - 1) { if (y % 2 == 0) { dY += 1; } else { bY += 1; } } var a = Wrap(aX, aY, size); var b = Wrap(bX, bY, size); var c = Wrap(cX, cY, size); var d = Wrap(dX, dY, size); /* * var posA = positions[a]; * var posB = positions[b]; * var posC = positions[c]; * var posD = positions[d]; * * var areaA = Area(posA, posB, posC) + Area(posD, posC, posB); * var areaB = Area(posA, posB, posD) + Area(posD, posC, posA); * * if (a < b) * { * var t = a; * * a = b; * b = d; * d = c; * c = t; * }*/ indices.Add(a); indices.Add(c); indices.Add(b); indices.Add(d); indices.Add(b); indices.Add(c); } } }
public void Write(SgtTerrain.Ring ring) { if (ring.Outer == outerRegion && ring.Inner == innerRegion) { return; } size = ring.Limit + 3; var terrain = Face.Terrain; var total = size * size; var newBasicRegion = ring.Outer.GetExpanded(1); if (positions == null || positions.Length != total) { basicRegion.Clear(); outerRegion.Clear(); positions = new Vector3[total]; normals = new Vector3[total]; coords1 = new Vector2[total]; coords2 = new Vector2[total]; } // Write position & uv data var stepX = ring.ExtentsX / ring.Detail; var stepY = ring.ExtentsY / ring.Detail; for (var y = newBasicRegion.minY; y <= newBasicRegion.maxY; y++) { for (var x = newBasicRegion.minX; x <= newBasicRegion.maxX; x++) { if (basicRegion.Contains(x, y) == false) { var index = Wrap(x, y, size); var point = ring.Center + x * stepX + y * stepY; var coord1U = (x / (double)ring.Detail + 1.0) / 2.0; // 0 .. 1 var coord1V = (y / (double)ring.Detail + 1.0) / 2.0; // 0 .. 1 var coord2U = x / (double)ring.Limit; // -u .. u var coord2V = y / (double)ring.Limit; // -v .. v var height = terrain.GetLocalHeight(point); var direction = point.normalized; var position = direction * height; positions[index] = (Vector3)position; coords1[index] = new Vector2((float)coord1U, (float)coord1V); coords2[index] = new Vector2((float)coord2U, (float)coord2V); } } } var parent = Face.LastLevel; WriteNormals(ring.Outer, outerRegion); if (parent != null) { // Write edges from parent to avoid normal seams from resolution shift if (ring.Outer.minX > -ring.Detail) { WriteParentNormals(parent, ring.Outer.minX, ring.Outer.minY, ring.Outer.minX, ring.Outer.maxY); // Left } if (ring.Outer.maxX < ring.Detail) { WriteParentNormals(parent, ring.Outer.maxX, ring.Outer.minY, ring.Outer.maxX, ring.Outer.maxY); // Right } if (ring.Outer.minY > -ring.Detail) { WriteParentNormals(parent, ring.Outer.minX, ring.Outer.minY, ring.Outer.maxX, ring.Outer.minY); // Bottom } if (ring.Outer.maxY < ring.Detail) { WriteParentNormals(parent, ring.Outer.minX, ring.Outer.maxY, ring.Outer.maxX, ring.Outer.maxY); // Top } } // Write indices WriteIndices(ring.Outer, ring.Inner, ring.Detail, size); var mesh = GetMesh(); mesh.Clear(); mesh.vertices = positions; mesh.normals = normals; mesh.uv = coords1; mesh.uv2 = coords2; mesh.SetTriangles(indices, 0); mesh.bounds = terrain.GetBounds(); if (terrain.MaxColliderDepth > Index) { if (meshCollider == null) { meshCollider = GetComponent <MeshCollider>(); } if (meshCollider == null) { meshCollider = gameObject.AddComponent <MeshCollider>(); } // Is this the last collider, but not the last LOD level? if (terrain.MaxColliderDepth == Index + 1 && ring.Inner.SizeX > 0 && ring.Inner.SizeY > 0) { var colliderMesh = GetColliderMesh(); WriteIndices(ring.Outer, default(SgtRectL), ring.Detail, size); colliderMesh.Clear(); colliderMesh.vertices = positions; colliderMesh.SetTriangles(indices, 0); meshCollider.sharedMesh = colliderMesh; } // If not, use the visual mesh else { PoolColliderMeshNow(false); meshCollider.sharedMesh = mesh; } } else { PoolColliderMeshNow(); } basicRegion = newBasicRegion; outerRegion = ring.Outer; innerRegion = ring.Inner; Face.LastLevel = this; if (terrain.OnCalculateLevel != null) { terrain.OnCalculateLevel(this, ring); } }