We have trouble with next idea. With just spooling animated geometry (point positions) to external file by our custom command, written with C++. Our animators use some plug-ins, which make secondary animation effects, and performed some "dynamic-style" animation (mt_spring, StrandCollisionFramework). They works good enough, but it requires some other style of scene sampling, than just sequental sampling of each geometry part at each timestep - we need some kind of coherency of all geometry at each timestep.
If we organize sampling cycle as (coding notation is just demonstrative)
foreach(geometry_part)
{
foreach(time_step)
{
geometry_part.Sample(/*at*/ time_step);
}
}
even if everyhing is passing fine - we have quadratic sampling time growing from timesteps count. So, we need other strategy
foreach(time_step)
{
foreach(geometry_part)
{
geometry_part.Sample(/*at*/ time_step);
}
}
Ok. How to organize this? Being organized just directly by swappng loops - it don't produce any noticeable results. If I try to move current frame position - it doesn't help too - tmeline mark moves - but objects don't update in viewports and GUI gets black after ~10 frame of sampling and recent part of process lasts and ends in such blind state. And it is anyway spends too much time, 20-50 times more. But greather trouble is with that geometry is not correct for dynamc-driven parts. So, we have awful long time of sampling and incorrect result at same time. Even if we sample just non-dynamic animated geometry - it doesn't matter.
As I seem - we just do not some important thing before starting sampling geometry. We can seet, that guys from Exocortex spool geometry to Alembic format without any troubles, with no GUI freezing, updatinf of viewports and absolutely correct. We wish same.
Here is simplified code of plug-in command which produces such trouble
XSIPLUGINCALLBACK CStatus Sandbox_Init(CRef &refContext)
{
XSI::Context ctx( refContext );
XSI::Command cmd(ctx.GetSource());
cmd.EnableReturnValue(true);
XSI::ArgumentArray args = cmd.GetArguments();
args.Add("From",0);
args.Add("To",0);
args.Add("Subframes",0);
args.AddWithHandler("Objects","Collection");
return XSI::CStatus:: OK;
};
XSIPLUGINCALLBACK CStatus Sandbox_Execute(const CRef &refContext)
{
Application app;
Context ctx(refContext);
// PARSE ATTRIBUTES
CValueArray args = ctx.GetAttribute(L"Arguments");
CValueArray collection = args[3];
int from = (int)args[0];
int to = (int)args[1]; if(from>to) from = to;
int subfr = (int)args[2]; if(subfr<0) subfr = 0;
// WHICH OBJECTS?
CRefArray objects;
for(int i=0; i<collection.GetCount();i++)
{
CValue val = collection[i];
CRef ref(val);
if(ref.GetClassID() != siX3DObjectID) continue;
XSI::X3DObject obj(ref);
if(!obj.IsValid()) continue;
XSI:: PolygonMesh geo = obj.GetActivePrimitive().GetGeometry();
if(geo.GetRef().GetClassID() != XSI::siPolygonMeshID) continue;
if(geo.GetPoints().GetCount() == 0) continue;
objects.Add(ref);
};
// ACCESS PLAYER CONTROL
XSI:: Project prj = app.GetActiveProject();
XSI::CRefArray proplist = prj.GetProperties();
XSI:: Property playctrl(proplist.GetItem(L"Play Control"));
// EACH SUBFRAME
for(int i=from;i<=to;i++)
{
for(int j=0;j<=subfr;j++)
{
double time = i+j/(double)(subfr+1);
playctrl.PutParameterValue("Current", time);
for(int k=0; k<objects.GetCount();k++)
{
XSI:: X3DObject obj(objects[k]);
const XSI::MATH::CTransformation wrldTransform = obj.GetKinematics().GetGlobal().GetTransform(time);
// ...IT PRODUCES TROUBLES.
XSI:: PolygonMesh prim = obj.GetActivePrimitive().GetGeometry(time,siConstructionModeAnimation);
};
};
};
ctx.PutAttribute(L"ReturnValue",true);
return CStatus:: OK;
};
XSIPLUGINCALLBACK CStatus XSILoadPlugin( PluginRegistrar& in_reg )
{
in_reg.PutAuthor(L"Joe");
in_reg.PutName(L"Sandbox");
in_reg.PutVersion(0,1);
// SANDBOX
in_reg.RegisterCommand(L"Sandbox",L"Sandbox");
return CStatus:: OK;
};
XSIPLUGINCALLBACK CStatus XSIUnloadPlugin( const PluginRegistrar& in_reg )
{
return CStatus:: OK;
};
Thank you.