// FindObjectCenter(Object_Identifier,Shoot_Direction,Divisions_1,Divisions_2,CoM,Volume) // Calculates object center of mass location and stores to 'CoM' // Stores total volume to 'Volume' (assuming constant density) // 'Shoot_Direction' is which axis to shoot trace rays along // Divisions_1 and 2 are the divisions of the 2d mesh perpindicular to Shoot_Direction // 2009.09.06 Christopher Shake (cshake+pov@gmail.com) #macro FindObjectCenter(Object_Identifier,Shoot_Direction,Divisions_1,Divisions_2,CoM,Volume) #local maxcorner = max_extent(Object_Identifier); #local mincorner = min_extent(Object_Identifier); #local max_x = max(maxcorner.x,mincorner.x); #local min_x = min(maxcorner.x,mincorner.x); #local max_y = max(maxcorner.y,mincorner.y); #local min_y = min(maxcorner.y,mincorner.y); #local max_z = max(maxcorner.z,mincorner.z); #local min_z = min(maxcorner.z,mincorner.z); #local bound_center = (mincorner+maxcorner)/2; // center of bounding box, as reference //Verify that Shoot_Direction is along a primary axis and set up the mesh directions #if(abs(Shoot_Direction.x) > abs(Shoot_Direction.y) & abs(Shoot_Direction.x) > abs(Shoot_Direction.z)) #local Shoot_Direction = x; #local min_1=min_y;#local max_1=max_y;#local min_2=min_z;#local max_2=max_z;#local max_d=max_x; #else #if(abs(Shoot_Direction.y) > abs(Shoot_Direction.x) & abs(Shoot_Direction.y) > abs(Shoot_Direction.z)) #local Shoot_Direction = y; #local min_1=min_z;#local max_1=max_z;#local min_2=min_x;#local max_2=max_x;#local max_d=max_y; #else #if(abs(Shoot_Direction.z) > abs(Shoot_Direction.y) & abs(Shoot_Direction.z) > abs(Shoot_Direction.x)) #local Shoot_Direction = z; #local min_1=min_x;#local max_1=max_x;#local min_2=min_y;#local max_2=max_y;#local max_d=max_z; #else #debug "Error: FindObjectCenter: Shoot_Direction isn't along a primary axis, defaulting to y\n" #local Shoot_Direction = y; // default #local min_1=min_z;#local max_1=max_z;#local min_2=min_x;#local max_2=max_x;#local max_d=max_y; #end #end #end // calculate CoM #declare CoM = <0,0,0>; #declare Volume = 0; #local d1 = abs(max_1-min_1)/Divisions_1; #local d2 = abs(max_2-min_2)/Divisions_2; #local temp_norm = <0,0,0>; #local curr_1 = min_1+d1/2; #while (curr_1 < max_1) #local curr_2 = min_2+d2/2; #while (curr_2 < max_2) #local more_sections = true; // deals with voids in the object #if(vlength((Shoot_Direction=x))>1) #local shoot_start = ; #end #if(vlength((Shoot_Direction=y))>1) #local shoot_start = ; #end #if(vlength((Shoot_Direction=z))>1) #local shoot_start = ; #end #local vtemp = shoot_start*Shoot_Direction; #while(more_sections & (vtemp.x+vtemp.y+vtemp.z) <= max_d) // shoot ray along this '1-d' 'slice' to find ends #local hit_min = trace(Object_Identifier,shoot_start,Shoot_Direction,temp_norm); #if(vlength(temp_norm)!=0) // object exists in this 'slice', hit_min is now the first 'outside' edge // shoot another to see the next edge #local hit_max = trace(Object_Identifier,hit_min,Shoot_Direction,temp_norm); #if(vlength(temp_norm)!=0) #local point_vol = (vlength((hit_max-hit_min)*Shoot_Direction))*d1*d2; #local curr_ctr = (hit_max+hit_min)/2; #declare CoM = CoM + curr_ctr*point_vol; #declare Volume = Volume + point_vol; // now reset the starting position of the ray shoot in case the object has voids #local shoot_start = hit_max; #else #local shoot_start = hit_min+Shoot_Direction; #end #else #local more_sections = false; #end #local vtemp = shoot_start*Shoot_Direction; #end #local curr_2 = curr_2 + d2; #end #local curr_1 = curr_1 + d1; #end #declare CoM = CoM/Volume; // 'CoM' contains the calculated center of mass // 'Volume' contains the calculated volume of the object #end