[Closed] Determine if a node has consistent topology
I’m trying to determine if a node has consistent topology throughout the scene.
The most reasonable way I’ve been able to find is using NumPoints. I realize this may not catch objects for which the vertex count remains the same but the face count or ordering does not, but I am fine with that.
This is how I’ve implemented it:
def_visible_primitive(CheckTopologyConsistency, "CheckTopologyConsistency");
Value* CheckTopologyConsistency_cf(Value **arg_list, int count)
{
check_arg_count(CheckTopologyConsistency, 1, count);
INode* node = arg_list[0]->to_node();
TimeValue start = GetCOREInterface()->GetAnimRange().Start();
TimeValue end = GetCOREInterface()->GetAnimRange().End();
Object* obj = node->EvalWorldState(start).obj;
if (!obj)
{
return &true_value;
}
int numPoints = obj->NumPoints();
const int tpf = GetTicksPerFrame();
for (int t = start + tpf; t < end; t += tpf)
{
Object* obj = node->EvalWorldState(t).obj;
if (!obj)
{
continue;
}
if (obj->NumPoints() != numPoints)
{
return &false_value;
}
}
return &true_value;
}
This works, but is very slow, due to many object evaluations. Does anyone know a better way?
Event Detected: Event#geometryChanged, Nodes #(7855)
Event Detected: Event#topologyChanged, Nodes #(7855)
These two events fire even if it’s not user initiated. I’ve animated a volume select and added a delete mesh on top and these among others fire each frame.
So I guess you can run trough your timeline, maybe wiht a viewport update=off, and check if your node is present in one of the relevant events.
Thanks, that’s an interesting idea. Unfortunately disabling redraw also disables the evaluations, and no events are produced. Not disabling redraw works, but is slower than the original implementation.
Using validity intervals to eliminate many objects makes it much faster.
def_visible_primitive(CheckTopologyConsistency, "CheckTopologyConsistency");
Value* CheckTopologyConsistency_cf(Value **arg_list, int count)
{
check_arg_count(CheckTopologyConsistency, 1, count);
INode* node = arg_list[0]->to_node();
Interval animRange = GetCOREInterface()->GetAnimRange();
TimeValue start = animRange.Start();
TimeValue end = animRange.End();
ObjectState state = node->EvalWorldState(start);
Object* obj = state.obj;
if (!obj)
{
return &true_value;
}
if (obj->ObjectValidity(start) == FOREVER)
{
return &true_value;
}
bool isMeshOrPoly =
obj->IsSubClassOf(Class_ID(TRIOBJ_CLASS_ID, 0)) ||
obj->IsSubClassOf(Class_ID(POLYOBJ_CLASS_ID, 0));
//this would be great if all objects actually implemented it.
//doesn't catch cases for procedural objects which have changing topology
//oh well, at least we can eliminate editable_mesh and editable_poly from the full scan
if (isMeshOrPoly && obj->ChannelValidity(start, TOPO_CHAN_NUM) == FOREVER)
{
return &true_value;
}
int numPoints = obj->NumPoints();
const int tpf = GetTicksPerFrame();
for (int t = start + tpf; t < end; t += tpf)
{
Object* obj = node->EvalWorldState(t).obj;
if (!obj)
{
continue;
}
if (obj->NumPoints() != numPoints)
{
return &false_value;
}
}
return &true_value;
}
This doesn’t seem to catch particle systems though.
first of all it’s a big limitation to check only deformable node objects.
it seems like the checking number of mesh vertices is more universal.
do you really want to know which objects keep their mesh topology consistent (keep same number of vertices at least) during whole scene?
Yes, or more specifically, I need to know which objects have changing topology.
Can you use the NodeEventCallBack system?
fn cbTopologyChange ev nd =
(
print "node changed"
print nd
)
callbackItem = NodeEventCallback topologyChanged:cbTopologyChange