cover_image

线下业务的3D设计师提效攻略

58UXD 58UXD
2023年03月13日 06:05

图片

图片
随着58到家在过去两年的线下业务高速发展,开店装修设计需求量激增。经历了制定SI手册和业务流程规范化培训,开店运行已经逐步成熟。
结合自身的VR临感平台,向58到家业务侧提供VR的场景效果展示,有助于对齐各方目标,在施工过程中可以更加直观的表达设计意图,为门店落地保质保量的提供支持。

图片
通过C4D + Python,创建C4D的自动化脚本实现搭建3D场景的目的。C4D可以加载AutoCAD,并读取AutoCAD的图层信息和图块信息,以此来构建墙体和放置家具。

图片
工作内容主要分三个部分:
  CAD图层和图块制作  
针对不同的家具和物体都分别设置一个独立的CAD图层。并针对墙体和门窗定义有特点的图层名称,例如玻璃门定义为glassdoor、墙体定义为wall,玻璃隔墙glasswall。这样可以在后续的python环节准确地识别。
图层都定义好之后,我们根据要使用的家具尺寸规格制作家具图块。C4D可以识别CAD图块的位置和旋转信息。
  C4D中使用的家具和物料的模型制作  
在C4D中导入或建模,将模型名称与CAD中的图层名称对应匹配。并把制作好的模型轴心放置到模型最底部的中心点。这里需要注意轴心的朝向需要与CAD的图块朝向相匹配,否则在自动摆放的环节会出现朝向错误。
  python脚本编写  
在这里需要对C4D的Python API文档有一定的了解,或者借助ChatGPT帮助。
我们先缕清逻辑依次执行:读取CAD信息、构建墙体、创建门洞和窗洞、摆放门窗、摆放家具、创建灯光和相机。
按CAD图层获取图块信息
根据C4D的python API,读取CAD的图层和图块信息,返回一个python字典类型数据。
    def getlayers(self,name=None):        dic={}        for layer in self.layers(mode='all'):            dic[layer]=[]            for obj in self.childrens():                if obj.GetLayerObject(doc)[c4d.ID_BASELIST_NAME]==layer:                    dic[layer].append(obj)                continue        if name is None:            return  dic        return dic[name]
构建墙体轮廓
识别到CAD的图层信息,根据读取到的墙体轮廓信息,创建C4D的挤压生成器,生成墙体和踢脚线。
    def createWall(self,up=None):        connect_wall=c4d.BaseObject(1011010)        connect_wall[c4d.CONNECTOBJECT_WELD]=0        connect_wall[c4d.CONNECTOBJECT_PHONG_MODE]=3        if up is None:            self.doc.InsertObject(connect_wall)        else:            self.doc.InsertObject(connect_wall,up)        #踢脚线        extruding_foot=c4d.BaseObject(5116)        extruding_foot[c4d.EXTRUDEOBJECT_EXTRUSIONOFFSET]=self.WALLFOOT        extruding_foot[c4d.ID_BASELIST_NAME]=self.WALLNAME        extruding_foot[c4d.ID_BASEOBJECT_ROTATION_ORDER]=5        extruding_foot[c4d.ID_BASEOBJECT_REL_ROTATION,c4d.VECTOR_X]=c4d.utils.DegToRad(-90)        extruding_foot[c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_Y]=0        extruding_foot[c4d.CAPSANDBEVELS_CAP_ENABLE_START]=1        extruding_foot[c4d.CAPSANDBEVELS_CAP_ENABLE_END]=0        doc.InsertObject(extruding_foot,parent=connect_wall)        #踢脚线上材质        wallfootmtl=self.doc.SearchMaterial('黑色氟碳漆')        self.setMaterial(extruding_foot,wallfootmtl,pro=3,tile=1,seaml=1,log='')        #墙体        extruding_up=c4d.BaseObject(5116)        extruding_up[c4d.EXTRUDEOBJECT_EXTRUSIONOFFSET]=self.STORYHEIGHT - self.WALLFOOT        extruding_up[c4d.ID_BASELIST_NAME]=self.WALLNAME        extruding_up[c4d.ID_BASEOBJECT_ROTATION_ORDER]=5        extruding_up[c4d.ID_BASEOBJECT_REL_ROTATION,c4d.VECTOR_X]=c4d.utils.DegToRad(-90)        extruding_up[c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_Y]=self.WALLFOOT        extruding_up[c4d.CAPSANDBEVELS_CAP_ENABLE_START]=0        extruding_up[c4d.CAPSANDBEVELS_CAP_ENABLE_END]=1        doc.InsertObject(extruding_up,parent=connect_wall)        #墙面上材质        mtl=self.doc.SearchMaterial('墙面木纹')        self.setMaterial(extruding_up,mtl,pro=3,tile=1,seaml=1,log='')        #墙体轮廓线条        connect_up=c4d.BaseObject(1011010)        connect_up[c4d.CONNECTOBJECT_WELD]=0        connect_up[c4d.CONNECTOBJECT_PHONG_MODE]=3        connect_up[c4d.ID_BASELIST_NAME]=self.WALLSPLINENAME        doc.InsertObject(connect_up,parent=extruding_up)        #踢脚线轮廓线条        connect_foot=c4d.BaseObject(1011010)        connect_foot[c4d.CONNECTOBJECT_WELD]=0        connect_foot[c4d.CONNECTOBJECT_PHONG_MODE]=3        connect_foot[c4d.ID_BASELIST_NAME]=self.WALLSPLINENAME        doc.InsertObject(connect_foot,parent=extruding_foot)        for spline in self.layersdic['wall']:            newsp_foot=spline.GetClone()            newsp_foot=self.changeSpline(newsp_foot)            newsp_foot[c4d.ID_LAYER_LINK]=doc.GetLayerObjectRoot().GetDown()            self.doc.InsertObject(newsp_foot,parent=connect_foot)        for spline in self.layersdic['wall']:            newsp_up=spline.GetClone()            newsp_up=self.changeSpline(newsp_up)            newsp_up[c4d.ID_LAYER_LINK]=doc.GetLayerObjectRoot().GetDown()            self.doc.InsertObject(newsp_up,parent=connect_up)        c4d.EventAdd()        return connect_wall
创建窗洞
创建一个窗户大小的方块,用于墙体布尔。使用C4D的布尔工具,对墙体模型挖洞。
def subtractWindow(self): extruding=c4d.BaseObject(5116) extruding[c4d.EXTRUDEOBJECT_EXTRUSIONOFFSET]=self.WINDOWUP-self.WINDOWDOWN extruding[c4d.ID_BASELIST_NAME]=self.WINDOWNAME extruding[c4d.ID_BASEOBJECT_ROTATION_ORDER]=5 extruding[c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_Y]=self.WINDOWDOWN extruding[c4d.ID_BASEOBJECT_REL_ROTATION,c4d.VECTOR_X]=c4d.utils.DegToRad(-90) return extruding
创建门洞
创建一个门大小的方块,用于墙体布尔。使用C4D的布尔工具,对墙体模型挖洞。
def subtractDoor(self): extruding=c4d.BaseObject(5116) extruding[c4d.EXTRUDEOBJECT_EXTRUSIONOFFSET]=self.DOORHEIGHT extruding[c4d.ID_BASELIST_NAME]=self.DOORNAME extruding[c4d.ID_BASEOBJECT_ROTATION_ORDER]=5 extruding[c4d.ID_BASEOBJECT_REL_ROTATION,c4d.VECTOR_X]=c4d.utils.DegToRad(-90) return extruding
装配门
根据CAD的图层和图块信息,将准备好的模型配置到对应位置。
def setDoors(self,hardData): harddata=hardData.GetChildren() for obj in harddata: for layername,splines in self.layersdic.items(): if obj[c4d.ID_BASELIST_NAME]==layername and 'door' in layername: for spline in splines: #获得图形坐标轮廓尺寸 pos=spline.GetAbsPos() lenth_vec,angle_vec=self.getSplineAngle(spline) newobj=obj.GetClone() newobj=self.stretchModel(newobj,lenth_vec,self.DOORHEIGHT,self.DEFAULT_DOORSIZE) newobj.SetAbsPos(c4d.Vector(pos.x,0,pos.y)) newobj.SetAbsRot(angle_vec) self.doc.InsertObject(newobj) c4d.EventAdd() return True
装配窗户
将窗户模型匹配到窗洞位置和旋转角度,并根据窗洞的尺寸自动生成匹配宽度。
def setWindows(self,hardData):        harddata=hardData.GetChildren()        for obj in harddata:            for layername,splines in self.layersdic.items():                if obj[c4d.ID_BASELIST_NAME]==layername and 'window' in layername:                    for spline in splines:                        lenth_vec,angle_vec=self.getSplineAngle(spline)                        pos=spline.GetAbsPos()                        if lenth_vec>300:                            n=int(lenth_vec/self.DEFAULT_WINDOWSIZE['window'][0])                            w=lenth_vec/n                            connect=c4d.BaseObject(1011010)                            connect[c4d.CONNECTOBJECT_WELD]=0                            connect[c4d.CONNECTOBJECT_PHONG_MODE]=3                            connect[c4d.ID_BASELIST_NAME]=self.WINDOWMERGE                            doc.InsertObject(connect)                            newobj=self.confitWindows(obj,n,w,connect)                            #print(newobj)                        else:                            newobj=obj.GetClone()                            newobj=self.stretchModel(newobj,lenth_vec,self.DOORHEIGHT,self.DEFAULT_WINDOWSIZE)                            self.doc.InsertObject(newobj)                        newobj.SetAbsPos(c4d.Vector(pos.x,self.WINDOWDOWN,pos.y))                        newobj.SetAbsRot(angle_vec)                        #self.GeRayCollider(cpolygon,newobj)                    c4d.EventAdd()        return True
装配家具
根据读取到的CAD图层和图块信息,将制作好的C4D家具模型复制并摆放到对应的CAD图块位置。
#装配单个可拉伸家具 def deformatFurniture(self,furname,hardData): harddata=hardData.GetChildren() for obj in harddata: if obj[c4d.ID_BASELIST_NAME]==furname: for spline in self.layersdic[furname]: lenth_vec,angle_vec=self.getSplineAngle(spline) #size=spline.GetRad() pos=spline.GetAbsPos() newobj=obj.GetClone() newobj=self.stretchModel(newobj,lenth_vec,self.DEFAULT_FURNITURE[furname][1],self.DEFAULT_FURNITURE) newobj.SetAbsPos(c4d.Vector(pos.x,0,pos.y)) angle_vec.x=-angle_vec.x newobj.SetAbsRot(angle_vec) self.doc.InsertObject(newobj) c4d.EventAdd() return True
#装配场景中的可拉伸家具 def setDeformFurn(self,hardData): names=list(self.DEFAULT_FURNITURE.keys()) for name in names: self.deformatFurniture(name,hardData) return True
创建灯光
在每个房间创建灯光,照亮房间。
def CreateLight(self,pos,size): obj=c4d.BaseObject(5102) obj[c4d.LIGHT_TYPE]=8 obj[c4d.ID_BASEOBJECT_REL_POSITION]=c4d.Vector(pos.x,self.LIGHTHEIGHT,pos.y) obj.SetRotationOrder(c4d.ROTATIONORDER_XYZGLOBAL) obj[c4d.ID_BASEOBJECT_REL_ROTATION]=c4d.Vector(-1.571, 0, 0) obj[c4d.LIGHT_AREADETAILS_SIZEX]=size.x*self.SCALE obj[c4d.LIGHT_AREADETAILS_SIZEY]=size.y*self.SCALE
tarTag1=c4d.BaseTag(1029526) tarTag1[c4d.LIGHTTAG_POWER]=0.3 tarTag1[c4d.OCT_LIGHTTAG_TYPE_SELECT]=1 tarTag1[c4d.LIGHTTAG_KEEP_INSTANCE_POWER]=1 tarTag1[c4d.LIGHTTAG_VISIBLE_ON_SPECULAR]=0 tarTag1[c4d.LIGHTTAG_VIS_CAM]=0 tarTag1[c4d.LIGHTTAG_VIS_SHADOW]=0 tarTag1[c4d.LIGHTTAG_VIS_GEN]=0
obj.InsertTag(tarTag1) doc.InsertObject(obj) c4d.EventAdd() return obj
创建相机位置
在每个房间创建一个摄像机,用于渲染全景。
#设置全景相机位置 def setCamera(self,pos): campos=c4d.Vector(pos.x,self.POSY,pos.y) camobj=c4d.BaseObject(5103) #camsuTag=c4d.BaseObject(5678) camTag=c4d.BaseTag(1029524) camTag[1439]=1 camTag[c4d.OCTANECAMERA_ENABLE_IMAGER]=1 camTag[c4d.OCT_CAMIMAGER_EN_DENOISER]=1 camTag[c4d.OCTANECAMERA_EXPOSURE]=4.0
camTag[c4d.OCTANECAMERA_HCOMPRESSION]=1.0 camTag[c4d.OCT_CAMERA_IMAGER_ORDER]=1 camTag[c4d.OCTANECAMERA_RESPONSE]=5221 camTag[c4d.OCTANECAMERA_NAT_RESPONSE]=1 camTag[c4d.OCTANECAMERA_GAMMA]=4.0 camobj[c4d.CAMERAOBJECT_SHOW]=0        camobj.InsertTag(camTag) camobj.SetRelPos(campos) doc.InsertObject(camobj) c4d.EventAdd() return camobj

图片
现在得益于ChatGPT等AI工具编写代码功能加持,通过python实现根据CAD文件搭建C4D场景,更加方便地为工作中的重复性高的内容编写脚本工具。

图片

3D设计  陈明
逆水行舟  不进则退

图片

扫码进群

图片

转载时请连同下方内容一起转发

请与该公众号联系获取内容授权

长按二维码   轻松关注

微信公众号:i58UXD

图片

58同城用户体验设计中心


图片

图片


58到家 · 目录
上一篇公众号运营设计全套秘籍下一篇转化率翻倍秘诀:打造用户信任三角(上)
继续滑动看下一个
58UXD
向上滑动看下一个