Example #1
0
        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);
            }
        }
Example #2
0
        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);
        }