Notifications
Clear all
[Closed] Viewport Statistics Improvement
Page 2 / 2
Prev
Aug 07, 2015 2:55 pm
Using the dennisT version with support for objects arrays, gives 0.017s for 10212 objects and a total of 49017600 tris, using GetTriMeshFaceCount gives 0.539s. No type check is done on the object.
def_visible_primitive_debug_ok(numVertsAndTris, "numVertsAndTris");
Value* numVertsAndTris_cf(Value** arg_list, int count)
{
check_arg_count(numVertsAndTris, 1, count);
auto arr = static_cast<Array*>(arg_list[0]);
if(!is_array(arr))
{
arr = new Array(1);
arr->append(arg_list[0]);
}
one_typed_value_local(Array *result);
vl.result = new Array(2);
ulong vertices = 0;
ulong faces = 0;
for (int i = 1; i <= arr->size; i++)
{
INode* node = arr->get(i)->to_node();
TimeValue t = MAXScript_time();
const ObjectState& os = node->EvalWorldState(t); // Get the object that is referenced at the time
Object* ob = os.obj;
if (ob && (ob->SuperClassID() == GEOMOBJECT_CLASS_ID || ob->SuperClassID() == SHAPE_CLASS_ID))
{
BOOL needDel;
NullView nullView; // Set up a null viewport so that we get the right mesh..
Mesh *mesh = static_cast<GeomObject*>(ob)->GetRenderMesh(t, node, nullView, needDel); // Type cast to a geometric object and then retrieve
int numv = mesh->numVerts;
int numf = mesh->numFaces;
if (needDel) delete mesh;
vertices += numv;
faces += numf;
}
}
vl.result->append(new Integer(vertices));
vl.result->append(new Integer(faces));
return_value(vl.result);
}
Aug 07, 2015 2:55 pm
and finally! universal GET_VERTS_AND_FACES method:
for some situations 200! times faster then buil-in GetTriMeshFaceCount
def_visible_primitive(getNumVertsAndFaces, "getNumVertsAndFaces");
Value* getNumVertsAndFaces_cf(Value** arg_list, int count)
{
check_arg_count_with_keys(getNumVertsAndFaces, 1, count);
INode* node = arg_list[0]->to_node();
TimeValue t = MAXScript_time();
Object* obj = node->GetObjectRef();
int id = -3;
if (obj)
{
int numv, numf;
TimeValue t = MAXScript_time();
Object* osobj = obj->Eval(t).obj;
BOOL renderMesh = key_arg_or_default(render, &false_value)->to_bool();
BOOL faces = key_arg_or_default(faces, &true_value)->to_bool();
if (renderMesh)
{
if ((id = 1, osobj->SuperClassID() == GEOMOBJECT_CLASS_ID) || (id = 2, osobj->ClassID() == EPOLYOBJ_CLASS_ID) || (id = 3, osobj->SuperClassID() == SHAPE_CLASS_ID))
{
BOOL needDel;
NullView nullView; // Set up a null viewport so that we get the right mesh..
Mesh *mesh = ((GeomObject*)osobj)->GetRenderMesh(t, node, nullView, needDel); // Type cast to a geometric object and then retriev
numv = mesh->numVerts;
numf = mesh->numFaces;
if (needDel) delete mesh;
return new Point3Value(Point3(numv, numf, id));
}
}
if (id = 1, osobj->ClassID() == Class_ID(EDITTRIOBJ_CLASS_ID, 0))
{
Mesh* mesh = &((TriObject*)osobj)->mesh;
numv = mesh->numVerts;
numf = mesh->numFaces;
return new Point3Value(Point3(numv, numf, id));
}
if ((id = -2, osobj->ClassID() == Class_ID(POLYOBJ_CLASS_ID, 0)) || (id = 2, osobj->ClassID() == EPOLYOBJ_CLASS_ID))
{
if (faces)
{
MNMesh* mesh = &((PolyObject*)osobj)->mm;
numv = mesh->numv;
numf = mesh->TriNum();
return new Point3Value(Point3(numv, numf, id));
}
osobj->PolygonCount(t, numf, numv);
return new Point3Value(Point3(numv, numf, id));
}
GetTriMeshFaceCount (t, osobj, numf, numv);
return new Point3Value(Point3(numv, numf, 0));
}
return new Point3Value(Point3(-1,-1,id));
}
Aug 07, 2015 2:55 pm
Ok updated code with local bounding box and using the getNumVertsAndFaces if available, with fallback to GetTriMeshFaceCount when not available.
/*
Advanced Viewport Stats
(c) 2015 Dave Wortley & Daniel Santana
*/
try(unregisterRedrawViewsCallback drawStatsInfo.drawObjNameInfo)catch()
gc light:true
global drawStatsInfo
try(dw_ds_callback.enabled = false)catch()
dw_ds_callback = undefined
global dw_ds_callback
fn dw_ds_formatNumber val =
(
local l = val.count
while (l - 2) > 1 do (val = replace val (l - 2) 0 ","; l -= 3)
val
)
struct drawStatsInfo
(
lastObjectHandle,
lastObjectName,
lastObjectLayer,
lastObjectClass,
lastObjectSuperClass,
lastObjectParent,
lastObjectChilds,
lastObjectMat,
lastObjectFaceCount,
lastObjectVertCount,
lastObjectSize,
lastObjectDebug = "",
totalCounts,
totalFaceCount,
totalVertCount,
totalDebug = "",
useDlx = getNumVertsAndFaces != undefined,
updateObjectSizeDebug ="
",
disableTotalCount = true,
debug = false,
cfg = "$plugcfg/drawstatsinfo.ini",
ver = 0.8,
enabled = false,
fn updateObjectStats force:false =
(
st = timestamp()
if selection.count != 1 do return()
obj = selection[1]
if force == false and drawStatsInfo.lastObjectHandle == GetHandleByAnim obj do return()
drawStatsInfo.lastObjectHandle = GetHandleByAnim obj
drawStatsInfo.lastObjectName = obj.name
drawStatsInfo.lastObjectClass = (classof obj) as string
drawStatsInfo.lastObjectSuperClass = (superclassof obj) as string
drawStatsInfo.lastObjectLayer = obj.layer.name
drawStatsInfo.lastObjectParent = (if obj.parent == undefined then "sceneRootNode" else obj.parent.name)
drawStatsInfo.lastObjectChilds = dw_ds_formatNumber (obj.children.count as string)
drawStatsInfo.lastObjectMat = (if obj.material != undefined then classof obj.material as string + ": " + obj.material.name as string else "Unassigned")
drawStatsInfo.lastObjectFaceCount = (if superclassof obj == geometryclass then "
Faces: " + (dw_ds_formatNumber (obj.mesh.faces.count as string)) else "")
drawStatsInfo.lastObjectVertCount = (if superclassof obj == geometryclass then "
Vertices: " + (dw_ds_formatNumber (obj.mesh.vertices.count as string)) else "")
bbox = nodeLocalBoundingBox obj
s = bbox[2] - bbox[1]
f = units.formatValue
drawStatsInfo.lastObjectSize = "
Size: X=" + f(s.x) + " Y=" + f(s.y) + " Z:" + f(s.z)
--if drawStatsInfo.debug do
(
ss = stringstream ""
format "
[DEBUG]
updateObject took: %s
" ((timestamp()-st)/1000.0) to:ss
drawStatsInfo.lastObjectDebug = ss as string
--format (ss as string)
)
),
fn drawObjNameInfo =
(
try
(
textColour = (colorMan.getColor #activeViewportBorder) * 255.0
textColour = color 196 196 196
--tt = fileProperties.getItems "Mesh Totals"
--st = fileProperties.getItems "Scene Totals"
drawStatsInfo.updateObjectStats()
dtext = case of
(
(selection.count == 0): (
""
)
(selection.count == 1): (
"Object: " + drawStatsInfo.lastObjectName + \
"
Class: " + drawStatsInfo.lastObjectClass + " (" + drawStatsInfo.lastObjectSuperClass + ")" + \
"
Layer: " + drawStatsInfo.lastObjectLayer + \
"
Parent: " + drawStatsInfo.lastObjectParent + \
"
Children: " + drawStatsInfo.lastObjectChilds + \
"
Material: " + drawStatsInfo.lastObjectMat + \
drawStatsInfo.lastObjectFaceCount + \
drawStatsInfo.lastObjectVertCount + \
drawStatsInfo.lastObjectSize + \
(if drawStatsInfo.debug then drawStatsInfo.lastObjectDebug else "") + \
(if drawStatsInfo.debug then drawStatsInfo.totalDebug else "") + \
(if drawStatsInfo.debug then drawStatsInfo.updateObjectSizeDebug as string else "") + \
(if not drawStatsInfo.disableTotalCount then "
Total Faces: " + drawStatsInfo.totalFaceCount else "
") + \
--"
Total Vertices: " + drawStatsInfo.totalVertCount + \
"
Scene Object Count: " + objects.count as string + \
"
FPS: " + viewport.getFPS() as string
)
(selection.count > 1): (
types = #()
for o in selection do appendifunique types ((classof o))
(selection.count as string) + " Objects Selected" + \
"
" + (types.count as string) + " classes " + (types as string) + \
"
Geometry: " + (for o in selection where superclassof o == geometryclass collect o).count as string + \
"
Shapes: " + (for o in selection where superclassof o == shape collect o).count as string + \
"
Lights: " + (for o in selection where superclassof o == light collect o).count as string + \
"
Cameras: " + (for o in selection where superclassof o == camera collect o).count as string + \
"
Helpers: " + (for o in selection where superclassof o == helper collect o).count as string + \
"
Space Warps: " + (for o in selection where superclassof o == spacewarpObject collect o).count as string + \
"
Particle Systems: " + (for o in selection where superclassof o == particlesystem collect o).count as string + \
"
Bone Objects: " + (for o in selection where superclassof o == geometryclass collect o).count as string
)
)
local pos = [10,38]
gw.setTransform(Matrix3 1)
gw.wText [pos.x, pos.y, 0] dtext color:textColour
)
catch(print ("issue" + (getCurrentException())))
),
fn loadSettings =
(
if not doesfileexist cfg do return false
if hasINISetting drawStatsInfo.cfg "Options" "Debug" do
drawStatsInfo.debug = getIniSetting drawStatsInfo.cfg "Options" "Debug" as BooleanClass
if hasINISetting drawStatsInfo.cfg "Options" "TotalCount" do
drawStatsInfo.disableTotalCount = getIniSetting drawStatsInfo.cfg "Options" "TotalCount" as BooleanClass
if hasINISetting drawStatsInfo.cfg "Options" "Enabled" do
drawStatsInfo.enabled = getIniSetting drawStatsInfo.cfg "Options" "Enabled" as BooleanClass
),
fn show =
(
global dw_ds_DrawStatsInfoUI
try(destroydialog dw_ds_DrawStatsInfoUI)catch()
rollout dw_ds_DrawStatsInfoUI "Viewport Stat Options" width:245
(
group "Options"
(
checkbox ckbDebug "Debug mode" checked:drawStatsInfo.debug
on ckbDebug changed val do drawStatsInfo.debug = ckbDebug.checked
checkbox ckbTotal "Enable total face count" checked:(not drawStatsInfo.disableTotalCount)
)
checkbutton ckbEnable "Enabled" checked:drawStatsInfo.enabled
button btnClose "Close" align:#right
on btnClose pressed do try(destroydialog dw_ds_DrawStatsInfoUI)catch()
label lblVer "Version: 0.000" align:#left
hyperLink lblAbout1 "© 2015 Dave Wortley" address:"http://www.taylorjames.com/" across:3 align:#left
label lblAboutM "and" align:#middle offset:[15,0]
hyperLink lblAbout2 "Daniel Santana" address:"http://www.ycdivfx.com/" align:#left
on dw_ds_DrawStatsInfoUI open do lblVer.text = "Version: " + drawStatsInfo.ver as string
on dw_ds_DrawStatsInfoUI close do
(
setIniSetting drawStatsInfo.cfg "Options" "Debug" (drawStatsInfo.debug as string)
setIniSetting drawStatsInfo.cfg "Options" "TotalCount" (drawStatsInfo.disableTotalCount as string)
setIniSetting drawStatsInfo.cfg "Options" "Enabled" (drawStatsInfo.enabled as string)
)
on ckbTotal changed val do
(
drawStatsInfo.disableTotalCount = not val
if not drawStatsInfo.disableTotalCount do ::dw_ds_updateTotals ok ok
)
on ckbEnable changed val do
(
::drawStatsInfo.enabled = val
::drawStatsInfo.enable()
)
)
createdialog dw_ds_DrawStatsInfoUI
),
fn createMacros =
(
files = getfiles (pathConfig.appendPath (getdir #usermacros) "*.mcr")
macr = for f in files where findstring (tolower (getfilenamefile f)) "dwdsviewportstats" != undefined collect f
if macr.count == 0 do
(
macros.new "Views" "Macro_DwDsViewportStats" "DrawStatsInfoUI" "DrawStatsInfoUI" "
on execute do
(
::drawStatsInfo.show();
)
"
format "DrawStatsInfo Macro created.
"
)
),
fn enable =
(
try(unregisterRedrawViewsCallback drawStatsInfo.drawObjNameInfo)catch()
if drawStatsInfo.enabled do registerRedrawViewsCallback (drawStatsInfo.drawObjNameInfo)
),
fn setup =
(
drawStatsInfo.loadSettings()
drawStatsInfo.createMacros()
drawStatsInfo.enable()
)--,
--init = setup()
)
if not IsNetServer() do
(
drawStatsInfo = drawStatsInfo()
drawStatsInfo.setup()
global dw_ds_updateTotals
global dw_ds_updateObject
global dw_ds_updateObjectSize
fn dw_ds_updateTotals evt nds =
(
try(
st = timestamp()
drawStatsInfo.totalCounts = objects.count as string
--tv = 0
tf = 0
--for o in objects where superclassof o == geometryclass do (try(tv += o.mesh.numvertices)catch())
if not drawStatsInfo.disableTotalCount and drawStatsInfo.useDlx then tf = (getnumVertsAndFaces (objects as array))[2]
else if not drawStatsInfo.disableTotalCount do for o in objects where superclassof o == geometryclass do (try(tf += (GetTriMeshFaceCount o)[1]/*o.mesh.numfaces*/)catch())
drawStatsInfo.totalFaceCount = dw_ds_formatNumber (tf as string)
--drawStatsInfo.totalVertCount = tv as string
drawStatsInfo.updateObjectStats force:true
--if drawStatsInfo.debug do
(
ss = stringstream ""
format "updateTotals took: %s" ((timestamp()-st)/1000.0) to:ss
drawStatsInfo.totalDebug = ss as string
--format (ss as string)
)
)catch()
)
fn dw_ds_updateObject evt nds =
(
try
(
drawStatsInfo.updateObjectStats force:true
)
catch()
)
fn dw_ds_updateObjectSize evt nds =
(
try
(
st = timestamp()
if selection.count != 1 do return()
obj = selection[1]
s = obj.max - obj.min
f = units.formatValue
drawStatsInfo.lastObjectSize = "
Size: X=" + f(s.x) + " Y=" + f(s.y) + " Z:" + f(s.z)
--if drawStatsInfo.debug do
(
ss = stringstream ""
format "
updateObjectSize took: %s" ((timestamp()-st)/1000.0) to:ss
drawStatsInfo.updateObjectSizeDebug = ss as string
--format (ss as string)
)
)
catch(print "ooops")
)
dw_ds_updateTotals undefined undefined
dw_ds_callback = NodeEventCallback enabled:true mouseup:true delay:50 topologyChanged:(dw_ds_updateTotals) added:(dw_ds_updateTotals) deleted:(dw_ds_updateTotals) materialStructured:(dw_ds_updateObject) nameChanged:(dw_ds_updateObject) geometryChanged:(dw_ds_updateObjectSize) controllerOtherEvent:(dw_ds_updateObjectSize)
)
modified dennisT extension code (returned id only makes sense for single objects)
def_visible_primitive_debug_ok(getNumVertsAndFaces, "getNumVertsAndFaces");
Value* getNumVertsAndFaces_cf(Value** arg_list, int count)
{
check_arg_count_with_keys(numVertsAndTris, 1, count);
auto arr = static_cast<Array*>(arg_list[0]);
if(!is_array(arr))
{
arr = new Array(1);
arr->append(arg_list[0]);
}
int id = -3;
one_typed_value_local(Array *result);
vl.result = new Array(3);
ulong total_vertices = 0;
ulong total_faces = 0;
int numf, numv = 0;
BOOL renderMesh = key_arg_or_default(render, &false_value)->to_bool();
BOOL faces = key_arg_or_default(faces, &true_value)->to_bool();
for (int i = 1; i <= arr->size; i++)
{
auto node = arr->get(i)->to_node();
auto t = MAXScript_time();
const auto& os = node->EvalWorldState(t); // Get the object that is referenced at the time
auto ob = os.obj;
if (!ob) continue;
if (renderMesh)
{
if ((id = 1, ob->SuperClassID() == GEOMOBJECT_CLASS_ID) || (id = 2, ob->ClassID() == EPOLYOBJ_CLASS_ID) || (id = 3, ob->SuperClassID() == SHAPE_CLASS_ID))
{
BOOL needDel;
NullView nullView; // Set up a null viewport so that we get the right mesh..
auto mesh = static_cast<GeomObject*>(ob)->GetRenderMesh(t, node, nullView, needDel); // Type cast to a geometric object and then retriev
total_vertices += mesh->numVerts;
total_faces += mesh->numFaces;
if (needDel) delete mesh;
continue;
}
}
if (id = 1, ob->ClassID() == Class_ID(EDITTRIOBJ_CLASS_ID, 0))
{
auto mesh = &static_cast<TriObject*>(ob)->mesh;
total_vertices += mesh->numVerts;
total_faces += mesh->numFaces;
continue;
}
if ((id = -2, ob->ClassID() == Class_ID(POLYOBJ_CLASS_ID, 0)) || (id = 2, ob->ClassID() == EPOLYOBJ_CLASS_ID))
{
if (faces)
{
auto mesh = &static_cast<PolyObject*>(ob)->mm;
total_vertices += mesh->numv;
total_faces += mesh->TriNum();
continue;
}
ob->PolygonCount(t, numf, numv);
total_vertices += numv;
total_faces += numf;
continue;
}
GetTriMeshFaceCount(t, ob, numf, numv);
total_vertices += numv;
total_faces += numf;
}
vl.result->append(new Integer(total_vertices));
vl.result->append(new Integer(total_faces));
vl.result->append(new Integer(id));
return_value(vl.result);
}
Page 2 / 2
Prev