从 Rhino3d 导出图层为 obj

Export layers as obj from Rhino3d

任务

从 Rhino 导出图层为 obj 文件。

问题

使用 Python 脚本时,我 运行 导出命令。界面中会显示一个对话框,而不是导出模型。如果我点击导出界面,它工作正常。然而,它会为每一层弹出对话框。虽然我有很多层,但我想自动化整个导出过程。

最终目标是通过three.js在webGL中显示obj文件。

我是 Python 和 Rhino 的新手,但知道 PHP 和 JavaScript,所以我对这些概念有足够的了解并且看过一些关于 Python 的教程这样我就可以开始处理这个脚本了。

我试过的

我正在使用 Rhino,Atom/Python。

import scriptcontext
import rhinoscriptsyntax as rs
from Rhino.Geometry import Point3d

def layerNames(sort=False):
    rc = []
    for layer in scriptcontext.doc.Layers:
        if not layer.IsDeleted: rc.append(layer.FullPath)
    if sort: rc.sort()
    return rc


rs.EnableRedraw(False)

strPath = rs.DocumentPath()
strName = rs.DocumentName()

arrLayers = layerNames(False)
for layerName in arrLayers:
    objs = scriptcontext.doc.Objects.FindByLayer(layerName)
    rs.Command("_-Export "+layerName+".obj", False) 

备注

我在考虑使用python本地文件保存(打开("layername.json","a")。想法是以某种方式从每一层的对象中获取网格,转换到 three.js json 并改用它。但我不知道如何从图层中获取网格。我已导入 Rhino.Geometry 以查看它是否有帮助。我不知道如何找到要转换的网格,或者如果我可以以某种方式以自动方式使用本机导出命令并仅使用 obj 文件。

事实证明这很简单。您需要提供完整的文件路径、名称和扩展名。对话框可以使用多个 _Enter 命令自动执行。在此脚本中,使用默认的 obj 选项。选项可以附加到 _-Export 命令,但是在调用它们各自的 _Enter 命令之前。

import scriptcontext
import rhinoscriptsyntax as rs

def layerNames(sort=False):
    rc = []
    for layer in scriptcontext.doc.Layers:
        if not layer.IsDeleted: rc.append(layer.FullPath)
    if sort: rc.sort()
    return rc

fileName = rs.DocumentName()
filePath = rs.DocumentPath().rstrip(fileName)
extension = ".obj"

arrLayers = layerNames(False)

for layerName in arrLayers:
    objs = scriptcontext.doc.Objects.FindByLayer(layerName)
    if len(objs) > 0:
        rs.UnselectAllObjects()
        for obj in objs:
            obj.Select(True)
        scriptcontext.doc.Views.Redraw()
        rs.Command("_-Export "+filePath+layerName+extension+" _Enter _Enter")

在我的笔记中,我提到使用网格对象并通过 Python 编写我自己的文件。这仍然是一个可行的选择,但该方法尚未在 Mac for Rhino 上实现。我现在要使用递归函数来查找嵌套层。完成后我将 post 解决 Gist。

这是导出 dae、obj 和 stl 的最终脚本。适当的设置是相当积极的多边形减少。调整角度和密度来改变它。

我发现您需要先将密度设置为零,然后再将其设置为另一个值,这解决了网格转换中的多边形计数问题。

Also available on gist.

import os
import scriptcontext
import rhinoscriptsyntax as rs


print "//export run started/////////////"

# this function via mcneel/rhinoscriptsyntax
#https://github.com/mcneel/rhinoscriptsyntax/blob/master/Scripts/rhinoscript/layer.py
def layerNames(sort=False):
    rc = []
    for layer in scriptcontext.doc.Layers:
        if not layer.IsDeleted: rc.append(layer.FullPath)
    if sort: rc.sort()
    return rc

def GetDAESettings():
    e_str = ""
    return e_str

def GetOBJSettings():
    e_str = "_Geometry=_Mesh "
    e_str+= "_EndOfLine=CRLF "
    e_str+= "_ExportRhinoObjectNames=_ExportObjectsAsOBJGroups "
    e_str+= "_ExportMeshTextureCoordinates=_Yes "
    e_str+= "_ExportMeshVertexNormals=_No "
    e_str+= "_CreateNGons=_No "
    e_str+= "_ExportMaterialDefinitions=_No "
    e_str+= "_YUp=_No "
    e_str+= "_WrapLongLines=Yes "
    e_str+= "_VertexWelding=_Welded "
    e_str+= "_WritePrecision=4 "
    e_str+= "_Enter "

    e_str+= "_DetailedOptions "
    e_str+= "_JaggedSeams=_No "
    e_str+= "_PackTextures=_No "
    e_str+= "_Refine=_Yes "
    e_str+= "_SimplePlane=_No "

    e_str+= "_AdvancedOptions "
    e_str+= "_Angle=50 "
    e_str+= "_AspectRatio=0 "
    e_str+= "_Distance=0.0"
    e_str+= "_Density=0 "
    e_str+= "_Density=0.45 "
    e_str+= "_Grid=0 "
    e_str+= "_MaxEdgeLength=0 "
    e_str+= "_MinEdgeLength=0.0001 "

    e_str+= "_Enter _Enter"

    return e_str

def GetSTLSettings():
    eStr = "_ExportFileAs=_Binary "
    eStr+= "_ExportUnfinishedObjects=_Yes "
    eStr+= "_UseSimpleDialog=_No "
    eStr+= "_UseSimpleParameters=_No "
    eStr+= "_Enter _DetailedOptions "
    eStr+= "_JaggedSeams=_No "
    eStr+= "_PackTextures=_No "
    eStr+= "_Refine=_Yes "
    eStr+= "_SimplePlane=_No "
    eStr+= "_AdvancedOptions "
    eStr+= "_Angle=15 "
    eStr+= "_AspectRatio=0 "
    eStr+= "_Distance=0.01 "
    eStr+= "_Grid=16 "
    eStr+= "_MaxEdgeLength=0 "
    eStr+= "_MinEdgeLength=0.0001 "
    eStr+= "_Enter _Enter"
    return eStr

settingsList = {
    'GetDAESettings': GetDAESettings,
    'GetOBJSettings': GetOBJSettings,
    'GetSTLSettings': GetSTLSettings
}




fileName = rs.DocumentName()
filePath = rs.DocumentPath().rstrip(fileName)

arrLayers = layerNames(False)



def initExportByLayer(fileType="obj", visibleonly=False, byObject=False):
    for layerName in arrLayers:
        layer = scriptcontext.doc.Layers.FindByFullPath(layerName, True)
        if layer >= 0:
            layer = scriptcontext.doc.Layers[layer]
            save = True;
            if visibleonly:
                if not layer.IsVisible:
                    save = False
            if  rs.IsLayerEmpty(layerName):
                save = False
            if save:
                cutName = layerName.split("::")
                cutName = cutName[len(cutName)-1]
                objs = scriptcontext.doc.Objects.FindByLayer(cutName)
                if len(objs) > 0:
                    if byObject:
                        i=0
                        for obj in objs:
                            i= i+1
                            saveObjectsToFile(cutName+"_"+str(i), [obj], fileType)
                    else:
                        saveObjectsToFile(cutName, objs, fileType)



def saveObjectsToFile(name, objs, fileType):
    rs.EnableRedraw(False)
    if len(objs) > 0:
        settings = settingsList["Get"+fileType.upper()+"Settings"]()
        rs.UnselectAllObjects()
        for obj in objs:
            obj.Select(True)
        name = "".join(name.split(" "))
        command = '-_Export "{}{}{}" {}'.format(filePath, name, "."+fileType.lower(), settings)
        rs.Command(command, True)
        rs.EnableRedraw(True)


initExportByLayer("obj",True, False)
initExportByLayer("dae",True, False)
initExportByLayer("stl",True, False)

print "//export run ended/////////////"