You need to calculate the pivot in all cases to do the translation correctly, not only the cone. I'm doing that in my code by the way.
The problem with the cone and any other object that isn't a cube is that well, the bounding box is a cube. While the cone has a pointed end in the top, the bounding box doesn't, so the calculations will be based on the invisible box corner.
So if you want precision, you'll have to iterate all points positions.
And If you use Align you would still need to calculate the max/min position in at least one object.
I did a test with my previous code:
100 Objects
160,000 Tris
80,000 Points
= 3.358 seconds
Not bad considering the amount of calculation needed.
But still, Align should be much faster, so I wrote a version based on Align.
Code: Select all
// JScript
/*----------------------
axis : x=0, y=1, z=2
negative = 1 (boolean) If true(or 1) it will be aligned to the negative side of the axis
----------------------*/
var axis = 1
var negative = 0
var sel = Selection;
toTheGround(sel, axis, negative)
function toTheGround(sel, axis, negative){
// Create Undo (2012 and later)
var xsiVer = Application.Version().split(".")[0]
if (xsiVer >= 10) openUndo('toTheGround')
// Put Only the first object to the ground
// The rest will be aligned with the Align command
var obj = sel(0)
// Calculate the Global transform so the values won't be affected by SRT or parent values
var oTransform = obj.Kinematics.Global.Transform;
//Get the real minimun point position (not BBox)
var bb = getMaxMinPos(obj)
var toGround = - bb[(axis + 3)]
// Calculate the distance the object has to be moved
if (axis == 0) oItemPos = obj.Kinematics.Global.posx.value
if (axis == 1) oItemPos = obj.Kinematics.Global.posy.value
if (axis == 2) oItemPos = obj.Kinematics.Global.posz.value
toGround = oItemPos + toGround
// Just in case you want it in the Negative part of the Axis
if (negative) toGround = - toGround
// Translate the object to ground with OM
if (axis == 0) obj.Kinematics.Global.posx = toGround
if (axis == 1) obj.Kinematics.Global.posy = toGround
if (axis == 2) obj.Kinematics.Global.posz = toGround
// Prepare the variables to adjust the Align arguments
// siAlignGMIN is 0 and siAlignGMAX is 2, so we need to add 2 when doing negative axis calculations
var neg = negative *2
// while siX, and siY values are 1 and 2, siZ value is 4, so we need an exception
if (axis == 2) axis = 3
// Now, align the rest of objects
Align( sel, axis+1, 0+neg, 0+neg, 0+neg, 3+neg, 3+neg, 3+neg)
// Close Undo
if (xsiVer >= 10) closeUndo()
}
function getMaxMinPos(obj){
// Create arrays
var x =[]; var y =[]; var z =[];
// Get All Points
var points = obj.ActivePrimitive.Geometry.Points
// Iterate All Points to get their Positions
for ( var i=0, a = points.Count; i < a; i++ ) {
var point = points(i)
// Get Local Position
var LocalPos = point.Position
// Convert Local Position to Global
var GlobalPos = XSIMath.MapObjectPositionToWorldSpace(obj.Kinematics.Global.Transform, LocalPos)
// Gather All Points positions to x, y, z arrays
x.push (GlobalPos.x)
y.push (GlobalPos.y)
z.push (GlobalPos.z)
}
// Get the Max and Min values
var maxX = Math.max.apply(Math, x)
var maxY = Math.max.apply(Math, y)
var maxZ = Math.max.apply(Math, z)
var minX = Math.min.apply(Math, x)
var minY = Math.min.apply(Math, y)
var minZ = Math.min.apply(Math, z)
return [maxX, maxY, maxZ, minX, minY, minZ]
}
Hmm I Like it. I'll put it into mAligner soon.