// 5.2. - 5.6. recursively fitting a straight or quadratic line segment on this sequence of path nodes, // called from tracepath() // Returns a segment (a list of those doubles is a segment). public static IEnumerable <Segment> Fit(IReadOnlyList <InterpolationPoint> path, SequenceIndices sequence, Tracing tracing, SvgRendering rendering) { var pathLength = path.Count; // return if invalid sequence.End // TODO: When would this ever happen? if ((sequence.End > pathLength) || (sequence.End < 0)) { yield break; } // TODO: This is actually the number of line segments in the sequence. Not the number of points in the sequence. var sequenceLength = sequence.End - sequence.Start; sequenceLength += sequenceLength < 0 ? pathLength : 0; int errorIndex; var lineResult = LineSegment.Fit(path, tracing.LTres, sequence, sequenceLength, out errorIndex, rendering); if (lineResult != null) { yield return(lineResult); yield break; } // 5.3. If the straight line fails (an error>ltreshold), find the point with the biggest error var fitIndex = errorIndex; var splineResult = SplineSegment.Fit(path, tracing.QTres, sequence, sequenceLength, ref errorIndex, rendering); if (splineResult != null) { yield return(splineResult); yield break; } // 5.5. If the spline fails (an error>qtreshold), find the point with the biggest error, var splitIndex = (fitIndex + errorIndex) / 2; // 5.6. Split sequence and recursively apply 5.2. - 5.6. to startpoint-splitpoint and splitpoint-endpoint sequences foreach (var segmentPart in Fit(path, new SequenceIndices { Start = sequence.Start, End = splitIndex }, tracing, rendering)) { yield return(segmentPart); } foreach (var segmentPart in Fit(path, new SequenceIndices { Start = splitIndex, End = sequence.End }, tracing, rendering)) { yield return(segmentPart); } }
private void GenerateSplinePlanes(float planeGive, SplineSegment mainSpline, out Plane startPlane, out Plane endPlane) { var startNodePos = mainSpline.FirstControlPoint.Position; var startNodeControl = NodeConnection.ThisNode.GetNodeControl(NodeConnection.NextNode).Flatten().normalized; startPlane = new Plane(startNodeControl, startNodePos + startNodeControl * planeGive); var endNodePos = mainSpline.SecondControlPoint.Position; var endNodeControl = NodeConnection.NextNode.GetNodeControl(NodeConnection.ThisNode).Flatten().normalized; endPlane = new Plane(endNodeControl, endNodePos + endNodeControl * planeGive); }
public void EnterSplineSegment(int previousSplineExitPoint, SplineComputer spline, int entryPoint, Spline.Direction direction) { if (!isEngine) { return; } if (back != null) { segment.end = previousSplineExitPoint; back.segment = segment; } segment = new SplineSegment(spline, entryPoint, direction); }
public Vector3 GetTangent(int segidx, float segpos) { SplineSegment ss = mSegments[segidx]; if (Reparam == ReparamType.None) { return(GetTangent(ss, segpos / ss.mLength)); } else { return(GetTangent(ss, GetReparam(ss, segpos / ss.mLength))); } }
private void OnSplineUpdate(SplineUpdateInfo inInfo) { Vector3 diff = inInfo.Point - transform.position; transform.position = inInfo.Point; float speed = diff.magnitude / Routine.DeltaTime; Debug.Log("Speed: " + speed.ToString()); SplineSegment seg = inInfo.GetSegment(); GetComponent <SpriteRenderer>().color = Color.Lerp((Color)inInfo.Spline.GetVertexUserData(seg.VertexA), (Color)inInfo.Spline.GetVertexUserData(seg.VertexB), seg.Interpolation); }
public Vector3 GetPositionByT(int segidx, float t, out float offset) { SplineSegment ss = mSegments[segidx]; offset = ss.mStartlen + ss.mLength * t; if (Reparam == ReparamType.None) { return(GetPosition(ss, t)); } else { return(GetPosition(ss, GetReparam(ss, t))); } }
void ApplyOffset() { if (isEngine) { ResetSegments(); return; } float totalMoved = 0f, moved = 0f; double start = front.tracer.UnclipPercent(front.tracer.result.percent); //Travel backwards along the front wagon's spline Spline.Direction inverseDirection = front.segment.direction; InvertDirection(ref inverseDirection); SplineComputer spline = front.segment.spline; double percent = front.segment.Travel(start, offset, inverseDirection, out moved, front.segment.spline.isClosed); totalMoved += moved; //Finalize if moved fully without reaching a spline end or a junction if (Mathf.Approximately(totalMoved, offset)) { if (segment != front.segment) { if (back != null) { back.segment = segment; } } if (segment != front.segment) { segment = front.segment; } ApplyTracer(spline, percent, front.tracer.direction); return; } //Otherwise, move along the current recorded spline segment if (segment != front.segment) { inverseDirection = segment.direction; InvertDirection(ref inverseDirection); spline = segment.spline; percent = segment.Travel(offset - totalMoved, inverseDirection, out moved, segment.spline.isClosed); totalMoved += moved; } ApplyTracer(spline, percent, segment.direction); }
protected float GetLength(SplineSegment ss) { float len = 0; Vector3 start, end; float t = 0, dt = 1 / (float)StepCount; int idx = 0; start = ss.mStartpos; while (idx < StepCount) { t += dt; end = GetPosition(ss, t); len += (end - start).magnitude; start = end; ++idx; } return(len); }
public SplineSegment GetSpline(bool recalculate = false, bool applyModifiers = true) { if (recalculate) { RecalculateSpline(); } if (applyModifiers) { foreach (var connectionComponent in Components) { var splineMod = connectionComponent as ISplineModifier; if (splineMod != null) { _spline = splineMod.ProcessSpline(_spline); } } } return(_spline); }
private void Temp(Color c, SplineNode node, SplineSegment segment) { int depth = segment.Depth(); if (depth == _depth | viewAllNodes) { if (segment.ChildCount <= 0) { Handles.color = c.Whitten(.3f); Handles.DrawDottedLine(node.PositionStart, segment.GlobalPosition(), 2f); Handles.color = c.Blacken(.3f); Handles.DrawLine(node.PositionEnd, segment.GlobalPosition()); } } foreach (SplineSegment child in segment.Children) { Temp(c, node, child); } }
protected float GetReparam(SplineSegment ss, float u) { if (u <= 0) { return(0); } else if (u >= 1) { return(1); } switch (Reparam) { case ReparamType.RungeKutta: { int ridx = (int)(u * (float)StepCount); float uc = (u - ss.mPrecomps[ridx]) / mPrecompdiv; return(Mathf.Lerp(ss.mParams[ridx], ss.mParams[ridx + 1], uc)); } case ReparamType.Simple: { int ridx = 0; for (int i = 1; i < StepCount + 1; ++i) { if (ss.mPrecomps[i] > u) { ridx = i - 1; break; } } float uc = (u - ss.mPrecomps[ridx]) / (ss.mPrecomps[ridx + 1] - ss.mPrecomps[ridx]); return(Mathf.Lerp(ss.mParams[ridx], ss.mParams[ridx + 1], uc)); } default: return(0); } }
private void RecursiveDrawSegment(SplineSegment segment) { foreach (SplineSegment child in segment.Children) { RecursiveDrawSegment(child); } int depth = segment.Depth(); Vector3 gPosition = segment.GlobalPosition(); Vector3 gScale = segment.GlobalPosition(); Quaternion gRotation = segment.GlobalRotation(); if (depth == _depth | viewAllNodes) { Gizmos.color = Palette.ColorWheel(segment.Depth(), 6); UnityEditor.Handles.color = Gizmos.color; UnityEditor.Handles.DrawWireDisc(gPosition, gRotation * Vector3.forward, 7f - depth); UnityEditor.Handles.DrawLine(gPosition, gPosition + segment.GlobalRotation() * (Vector3.forward * (depth + 1) * 5f)); //UnityEditor.Handles.Label(compareLocalGlobal ? segment.LocalPosition : segment.GlobalPosition(), segment.Depth().ToString()); UnityEditor.Handles.Label(segment.GlobalPosition() + Vector3.down * segment.Depth() * 10, "L:" + segment.LocalScale.ToString() + " G:" + segment.GlobalScale()); } }
/** * This function updates the spline mesh. It is called automatically once in a while, if updateMode isn't set to DontUpdate. */ public void UpdateMesh( ) { Setup( ); //Reset the generated meshes if (BentMesh) { BentMesh.Clear( ); } if (baseMesh == null || spline == null || segmentCount <= 0) { return; } //Gather model data Vector3[] verticesBase = baseMesh.vertices; Vector3[] normalsBase = baseMesh.normals; Vector4[] tangentsBase = baseMesh.tangents; Vector2[] uvBase = baseMesh.uv; int[] trianglesBase = baseMesh.triangles; //Allocate some memory for new mesh data Vector3[] verticesNew = new Vector3[verticesBase.Length * segmentCount]; Vector3[] normalsNew = new Vector3[normalsBase.Length * segmentCount]; Vector4[] tangentsNew = new Vector4[tangentsBase.Length * segmentCount]; Vector2[] uvNew = new Vector2[uvBase.Length * segmentCount]; int[] trianglesNew = new int[trianglesBase.Length * segmentCount]; //Group front/rear vertices together List <int> verticesFront = new List <int>( ); List <int> verticesBack = new List <int>( ); Vector3 centerFront = Vector3.zero; Vector3 centerBack = Vector3.zero; for (int i = 0; i < verticesBase.Length; i++) { if (verticesBase[i].z > 0f) { verticesFront.Add(i); centerFront += verticesBase[i]; } else if (verticesBase[i].z < 0f) { verticesBack.Add(i); centerBack += verticesBase[i]; } } centerFront /= verticesFront.Count; centerBack /= verticesBack.Count; if (splineSegment >= 0 && splineSegment < spline.SegmentCount) { SplineSegment currentSegment = spline.SplineSegments[splineSegment]; int vIndex = 0; for (int segment = 0; segment < segmentCount; segment++) { float param0 = (float)segment / segmentCount; float param1 = (float)(segment + 1) / segmentCount; if (param1 == 1f) { param1 -= 0.00001f; } param0 = currentSegment.ConvertSegmentToSplineParamter(param0); param1 = currentSegment.ConvertSegmentToSplineParamter(param1); CalculateBentMesh(ref vIndex, verticesFront, verticesBack, ref centerFront, ref centerBack, param0, param1, verticesBase, normalsBase, tangentsBase, uvBase, verticesNew, normalsNew, tangentsNew, uvNew); for (int i = 0; i < trianglesBase.Length; i++) { trianglesNew[i + (segment * trianglesBase.Length)] = trianglesBase[i] + (verticesBase.Length * segment); } } BentMesh.vertices = verticesNew; BentMesh.uv = uvNew; if (normalsBase.Length > 0) { BentMesh.normals = normalsNew; } if (tangentsBase.Length > 0) { BentMesh.tangents = tangentsNew; } BentMesh.triangles = trianglesNew; } else { int vIndex = 0; for (int segment = 0; segment < segmentCount; segment++) { float param0 = (float)segment / segmentCount; float param1 = (float)(segment + 1) / segmentCount; if (param1 == 1f) { param1 -= 0.00001f; } CalculateBentMesh(ref vIndex, verticesFront, verticesBack, ref centerFront, ref centerBack, param0, param1, verticesBase, normalsBase, tangentsBase, uvBase, verticesNew, normalsNew, tangentsNew, uvNew); for (int i = 0; i < trianglesBase.Length; i++) { trianglesNew[i + (segment * trianglesBase.Length)] = trianglesBase[i] + (verticesBase.Length * segment); } } BentMesh.vertices = verticesNew; BentMesh.uv = uvNew; if (normalsBase.Length > 0) { BentMesh.normals = normalsNew; } if (tangentsBase.Length > 0) { BentMesh.tangents = tangentsNew; } BentMesh.triangles = trianglesNew; } }
public void Execute(ArchetypeChunk chunk, int index, int entityOffset) { var localToParentAcessor = chunk.GetNativeArray(localToParentType); var animationAcessor = chunk.GetNativeArray(splineAnimationType); var justSpawnedAcessor = default(NativeArray <JustSpawned>); if (chunk.Has(justSpawnedType)) { justSpawnedAcessor = chunk.GetNativeArray(justSpawnedType); } for (int i = 0; i < chunk.Count; i++) { SplineAnimationSpeed anim = animationAcessor[i]; var elements = elementAcessor[anim.spline]; var segments = segmentAcessor[anim.spline]; if (anim.index >= elements.Length) { continue; } float move = anim.speed * deltaTime; if (justSpawnedAcessor.IsCreated) { move = anim.speed * justSpawnedAcessor[i].deltaTime; } float left; SplineSegment segment = segments[anim.segIndex]; while (move >= (left = (segment.end - anim.t) / (segment.end - segment.start) * segment.length)) { move -= left; if (++anim.segIndex >= segments.Length || segments[anim.segIndex].start == 0) { if (anim.isLoop) { if (++anim.index >= elements.Length) { anim.index = 0; anim.segIndex = 0; } } else { if (++anim.index >= elements.Length - 1) { anim.index = elements.Length; anim.segIndex = 0; anim.t = 0; break; } } } segment = segments[anim.segIndex]; anim.t = segment.start; } if (anim.index >= elements.Length) { SplineElement last = elements[elements.Length - 1]; localToParentAcessor[i] = new LocalToParent { Value = math.float4x4(last.rotation, last.point) }; } else { anim.t += (move / segment.length) * (segment.end - segment.start); SplineElement start = elements[anim.index]; SplineElement end = anim.index < elements.Length - 1 ? elements[anim.index + 1] : elements[0]; float3 position = Bezier.GetPoint(start.point, start.point + start.forward, end.point + end.backward, end.point, anim.t); quaternion rotation = math.nlerp(start.rotation, end.rotation, anim.t); localToParentAcessor[i] = new LocalToParent { Value = math.float4x4(rotation, position) }; } animationAcessor[i] = anim; } }
/// <summary> /// Computes keyframe times to ensure a constant speed along the given spline. /// </summary> /// <remarks> /// If the speed is 0 or omitted, it will be auto-computed so the animation completes in 1s. /// </remarks> public static float[] ComputeSplineTimes(Vector3[] positions, float speed = 0f) { bool isUnitLength = (speed == 0f); if (isUnitLength) speed = 1f; int frameCount = positions.Length; float[] times = new float[frameCount]; times[0] = 0f; if (frameCount < 4) { for (int i = 1; i < frameCount; ++i) times[i] = times[i - 1] + (positions[i] - positions[i - 1]).magnitude / speed; } else { times[1] = (positions[1] - positions[0]).magnitude / speed; int samplesPerSegment = 16; Vector3 oldPosition = positions[1]; for (int j = 2; j < frameCount - 1; ++j) { SplineSegment segment = new SplineSegment(positions[j-2], positions[j-1], positions[j], positions[j+1]); float segmentLength = 0f; for (int i = 0; i < samplesPerSegment; ++i) { float t = (float)i / (float)(samplesPerSegment - 1); Vector3 position = segment.GetPosition(t); segmentLength += (position - oldPosition).magnitude; oldPosition = position; } times[j] = times[j-1] + segmentLength / speed; } float endDistance = (positions[frameCount - 1] - positions[frameCount - 2]).magnitude; times[frameCount - 1] = times[frameCount - 2] + endDistance / speed; } if (isUnitLength) { float totalTime = 0f; foreach (float time in times) totalTime += time; for (int i = 0; i < times.Length; ++i) times[i] /= totalTime; } return times; }
private void UpdateMesh(Mesh dstMesh, int splineSegment, ref List <Vector3> lightProbePositions) { Vector2 probeExtents = new Vector2(baseMesh.bounds.extents.x + lightProbeExtrude.x, lightProbeExtrude.y); Vector3[] segmentProbePositions = { new Vector3(0, probeExtents.y + lightProbeHeight * 0.5f, 0), new Vector3(probeExtents.x, probeExtents.y, 0), new Vector3(probeExtents.x, probeExtents.y + lightProbeHeight, 0), new Vector3(-probeExtents.x, probeExtents.y, 0), new Vector3(-probeExtents.x, probeExtents.y + lightProbeHeight, 0) }; //Gather model data Vector3[] verticesBase = baseMesh.vertices; Vector3[] normalsBase = baseMesh.normals; Vector4[] tangentsBase = baseMesh.tangents; Vector2[] uvBase = baseMesh.uv; Vector2[] uvLightmap = baseMesh.uv2; ArrayList allTrianglesBase = new ArrayList(); for (int q = 0; q < baseMesh.subMeshCount; ++q) { allTrianglesBase.Add(baseMesh.GetTriangles(q)); } var localSegmentCount = segmentCount / splineSegmentCount; //Allocate some memory for new mesh data Vector3[] verticesNew = new Vector3[verticesBase.Length * localSegmentCount]; Vector3[] normalsNew = new Vector3[normalsBase.Length * localSegmentCount]; Vector4[] tangentsNew = new Vector4[tangentsBase.Length * localSegmentCount]; Vector2[] uvNew = new Vector2[uvBase.Length * localSegmentCount]; Vector2[] lightmapUvNew = new Vector2[uvBase.Length * localSegmentCount]; ArrayList allTrianglesNew = new ArrayList(); for (int q = 0; q < baseMesh.subMeshCount; ++q) { allTrianglesNew.Add(new int[baseMesh.GetTriangles(q).Length *localSegmentCount]); } //Group front/rear vertices together List <int> verticesFront = new List <int>( ); List <int> verticesBack = new List <int>( ); Vector3 centerFront = Vector3.zero; Vector3 centerBack = Vector3.zero; Vector3 minCorner = new Vector3(Mathf.Infinity, Mathf.Infinity, Mathf.Infinity); for (int i = 0; i < verticesBase.Length; i++) { if (verticesBase[i].z > 0f) { verticesFront.Add(i); centerFront += verticesBase[i]; } else if (verticesBase[i].z < 0f) { verticesBack.Add(i); centerBack += verticesBase[i]; } minCorner = Vector3.Min(minCorner, verticesBase[i]); verticesBase[i].x = verticesBase[i].x + xyOffset.x; verticesBase[i].y = verticesBase[i].y + xyOffset.y; } centerFront /= verticesFront.Count; centerBack /= verticesBack.Count; // float meshAspect = (xyScale.x * baseMesh.bounds.size.x) / baseMesh.bounds.size.z; // Vector2 lightmapScale = new Vector2( // (baseMesh.bounds.size.x * xyScale.x), // spline.Length/(float)splineSegmentCount); //;;Debug.Log ("lightmapScale " + lightmapScale.x + "," + lightmapScale.y + " " + splineSegmentCount + " " + localSegmentCount + " " + baseMesh.bounds.size); int vIndex = 0; int boxDimension = (int)Mathf.Round(Mathf.Sqrt(localSegmentCount) + 0.5f); //;;Debug.Log ("boxDimension " + boxDimension); for (int segment = 0; segment < localSegmentCount; segment++) { float localParam0 = (float)segment / localSegmentCount; float localParam1 = (float)(segment + 1) / localSegmentCount; if (localParam1 == 1f) { localParam1 -= 0.00001f; } float splineParam0 = localParam0; float splineParam1 = localParam1; if (splitMesh && splineSegment < spline.SegmentCount) { SplineSegment currentSegment = spline.SplineSegments[splineSegment]; splineParam0 = currentSegment.ConvertSegmentToSplineParamter(localParam0); splineParam1 = currentSegment.ConvertSegmentToSplineParamter(localParam1); } int onX = segment / boxDimension; //int onY = segment % boxDimension; //;;Debug.Log(onX + " " + onY); var columnStartingSegment = onX * boxDimension; var lightmapOffset = new Vector2( onX, -Mathf.Max(0f, (float)columnStartingSegment / (float)localSegmentCount)); CalculateBentMesh(ref vIndex, verticesFront, verticesBack, ref centerFront, ref centerBack, splineParam0, splineParam1, localParam0, localParam1, new Vector2(1.0f / ((float)boxDimension), (float)(boxDimension - 1)), lightmapOffset, verticesBase, normalsBase, tangentsBase, uvBase, uvLightmap, verticesNew, normalsNew, tangentsNew, uvNew, lightmapUvNew); for (int q = 0; q < allTrianglesNew.Count; ++q) { int[] trianglesNew = allTrianglesNew[q] as int[]; int[] trianglesBase = allTrianglesBase[q] as int[]; for (int i = 0; i < trianglesBase.Length; i++) { trianglesNew[i + (segment * trianglesBase.Length)] = trianglesBase[i] + (verticesBase.Length * segment); } } } var localLightProbeSegmentCount = lightProbeSegmentCount / splineSegmentCount; for (int segment = 0; segment < localLightProbeSegmentCount + 1; segment++) { float param0 = (float)segment / localLightProbeSegmentCount; float paramC = ((float)segment + 0.5f) / localLightProbeSegmentCount; if (splitMesh && splineSegment < spline.SegmentCount) { SplineSegment currentSegment = spline.SplineSegments[splineSegment]; param0 = currentSegment.ConvertSegmentToSplineParamter(param0); paramC = currentSegment.ConvertSegmentToSplineParamter(paramC); } Vector3 pos0 = spline.transform.InverseTransformPoint(spline.GetPositionOnSpline(param0)); Quaternion rot0 = spline.GetOrientationOnSpline(param0) * Quaternion.Inverse(spline.transform.localRotation); Vector3 posC = spline.transform.InverseTransformPoint(spline.GetPositionOnSpline(paramC)); Quaternion rotC = spline.GetOrientationOnSpline(paramC) * Quaternion.Inverse(spline.transform.localRotation); foreach (var probePos in segmentProbePositions) { lightProbePositions.Add(pos0 + rot0 * probePos); } if (segment != localLightProbeSegmentCount) { lightProbePositions.Add(posC + rotC * segmentProbePositions[0]); } } dstMesh.vertices = verticesNew; dstMesh.uv = uvNew; dstMesh.uv2 = lightmapUvNew; if (normalsBase.Length > 0) { dstMesh.normals = normalsNew; } if (tangentsBase.Length > 0) { dstMesh.tangents = tangentsNew; } dstMesh.subMeshCount = allTrianglesNew.Count; for (int q = 0; q < allTrianglesNew.Count; ++q) { int[] trianglesNew = allTrianglesNew[q] as int[]; dstMesh.SetTriangles(trianglesNew, q); } }
/// <summary> Creates the mesh given the 4 control points </summary> public void SetupSegment(Vector3 P0, Vector3 P1, Vector3 P2, Vector3 P3) { _segment = new SplineSegment(P0, P1, P2, P3); SetupMesh(); }
public Vector3 GetNormalByT(int segidx, float t) { SplineSegment ss = mSegments[segidx]; return(GetNormal(ss, t)); }
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; } } }
/// <summary> /// This function adds an offset to a BranchingSplineParameter while automatically switching splines when a juction is passed. /// </summary> /// <param name='bParam'> /// A BranchingSplineParameter. /// </param> /// <param name='distanceOffset'> /// An offset that shall be added to the BranchingSplineParameter (in game units). /// </param> /// <param name='bController'> /// A BranchingController-delegate that decides which path to follow if a junction is passed. /// </param> /// <returns> /// True if the spline used as reference path has been changed; False if not. /// </returns> public bool Advance(BranchingSplineParameter bParam, float distanceOffset, BranchingController bController) { bool splineChange = false; if (!SplinesAvailable) { return(false); } if (++recoursionCounter > 12) { recoursionCounter = 0; return(false); } CheckParameter(bParam); Spline currentSpline = bParam.spline; SplineNode currentNode = IsOnSplineNode(bParam.parameter, currentSpline); //Parameter on node? if (currentNode != null) { BranchingSplinePath nextPath = ChoseSpline(currentNode, bParam, bController, distanceOffset > 0); bParam.spline = nextPath.spline; bParam.direction = nextPath.direction; bParam.parameter = currentNode.Parameters[bParam.spline].PosInSpline; SplineNode[] adjacentNodes = GetAdjacentSegmentNodes(nextPath.spline, currentNode); SplineNode nextNode = adjacentNodes[ForwardOnSpline(nextPath.direction, distanceOffset) ? 1 : 0]; if (nextNode != null) { bParam.parameter += (nextNode.Parameters[bParam.spline].PosInSpline - currentNode.Parameters[bParam.spline].PosInSpline) * 0.001f; Advance(bParam, distanceOffset, bController); splineChange = false; } else { splineChange = false; } } else { SplineSegment currentSegment = currentSpline.GetSplineSegment(bParam.parameter); float signedSplineLength = currentSpline.Length * (bParam.Forward ? 1 : -1); float normalizedOffsetDir = distanceOffset / signedSplineLength; float newParameter = bParam.parameter + normalizedOffsetDir; float clampedParameter = currentSegment.ClampParameterToSegment(newParameter); float offsetDifference = newParameter - clampedParameter; bParam.parameter = clampedParameter; if (Mathf.Approximately(offsetDifference, 0)) { splineChange = false; } else { splineChange = Advance(bParam, offsetDifference * signedSplineLength, bController); } } recoursionCounter = 0; return(splineChange); }
public void Build() { int idx, count; SplinePoint p1, p2, p3, p4; if (mPoints.Count < 2) { mSegments = null; Length = 0; return; } if (WrapType == WrapMode.Loop) { count = mPoints.Count; } else { count = mPoints.Count - 1; } mSegments = new SplineSegment[count]; Length = 0; idx = 0; if (WrapType == WrapMode.Loop) { while (idx < count) { p1 = mPoints[XSplineUtil.WrapIndex(idx - 1, mPoints.Count)]; p2 = mPoints[XSplineUtil.WrapIndex(idx, mPoints.Count)]; p3 = mPoints[XSplineUtil.WrapIndex(idx + 1, mPoints.Count)]; p4 = mPoints[XSplineUtil.WrapIndex(idx + 2, mPoints.Count)]; mSegments[idx] = new SplineSegment(InterpolateType); if (InterpolateType == SplineType.Linear || InterpolateType == SplineType.Bezier) { BuildSegment(mSegments[idx], p1, p2, p3, p4); } else { BuildSegment(mSegments[idx], p2, p1, p4, p3); } ++idx; } } else { while (idx < count) { p1 = mPoints[XSplineUtil.ClampIndex(idx - 1, mPoints.Count)]; p2 = mPoints[XSplineUtil.ClampIndex(idx, mPoints.Count)]; p3 = mPoints[XSplineUtil.ClampIndex(idx + 1, mPoints.Count)]; p4 = mPoints[XSplineUtil.ClampIndex(idx + 2, mPoints.Count)]; mSegments[idx] = new SplineSegment(InterpolateType); if (InterpolateType == SplineType.Linear || InterpolateType == SplineType.Bezier) { BuildSegment(mSegments[idx], p1, p2, p3, p4); } else { BuildSegment(mSegments[idx], p2, p1, p4, p3); } ++idx; } } ++mBuildnum; }
/// <summary> /// This function updates the spline mesh. It is called automatically once in a while, if updateMode isn't set to DontUpdate. /// </summary> public void UpdateMesh( ) { SetupMesh( ); bentMesh.Clear( ); if (baseMesh == null || spline == null || segmentCount <= 0) { return; } SetupMeshBuffers( ); float startParam; float endParam; float deltaParam; switch (splitMode) { case SplitMode.BySplineSegment: SplineSegment[] splineSegments = spline.SplineSegments; splineSegment = Mathf.Clamp(splineSegment, 0, splineSegments.Length - 1); SplineSegment segment = splineSegments[splineSegment]; startParam = (float)segment.StartNode.Parameters[spline].position; endParam = startParam + (float)segment.NormalizedLength; break; case SplitMode.BySplineParameter: startParam = segmentStart; endParam = segmentEnd; break; case SplitMode.DontSplit: default: startParam = 0; endParam = 1; break; } deltaParam = endParam - startParam; float param0 = 0f; float param1 = 0f; SplineMeshModifier[] splineMeshModifiers = GetComponentsInChildren <SplineMeshModifier>( ); for (int segmentIdx = 0; segmentIdx < segmentCount; segmentIdx++) { MeshData currentBaseMesh; if (segmentIdx == 0 && startBaseMesh != null) { currentBaseMesh = meshDataStart; } else if (segmentIdx == segmentCount - 1 && endBaseMesh != null) { currentBaseMesh = meshDataEnd; } else { currentBaseMesh = meshDataBase; } param0 = startParam + deltaParam * (float)(segmentIdx) / segmentCount; param1 = startParam + deltaParam * (float)(segmentIdx + 1) / segmentCount; BendMesh(param0, param1, currentBaseMesh, meshDataNew, splineMeshModifiers); } meshDataNew.AssignToMesh(bentMesh); }
protected void BuildSegment(SplineSegment ss, SplinePoint p1, SplinePoint p2, SplinePoint p3, SplinePoint p4) { if (InterpolateType == SplineType.Linear) { PreparePoint(p1, p2, p3); PreparePoint(p2, p3, p4); ss.mStartpos = p2.mPoint; ss.mEndpos = p3.mPoint; ss.mStartctrl = ss.mStartpos + p2.mNextctrl; ss.mEndctrl = ss.mEndpos + p3.mPrevctrl; } if (InterpolateType == SplineType.Bezier) { PreparePoint(p1, p2, p3); PreparePoint(p2, p3, p4); ss.mStartpos = p2.mPoint; ss.mEndpos = p3.mPoint; ss.mStartctrl = ss.mStartpos + p2.mNextctrl; ss.mEndctrl = ss.mEndpos + p3.mPrevctrl; } else if (InterpolateType == SplineType.CatmullRom) { ss.mStartpos = p1.mPoint; ss.mEndpos = p4.mPoint; ss.mStartctrl = p2.mPoint; ss.mEndctrl = p3.mPoint; } ss.mStartlen = Length; float seglen = GetLength(ss); Length += seglen; ss.mLength = seglen; ss.mEndlen = Length; switch (Reparam) { case ReparamType.None: ss.mParams = null; ss.mPrecomps = null; break; case ReparamType.Simple: { mPrecompdiv = 1 / (float)StepCount; float param = 0, length = 0; Vector3 prev, next; ss.mParams = new float[StepCount + 1]; ss.mPrecomps = new float[StepCount + 1]; for (int i = 1; i < StepCount + 1; ++i) { prev = GetPosition(ss, param); param += mPrecompdiv; next = GetPosition(ss, param); length += (next - prev).magnitude; ss.mPrecomps[i] = length / seglen; ss.mParams[i] = param; } ss.mParams[0] = 0; ss.mParams[StepCount] = 1; ss.mPrecomps[0] = 0; ss.mPrecomps[StepCount] = 1; mPrecompdiv = 1 / (float)StepCount; } break; case ReparamType.RungeKutta: float dlen = seglen / (float)StepCount, lparam = 0; ss.mParams = new float[StepCount + 1]; ss.mPrecomps = new float[StepCount + 1]; for (int i = 0; i < StepCount + 1; ++i) { ss.mParams[i] = GetReparamRungeKutta(ss, lparam); ss.mPrecomps[i] = lparam / seglen; lparam += dlen; } ss.mParams[0] = 0; ss.mParams[StepCount] = 1; ss.mPrecomps[0] = 0; ss.mPrecomps[StepCount] = 1; mPrecompdiv = 1 / (float)StepCount; break; } }