写了一个C4D的点对齐脚本——Alignment_V1.0
最近要做一些板式家具小模型,碰到点对齐的问题。可以实现像SketchUp那样快速地对齐点和面。文末附脚本下载方式
最近要做一些板式家具小模型,碰到点对齐的问题。横板与竖板顶上,用吸附来回切换视图太麻烦,所以写了这个脚本,可以实现像SketchUp那样快速地对齐点和面。文末附下载链接。
使用方法
-1.选中C掉的对象面或者点。
-2.选择要对齐的轴-x或者其他轴即可对齐。需要注意的一点是这里的轴方向是指世界轴的方向,不是选集轴的方向。点选集会自动按选中轴的方向贴合。
另外一个例子,选集点只有一半对齐到了面:
当选择的轴方向上没有面可以对齐,点选集会对齐到物体自身的边界框。如下图所示:
-3.如果Fixed to window没有勾选,则窗口在执行完命令会自动关闭。
脚本实现方法
在选中的点对象上,发射一条指定方向的射线。这条射线如果与自己的面相交,那么把交点的坐标记录下来,以此作为目标位置移动到这里。
好在C4D中已经有这个类和相关的方法了,可以直接拿来用。
ge = c4d.utils.GeRayCollider()ge.Init(op, force=False)
_ = ge.Intersect(pos + vector * 0.001, vector, d, only_test=False)
z = ge.GetNearestIntersection()
我这里pos + vector * 0.001是在pos位置的vector方向上做了0.1%的偏移,因为测试时发现产生的射线会跟自己的发射点有碰撞(无语)。z会返回一些碰撞的信息,可以参考C4D的文档:
intersection["face_id"] # The polygon index, int
intersection["tri_face_id"] # If first half of quad or triangle face_id + 1, else -(face_id + 1), int
intersection["hitpos"] # Position of the intersection, c4d.Vector
intersection["distance"] # Distance to the intersection, float
intersection["s_normal"] # Same as f_normal (reserved for phong normal at the intersection (Not normalized)), c4d.Vector
intersection["f_normal"] # Face normal (Not normalized), c4d.Vector
intersection["barrycoords"] # Barycentric coordinates of the intersection (x = u, y = v, z = d), c4d.Vector
intersection["backface"] # True if the intersected face's normal points away from the camera, otherwise False, bool
如果射线没有碰撞到任何面会返回None,我这里还通过intersection["backface"]排除掉了点选集对自己的碰撞结果。在多个点发射射线的情况下找到一个最小距离,然后将最小距离分别设置给选集中的点向量即可。除此之外,如果所有点选集发射的射线的返回结果都为None,那么将对齐到选中对象自己的BBox边界值,可以实现与自身外轮廓对齐的效果。
class Align(c4d.gui.GeDialog):
def __init__(self):
pass
#创建发射器,并获得碰撞点信息设置给目标的
def shot(self,op, vector, d=99999):
if op.GetRealType() == 5100:
c4d.CallCommand(12139)
ge = c4d.utils.GeRayCollider()
ge.Init(op, force=False)
points = op.GetPointS()
sel = points.GetAll(op.GetPointCount())
dis = []
selections = []
pos_list = []
for index, selected in enumerate(sel):
if not selected:
continue
pos = op.GetPoint(index)
pos_list.append(pos)
_ = ge.Intersect(pos + vector * 0.001, vector, d, only_test=False)
z = ge.GetNearestIntersection()
selections.append(index)
if z:
# hitpos = z['hitpos']
if not z['backface']:
distance = z['distance'] + 0.001
dis.append(distance)
try:
if len(dis):
min_dis = min(dis)
else:
level,d = self.get_dis(op,vector,pos_list)
min_dis = abs(level - d)
except ValueError:
min_dis = 0
if min_dis > 0:
doc.StartUndo()
for i in selections:
op.SetPoint(i, op.GetPoint(i) + vector * min_dis)
doc.AddUndo(c4d.UNDOTYPE_CHANGE, op)
doc.EndUndo()
c4d.EventAdd()
return min_dis
else:
c4d.gui.MessageDialog("Please select the point of the c4d.polygonObject!")
return False
#获取最值点
def get_dis(self,op,vector,pos_list):
all_pos = op.GetAllPoints()
if vector[0] > 0:
return max([dec[0] for dec in all_pos]),max([vec[0] for vec in pos_list])
elif vector[0] < 0:
return min([dec[0] for dec in all_pos]),min([vec[0] for vec in pos_list])
elif vector[1] > 0:
return max([dec[1] for dec in all_pos]),max([vec[1] for vec in pos_list])
elif vector[1] < 0:
return min([dec[1] for dec in all_pos]),min([vec[1] for vec in pos_list])
elif vector[2] > 0:
return max([dec[2] for dec in all_pos]),max([vec[2] for vec in pos_list])
elif vector[2] < 0:
return min([dec[2] for dec in all_pos]),min([vec[2] for vec in pos_list])
【下载方式】
关注【西技大神】微信公众号,后台留言【10008】,即可获得下载链接。原创不易,欢迎打赏。














































































