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

Point param + time offset using PF_CHECKOUT_PARAM

Community Beginner ,
Jul 08, 2019 Jul 08, 2019

Hi all,

I'm new to the AE SDK, and pretty new to C++, so bear with me.

In trying to wrap my head around how all of this works, I've tried to keep this simple.

I am trying to draw a trail of rectangles following a point parameter.

I have successfully drawn a rectangle (PF_FILL) at the position of the point parameter, and attempted to use PF_CHECKOUT_PARAM to access the value of the point parameter at a different time by running it through a loop and subtracting my iterator from "current_time"...however all that happens is I get all of the rectangles on top of each other. For the sake of debugging, the rectangle that's supposed to be at the exact position of the point parameter is drawn wide, and the other "trail" rectangles are drawn tall, so I actually get a cross and know that the other rectangles are being drawn.

I do have the two flags set:

PF_OutFlag_WIDE_TIME_INPUT | PF_OutFlag_NON_PARAM_VARY

I've also noticed that there are weird flickering artifacts, sometimes in the shape of the rectangles if I scrub along the timeline or even play with my color picker param that drives the color of the rectangles that I am drawing.

Any help would be greatly appreciated, thanks!

static PF_Err

Render(

PF_InData *in_data,

PF_OutData *out_data,

PF_ParamDef *params[],

PF_LayerDef *output)

{

PF_ParamDef checkout;

PF_Rect r;

PF_Err err = PF_Err_NONE;

AEGP_SuiteHandler suites(in_data->pica_basicP);

// get x and y from point paramter

A_long  x = FIX2INT(params[SKELETON_POSITION]->u.td.x_value),

        y = FIX2INT(params[SKELETON_POSITION]->u.td.y_value);

// get color value from color parameter

PF_Pixel color = params[SKELETON_COLOR]->u.cd.value;

color.alpha = 255;

// wide rect at the position of the point parameter

r.left = x - 44;

r.right = x + 44;

r.top = y + 4;

r.bottom = y - 4;

// draw main rectangle

PF_FILL(&color, &r, output);

for (int i = 0; i < 20; i++)

{

AEFX_CLR_STRUCT(checkout);

// checkout the point paramter at current_time - i

ERR(PF_CHECKOUT_PARAM(in_data, POSITION_ID, in_data->current_time - i, in_data->time_step, in_data->time_scale, &checkout));

// not sure of syntax for "checkout.u.td.x_value"...

// get x2 and y2

A_long x2 = FIX2INT(checkout.u.td.x_value);

A_long y2 = FIX2INT(checkout.u.td.y_value);

// tall rects for trail

r.left = x2 - 4;

r.right = x2 + 4;

r.top = y2 + 44;

r.bottom = y2 - 44;

// draw the trail rects

PF_FILL(&color, &r, output);

ERR(PF_CHECKIN_PARAM(in_data, &checkout));

}

return err;

}

TOPICS
SDK
1.4K
Translate
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

correct answers 1 Correct answer

Deleted User
Jul 08, 2019 Jul 08, 2019

Not sure if this is relevant, but when you render a frame based on external conditions/triggers, i.e. some information AE does not know anything about, AE can't determine if it should keep/use the frame already in the cache or not. For these cases, you can use GuidMixInPtr() to add in some extra bits if you change a frame and want it to be definitely re-renderered/cache purged.

Translate
Community Beginner ,
Jul 08, 2019 Jul 08, 2019

I looked a little closer at the Checkout example and realized I was missing the fact that I need to multiply "in_data->time_step" with "current_Time - i":

ERR(PF_CHECKOUT_PARAM(in_data, POSITION_ID, in_data->current_time - i * in_data->time_step, in_data->time_step, in_data->time_scale, &checkout)); 

This solved the main problem, but I am getting strange artifacts that seem to be tied to the RAM preview. If I Purge After Effect's memory, and play it from the beginning, it is almost perfectly fine...a few frames flicker to old or incorrect versions of the path I am drawing. If I change the animation of my point parameter, I get overlapping paths...two or three versions on top of each other. If I scrub around, I get not only overlapping paths, but the colors start to change between the paths. The color of my path is controlled by a color parameter.

I've attached a few images to show what is happening. I am assuming I need run some type of function to clear the frame every time I render...?

image1.png

image2.pngimage3.png

Translate
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 ,
Jul 08, 2019 Jul 08, 2019

did you set PF_OutFlag_WIDE_TIME_INPUT?

Translate
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
Guest
Jul 08, 2019 Jul 08, 2019

Not sure if this is relevant, but when you render a frame based on external conditions/triggers, i.e. some information AE does not know anything about, AE can't determine if it should keep/use the frame already in the cache or not. For these cases, you can use GuidMixInPtr() to add in some extra bits if you change a frame and want it to be definitely re-renderered/cache purged.

Translate
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 ,
Jul 13, 2019 Jul 13, 2019

I did have PF_OutFlag_WIDE_TIME_INPUT set, but for a while I had it under second list of "out_flags" as opposed to "out_flags2" ... definitely confused me for a bit trying to interpret all the PiPL flag errors I was getting.

GuidMixInPtr() fixed all the render glitches for me, thanks for that suggestion! It also forced me to learn how to implement the smart render system, which I can see having huge benefits as I get deeper into this.

Something I ran into was a whole bunch of memory write access errors...it took me a while before I realized it would only happen when I tried to write to a pixel outside the render area..(this would happen if I 'wiggled' my point parameter off the screen) To fix this I have started passing the "input_world->extent_hint" to all of my PF_Pixel functions and running a check to see if my pixel is within the PF_Rect before it writes it to the output_world at that point....sometimes I have to pass it a few layers deep ( SmartRender()  > MyLineAlgorithm() > PF_Pixel() ) is there a better way to do this? Not sure if it's a common enough problem for you guys to run into.

One other little question is about calculating parameter values between frames...currently I use "current_time - 1 * time_step" to get the value of a parameter at the previous frame. If instead I multiply a fraction of time_step, would I get in-between values?

Thanks!!

Translate
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
Guest
Jul 14, 2019 Jul 14, 2019

Always make sure you only access pixels within the given input and out boundaries (which for example also means respecting the rowBytes)! You should receive the exact dimensions you are allowed to access for writing as parameters, with input and output buffer being the same size unless there is boundary expansion. Normally you should not need to pass these along or even do a check, you can simply iterate over the given coordinates. Check the SDK samples, e.g. SDK_Noise to show how this can be done in a simple and multithreaded way for both Render() and SmartRender().

As for your second question, time is an A_long/integer, so you won't be able to pass fractional values anyway. If needed, simply to a linear interpolation of parameter values yourself, although I hardly see a use for that inbetween subsequent frames.

Translate
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 ,
Jul 15, 2019 Jul 15, 2019

Thanks for the pointer! ...understanding the example files is becoming easier and easier the more I do it...the iterate suite seems very useful.

Regarding the in-between values, I don't think I need to actually implement this, but for the sake of the thought experiment, the idea would be to calculate sub-frame values of a motion path that had some type of bezier interpolation between them -- I can accomplish this using valueAtTime() in an expression as described in the screenshot below, so it seems like After Effects "knows" where the blue dot would be along the arc between the three keyframes placed on three consecutive frames.

dots.png

Translate
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
Guest
Jul 16, 2019 Jul 16, 2019
LATEST

Yup, seems like simple inter-frame interpolation. Not sure if they would actually apply spline interpolation across several frames, I'd assume it is simple linear interpolation between two frames when calling valueAtTime().

So yes, basically you would just do that, get the parameter value from frame A and from A+1, then simply interpolate between these two based on the fractional index.

Translate
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