写了一个C4D的点对齐脚本——Alignment_V1.0

用户头像
北京/设计爱好者/3年前/210浏览
写了一个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】,即可获得下载链接。原创不易,欢迎打赏。

2
举报
|
收藏
分享
相关推荐
评论
用户头像
评论你的想法~
表情
喜欢TA的作品吗?喜欢就快来夸夸TA吧!
推荐素材
柯基狗三维插画
三维渲染炫彩背景
三维抽象矢量星球,寓意全球化、国际化,球形世界地图,点和线连接的矢量背景
红色喜庆风格的三维产品展台
三维渲染的简约极简简洁紫色风格海报背景
抽象紫色发光气球背景,三维渲染
扁平化抽象几何三维模型创意时尚海报
实验室三维场景
灰色三角四面体、点线链接构成三维空间科技矢量背景
旋转的漩涡和流动的线条,三维渲染
三维抽象矢量星球,寓意全球化、国际化,球形世界地图
三维渲染的老年医生
三维卡通齿轮场景
三维曲线空间背景
连接的锁链与方块背景,三维渲染
红色三维概念礼盒背景
茄子三维插画
黑暗房间内的圆柱展台,三维渲染
多彩三维创意散落的旋转球体
三维户型剖面图
三维渲染的简约简洁极简风格几何体场景海报
三维渲染发光霓虹灯通道
创意弹簧与小球 弹性的概念物体 三维渲染
三维假期旅行主题
三维上海城市天际线
你可能喜欢
相关收藏夹
地产VI
地产VI
地产VI
地产VI
大家都在看
登录注册