Bending Mesh along a circle/path

Hello folks, hope you are all well,
I’m creating a game something like this ==>

I am able to cut the mesh successfully, only problem is I want to bend the mesh part (which is being cut) along a circular path to make it feel like kinetic sand or butter slice.

I tried overriding vertex shader (transformVS) and apply some calculations to bend along Z axis (but it is only deforming object rather then making it bend) :

uniform float _OffsetSin;
uniform float _Frequency;
uniform float _Amplitude;

mat4 getModelMatrix() {
    return matrix_model;
}

vec4 getPosition() {
    dModelMatrix = getModelMatrix();
    vec3 localPosNew = vertex_position;

    vec4 result = vec4(0.0, ( sin( ( _OffsetSin + ( localPosNew.z * _Frequency ) ) ) * _Amplitude )  , 0.0 , 0.0);
    localPosNew.xyz += result.xyz;

    vec4 posW = dModelMatrix * vec4(localPosNew, 1.0);
    #ifdef SCREENSPACE
    posW.zw = vec2(0.0, 1.0);
    #endif
    dPositionW = posW.xyz;

    vec4 screenPos;
    #ifdef UV1LAYOUT
    screenPos = vec4(vertex_texCoord1.xy * 2.0 - 1.0, 0.5, 1);
    #else
    #ifdef SCREENSPACE
    screenPos = posW;
    #else
    screenPos = matrix_viewProjection * posW;
    #endif
    #endif

    return screenPos;
}
vec3 getWorldPosition() {
    return dPositionW;
}

Also tried implenting “bezier curve” with control points (still did not worked as expected):

uniform float _StartX;
uniform float _StartY;
uniform float _StartZ;

uniform float _ControlPoint1X;
uniform float _ControlPoint1Y;
uniform float _ControlPoint1Z;

uniform float _ControlPoint2X;
uniform float _ControlPoint2Y;
uniform float _ControlPoint2Z;

uniform float _ControlPoint3X;
uniform float _ControlPoint3Y;
uniform float _ControlPoint3Z;

uniform float _ControlPoint4X;
uniform float _ControlPoint4Y;
uniform float _ControlPoint4Z;

uniform float _ControlPoint5X;
uniform float _ControlPoint5Y;
uniform float _ControlPoint5Z;

uniform float _EndX;
uniform float _EndY;
uniform float _EndZ;

uniform float uTime;

mat4 getModelMatrix() {
    return matrix_model;
}

vec3 bezier(vec3 A, vec3 B, vec3 C, vec3 D, vec3 E, vec3 F, vec3 G, float t) {
    vec3 A1 = mix(A, B, t);
    vec3 B1 = mix(B, C, t);
    vec3 C1 = mix(C, D, t);
    vec3 D1 = mix(D, E, t);
    vec3 E1 = mix(E, F, t);
    vec3 F1 = mix(F, G, t);

    vec3 A2 = mix(A1, B1, t);
    vec3 B2 = mix(B1, C1, t);
    vec3 C2 = mix(C1, D1, t);
    vec3 D2 = mix(D1, E1, t);
    vec3 E2 = mix(E1, F1, t);

    vec3 A3 = mix(A2, B2, t);
    vec3 B3 = mix(B2, C2, t);
    vec3 C3 = mix(C2, D2, t);
    vec3 D3 = mix(D2, E2, t);

    vec3 A4 = mix(A3, B3, t);
    vec3 B4 = mix(B3, C3, t);
    vec3 C4 = mix(C3, D3, t);

    vec3 A5 = mix(A4, B4, t);
    vec3 B5 = mix(B4, C4, t);

    vec3 P = mix(A5, B5, t);

    return P;
}

vec3 bezier(vec3 A, vec3 B, vec3 C, vec3 D, float t) {
    vec3 E = mix(A, B, t);
    vec3 F = mix(B, C, t);
    vec3 G = mix(C, D, t);

    vec3 H = mix(E, F, t);
    vec3 I = mix(F, G, t);

    vec3 P = mix(H, I, t);

    return P;
}


vec3 bezier(vec3 A, vec3 B, vec3 C, vec3 D, vec3 E, float t) {
    vec3 A1 = mix(A, B, t);
    vec3 B1 = mix(B, C, t);
    vec3 C1 = mix(C, D, t);
    vec3 D1 = mix(D, E, t);

    vec3 A2 = mix(A1, B1, t);
    vec3 B2 = mix(B1, C1, t);
    vec3 C2 = mix(C1, D1, t);

    vec3 A3 = mix(A2, B2, t);
    vec3 B3 = mix(B2, C2, t);

    vec3 P = mix(A3, B3, t);

    return P;
}


vec3 bezier(vec3 A, vec3 B, vec3 C, vec3 D, vec3 E, vec3 F, float t) {
    vec3 A1 = mix(A, B, t);
    vec3 B1 = mix(B, C, t);
    vec3 C1 = mix(C, D, t);
    vec3 D1 = mix(D, E, t);
    vec3 E1 = mix(E, F, t);

    vec3 A2 = mix(A1, B1, t);
    vec3 B2 = mix(B1, C1, t);
    vec3 C2 = mix(C1, D1, t);
    vec3 D2 = mix(D1, E1, t);

    vec3 A3 = mix(A2, B2, t);
    vec3 B3 = mix(B2, C2, t);
    vec3 C3 = mix(C2, D2, t);

    vec3 A4 = mix(A3, B3, t);
    vec3 B4 = mix(B3, C3, t);

    vec3 P = mix(A4, B4, t);

    return P;
}


vec4 getPosition() {

    dModelMatrix = getModelMatrix();
    float timeNew = fract(uTime * 0.5);

    vec3 start=vec3(_StartX,_StartY,_StartZ);
    vec3 point1=vec3(_ControlPoint1X,_ControlPoint1Y,_ControlPoint1Z);
    vec3 point2=vec3(_ControlPoint2X,_ControlPoint2Y,_ControlPoint2Z);
    vec3 point3=vec3(_ControlPoint3X,_ControlPoint3Y,_ControlPoint3Z);
    vec3 point4=vec3(_ControlPoint4X,_ControlPoint4Y,_ControlPoint4Z);
    vec3 point5=vec3(_ControlPoint5X,_ControlPoint5Y,_ControlPoint5Z);
    vec3 end=vec3(_EndX,_EndY,_EndZ);

    vec3 posOffset = bezier(start, 
                            point1, 
                            point2, 
                            point3, 
                            point4, 
                            point5, 
                            end, 
                            timeNew);

    vec4 posW = dModelMatrix * vec4(vertex_position+posOffset, 1.0);

    #ifdef SCREENSPACE
    posW.zw = vec2(0.0, 1.0);
    #endif

    dPositionW = posW.xyz;

    vec4 screenPos;
    #ifdef UV1LAYOUT
    screenPos = vec4(vertex_texCoord1.xy * 2.0 - 1.0, 0.5, 1);
    #else
    #ifdef SCREENSPACE
    screenPos = posW;
    #else
    screenPos = matrix_viewProjection * posW;
    #endif
    #endif
    return screenPos;
}

vec3 getWorldPosition() {
    return dPositionW;
}

Also explored skinned mesh option but it seems it will not be feasible in my current case.
Please help, im out of options now, guide me onto some correct path.
Thanks.
Regards

Hi @Geniteam,

I don’t know the math to bend a set of vertices but here is a shadertoy shader that may provide some insight:

https://www.shadertoy.com/view/MdjSDD

Also, as an alternative, you can also do this in the CPU using the mesh.setPositions() update method:

https://playcanvas.github.io/#graphics/mesh-deformation.html

@Leonidas thanks for your suggestions ill definitely look into both

1 Like

maybe get inspired by this as well

or even better this
https://playcanvas.github.io/#graphics/shader-wobble.html

1 Like

thanks @mvaligursky I have tried both you had suggested , still thanks a lot pointing them out :slight_smile: , do share if anything else comes in mind

I think you could multiply the amount of bending using the vertex texture UV coord.

Imagining it with a black to white gradient texture, the vertices mapped more to the white would get the greater deformation; the more to the top of the V, the greater the deformation.

You could also do that the vertices at the top of the UV and just before the top also fall out a bit to create that kind of “butter” feeling.

This is the way I did grass in the past, and I think it might be a clever solution for this one.

@devMidgard thanks for the solution, can you please share your grass shader you did in past so I could get the idea of code, as im pretty much new to GLSL and material.chunks also dont have documentation.
Thanks
Regards

So this is basically the vertex shader I wrote for the grass:

vec4 getPosition(){
    vec2 uvCalc = vertex_texCoord0;
    
    vec2 quadPos = uvCalc * 2.0 - vec2(1.0, 0.5);
    vec2 scaleAndOffsetTime = vertex_normal.xy; // x= scale, y= offsetTime
    
    
    if(uvCalc.y > 0.5){
        quadPos.x += sin(uTime * scaleAndOffsetTime.y) * 0.35;
    }
    
    vec3 right 	= vec3(matrix_view[0][0], matrix_view[1][0], matrix_view[2][0]);
    vec3 up 	= vec3(matrix_view[0][1], matrix_view[1][1], matrix_view[2][1]);
    
    vec3 actualQuadCenter = vertex_position; // entity position
    
    vec3 pos = actualQuadCenter + (quadPos.x * right + quadPos.y * up) * scaleAndOffsetTime.x;
    
    dPositionW = pos;
    
    return matrix_viewProjection * vec4(pos, 1.0);
}

It has billboarding, but disregard that, what interests you is the way of using vertex_texCoord0, you can use it to check which coord in the UV the particular vertex is mapped on, if you use the Y axis you’ll get what I was trying to say, vertices mapped at 0 would stay undeformed, vertices mapped at 1 would get super deformed (Y axis goes from 0 to 1).

In my case, what I did was if the vertex is mapped greater than the center of the UV.y (0.5), then move it around creating the simplest wind effect. The vertices below that, would remain at the position they started at.

1 Like