• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Euler Filter in AE

Community Beginner ,
Aug 01, 2022 Aug 01, 2022

Copy link to clipboard

Copied

Hi,
I'm looking for an expression, script, or option to filter the rotations of a 3d camera output from the camera tracker so that the rotations shown in the graph editor are allowed to be greater than 360 or less than 0.  For example, I'm trying to avoid seeing the kind of graph in the image below when the camera is only rotating about 20 derees in any direction but the graph "pops between 359.xx and 0.xx quite often. This would make it much more intuative for me to read on modify the curves.   Any ideas of how I can fix this?

chestercopperpot_0-1659380494089.png

 

TOPICS
Error or problem , Expressions , How to , Resources , Scripting , User interface or workspaces

Views

678

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Aug 01, 2022 Aug 01, 2022

Copy link to clipboard

Copied

Unlike 3D programs, AE does not have such a filter that adjusts the graph automatically. An expression might be as trivail as value % 360, though it still flips and pops between keyframes when the values jump over. At the end of the day you can't really avoid cleaning up your graphs, but I'm sure there are soem scripts on AEScripts.com that can help.

 

Mylenium

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Aug 01, 2022 Aug 01, 2022

Copy link to clipboard

Copied

Thanks for your help.  I had forgot that I ran into this problem earilier and I had found a solution many years ago buried on an old HD.  It's called "advanced camera tracking.jsxbin".  Can't seem to find it on google anymore, but it solved the problem.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 01, 2022 Aug 01, 2022

Copy link to clipboard

Copied

The Camera Tracker does not manipulate Rotation. It only makes changes to Orientation on the One-node Camera that is created. Orientation is limited to X, Y, and Z values from 0º to 359º. There is no 360 value available. There is no way to count rotations. 

 

You can't add an offset expression to Orientation and see the results in the Graph Editor because Orientation is one of the few properties that does not have a Show Post Expression Graph switch. 

 

It would help if we knew what you were trying to do. You cannot modify any keyframed transform Properties Camera Tracking generates without fouling up the track. If you have a jittery track, you might be able to use the Smoother on Position, but Orientation has no smoothable (is that a word) properties. The only options are the Spatial Path and Temporal Graph. 

 

There is a free Normalize Track script that I use all the time to reset the Camera Track starting point to the comp center. Normalizing the track makes using Element 3D, Particular, and other 3D effects easy. I don't know what you are trying to accomplish, so I don't know if the Normalize Track script would help.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Aug 01, 2022 Aug 01, 2022

Copy link to clipboard

Copied

Well you can always pickwhip and bake out the orientations to be rotations.  I'm basically trying to get "human readible curves" in my graph editor that don't "pop" from 0 to 360 when they change by only 1 degree.  I can

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 02, 2022 Aug 02, 2022

Copy link to clipboard

Copied

Sounds like a perfect job for Automation Blocks 🙂

If you want to pick-whip and bake the rotation values to 1D properties, you can then select these 1D properties and run the tool "Euler Filter 1D Rotation", which I just created for you. You find it in the Community Library of Automation Blocks now at

Layer Properties/Keyframes/Filter/Euler Filter 1D Rotation

 

If you are curious - this is what the full implementation of the tool looks like:

Screenshot 2022-08-02 at 09.35.13.png

Mathias Möhl - Developer of tools like BeatEdit and Automation Blocks for Premiere Pro and After Effects

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Aug 03, 2022 Aug 03, 2022

Copy link to clipboard

Copied

That's very interesting!  I don't suppose this tool has anything that could support offsetting a tracked camera's orientation (or rotation) the "correct" way by converting the euler rotations to quaternions, performing the offsetting math, and returning the quaternions back to euler rotations?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 03, 2022 Aug 03, 2022

Copy link to clipboard

Copied

If just processes each component individually and solves the pops from 359.x to 0.x, which you describe.
I.e. for each frame it checks the value of the previous frame and then chooses for the current frame among all the equivalent rotation valuesthe one that is closest to the value of the previous frame.

Mathias Möhl - Developer of tools like BeatEdit and Automation Blocks for Premiere Pro and After Effects

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Oct 13, 2022 Oct 13, 2022

Copy link to clipboard

Copied

In my case, I imported Maya rotations into After Effects. The keyframs were applied to the Orientation property. The following script copies the keyframes onto the Rotation properties (xRotation, yRotation, and zRotation), and then applies a Euler filter, finally deleting the original Orientation keyframes:

 

{
    var comp = app.project.activeItem;    
    var selectedLayers = app.project.activeItem.selectedLayers;
        
	if(selectedLayers.length == 0)
    {
		alert("Please select at least one layer...");
	}
    else
    {
        app.beginUndoGroup("Convert 3D Orientation to X-Y-Z Rotation");
        
        for (var i = 0; i < selectedLayers.length; i++)
        {
            var layer = selectedLayers[i];
            CopyOrientationKeysToRotation(layer);           
            EulerFilterKeyframes(layer, "xRotation");
            EulerFilterKeyframes(layer, "yRotation");
            EulerFilterKeyframes(layer, "zRotation");
        }        
		app.endUndoGroup();
	}
} 

function EulerFilterKeyframes(layer, layer_property)
{
    var property = layer.property(layer_property);
    var key_index = property.nearestKeyIndex(0);
    var key_time = property.keyTime(key_index);
    var previous_value = null;     
    while(key_index < property.numKeys)
    {
        var current_value = property.keyValue(key_index);
        if(previous_value != null)
        {
            current_value = EulerFilterValue(previous_value, current_value);
            property.setValueAtTime(key_time, current_value);            
        }
        previous_value = current_value;
        key_index++;
        key_time = property.keyTime(key_index);
    }
}

function EulerFilterValue(previous_value, current_value)
{
    var full_rotations = 1/360;
    var delta = (current_value % 360) - (previous_value % 360);
    if(delta >= 180)
    {
        full_rotations--;
    }
    else if(delta <= -180)
    {
        full_rotations++;
    }

    return (full_rotations * 360) + (current_value % 360);
}

function CopyOrientationKeysToRotation(layer)
{    
    var property = layer.orientation;
    
    for (var j = 0; j < property.numKeys; j++)
    {
        var keyVal = property.keyValue(j+1);
        var keyPos = property.keyTime(j+1);
        layer.property("xRotation").setValueAtTime(keyPos, keyVal[0]);
        layer.property("yRotation").setValueAtTime(keyPos, keyVal[1]);
        layer.property("zRotation").setValueAtTime(keyPos, keyVal[2]);
    }

    while (property.numKeys != 0)
    {
        property.removeKey(1);
    }
    
    // Set orientation back to zero
    property.setValue([0, 0, 0])
}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Oct 13, 2022 Oct 13, 2022

Copy link to clipboard

Copied

Just select as menu layers as you want that has Orientation keyframes, and then run the script. It's not perfect, but it does the job. If there a section that just isn't aligned correctly, move your play-head to the start of those keyframes, select them all, click on the rotation value (X, Y, or Z) and just type after the value, +360 or -360. It should realign those keyframes.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Oct 13, 2022 Oct 13, 2022

Copy link to clipboard

Copied

LATEST

I updated the script to run more accurately:

{
    var comp = app.project.activeItem;    
    var selectedLayers = app.project.activeItem.selectedLayers;
        
	if(selectedLayers.length == 0)
    {
		alert("Please select at least one layer...");
	}
    else
    {
        app.beginUndoGroup("Convert 3D Orientation to X-Y-Z Rotation");
        
        for (var i = 0; i < selectedLayers.length; i++)
        {
            var layer = selectedLayers[i];
            CopyOrientationKeysToRotation(layer);           
            EulerFilterKeyframes(layer, "xRotation");
            EulerFilterKeyframes(layer, "yRotation");
            EulerFilterKeyframes(layer, "zRotation");
        }        
		app.endUndoGroup();
	}
} 

function EulerFilterKeyframes(layer, layer_property)
{

    var property = layer.property(layer_property);
    
    if(property.numKeys < 1) return;
    
    var key_index = property.nearestKeyIndex(0);
    var key_time = property.keyTime(key_index);
    var previous_value = null;     
    while(key_index < property.numKeys)
    {
        var current_value = property.keyValue(key_index);
        if(previous_value != null)
        {
            current_value = EulerFilterValue(previous_value, current_value);
            property.setValueAtTime(key_time, current_value);            
        }
        previous_value = current_value;
        key_index++;
        key_time = property.keyTime(key_index);
    }
}

function EulerFilterValue(previous_value, current_value)
{
    var full_rotations = Math.floor(1/360);
    var delta = (current_value % 360) - (previous_value % 360);
    if(delta >= 180)
    {
        full_rotations--;
    }
    else if(delta <= -180)
    {
        full_rotations++;
    }

    return (full_rotations * 360) + (current_value % 360);
}

function CopyOrientationKeysToRotation(layer)
{    
    var property = layer.orientation;
    
    for (var j = 0; j < property.numKeys; j++)
    {
        var keyVal = property.keyValue(j+1);
        var keyPos = property.keyTime(j+1);
        layer.property("xRotation").setValueAtTime(keyPos, keyVal[0]);
        layer.property("yRotation").setValueAtTime(keyPos, keyVal[1]);
        layer.property("zRotation").setValueAtTime(keyPos, keyVal[2]);
    }

    while (property.numKeys != 0)
    {
        property.removeKey(1);
    }
    
    // Set orientation back to zero
    property.setValue([0, 0, 0])
}

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines