Path Animation vs Bevel End Animation

INITIAL MESSAGE / PROBLEM STATEMENT: Hi there. Im not sure if there is a possibility at all to synchronize path animation and bevel end animation. But if you know a trick please let me know. The problem is: I want to let a path grow by animating the bevel end time of a path that has bevel object and at the same time let an object follow the path. The problem is: the path animation follows the path equally over time (when the evaluation time is evaluated linearly) and the the bevel end - also being animation linearly from 0 to 1 - goes faster and slower according to how many segments there are in the line. I could reformulate the question: how do I make bevel end animation follow a path linearly.

SOLUTION: A patch (modification of Blender’s code):

Patch:bevfac_mapping.patch.zip (3.87 KB)

Patched Builds:
Mac: Blender 2.69 with Bevel Factor Mapping Patch
Win: Blender 2.69 With bevel factor mapping patch
Ubuntu: Blender 2.69 with bevel factor mapping patch

I wrote a python script. See: https://www.dropbox.com/s/oubwc5uv2qoszwy/solution.mov


import bpy, bmesh, pprint


def segments_and_total_length():
    """ Returns the length of all the segments of a curve and the total length"""
    
    orig = bpy.context.object
    origpoints = [p.co for s in orig.data.splines for p in s.bezier_points]
    
    bpy.ops.object.duplicate()
    obj = bpy.context.object
    obj.data.bevel_object = None
    bpy.ops.object.convert(keep_original=False)
    bm = bmesh.new()
    bm.from_mesh(obj.data)
    
    total = 0
    segs = []
    seglength = 0
    
    for e in bm.edges:
        l = e.calc_length()
        total += l
        seglength += l
        if e.verts[1].co in origpoints:
            segs.append(seglength)
            seglength = 0
            
    bpy.context.scene.objects.unlink(obj)
    
    return segs, total


def linearize(curve, duration):
    """ Calculates the 'virtual' F-Curve that needs to be added 
        to the F-Curve of the Bevel Factor of a curve."""
    
    segs, total = segments_and_total_length()
    segcount = len(segs)
    
    
    
    at = 0
    points = {at:0}
    for i, seg in enumerate(segs):
        at += duration/total*seg
        #print("at="+str(duration)+"/"+str(total)+"*"+str(seg)+" = "+str(at))
        value = 1/segcount*(i+1)
        #print("value=1/"+str(segcount)+"*(1+"+str(i)+") = "+str(value))
        # linearDefault = value where a straight line would be
        linearDefault = 1/duration*at
        # we want to find the difference to the linearDefault
        points[at] = value - linearDefault
        
    return points


def absolute_linearize(curve, start, duration, min, max):
    """ linearized curve beginning at the specified start point"""
    rell = linearize(curve, duration)
    absl = {}
    for rkey in sorted(rell):
        v = min + (max-min)/duration*rkey + rell[rkey]*(max-min)
        #print (str(min)+"+"+str(max-min)+"/"+str(duration)+"*"+str(rkey)+"+"+str(rell[rkey])+"*"+str(max-min))
        absl[rkey+start] = min + (max-min)/duration*rkey + rell[rkey]*(max-min)
    #pprint.pprint(absl)
    return absl


def adjust_linear_fcurve(curve):
    """ with the remote control like abilities of python 
        this only works for linear animation fcurves. 
        Maybe we see a C-patch in the future, that deals with this 
        Blender internally"""
    orig_active = bpy.context.object
    bpy.ops.object.select_all(action='DESELECT')
    
    bpy.context.scene.objects.active = curve
    curve.select = True
    
    # getting start and end bevel factor animation fcurve
    fcurves = [fc for fc in curve.data.animation_data.action.fcurves if fc.data_path == "bevel_factor_end" or fc.data_path == "bevel_factor_start"]
    for fc in fcurves:
        pointlists = []
        # find ascending slope
        oldkf = None
        for kf in fc.keyframe_points:
            if oldkf == None:
                oldkf = kf
                continue
            if kf.co[1] > oldkf.co[1]:
                pointlists.append(absolute_linearize(curve, oldkf.co[0],kf.co[0]-oldkf.co[0], oldkf.co[1], kf.co[1]))
    
        for pl in pointlists:
            pk = [k for k in pl.keys()]
            pl.pop(pk[0])
            pl.pop(pk[-1])
            for at in sorted(pl):
                fc.keyframe_points.insert(at, pl[at])
                #pass
    bpy.context.scene.objects.active = orig_active
    orig_active.select = True
    
# in the console: 
# import linearCurveBevel as lb
# lb.adjust_linear_fcurve(C.object)

is there any easier way to do this :frowning:

CND, thanks for your explanations and work so far. I just now found another way that I’d like to share, I hope you don’t mind. Maybe it’s usable for ArfMan.

The problem occurs when the curve segments are not of equal length. The bevel factor velocity is dependent on the curve segment lengths, while the evaluation time for the path animation is not. We need a way to make the curve segments even length, which I did via converting to mesh and using the LoopTools addon, then converting back to curve.

This only works for the default (linear) follow path fcurve you get when you hit “Animate Path” in the follow path constraint.

Details:

  1. Set up the curve how you want it, including final resolution, but don’t give it any bevel or animations yet.
  2. Convert it to mesh with ALT+C, so that it becomes a mesh line.
  3. Activate the loop tools addon in user prefs (under Mesh).
  4. Select the line mesh, go to edit mode, select all vertices.
  5. Hit w -> LoopTools -> Space, in T-panel use Interpol: Linear. Now all edges have the same length.
  6. Go to object mode, convert line mesh back to curve with ALT+C. Now we have a curve with even segments.
  7. Setup path follow and bevel animation, convert the bevel anim fcurve to vector handles.

Now the end bevel and path animations are synchronized. :slight_smile:

Hi Sanne, thanks for looking into the problem. What we tried to do is to find a workaround for a shortcoming of Blender. A proper solution would be to directly improve the bevel animation provided by Blender. Here’s a proposal:


EDIT: while looking into Blender’s code I had a better idea: I will try (can’t promise anything) to map the bevel factors to the entire path length, so that it works similar to Path Animation. If as user you would like to map bevel factors to the path animation, you could do so with a driver.

I had to, for the work I’m doing currently :). I found your thread while researching the problem. Your explanation helped me find my workaround, thank you for that.

I’d love to see your proposal, but the attachment isn’t showing for me. Can you see it?

Ultimately, it would be nice if we were able to tell Blender to match bevel end animation to any path animation, without workarounds.

I tried to implement my python script in C. I am using a Mac, therefore the Blender Build is mac only.

I found out the idea I had in my python script is not suitable to map the bevel factor to a spline’s length. Yet the effect might be useful too. A linear animation of a bevel factor is still not running through the whole spline at the same speed; it breaks a bit in the curves. But if you want to simulate cars that might be helpful too.

CND, looks great, thanks for your work!

I’m on Linux, can’t use your build. I’m used to building my own Blender development version, so I could test a patch if you could/would provide one occasionally.

Sanne, don’t know how to create patches with XCode (yet). Using git should I create a new branch?
Here’s a screencast of it in action:

EDIT:
Ha! Finally! git diff > yourpatchfile.patch does it :slight_smile:
https://dl.dropboxusercontent.com/u/9632359/bevfac_mapping.patch

Just to give you an idea what this could be useful for:

Thanks for the patch! Applied fine.

Unfortunately I’m getting some compile errors about “ISO C90 forbids mixed declarations and code” and some others, seemingly my compiler is more pedantic than yours :). I’m using gcc 4.8.2.

Here’s a paste of the full cmake compile output, first error is at line 324, following some more through to line 358 where is stated “cc1: some warnings being treated as errors”. I guess this error level might be set by the blender devs, but I’m not sure. What I know is that I never got those kind of errors before. Maybe Blender coding standard preferences?

In case you’d like to talk to the developers and don’t know how yet, you could post to bf-committers mailing list. Here’s the page for signup and reading archives. For quick feedback you can also talk to them via IRC chat, server irc.freenode.net, channel #blendercoders.

I believe the animation guy is Joshua Leung aka Aligorith. He coded lots of animation tool enhancements, but I don’t know if he’s the one responsible for the bevel end functionality.

The video looks very exciting! Edit: woah, the next video also. Awesome!

I hope I fixed the mixed declaration issue with the new patch you can find here: https://developer.blender.org/D245
I had to add the new patch file as a comment…
bevfac_mapping.patch

Thanks CND. There are still some, though. I’m trying to fix them myself right now, maybe easier if you don’t get those errors. I’ll post results soon.

I see you already know about the patch tracker and didn’t need all my blathering about how to reach the developers - sorry. :wink:

Edit: continued on IRC

ok. it doesn’t crash anymore because of freeing memory stuff. but on my vitrualbox-ubuntu the curves did some strange kind of things.

Attachments

bevfac_mapping.patch.zip (3.87 KB)

Wow, great work!

Thanks for the new patch, compiled fine. Testing right now. I’m setting up my path animation as usual, set start and end keyframes for bevel end, set that f-curve to linear, set Map End to Spline - an it works! Awesome!

I don’t understand the other two options yet, though. Segment and Resolution seem to do roughly the same like it was before?

My curves also do some strange things. They flicker, sort of, sometimes, as in, they suddenly get longer for one frame or so, then flip back. Is that what you see also?

I had another crash once with your example file, but not with a new file I made. Now I can’t reproduce it, though. It happened after playing the animation, and, I believe, after hitting ESC. The output was:

read blend: /mnt/wrk/graph/blender/ba/cnd-bevfac-animation.blend
Calloc returns null: len=52118577408 in dlverts, total 10309124
Segmentation fault (core dumped)

Without this flickering it would be all I wished for! I’m very excited. Thank you again!

if you comment the line “BLI_freelistN(&segments);” it will work. But you will produce a memory leak: your memory gets slowly filled. If you have enough memory and you need the thing running right now --> good, otherwise no good :slight_smile:

FINALLY!! bevfac_mapping.patch
Took a while, but at least my mac is now triple boot :slight_smile:

Unbelievably cool! Works wonderfully. Oh, and thanks for making it available for Bevel Depth also. Now I’m crossing fingers that it gets approved and added to master for 2.71.

OSX, Ubuntu and…? Arch Linux? :slight_smile:

OSX, Ubuntu and… Windows, as you can tell now from my new graphicall builds I created for the community to test this new feature (took some time to get the windows environment running…).


Arch Linux? Now I know where your logo comes from :yes:

Ah, graphicall, great you are doing that, I hope it gets noticed and tested.

My avatar ist indeed part of the 3D Arch Linux logo I created for my desktop, to celebrate my switch from (a very customized) Ubuntu.

Edit: hey, I’m excited that your patch is getting reviewed. Thanks for keeping at it!