Difference between revisions of "User:LindaB Helendale/meshLODanalyzer"
Jump to navigation
Jump to search
(Created page with "Mesh LOD and Land Impact alalyzer (c) Lindab Helendale. Permission to use this script in any way granted. The script is combination of mesh asset server size script https://wik…") |
m |
||
(One intermediate revision by the same user not shown) | |||
Line 1: | Line 1: | ||
Mesh LOD and Land Impact | Mesh LOD and Land Impact analyzer (c) Lindab Helendale. | ||
Permission to use this script in any way granted. | Permission to use this script in any way granted. | ||
Line 11: | Line 11: | ||
< | <source lang="lsl2"> | ||
// Drop this script in a mesh object to see how the streaming (download) cost component of land impact | // Drop this script in a mesh object to see how the streaming (download) cost component of land impact | ||
// is calculated for that mesh. The script also shows how the download cost changes when the size of | // is calculated for that mesh. The script also shows how the download cost changes when the size of | ||
Line 219: | Line 219: | ||
} | } | ||
</ | </source> |
Latest revision as of 04:02, 7 September 2015
Mesh LOD and Land Impact analyzer (c) Lindab Helendale. Permission to use this script in any way granted.
The script is combination of mesh asset server size script
https://wiki.secondlife.com/wiki/User:LindaB_Helendale/getMeshLODsize
and mesh land impact script
https://wiki.secondlife.com/wiki/User:LindaB_Helendale/meshLODschemeCalculator
Drop the script in a mesh to see the contribution of LODs on the Land Impact and the effect of the scale of the mesh on the Land Impact.
// Drop this script in a mesh object to see how the streaming (download) cost component of land impact
// is calculated for that mesh. The script also shows how the download cost changes when the size of
// the mesh is changed, with breakdown of the cost to each LOD.
//
// To test the performance of different LOD reduction schemes, see
// http://wiki.secondlife.com/wiki/User:LindaB_Helendale/meshLODschemeCalculator
//
// The script is activated by dropping it in an object, resetting the script, rezzing the object,
// or touching the object.
//
// (c) LindaB Helendale, permission to use this script in any way granted.
float getObjectStreamingCost() {
return llList2Float(llGetObjectDetails(llGetKey(),[OBJECT_STREAMING_COST]),0);
}
float getRadius() {
return llVecMag(llGetScale())/2.0 ;
}
setRadius(float R) {
llSetScale(llGetScale()*R/getRadius());
if (llFabs(getRadius()-R)>0.01)
llOwnerSay("Warning: failed to set radius to " + (string)R + " The result was " + (string)getRadius());
}
list getLODtriangles() {
// Measure the triangle count for mesh LODs used in calculating the Streaming Cost/Download Cost
// component of the mesh Land Impact. Permission to use this script in any way granted.
// (c) LindaB Helendale
// See http://wiki.secondlife.com/wiki/User:LindaB_Helendale/getMeshLODsize for more info
vector S=llGetScale();
llSetScale(<1,1,1>); // we set equal scales to make sure the biggest radius is reached
float MeshTriangleBudgetScaler=50.0/3.0; // = MeshTriangleBudget(250000)/15000
list radius=[43.4422, 10.8605, 5.43027, 0.01];
list C;
integer i;
for(i=0;i<4;i++) {
setRadius(llList2Float(radius,i));
C += getObjectStreamingCost() * MeshTriangleBudgetScaler;
}
list tri;
tri = [ llList2Float(C,0),
16.0/15.0*llList2Float(C,1) - 1.0/15.0*llList2Float(C,0),
4.0/3.0*llList2Float(C,2) - 1.0/3.0*llList2Float(C,1),
llList2Float(C,3)
];
llSetScale(S);
return tri;
}
float getLODbytesize(float triangles) {
float MeshBytesPerTriangle=16;
float MeshMetaDataDiscount=384;
return triangles*MeshBytesPerTriangle + MeshMetaDataDiscount;
}
list LODdistances(float r) {
float max_distance = 512;
float dlowest = min(r/0.03, max_distance);
float dlow = min(r/0.06, max_distance);
float dmid = min(r/0.24, max_distance);
return [dlowest, dlow, dmid];
}
list LODweigths(float r) {
float max_distance = 512;
float dlowest = min(r/0.03, max_distance);
float dlow = min(r/0.06, max_distance);
float dmid = min(r/0.24, max_distance);
float max_area = 102932;
float min_area = 1;
float high_area = min(PI*dmid*dmid, max_area);
float mid_area = min(PI*dlow*dlow, max_area);
float low_area = min(PI*dlowest*dlowest, max_area);
float lowest_area = max_area;
lowest_area = lowest_area - low_area;
low_area = low_area - mid_area;
mid_area = mid_area - high_area;
high_area = llclamp(high_area, min_area, max_area);
mid_area = llclamp(mid_area, min_area, max_area);
low_area = llclamp(low_area, min_area, max_area);
lowest_area = llclamp(lowest_area, min_area, max_area);
float total_area = high_area + mid_area + low_area + lowest_area;
high_area = high_area / total_area;
mid_area = mid_area / total_area;
low_area = low_area / total_area;
lowest_area = lowest_area / total_area;
list weights=[high_area, mid_area, low_area, lowest_area];
return weights ;
}
float min(float a, float b) {
if (a<b) return a;
else return b;
}
float llclamp(float b,float bmin,float bmax) {
if (b<bmin) b=bmin;
if (b>bmax) b=bmax;
return b;
}
list get_LI_per_LOD(list triangles, float r) {
integer i;
list W=LODweigths(r);
list LI;
for(i=0;i<4;i++) {
LI += llList2Float(triangles,i)*llList2Float(W,i) * 3.0/50.0; // = 15000/MeshTriangleBudget
}
return LI;
}
print_LODs(list triangles, float r, integer percentage, integer showByteCounts) {
integer i;
float LItotal;
list LI = get_LI_per_LOD(triangles,r);
LItotal = llListStatistics(LIST_STAT_SUM, LI);
string txt;
for(i=0;i<4;i++) {
float li = llList2Float(LI,i);
if (percentage) li *= 100.0/LItotal;
txt += " " + llGetSubString((string)li,0,7) ;
}
llOwnerSay(llGetSubString((string)r,0,7) + " " + llGetSubString((string)LItotal,0,7) + txt);
if (showByteCounts) {
llOwnerSay(" ");
txt="";
for(i=0;i<4;i++) {
float tri = llList2Float(triangles,i);
txt += " " + llGetSubString(" " + (string)llRound(tri),-8,-1) ;
}
llOwnerSay("LOD sizes in triangles:" + txt);
txt="";
for(i=0;i<4;i++) {
float byt = getLODbytesize(llList2Float(triangles,i));
txt += " " + llGetSubString(" " + (string)llRound(byt),-8,-1) ;
}
llOwnerSay("LOD sizes in bytes: " + txt);
llOwnerSay(" ");
llOwnerSay("Note that the 'size in triangles' is lower than the actual triangle count, due to gzip compression of the data in asset server.");
}
}
show_landimpact_table() {
integer percentage = FALSE;
if (llGetNumberOfPrims()>1) {
llOwnerSay("Use this script with an unlinked mesh.");
return;
}
float radius=getRadius();
list triangles=getLODtriangles();
list LIcosts = llGetObjectDetails(llGetKey(),[OBJECT_SERVER_COST, OBJECT_STREAMING_COST,OBJECT_PHYSICS_COST]);
llOwnerSay("Mesh land impact analysis");
llOwnerSay("====================");
llOwnerSay("Server cost: " + (string)llList2Float(LIcosts,0));
llOwnerSay("Physics cost: " + (string)llList2Float(LIcosts,2));
llOwnerSay("Streaming (download) cost: " + (string)llList2Float(LIcosts,1));
float LIestimate = llListStatistics(LIST_STAT_SUM,get_LI_per_LOD(triangles,radius));
llOwnerSay(" Estimated DL cost: " + (string)LIestimate);
llOwnerSay(" Error of this model: " + (string)(llList2Float(LIcosts,1)-LIestimate));
llOwnerSay(" ");
llOwnerSay("LOD switch distances at the currect radius of " + (string)radius + " m with the default renderVolumeLODfactor debug settings:");
list LODdist=LODdistances(radius);
llOwnerSay(" Lowest to low: " + (string)llList2Float(LODdist,0) + " m");
llOwnerSay(" Low to mid: " + (string)llList2Float(LODdist,1) + " m");
llOwnerSay(" Mid to high: " + (string)llList2Float(LODdist,2) + " m");
llOwnerSay(" ");
llOwnerSay("Contribution of each LOD on the download cost:");
llOwnerSay("Radius Total LI highest LOD mid LOD low LOD lowest LOD");
print_LODs(triangles,radius,percentage,TRUE);
llOwnerSay(" ");
llOwnerSay("Effect of the mesh bounding sphere radius on the download cost:");
llOwnerSay("Radius Total LI highest LOD mid LOD low LOD lowest LOD");
print_LODs(triangles,0.1,percentage,FALSE);
print_LODs(triangles,0.25,percentage,FALSE);
print_LODs(triangles,0.5,percentage,FALSE);
for(radius=1;radius<20;radius++) print_LODs(triangles,radius,percentage,FALSE);
for(radius=20;radius<=55;radius+=5) print_LODs(triangles,radius,percentage,FALSE);
}
default
{
state_entry()
{
show_landimpact_table();
}
on_rez(integer p)
{
show_landimpact_table();
}
touch_start(integer num) {
show_landimpact_table();
}
}