Copy link to clipboard
Copied
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;
}
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.
Copy link to clipboard
Copied
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...?



Copy link to clipboard
Copied
did you set PF_OutFlag_WIDE_TIME_INPUT?
Copy link to clipboard
Copied
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.
Copy link to clipboard
Copied
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!!
Copy link to clipboard
Copied
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.
Copy link to clipboard
Copied
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.

Copy link to clipboard
Copied
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.
Get ready! An upgraded Adobe Community experience is coming in January.
Learn more