Ejemplo n.º 1
0
        private void DoLodLevel(GameObject rootTarget, Config.LodLevel config, int lodLevelIndex)
        {
            // Get a version of the spline in local space
            var spline = new SplineSegment(NodeConnection.GetSpline());

            spline.ApplyMatrix(rootTarget.transform.worldToLocalMatrix);

            if (config.SourceMesh == null)
            {
                Debug.LogError("No mesh defined for CreateRenderMesh component!");
                return;
            }

            List <CombineInstance> workingMeshes = new List <CombineInstance>(); // All the meshes that will be combined at the end
            var totalSplineLength = spline.Length;
            var scale             = config.SourceMesh.bounds.size;

            scale.Scale(config.Scale);
            var sourceMeshAxisLength = MeshTools.GetScalarFromAxis(scale, config.Axis);

            var perMeshLength     = Math.Min(totalSplineLength, sourceMeshAxisLength);
            var perMeshPercentage = perMeshLength / totalSplineLength;

            var snapDistance = config.SnapDistance;

            var matrix = Matrix4x4.TRS(
                config.Offset,
                Quaternion.Euler(config.Rotation),
                config.Scale);
            var mirrorMatrix = Matrix4x4.TRS(
                new Vector3(config.Offset.x, config.Offset.y, -config.Offset.z),
                Quaternion.Euler(config.Rotation),
                new Vector3(config.Scale.x, config.Scale.y, -config.Scale.z));
            var meshCombineMatrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3.one);

            int chunkCount    = 0;
            var currentResult = CreateNewBakeResult(config, rootTarget, lodLevelIndex, chunkCount);

            chunkCount++;
            float distanceAccumulator = 0;

            for (var i = SplineRange.x; i < 1; i += perMeshPercentage)
            {
                var startTime = i;
                var endTime   = Mathf.Clamp01(i + perMeshPercentage);

                if (Math.Abs(startTime - endTime) < .001f)
                {
                    break;
                }

                if (config.SplineInterpolation == SplineSegment.ESplineInterpolation.Uniform)
                {
                    startTime = spline.NaturalToUniformTime(startTime);
                    endTime   = spline.NaturalToUniformTime(endTime);
                }

                var distanceLeft = totalSplineLength - (endTime * totalSplineLength);
                if (endTime < 1 && distanceLeft <= snapDistance)
                {
                    endTime = 1;
                    i       = 1;
                }

                if (currentResult == null)
                {
                    var newChunkObject = new GameObject("Chunk" + chunkCount);
                    newChunkObject.transform.SetParent(rootTarget.transform);
                    newChunkObject.transform.localPosition = Vector3.zero;
                    newChunkObject.transform.localRotation = Quaternion.identity;
                    newChunkObject.transform.localScale    = Vector3.one;
                    currentResult = CreateNewBakeResult(config, newChunkObject, lodLevelIndex, chunkCount);
                    chunkCount++;
                }

                workingMeshes.Add(new CombineInstance()
                {
                    mesh      = config.SourceMesh.DistortAlongSpline(spline, matrix, startTime, endTime, snapDistance, config.SplineInterpolation),
                    transform = meshCombineMatrix,
                });

                if (config.Mirror)
                {
                    workingMeshes.Add(new CombineInstance()
                    {
                        mesh = config.SourceMesh.DistortAlongSpline(spline, mirrorMatrix, startTime, endTime, snapDistance, config.SplineInterpolation)
                               .FlipWindingOrder(),
                        transform = Matrix4x4.identity,
                    });
                }

                distanceAccumulator += perMeshPercentage * totalSplineLength;
                if ((distanceAccumulator > config.BreakDistance && totalSplineLength - distanceAccumulator > config.BreakDistance) || Mathf.Approximately(endTime, 1))
                {
                    distanceAccumulator = 0;
                    if (workingMeshes.Count > 0)
                    {
                        CombineInstance[] combineInstances = workingMeshes
                                                             .Where((instance => instance.mesh != null && instance.mesh.bounds.size.magnitude > 0)).ToArray();
                        currentResult.Mesh.CombineMeshes(combineInstances);
                    }
                    for (int j = 0; j < workingMeshes.Count; j++)
                    {
                        DestroyImmediate(workingMeshes[j].mesh);
                    }

                    if (config.OverrideNormal)
                    {
                        var n = new List <Vector3>();
                        n.Fill(Vector3.up, currentResult.Mesh.vertexCount);
                        currentResult.Mesh.SetNormals(n);
                    }
                    else
                    {
                        currentResult.Mesh.RecalculateNormals();
                    }

                    if (Mathf.Approximately(currentResult.Mesh.bounds.size.x, 0) ||
                        Mathf.Approximately(currentResult.Mesh.bounds.size.y, 0) ||
                        Mathf.Approximately(currentResult.Mesh.bounds.size.z, 0))
                    {
                        continue;
                    }

                    currentResult.Mesh.RecalculateTangents();
                    currentResult.Mesh.RecalculateBounds();
                    if (config.CopyToCollider)
                    {
                        currentResult.MeshCollider.enabled    = true;
                        currentResult.MeshCollider.sharedMesh = currentResult.Mesh;
                    }

                    currentResult.Renderer.shadowCastingMode = config.ShadowCastingMode;
                    currentResult.Filter.sharedMesh          = currentResult.Mesh;
                    currentResult.Renderer.sharedMaterials   = config.Materials.ToArray();
                    Results.Add(currentResult);
                    currentResult = null;
                }
            }
        }