Move object axis problem in python
-
Hi, guys! i'm a new python guy and i want to move my object axis only, like center axis tool .and now i can move the axis on Y axis like this:
it's work fine
but if i rotate the object , it's have a problem(I don't know why i can't upload my next GIF).I think this is a matrix problem, but matrix a little bit hard for me ,i have no idea how to fix it.
Hope you guys can help me.This is my code:
import c4d def main(): obj = doc.GetActiveObject() axis_offset = c4d.Vector(0,100,0) points = obj.GetAllPoints() count = obj.GetPointCount() obj_pos = obj.GetAbsPos() doc.AddUndo(c4d.UNDOTYPE_CHANGE,obj) for i in xrange(len(points)): points[i] = points[i] + (axis_offset*-1) obj.SetAllPoints(points) obj.SetAbsPos(obj_pos+axis_offset) obj.Message(c4d.MSG_UPDATE) c4d.EventAdd() if __name__=='__main__': main()
-
Hi,
I am a bit confused regarding what your actual question is, since your code does not contain any matrix operations. I assume you want to know how matrix transforms work, so that you can construct one? You can check the ScratchPixel section on matrices, they have a pretty good explanation on how you can define transforms with matrices (if you don't already know what vectors are you should probably read that chapter too, especially regarding the geometric meaning of the cross product). Note that practically every software has a slightly different interpretation of transformation matrices, so read ScratchPixel more as a general guide.
c4d.utils
defines three functions to construct a rotation matrix axis by axis, the example also modifies the offset component of the final rotation matrix so that it also translates points by 100 units along the y axis.90_DEGREE = math.pi * .5 # construct a rotation matrix for each axis. mg_x = c4d.utils.MatrixRotX(90_DEGREE) mg_y = c4d.utils.MatrixRotY(0) mg_z = c4d.utils.MatrixRotZ(-90_DEGREE) # multiplying matrices will give you a matrix which combines all transformations my_final_transform = mg_x * mg_y * mg_z # set the offset my_final_transform.off = c4d.Vector(0, 100, 0) # transform a point in global space some_point_in_global_space = c4d.Vector(100, 0, 0) transformed_point = my_final_transform * some_point_in_global_space
You can also construct matrices manually if you have one or multiple normals (or vectors if you also want to scale stuff), using the cross product:
# note that the x and y components are switched, so we rotate by 90 degree on # the axis orthogonal to the xy-plane (the z axis). x_component = c4d.Vector(0, 1, 0) # the y component is not an unit vector so we scale by 2 on that axis y_component = c4d.Vector(2, 0, 0) # define the z axis manually z_component = c4d.Vector(0, 0, 1) # or construct it using the x and y component z_component = x_component.Cross(y_component).GetNormaliezd() # the offset (the translation component) for the matrix off_component = c4d.Vector(100, 0, 0) # build the matrix my_transform = c4d.Matrix(off_component, x_component, y_component, z_component) #do stuff with it transformed = [] for p in points: transformed.append(my_transform * p)
Cheers
zipit -
@zipit
Thank you very much for your reply. Maybe I did not describe the problem clearly. Actually, the problem I encountered is like this:For example : if i use rotate tool rotate my object and click my script.
1.the axis can move correctly.
2.but the object moves with it.(this is my problem)I don't want my objects to move,and I want my object to stay in place and only move the object axis
thank you again.
Cheers
harry -
Hi,
well then you have to apply the invers of the translation you have applied to your points also to your object. Something like this:
my_vector = c4d.Vector(0, 100, 0) for i, p in enumerate(points): points[i] = p + my_vector my_object.SetAllPoints(points) my_object.SetRelPos(my_object.GetRelPos() - my_vector)
Cheers
zipit -
@zipit
yes it works. but if you object is rotated on X axis 90 degrees, and click the script ,something is wrong... -
@gheyret said in Move object axis problem in python:
@zipit
yes it works. but if you object is rotated on X axis 90 degrees, and click the script ,something is wrong...I do not have C4D here, so i cannot run your code, also "something is wrong" is a rather vague description.
However, if you rotate your object you have to respect the matrix of that object when reapplying the invers of your vector (since you are operating in local coordinates for vertices). See my examples on matrices above. There are methods to get and set global and local matrices of objects in
c4d.BaseObject
.Cheers
zipit -
@zipit
Thanks for everything. You're really been a big help for me.
It works!!!Cheers
Harry -
Hi Harry, thanks for reaching out us.
With regard to your topic, as suggested by @zipit - thanks a lot dude -, I strongly recommend in having a look at geometry fundamentals as presented in ScratchPixel or in our documentation at Matrix Fundamentals.
Taking in consideration the global object orientation in space you could reconsider your code to use the inverse global matrix directly applied to your offset vector.
# set the offset vector myOff = c4d.Vector(0,-100,0) # check op is valid and assume it's already a mesh if op is None: return # retrieve object global inverse matrix invOpMg = ~(op.GetMg()) #get the mesh points points = op.GetAllPoints() # browse over them and add the offset vector left multiplied by the inverse global matrix for i,p in enumerate(points): points[i] = p + invOpMg*myOff # set points and update op.SetAllPoints(points) op.Message(c4d.MSG_UPDATE) c4d.EventAdd()
Best, Riccardo
-
@r_gigante
Yes! It's really helpful.