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; } } }