Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to get Split Length to match spline segment length?
#1
Hello, 

I am using Curvy to make train tracks in a game, and I am very impressed with it. However, I have got a bit of a problem, and I would greatly appreciate some advice please. 

In my game the player can place the tracks in runtime, by clicking on the map and placing control points. Then, when they have finished placing a rail track, the generator converts this into a mesh, using a spline shape for the rail's cross-section like in demo scene 25. This all works well.

The problem I have is getting the generated track meshes to match up to the spline segments. I would like both to be the same length, so that if the player clicks on a track mesh segment, they can delete it, and also delete the spline segment underneath. 

At the moment the segments and mesh objects do not match up. Before the generator creates the rail track meshes, I have code that redistributes the control points so that their segments are the same length as the Volume Mesh modules SplitLength value. However, when I check the result in the scene view, the length of the rail meshes is bigger than the segment length. This means that the meshes overlap more than one segment.

Is there a way to get the length of the track meshes to be the same as the length of the spline segments, so that each mesh starts at the start of the segment and stops at its end? 
So each mesh equals the segment's F0-F1 length and position all along the spline?

Here is the code I am using (it uses part of your Equalize function):

Code:
public void RegulariseCPDistance(CurvySpline theSpline)
    {
        float splineLength = theSpline.Length;

        float numOfSegmentsNeeded;

        float numOfControlPointsNeeded;

        float numOfActualCPs;

        float numOfCPsToAdd;


        numOfSegmentsNeeded = Mathf.Ceil(splineLength / rail_Segment_Length);

        numOfControlPointsNeeded = numOfSegmentsNeeded + 1.0f;

        numOfActualCPs = theSpline.ControlPointCount;

        numOfCPsToAdd = numOfControlPointsNeeded - numOfActualCPs;

        if (numOfCPsToAdd > 0)
        {
            int numToAddInt = (int)numOfCPsToAdd;

            for (int i = 0; i < numToAddInt; i++)
            {
                theSpline.Add();
            }
        }
        else if (numOfCPsToAdd < 0)
        {
            // THIS BIT DOES NOT WORK YET!!!

            /*
            theSpline.Clear();

            int numToAddInt = (int)numOfControlPointsNeeded;

            for (int i = 0; i < numToAddInt; i++)
            {
                theSpline.Add();
            }
            */
        }

        int startCPIndex = Mathf.Clamp(theSpline.GetControlPointIndex(theSpline.ControlPointsList[0]), 0, theSpline.ControlPointCount - 2);
        int endCPIndex = Mathf.Clamp(theSpline.GetControlPointIndex(theSpline.ControlPointsList[theSpline.ControlPointCount - 1]), startCPIndex + 2, theSpline.ControlPointCount - 1);
        if (endCPIndex - startCPIndex < 2)
        {
            Debug.Log("CurvySpline.Equalize: Not a valid range selection!");
            return;
        }
        float segmentLength = theSpline.ControlPointsList[endCPIndex].Distance - theSpline.ControlPointsList[startCPIndex].Distance;

        float equal = buildVolumeMesh.SplitLength;

        float dist = theSpline.ControlPointsList[startCPIndex].Distance;

        Vector3[] newCpPositions = new Vector3[endCPIndex - startCPIndex - 1];

        for (int i = startCPIndex + 1; i < endCPIndex; i++)
        {
            int iterationIndex = i - startCPIndex - 1;
            newCpPositions[iterationIndex] = theSpline.InterpolateByDistance(dist + (iterationIndex + 1) * equal);
        }

        for (int i = startCPIndex + 1; i < endCPIndex; i++)
        {
            int iterationIndex = i - startCPIndex - 1;

            theSpline.ControlPointsList[i].SetLocalPosition(newCpPositions[iterationIndex]);
        }

        theSpline.Refresh();
    }
Reply
#2
Here is an update on my issue:

I have come up with an alternative solution to getting the segment lengths and mesh lengths to be the same. I am passing the Input Spline Path module only two control points at a time, and getting the generator to only make a mesh between these two control points.

I loop over all control points in the spline this way, so that all the segments have a mesh made for them.

However, I have a new problem when using this method - all of the mesh colliders are positioned over the final segment in the spline. So if I have a spline with 5 segments, the mesh in the last segment has 5 colliders, and none of the other segments have any colliders. I have tried to override the code in the Create Mesh module, but nothing changes.

Is there a way to get each segment to have its own mesh collider in the correct position?

Here is the code I am using:

Code:
    public void SplineSegmentiser(CurvySpline theSpline)
    {
        inputSplinePath.Spline = theSpline;

        float numOfSegmentsNeeded = Mathf.Ceil(theSpline.Length / rail_Segment_Length);

        int segmentsNeededInt = (int)numOfSegmentsNeeded;

        for (int i = 0; i < segmentsNeededInt; i++)
        {
            CurvySplineSegment fromCP = theSpline.ControlPointsList[i];

            CurvySplineSegment toCP = theSpline.ControlPointsList[i + 1];

            inputSplinePath.ClearRange();

            inputSplinePath.SetRange(fromCP, toCP);

            inputSplinePath.Refresh();

            createMesh.Refresh();

            rail_Path_Generator.Refresh();

            createMesh.SaveToScene(fromCP.gameObject.transform);

            createMesh.DeleteAllOutputManagedResources();
        }
    }
Reply
#3
Hi
Not knowing how your generator is setup, I might answer with irrelevant answer. If it is the case, please send me the reproduction case so I can give a better answer.
When you use the Split functionality of the Volume Mesh module, the code will split the generated mesh at the first row of vertices possible. So if you set Split length to 100, and the first row of vertices is only at 120, the mesh will be split at 120. So a fix to this is to set the Include CPs option of the Shape Extrusion module to true. That way you will always have a row of vertices at the position of CPs.
If this does not solve the issue, I am thinking of another solution:
You can have multiple shape extrusions, one for each segment. That needs the creation of a lot of modules, so creating them via API is the best. To limit the extrusion to only one segment, please use the Start CP and End CP parameters, under the Range tab, in the Input Spline Path module.
Did this help?
Have a nice day
Please consider leaving a review for Curvy. This will help a lot keeping Curvy relevant in the eyes of the Asset Store algorithm.
Reply
#4
Hello,

Thank you for your message, and explaining how Split Length works.

I think I will try to improve the method I am using in my second post. Basically, it sounds similar to your suggestion, as I loop through control points in the spline, and only generate a mesh between neighbouring control points.

This way each mesh is exactly as long as the segment. However, most of the meshes don't have a collider that matches their mesh. They have a mesh collider component, but the mesh they use for this is actually the mesh of the last segment in the spline. So the last mesh in the spline has many mesh colliders positioned over it - each one a component of each of the other mesh game objects in the spline.

The only way I managed to get this working, is to set createMesh.AutoUpdateColliders = false, and to add the mesh colliders myself:

Code:
            GameObject meshSegment = createMesh.SaveToScene(fromCP.gameObject.transform);

            MeshCollider segmentCollider = meshSegment.transform.GetChild(0).gameObject.AddComponent<MeshCollider>();

            segmentCollider.convex = true;

Is this an ok fix for this?
Reply
#5
Hi
The mesh collider you add automatically has the right mesh assigned to it by default? If so, then yes, your fix seems ok to me.
I will try tomorrow to reproduce the issue you had with the mesh colliders, and if I do reproduce it, try to fix it. If you have a reproduction case feel free to send it to me.
Have a nice day
Please consider leaving a review for Curvy. This will help a lot keeping Curvy relevant in the eyes of the Asset Store algorithm.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Force spline normal to be always world up GameJazz 12 21 Yesterday, 01:20 PM
Last Post: _Aka_
  Gap between spline mesh segments Beaver_Boy 8 16 08-06-2022, 12:11 PM
Last Post: _Aka_
  How to stop spline refreshing when a control point is deleted or removed? Beaver_Boy 4 6 07-23-2022, 11:24 AM
Last Post: _Aka_
  SetRange for closed Segment tairoark 2 6 06-14-2022, 09:25 PM
Last Post: tairoark

Forum Jump: