Search Unity

SplineMesh, the plugin to create curved content

Discussion in 'Assets and Asset Store' started by methusalah999, Dec 14, 2017.

  1. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    Oh yes, you're right.

    I'll make a change to the destroying method in UOUtility, because I think it is only the DestroyImmediate that need to be wrapped in compile directive.

    Thanks for pointing this out, I haven't tried a full build recently.
     
  2. Caruos

    Caruos

    Joined:
    Dec 30, 2016
    Posts:
    42
    Hello @methusalah999,

    I really appreciate that you are constantly improving SplineMesh, that's the sign of a dedicated programmer ;)

    With that being said, I build the railgrind mechanic in my game around the 1.0.1 SplineMesh (that I modified quite a bit to implement spline rotation), I'm considering whether or not I should jump to the 1.1 SplineMesh, which would require some heavy modifications in my code... So if you are considering to add some other changes in the short-term (let's say, within 2-3 months), it would probably be better for me to wait for the next version.

    Could you please give me an (estimated) release schedule for the next version ? If it's in a long time then no problem, I'll switch to 1.1 and work around it ;)
     
  3. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    I think I will publish a new backward compatible version soon to make some bugfixes and adjustments.

    The next major iteration will not come before summer I think.
     
    Caruos likes this.
  4. asdzxcv777

    asdzxcv777

    Joined:
    Jul 17, 2017
    Posts:
    29
    hello .. i was going through the code in mesh bender and i was having difficulty in understanding it.
    for example " mesh will always be bent in the x axis" . i thought mesh would be bent along spline . so what does mesh being bent along x axis mean ??
    also
    bent.v = q * bent.v + sample.location;
    bent.n = q * bent.n;
    how does this work ??
     
  5. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    Mesh is bent along it's own X axis. MeshBender will take the vertices at minimum X first, then to the maximum X in the mesh space and place then along the curve. You can set a rotation in the case your mesh is oriented differently.

    The two lines of code are the final transformation of a mesh vertex and associated normal. q represents the rotation to apply according to spline tangent, roll and up vector at this distance along curve. The vertex is oriented and offset, while the normal is only oriented.
     
    asdzxcv777 likes this.
  6. asdzxcv777

    asdzxcv777

    Joined:
    Jul 17, 2017
    Posts:
    29
    Could the deformation be done in vertex shader like its done in Ue4??
     
  7. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    So the graphic card could participate and save CPU time? I'm sure it could, and to be honest, I think it should :)

    I've never worked with shaders. Have you?
     
  8. asdzxcv777

    asdzxcv777

    Joined:
    Jul 17, 2017
    Posts:
    29
    Code (CSharp):
    1. Shader "Unlit/road"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex("Texture", 2D) = "white" {}
    6.     }
    7.         SubShader
    8.     {
    9.         Tags { "RenderType" = "Opaque" }
    10.         LOD 100
    11.         Pass
    12.         {
    13.             CGPROGRAM
    14.             #pragma vertex vert
    15.             #pragma fragment frag
    16.             // make fog work
    17.             #pragma multi_compile_fog
    18.             #include "UnityCG.cginc"
    19.             float3 SplineStartPos;
    20.             float3 SplineStartTangent;
    21.             float3 SplineEndPos;
    22.             float3 SplineEndTangent;
    23.             float minZ;
    24.             float length;
    25.             struct appdata
    26.             {
    27.                 float4 vertex : POSITION;
    28.                 float3 normal : NORMAL;
    29.                 float2 uv : TEXCOORD0;
    30.             };
    31.             struct v2f
    32.             {
    33.                 float3 normal : NORMAL;
    34.                 float2 uv : TEXCOORD0;
    35.                 UNITY_FOG_COORDS(1)
    36.                 float4 vertex : SV_POSITION;
    37.             };
    38.             sampler2D _MainTex;
    39.             float4 _MainTex_ST;
    40.             float3 SplineEvalPos(float3 StartPos, float3 StartTangent, float3 EndPos, float3 EndTangent, float A)
    41.             {
    42.                 float A2 = A * A;
    43.                 float A3 = A2 * A;
    44.                 return (((2 * A3) - (3 * A2) + 1) * StartPos) + ((A3 - (2 * A2) + A) * StartTangent) + ((A3 - A2) * EndTangent) + (((-2 * A3) + (3 * A2)) * EndPos);
    45.             }
    46.             float3 SplineEvalDir(float3 StartPos, float3 StartTangent, float3 EndPos, float3 EndTangent, float A)
    47.             {
    48.                 float3 C = (6 * StartPos) + (3 * StartTangent) + (3 * EndTangent) - (6 * EndPos);
    49.                 float3 D = (-6 * StartPos) - (4 * StartTangent) - (2 * EndTangent) + (6 * EndPos);
    50.                 float3 E = StartTangent;
    51.                 float A2 = A * A;
    52.                 return normalize((C * A2) + (D * A) + E);
    53.             }
    54.             float4 LookRotation(float3 forward, float3 up)
    55.             {
    56.                 forward = normalize(forward);
    57.                 float3 right = normalize(cross(up, forward));
    58.                 up = cross(forward, right);
    59.                 float m00 = right.x;
    60.                 float m01 = right.y;
    61.                 float m02 = right.z;
    62.                 float m10 = up.x;
    63.                 float m11 = up.y;
    64.                 float m12 = up.z;
    65.                 float m20 = forward.x;
    66.                 float m21 = forward.y;
    67.                 float m22 = forward.z;
    68.                 float num8 = (m00 + m11) + m22;
    69.                 float4 quaternion;
    70.                 if (num8 > 0.0f)
    71.                 {
    72.                     float num = (float)sqrt(num8 + 1.0f);
    73.                     quaternion.w = num * 0.5f;
    74.                     num = 0.5f / num;
    75.                     quaternion.x = (m12 - m21) * num;
    76.                     quaternion.y = (m20 - m02) * num;
    77.                     quaternion.z = (m01 - m10) * num;
    78.                     return quaternion;
    79.                 }
    80.                 if ((m00 >= m11) && (m00 >= m22))
    81.                 {
    82.                     float num7 = (float)sqrt(((1.0f + m00) - m11) - m22);
    83.                     float num4 = 0.5f / num7;
    84.                     quaternion.x = 0.5f * num7;
    85.                     quaternion.y = (m01 + m10) * num4;
    86.                     quaternion.z = (m02 + m20) * num4;
    87.                     quaternion.w = (m12 - m21) * num4;
    88.                     return quaternion;
    89.                 }
    90.                 if (m11 > m22)
    91.                 {
    92.                     float num6 = (float)sqrt(((1.0f + m11) - m00) - m22);
    93.                     float num3 = 0.5f / num6;
    94.                     quaternion.x = (m10 + m01) * num3;
    95.                     quaternion.y = 0.5f * num6;
    96.                     quaternion.z = (m21 + m12) * num3;
    97.                     quaternion.w = (m20 - m02) * num3;
    98.                     return quaternion;
    99.                 }
    100.                 float num5 = (float)sqrt(((1.0f + m22) - m00) - m11);
    101.                 float num2 = 0.5f / num5;
    102.                 quaternion.x = (m20 + m02) * num2;
    103.                 quaternion.y = (m21 + m12) * num2;
    104.                 quaternion.z = 0.5f * num5;
    105.                 quaternion.w = (m01 - m10) * num2;
    106.                 return quaternion;
    107.             }
    108.             v2f vert(appdata v)
    109.             {
    110.                 float t = (v.vertex.z - minZ) / length;
    111.                 float3 newVert = SplineEvalPos(SplineStartPos, SplineStartTangent, SplineEndPos, SplineEndTangent,t);
    112.                 float3 newTangent = SplineEvalDir(SplineStartPos, SplineStartTangent, SplineEndPos, SplineEndTangent,t);
    113.                 float3 newNormal = cross(newTangent, normalize(cross(float3(0, 1, 0), newTangent)));
    114.                 float4 q = LookRotation(newTangent, newNormal);
    115.                 newNormal = q * newNormal;
    116.                 v.vertex.z = 0;
    117.                 newVert = q * v.vertex + newVert;
    118.                 v2f o;
    119.                 o.vertex = UnityObjectToClipPos(newVert);
    120.                 o.normal = newNormal;
    121.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    122.                 UNITY_TRANSFER_FOG(o,o.vertex);
    123.                 return o;
    124.             }
    125.             fixed4 frag(v2f i) : SV_Target
    126.             {
    127.                 // sample the texture
    128.                 fixed4 col = 0;
    129.             col.rgb = i.normal*0.5f + 0.5f;
    130.             // apply fog
    131.             UNITY_APPLY_FOG(i.fogCoord, col);
    132.             return col;
    133.         }
    134.         ENDCG
    135.     }
    136.     }
    137. }
    Here ...
    I tried writing the logic in shader and its kind of working but not properly
    This mesh bends along local z
    Maybe someone more clever can improve upon this

    The mesh bending logic is still not clear to me 100% eg why does vertex.z have to be 0
     
  9. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    Sorry for the late answer, I'm sick.

    Dude this seems to be a serious contribution. I will need time to process this thing. Can you give some information about how you put it to use?

    If you have questions regarding my code, don't hesitate to send me PMs, I will take a look as far as my brain starts to work properly again.

    Thanks for the sharing !
     
  10. Infitek

    Infitek

    Joined:
    Feb 9, 2017
    Posts:
    3
    Hello ! Thank you for your wonderful asset.
    I have a question about reversing the direction of each node, do you know how I could do that ?
    ( I have a minecart that travels across some rails and when it reaches its destination, I reverse the List of nodes so it can go backwards but the direction Vector of each nodes does not change, so the mine cart turns strangely, I hope I'm understandable..)

    Thank you for your time
     
  11. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    Hi there.

    I wouldn't do that. In addition to the useless curve calculations, you will have to reverse all the curved content as well, like the rail and props you will certainly want to have along the spline. I suggest you to add some boolean to your minecart's logic "isGoingForward" and look for the next node to go according to this boolean.

    Still, if you want to reverse direction of each node, you can get it with CubicBezierCurve.GetInverseDirection()
     
  12. Infitek

    Infitek

    Joined:
    Feb 9, 2017
    Posts:
    3
    Thank you for the quick answer, yeah I did as you said, and ideed I work as expected juste by lowering the rateof the follower.

    Just a last question, is there a way to make the follower move more linearly ? Actually it goes slower at the start and at the end of a node, like a Slerp, it is possible to change that ?
    Thank you again
     
  13. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    When you go throught a bezier curve, you can use either the time or the distance.

    The time "t" goes from 0 on the start node, to 1 at the end node. It is not linear because it goes "faster" on the less curved parts, as shown on this gif from wikipedia.


    The distance, on the other hand, is linear whatever the curvature.

    If you observe speed change with you follower, please try to get the curve sample by distance, not by time, using the speed you want.
     
  14. Caruos

    Caruos

    Joined:
    Dec 30, 2016
    Posts:
    42
    Hello @methusalah999,
    I've jumped from SplineMesh 1.0.1 to 1.1, it took some time to rework my code aroung it but I don't regret it at all ! The workflow to make inner loops is so much faster now !

    The next thing I think this asset needs the most is multicolor texture on the spline extrusion. It already has most of the elements needed, but there aren't any demo examples about it and it took me some code tweaking to get the results I wanted. As usual, I will gladly share them :

    ExtrusionSegment.cs (Changes are marked with #CHANGE)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using UnityEngine;

    namespace SplineMesh {
    [ExecuteInEditMode]
    [DisallowMultipleComponent]
    [RequireComponent(typeof(MeshFilter))]
    [RequireComponent(typeof(MeshRenderer))]
    public class ExtrusionSegment : MonoBehaviour {
    private MeshFilter mf;
    private Mesh result;
    private List<Vertex> shapeVertices = new List<Vertex>();
    private CubicBezierCurve curve;
    private float textureScale = 1;

    private void OnEnable() {
    mf = GetComponent<MeshFilter>();
    if (mf.sharedMesh == null) {
    mf.sharedMesh = new Mesh();
    }
    }

    /// <summary>
    /// Set the cubic Bézier curve to use to bend the source mesh, and begin to listen to curve control points for changes.
    /// </summary>
    /// <param name="curve"></param>
    /// <param name="update">If let to true, update the resulting mesh immediatly.</param>
    public void SetCurve(CubicBezierCurve curve, bool update = true) {
    if (this.curve != null) {
    this.curve.Changed.RemoveListener(() => Compute());
    }
    this.curve = curve;
    curve.Changed.AddListener(() => Compute());
    if (update) Compute();
    }

    /// <summary>
    /// Set the source mesh.
    /// </summary>
    /// <param name="mesh"></param>
    /// <param name="update">If let to true, update the resulting mesh immediatly.</param>
    public void SetShapeVertices(List<Vertex> shapeVertices, bool update = true) {
    this.shapeVertices = shapeVertices;
    if (update) Compute();
    }

    public void SetTextureScale(float textureScale, bool update = true) {
    this.textureScale = textureScale;
    if (update) Compute();
    }

    private List<OrientedPoint> GetPath() {
    var path = new List<OrientedPoint>();
    CurveSample sample;
    for (float t = 0; t < 1; t += 1 / 30.0f) {
    sample = curve.GetSample(t);
    path.Add(new OrientedPoint() {
    position = sample.location,
    rotation = sample.Rotation,
    scale = sample.scale,
    roll = sample.roll

    //#CHANGE
    , distanceInCurve = sample.distanceInCurve

    });
    }
    sample = curve.GetSample(1);
    path.Add(new OrientedPoint() {
    position = sample.location,
    rotation = sample.Rotation,
    scale = sample.scale,
    roll = sample.roll

    //#CHANGE
    , distanceInCurve = sample.distanceInCurve

    });
    return path;
    }

    public void Compute() {
    List<OrientedPoint> path = GetPath();

    int vertsInShape = shapeVertices.Count;
    int segments = path.Count - 1;
    int edgeLoops = path.Count;
    int vertCount = vertsInShape * edgeLoops;

    var triangleIndices = new List<int>(vertsInShape * 2 * segments * 3);
    var vertices = new Vector3[vertCount];
    var normals = new Vector3[vertCount];
    var uvs = new Vector2[vertCount];

    int index = 0;
    foreach (OrientedPoint op in path) {
    foreach (Vertex v in shapeVertices) {
    var position = v.point;
    // apply scale
    position = Vector3.Scale(position, new Vector3(op.scale.x, op.scale.y, 0));

    // apply roll
    position = Quaternion.AngleAxis(op.roll, Vector3.forward) * position;

    vertices[index] = op.LocalToWorld(position);
    normals[index] = op.LocalToWorldDirection(v.normal);

    //#CHANGE
    //uvs[index] = new Vector2(v.uCoord, path.IndexOf(op) / ((float)edgeLoops) * textureScale);
    uvs[index] = new Vector2(v.uCoord, textureScale * op.distanceInCurve);


    index++;
    }
    }
    index = 0;
    for (int i = 0; i < segments; i++) {
    for (int j = 0; j < shapeVertices.Count; j++) {
    int offset = j == shapeVertices.Count - 1 ? -(shapeVertices.Count - 1) : 1;
    int a = index + shapeVertices.Count;
    int b = index;
    int c = index + offset;
    int d = index + offset + shapeVertices.Count;
    triangleIndices.Add(c);
    triangleIndices.Add(b);
    triangleIndices.Add(a);
    triangleIndices.Add(a);
    triangleIndices.Add(d);
    triangleIndices.Add(c);
    index++;
    }
    }

    mf.sharedMesh.Clear();
    mf.sharedMesh.vertices = vertices;
    mf.sharedMesh.normals = normals;
    mf.sharedMesh.uv = uvs;
    mf.sharedMesh.triangles = triangleIndices.ToArray();
    }

    [Serializable]
    public class Vertex {
    public Vector2 point;
    public Vector2 normal;
    public float uCoord;

    public Vertex(Vector2 point, Vector2 normal, float uCoord) {
    this.point = point;
    this.normal = normal;
    this.uCoord = uCoord;
    }
    }

    public struct OrientedPoint {
    public Vector3 position;
    public Quaternion rotation;
    public Vector2 scale;
    public float roll;

    //#CHANGE
    public float distanceInCurve;

    public Vector3 LocalToWorld(Vector3 point) {
    return position + rotation * point;
    }

    public Vector3 LocalToWorldDirection(Vector3 dir) {
    return rotation * dir;
    }
    }

    }
    }

    upload_2019-3-6_22-50-14.jpeg

    upload_2019-3-6_22-37-39.png

    I would also like to see how shaders can be implemented as explained above (as long as it's reasonably flexible and user friendly, as shaders tend to look really hard to read). Whatever path you choose, I'll be very interested !
     
  15. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    I will have to look into that becaus eI don't understand what you are trying to do that is not already present in meshExtruder. Or is there a regression in v1.1?
     
  16. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    Hi there !

    If you like my code, I've shared a little more today with DebugPlus, a usefull tool to draw any gizmo and log on screen during play mode, with a single line of code.

    Check it out on Github or on the Unity forum.
     
  17. Caruos

    Caruos

    Joined:
    Dec 30, 2016
    Posts:
    42
    My goal was to have all stripes to be the same lenght, and I couldn't achieve it with the base code - the stripes were very large on long curves, then very small on short curves. I'm not sure it's achievable at all with the uv formula in the ExtrusionSegment script - though I would be glad to be proven wrong.
     
  18. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    I understand and it's a regression indeed. I've changed the way extrusion is done. It now creates a single mesh per curve, not only one big mech for the whole spline. I did this because edition in real time was becoming impossible with a large number of curves.

    But the UV calculation should still be made in the spline space, not each curve. I created a ticket.

    A solution would be to have a texture offset in addition to the texture scale in ExtrusionSegment. Then here in ExtrusionSegment, we should ignore edgeLoops to avoid scaling the texture accordingly to the curve length, and add this length to the UV to offset it.

    The next ExtrusionSegment would then use this offset and apply its own and so on. I can't work on it for the moment, though.

    Thanks for your contribution, @Caruos
     
  19. Caruos

    Caruos

    Joined:
    Dec 30, 2016
    Posts:
    42
    I tried your texture offset idea, and the result is great :


    SplineExtrusion.cs (Changes are marked with #CHANGE)

    private void GenerateMesh() {
    UOUtility.DestroyChildren(generated);

    int i = 0;

    //#CHANGE
    textureOffset = 0.0f;

    foreach (CubicBezierCurve curve in spline.GetCurves()) {
    GameObject go = UOUtility.Create("segment " + i++,
    generated,
    typeof(MeshFilter),
    typeof(MeshRenderer),
    typeof(ExtrusionSegment),
    typeof(MeshCollider));
    go.GetComponent<MeshRenderer>().material = material;

    ExtrusionSegment mb = go.GetComponent<ExtrusionSegment>();
    mb.SetShapeVertices(shapeVertices, false);
    mb.SetTextureScale(textureScale, false);
    mb.SetCurve(curve, true);

    //#CHANGE
    mb.SetTextureOffset(textureOffset, true);
    textureOffset += curve.Length;
    }
    }

    ExtrusionSegment.cs
    (Changes are marked with #CHANGE)

    //#CHANGE (add function)
    public void SetTextureOffset(float textureOffset, bool update = true)
    {
    this.textureOffset = textureOffset;
    if (update) Compute();
    }

    foreach (OrientedPoint op in path) {
    foreach (Vertex v in shapeVertices) {
    var position = v.point;
    // apply scale
    position = Vector3.Scale(position, new Vector3(op.scale.x, op.scale.y, 0));

    // apply roll
    position = Quaternion.AngleAxis(op.roll, Vector3.forward) * position;

    vertices[index] = op.LocalToWorld(position);
    normals[index] = op.LocalToWorldDirection(v.normal);

    //#CHANGE
    //uvs[index] = new Vector2(v.uCoord, path.IndexOf(op) / ((float)edgeLoops) * textureScale);
    uvs[index] = new Vector2(v.uCoord, textureScale * (op.distanceInCurve + textureOffset));

    index++;
    }

    }

    upload_2019-3-9_12-55-5.png

    I couldn't get good results with path.IndexOf(op), the stripes where smaller near the beginning and the end of each curve - presumably because of how the mesh is build. Adding the distanceInCurve data in the OrientedPoint class isn't that difficult and it solved all problems, so it's something to consider.
     
    Last edited: Mar 9, 2019
    methusalah999 likes this.
  20. Kinosei

    Kinosei

    Joined:
    Dec 3, 2015
    Posts:
    7
    That's a nice tool, I'm looking forward on using it on my game as it's simple and precise to work with and create a path around a forest.
    But I'm having a problem: When I reload the scene, the spline doubles the mesh, and I have to go there and delete the previous one, as if it was reloading the script and generating the path once again. I'm using the pipe example. If I leave the script off it won't move my object, then I turn it on and it duplicates the same way.
    What could be done to avoid this?
    Thanks!
     
    Last edited: Mar 11, 2019
  21. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    Life cycle of generated objects is not perfect in the showcase. It may be a little tricky, depending on what you need.

    For example, you won't manage objects the same way if you need them to be modified during play mode, and if you need them to be generated static and saved on the scene once and for all to have baked lightmaps.

    In general, if something is messed up, you will find easy to delete all generated objects and then deactivate/reactivate the parent to have things generated correctly.

    I'm still working on a better way, suggestions are welcome
     
    Last edited: Mar 11, 2019
  22. Kinosei

    Kinosei

    Joined:
    Dec 3, 2015
    Posts:
    7
    I see. It's not the best way, but I can use it and have the static mesh when I finish then. Thanks!
    I'm a very newbie programmer, but this issue seems to have something to do with the Awake() or Start() functions. Isn't it creating the mesh on one of those?
     
  23. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    In the showcase examples, the meshes are generally created onEnable, onValidate and when the spline node list change (adding of removing a node).

    The reason why this logic is in a script called "Example" is that it may not suits all situations. Example scripts are examples of user implementations, mostly for inspiration and you will most likely have to adapt it to you specific needs.

    But still, I will try and find a solution that works in more situations.
     
  24. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    @Caruos your contribution is working great so far
    splineExtrusionUV.gif

    @Kinosei I've changed the way objects are generated, without relying on Object instance. It's now more simple but won't work with many instances of the same component. Now the spline is searched throught parents and you can manage to have many instance of the same component in many children, as shown in examples with left and right rails.

    Hopefully it will be less buggy and more satisfying.

    It's live on github, and soon on the asset store
     
    Last edited: Mar 16, 2019
    Caruos likes this.
  25. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    SplineMesh 1.1.1 is on the asset store, with 2 bugfixes.

    Have fun bending things !
     
  26. GingerKendal3

    GingerKendal3

    Joined:
    May 16, 2018
    Posts:
    8
    This looks pretty impressive, however, I ran into an issue right off the bat. Hopefully you can help.

    I can't seem to create a new node by Click + Alt and dragging the node to a new position. I threw in a few debug logs and looked through some code to see if it was something obvious but I couldn't find anything. Hopefully, I am not being dumb. Any chance something changed in this release or possibly incompatible Unity version?

    I am using 2019.2.0a8 - tested on clean project and simply added the Spline GameObject and tried duplicating a node.
     
  27. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    I've just tested with Unity 2018.3 and latest SplineMesh and it works. 2019.2 is alpha, so it may be a bug or a backward incompatibility. I'll try it soon.

    Please note that new nodes have A scale of zero, which may be the reason why you couldn't see your curved content. But the node and attached new curve should still be visible in the editor.

    Have you tried adding a node programatically in your script?
     
  28. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    contortion.gif

    I'm working on a new feature for SplineMesh. Do you like it?

    One major limitation is that the MeshBender can only work on a single curve at a time. This had to change !

    Do you guys have any suggested feature for the next version of SplineMesh?

    Have fun bending things !
     
    montanhabio and Caruos like this.
  29. GingerKendal3

    GingerKendal3

    Joined:
    May 16, 2018
    Posts:
    8
    Tested both versions in a clean project - node creation by alt dragging 2018.3 works but it does not work in 2019.2.

    Behavior:
    2018.3: Holding down alt activates the SceneView Orbit mode, however, clicking on the move gizmo overrides it and allows dragging (creation of a new node).

    2019.2: Holding down alt activates the SceneView Orbit mode and clicking on the move gizmo no longer overrides and activates the move gizmo. The click and dragging will just continue to rotate the camera.Thus cannot create a new node.

    Programmatically adding nodes works in both versions. Probably just a gizmo behavioral change, yeah? With SceneView Orbit that is. I skimmed through the changelogs and didn't notice anything that would change it
     
  30. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    Thanks for the digging, I will have to look into it
     
  31. Caruos

    Caruos

    Joined:
    Dec 30, 2016
    Posts:
    42
    That's really cool and has a lot of potential, I can't wait to try it !

    I would suggest an option to "fill" (create a mesh and apply a texture) the starting and ending faces in a spline extrusion.

    upload_2019-3-20_19-50-9.png
    It doesn't look good, and applying the texture on a separate object (that must be redimensioned every time you change the spline) is quite tedious.
     
  32. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    Agreed. I will have to resurrect my old triangulation algorithm for this one but you are right, it must be done.
     
  33. jRocket

    jRocket

    Joined:
    Jul 12, 2012
    Posts:
    700
    I am trying to generate a spline at runtime from a set of points. Anyone know how one might define the "direction" of a SplineNode from a set of given points?
     
  34. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    I'm interested in that too :)
     
  35. Caruos

    Caruos

    Joined:
    Dec 30, 2016
    Posts:
    42
    :confused: I don't really understand the question. For any set of given points, you have an infinity of possible directions for an infinity of possible trajectories.

    For a straight line between (X1,Y1,Z1) and (X2,Y2,Z2), the direction at point 1 is the vector (X2-X1 , Y2-Y1 , Z2-Z1).
    For a circular trajectory, the directions will look like this :


    I'm working on a sheet that automatically calculates positions and directions for basic shapes (straight lines, circles, sinusoids, spirals etc...) Once it's complete and accurate enough I'll share it here.
    upload_2019-3-26_20-20-45.png
     
  36. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    I think @jRocket wants to create a smooth path by placing points and letting an algorithm decides the directions.

    This asset is doing that, and the code is provided, if you are looking for inspiration. Note that it is not open-source, as far as I know. @SebastianLague could you confirm?
     
  37. jRocket

    jRocket

    Joined:
    Jul 12, 2012
    Posts:
    700
    Yes, some smooth spline based on previous/next points is what I was going for. I tried setting the handle(direction) to the midpoint between the current next and node, which isn't quite right. I'll take a look at that other asset. Thanks! :)
     
  38. jRocket

    jRocket

    Joined:
    Jul 12, 2012
    Posts:
    700
    I think if I treat the SplineNode.Direction as the next point in the spline, it may work. Correct me if I am wrong, but I believe SplineNode.Direction refers to the bezier handle position, rather than an actual vector direction.
     
  39. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    you're right, direction is control point in the bezier curve vocabulary. To make a smooth bezier path from a list of point, you will have to place these control point so that the tangent at each node is something average between the segment before and the segment after, weighted by the segment length, something like that.

    I'm pretty sure you could find documentation easily on the subject.
     
  40. tux83

    tux83

    Joined:
    Jan 2, 2014
    Posts:
    19
    Hi, I'm using this plugin, but i can't made a prefab..
    __
    error:

    InvalidOperationException : Destroy a GameObject inside a prefab instance is not allowed.
    __

    How to save my object spline settings in parent prefab?
    is it possible like as the GameObject ?


    thanks
     
  41. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    you have delete the generated content before you save the prefab. Generated content must never be saved, except in the scene for baking
     
  42. Pheck

    Pheck

    Joined:
    Jul 9, 2009
    Posts:
    225
    fyi
    I just grabbed the update from the store and see lots of compile errors. things like code trying to assign a mesh to a sourcemesh type variable, etc.
     
  43. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    Thanks I'll check this soon
     
  44. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    I can't reproduce any issue on a clean setup. If the problem occur in your code, I'm afraid version 1.2 is not backward compatible and you will need to changes some things, especially in the setup of the MeshBender components.

    It's no big deal at all, please refer to examples.

    If you need help, or if you spot any issue with the asset, don't hesitate to give me details.
     
  45. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    SplineMesh evolves again to support the most requested feature : bend a mesh on any interval on a spline.

    It's also possible to make a spline loop (experimental) and performances have been enhanced on mesh bending.

    Version 1.2 is now live on the asset store.

    As always : free, #opensource and with love !


    growingRoots.gif
     
    Caruos likes this.
  46. jRocket

    jRocket

    Joined:
    Jul 12, 2012
    Posts:
    700
    I got compile errors when I tried to do a standalone build. I believe that's due to including UnityEditor in many places which is editor-only. Easy enough to fix though :)
     
  47. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    I thought I had tested a build, it must be because of a last-minute modification. I'll check that soon, thanks !
     
  48. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    On second though, I think it is totally doable to create and save the curved content in the prefab. You could want to have some tentacle calculated once and for all in a prefab, for example.

    In that case, you will have to prevent your content to be bent outside the prefab editor. Just delete the calculation code in update/onEnable/start methods and have it done manually. For example, you could have an Editor for your script to show a button in the inspector, and trigger the content bending on button pressed only.

    Be aware that in some cases, your curved content may be heavy (big meshes with a lot of vertices) and the prefab file may become fat.
     
  49. tux83

    tux83

    Joined:
    Jan 2, 2014
    Posts:
    19

    Could you explain step by step how to made a prefab from simple spline ?

    thank you
     
  50. methusalah999

    methusalah999

    Joined:
    May 22, 2017
    Posts:
    643
    I totally depends on what you are trying to do but in general:
    • create you own script based on one of the SplineMesh examples,
    • remove all code that add or delete children from your compoenent's callbacks (Update, OnValidate, OnEnable...)
    • create a way to update manually (a button in a custom editor for example)

    This way, the editor mode and play mode won't try to mess with your prefab hierarchy, which is forbidden. Say that you delete a node of your spline, the associated content won't be deleted (which may be odd).

    In your prefab stage, you will have to manually update things. You can also test the PrefabStage in the script to update things automatically when you are in prefab mode, but I've never done that.

    For further information, please send me a PM with more details on what you are trying to acheive.