void LateUpdateBounds() { // make sure we're at sea level. we will expand the bounds which only works at sea level float y = transform.position.y; if (!Mathf.Approximately(y, OceanRenderer.Instance.SeaLevel)) { transform.position += (OceanRenderer.Instance.SeaLevel - y) * Vector3.up; } var bounds = _boundsLocal; OceanChunkRenderer.ExpandBoundsForDisplacements(transform, ref bounds); _mesh.bounds = bounds; if (_drawBounds) { OceanChunkRenderer.DebugDrawRendererBounds(_rend); } }
GameObject CreateLOD(int lodIndex, bool biggestLOD, Mesh[] meshData, Params parms) { // first create parent gameobject for the lod level. the scale of this transform sets the size of the lod. string lodParentName = "LOD" + lodIndex; // if it exists already, destroy it so it can be created fresh Transform parentTransform = transform.Find(lodParentName); if (parentTransform != null) { DestroyImmediate(parentTransform.gameObject); parentTransform = null; } GameObject parent = new GameObject(); parent.name = "LOD" + lodIndex; parent.transform.parent = transform; parent.transform.localPosition = Vector3.zero; parent.transform.localRotation = Quaternion.identity; // add a shape camera below it _shapeCameras[lodIndex].transform.parent = parent.transform; _shapeCameras[lodIndex].transform.localScale = Vector3.one; _shapeCameras[lodIndex].transform.localPosition = Vector3.zero; bool generateSkirt = parms._generateSkirt && biggestLOD; Vector2[] offsets; PatchType[] patchTypes; PatchType leadSideType = generateSkirt ? PatchType.FatXOuter : PatchType.SlimX; PatchType trailSideType = generateSkirt ? PatchType.FatXOuter : PatchType.FatX; PatchType leadCornerType = generateSkirt ? PatchType.FatXZOuter : PatchType.SlimXZ; PatchType trailCornerType = generateSkirt ? PatchType.FatXZOuter : PatchType.FatXZ; PatchType tlCornerType = generateSkirt ? PatchType.FatXZOuter : PatchType.SlimXFatZ; PatchType brCornerType = generateSkirt ? PatchType.FatXZOuter : PatchType.FatXSlimZ; if (lodIndex != 0) { // instance indices: // 0 1 2 3 // 4 5 // 6 7 // 8 9 10 11 offsets = new Vector2[] { new Vector2(-1.5f, 1.5f), new Vector2(-0.5f, 1.5f), new Vector2(0.5f, 1.5f), new Vector2(1.5f, 1.5f), new Vector2(-1.5f, 0.5f), new Vector2(1.5f, 0.5f), new Vector2(-1.5f, -0.5f), new Vector2(1.5f, -0.5f), new Vector2(-1.5f, -1.5f), new Vector2(-0.5f, -1.5f), new Vector2(0.5f, -1.5f), new Vector2(1.5f, -1.5f), }; // usually rings have an extra side of verts that point inwards. the outermost ring has both the inward // verts and also and additional outwards set of verts that go to the horizon patchTypes = new PatchType[] { tlCornerType, leadSideType, leadSideType, leadCornerType, trailSideType, leadSideType, trailSideType, leadSideType, trailCornerType, trailSideType, trailSideType, brCornerType, }; } else { // first LOD has inside bit as well: // 0 1 2 3 // 4 5 6 7 // 8 9 10 11 // 12 13 14 15 offsets = new Vector2[] { new Vector2(-1.5f, 1.5f), new Vector2(-0.5f, 1.5f), new Vector2(0.5f, 1.5f), new Vector2(1.5f, 1.5f), new Vector2(-1.5f, 0.5f), new Vector2(-0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(1.5f, 0.5f), new Vector2(-1.5f, -0.5f), new Vector2(-0.5f, -0.5f), new Vector2(0.5f, -0.5f), new Vector2(1.5f, -0.5f), new Vector2(-1.5f, -1.5f), new Vector2(-0.5f, -1.5f), new Vector2(0.5f, -1.5f), new Vector2(1.5f, -1.5f), }; // all interior - the "side" types have an extra skirt that points inwards - this means that this inner most // section doesn't need any skirting. this is good - this is the highest density part of the mesh. patchTypes = new PatchType[] { tlCornerType, leadSideType, leadSideType, leadCornerType, trailSideType, PatchType.Interior, PatchType.Interior, leadSideType, trailSideType, PatchType.Interior, PatchType.Interior, leadSideType, trailCornerType, trailSideType, trailSideType, brCornerType, }; } // debug toggle to force all patches to be the same. they'll be made with a surrounding skirt to make sure patches // overlap if (parms._forceUniformPatches) { for (int i = 0; i < patchTypes.Length; i++) { patchTypes[i] = PatchType.Fat; } } // create the ocean patches for (int i = 0; i < offsets.Length; i++) { // instantiate and place patch Transform inst = Instantiate(_chunkPrefab) as Transform; inst.parent = parent.transform; Vector2 pos = offsets[i]; inst.localPosition = new Vector3(pos.x, 0f, pos.y); inst.localScale = Vector3.one; OceanChunkRenderer ocr = inst.GetComponent <OceanChunkRenderer>(); ocr.SetInstanceData(lodIndex, parms._lodCount, parms._baseVertDensity); inst.GetComponent <MeshFilter>().mesh = meshData[(int)patchTypes[i]]; // rotate side patches to point the +x side outwards bool rotateXOutwards = patchTypes[i] == PatchType.FatX || patchTypes[i] == PatchType.FatXOuter || patchTypes[i] == PatchType.SlimX || patchTypes[i] == PatchType.SlimXFatZ; if (rotateXOutwards) { if (Mathf.Abs(pos.y) >= Mathf.Abs(pos.x)) { inst.localEulerAngles = -Vector3.up * 90f * Mathf.Sign(pos.y); } else { inst.localEulerAngles = pos.x < 0f ? Vector3.up * 180f : Vector3.zero; } } // rotate the corner patches so the +x and +z sides point outwards bool rotateXZOutwards = patchTypes[i] == PatchType.FatXZ || patchTypes[i] == PatchType.SlimXZ || patchTypes[i] == PatchType.FatXSlimZ || patchTypes[i] == PatchType.FatXZOuter; if (rotateXZOutwards) { // xz direction before rotation Vector3 from = new Vector3(1f, 0f, 1f).normalized; // target xz direction is outwards vector given by local patch position - assumes this patch is a corner (checked below) Vector3 to = inst.localPosition.normalized; if (Mathf.Abs(inst.localPosition.x) < 0.0001f || Mathf.Abs(Mathf.Abs(inst.localPosition.x) - Mathf.Abs(inst.localPosition.z)) > 0.001f) { Debug.LogWarning("Skipped rotating a patch because it isn't a corner, click here to highlight.", inst); continue; } // detect 180 degree rotations as it doesnt always rotate around Y if (Vector3.Dot(from, to) < -0.99f) { inst.localEulerAngles = Vector3.up * 180f; } else { inst.localRotation = Quaternion.FromToRotation(from, to); } } } return(parent); }