Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to expand/contract path?
#1
I am making a futuristic space race track and want asteroids on either side of the race track.

This is what I have so far (I don't have a road 3d model yet so I am just using the Barbed Wire from the tutorial for testing):
[Image: jBWcmwj.png]

My problem is that the farther the control point is from the path's center, a wider gap is created. I want a consistent gap size, like the red lines in the screenshot as opposed to the green lines.

Currently I am doing this with TRS Path two times, one scales the path by 0.75 for the inner asteroid belt, and the other scales the path by 1.25 for the outer asteroid belt. This obviously works by percentage which is why there is a larger gap the farther it is from the center.

There does not seem to be a expand/contract path modifier which would have been nice.

What I mean by that is to push or pull the path outward or inward from its median center. In Blender, I can illustrate this with the Push/Pull command:

This is a simple scale, just like what TRS Path does:
[Image: 42oUrGB.gif]

And this is Blender's Push/Pull command, notice it tries to maintain the distance outward/inward, this is what I need:
[Image: XBGYu8e.gif]


The other way I was attempting this was to not use any TRS Path modifier but using the Translation properties in the Volume Spots node that are scattering the asteroids.

[Image: QDnU8Wz.png]

The big problem with it is it requires the asteroids to have non-randomized rotations, since translation can only work in either world or local space (would have been nice to be able to choose between local, world, or "curve" space, where +Z is pointing towards the spline tangent direction).

Any way to fix this?
Reply
#2
Ok, so a few hours after posting that, I was able to come up with my own solution (I couldn't reply because I was in the moderation queue).

I figured out how to create a cg module and made an "Expand/Contract Path" module which does a similar thing to Blender's Push/Pull command.

[Image: n1LDXUG.gif]

Also added some properties I might find useful later on:

[Image: DM3oMd7.gif]

Is there any 3rd-party repository where we can submit/share cg modules? I'd love to share this and get feedback.
Reply
#3
Hi Ferdinand
Sorry for the wait before your thread was validated. I am on vacation right now, so I don't check the forum as often as usual.
Thanks for wanting to share the code for your module. Please post it here, and I will take a look at it and let you know what I think about it once back from vacation.
If you need anything else please let me know.
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
Thanks, here's the code:

Code:
using System;
using UnityEngine;

namespace FluffyUnderware.Curvy.Generator.Modules
{
    [ModuleInfo("Modifier/Expand\u200A\u2215\u200AContract Path", ModuleName="Expand/Contract Path", Description="")]
    public class ModifierExpandContractPath : CGModule, IOnRequestProcessing, IPathProvider
    {
        [HideInInspector]
        [InputSlotInfo(typeof(CGPath), Name = "Input Path", ModifiesData = true)]
        public CGModuleInputSlot InPath = new CGModuleInputSlot();

        [HideInInspector]
        [OutputSlotInfo(typeof(CGPath), Name = "Modified Path")]
        public CGModuleOutputSlot OutPath = new CGModuleOutputSlot();

        #region ### Serialized Fields ###

        [SerializeField]
        [Tooltip("Distance of expansion/contraction. Negative values are ok.")]
        float m_Amount;

        [SerializeField]
        [Tooltip("Angle in degrees to spin the new path about the original path.")]
        float m_AngleOffset;

        #endregion

        #region ### Public Properties ###

        public float Amount
        {
            get => m_Amount;
            set
            {
                if (Math.Abs(m_Amount - value) > Mathf.Epsilon)
                {
                    m_Amount = value;
                    Dirty = true;
                }
            }
        }

        public float AngleOffset
        {
            get => m_AngleOffset;
            set
            {
                if (Math.Abs(m_AngleOffset - value) > Mathf.Epsilon)
                {
                    m_AngleOffset = value;
                    Dirty = true;
                }
            }
        }

        public bool PathIsClosed => IsConfigured && InPath.SourceSlot().PathProvider.PathIsClosed;

        #endregion

        #region ### Unity Callbacks ###

#if UNITY_EDITOR
        protected override void OnValidate()
        {
            base.OnValidate();
            Dirty = true;
        }
#endif

        public override void Reset()
        {
            base.Reset();
            Amount = 0;
            AngleOffset = 0;
        }

        #endregion


        static readonly Quaternion s_Right = Quaternion.Euler(0, -90, 0);

        #region ### IOnRequestProcessing ###

        public CGData[] OnSlotDataRequest(CGModuleInputSlot requestedBy, CGModuleOutputSlot requestedSlot, params CGDataRequestParameter[] requests)
        {
            CGData[] result;
            if (requestedSlot == OutPath)
            {
                CGPath data = InPath.GetData<CGPath>(out bool isDisposable, requests);
#if CURVY_SANITY_CHECKS
                Assert.IsTrue(data == null || isDisposable);
#endif

                if (data != null && m_Amount != 0)
                {
                    for (int i = 0; i < data.Count; i++)
                    {
                        // Direction is forward, so we need to rotate it to the right, we also spin it around by the angle offset
                        Quaternion rot = Quaternion.LookRotation(data.Directions.Array[i], data.Normals.Array[i]) *
                                        Quaternion.Euler(0, 0, 90+m_AngleOffset) * s_Right;

                        data.Positions.Array[i] += rot * (Vector3.forward * m_Amount);
                    }
                    data.Recalculate();
                }
                result = new CGData[] { data };
            }
            else
                result = null;

            return result;
        }

        #endregion
    }
}


Here is the editor script for it:
Code:
using UnityEditor;
using FluffyUnderware.Curvy.Generator.Modules;

namespace FluffyUnderware.CurvyEditor.Generator.Modules
{
    [CustomEditor(typeof(ModifierExpandContractPath))]
    public class ModifierExpandContractPathEditor : CGModuleEditor<ModifierExpandContractPath>
    {
    }
}
Reply
#5
Hi Ferdinand,
I modified the code above to avoid using the "new ();" expression, since it is not compatible with all the currently supported Unity version. Let me know if you have any issue with me changing this.
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
#6
Hi Ferdinand,
About your ModifierExpandContractPath, it is a useful one, and I see it as an evolution of the existing Path Relative Translation module. Your module allows to define what direction to translate into, whereas the Path Relative Translation always translates (positively or negatively) towards the binormal of the spline.
In the future, Path Relative Translation will be able to translate in custom directions like in your module.
Thanks and 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
Wink Train carriage with 2 bogies following a path arcadeperfect 9 27 08-25-2023, 02:56 PM
Last Post: arcadeperfect
  Generator does not exactly follow the path F.A.L. 3 4 04-24-2023, 03:49 PM
Last Post: _Aka_
Question Spline path "Range" option: how to go from end to start CP? niuage 4 13 03-07-2022, 10:48 AM
Last Post: niuage
Question Generating a path from selected point to the beginning of spline on a closed spline? Zendariel 5 414 10-29-2021, 01:57 PM
Last Post: _Aka_

Forum Jump: