Конвертировать Rhino Mesh в BufferGeometry JSON - PullRequest
0 голосов
/ 07 ноября 2019

Я пытаюсь преобразовать меш-носорог в питоне Grasshopper в BufferGeometry, который будет читаться в Three.js / WebGL. В Three.js есть конвертеры, доступные для перехода из .obj в three.js, но для моего рабочего процесса мне нужно, чтобы эти файлы выводились из GH в виде JSON без предварительного сохранения его в формате .obj.

IУ меня был старый конвертер, который вводил сетку носорога, а затем выводил геометрию, но начиная с Three.js r.99 этот формат JSON устарел. Я создал скрипт, который вводит сетку и создает структуру данных, такую ​​как JSON Geometry Format 4 . Геометрия успешно загружается с использованием OBJLoader , но я получаю следующую ошибку:

glDrawArrays: попытка доступа к вершинам вне диапазона в атрибуте 1

Заранее спасибо!

from System import Guid
import rhinoscriptsyntax as rs
import json

# initiate lists to fill
geometryList = []
childrenList = []
# loop through input meshes
for i, mesh in enumerate(meshes):
    # get UUID
    geometry_guid = str(Guid.NewGuid())
    # JSON BufferGeometry Structure
    geometryDict = {
        "uuid": geometry_guid,
        "type": "BufferGeometry",
        "data": {
            "attributes":{
              "position":{
                "itemSize": 3,
                "type": "Float32Array",
                "array":[],
                "normalized": False
              },
              "normal":{
                "itemSize": 3,
                "type": "Float32Array",
                "array":[],
                "normalized": False
              }
            }
        }
    }
    # children Dict
    # values such as name, visible are input values from GH
    childrenDict = {
        "uuid": str(Guid.NewGuid()),
        "type": "Mesh",
        "name": name,
        "matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],
        "geometry": geometry_guid,
        "material": material.d['uuid'],
        "visible":visible,
        "castShadow": cast_shadow,
        "receiveShadow": receive_shadow,
        "userData": {}
    }
    # start index
    vertexIndex = 0
    # vertex array creation
    vertexArray = [None] * (len(rs.MeshVertices(mesh)) *3)
    # loop through vertices and append to vertex array
    for vertex in rs.MeshVertices(mesh):

        vertexArray[vertexIndex*3] = vertex[0]
        vertexArray[vertexIndex*3+1] = vertex[1]
        vertexArray[vertexIndex*3+2] = vertex[2]

        vertexIndex+=1
    # add to geometry dictionary
    geometryDict['data']['attributes']['position']['array'] = vertexArray

    # loop through faces
    faceVertices = []
    for face in rs.MeshFaceVertices(mesh):

        faceVertices.append(face[0])
        faceVertices.append(face[1])
        faceVertices.append(face[2])

        if face[2] != face[3]:
            faceVertices.append(face[2])
            faceVertices.append(face[3])
            faceVertices.append(face[0])

    # normal index
    normalIndex = 0
    # normal array creation
    normalArray = [None] * (len(rs.MeshFaceNormals(mesh)) *3)

    for normal in rs.MeshFaceNormals(mesh):

        normalArray[normalIndex*3] = normal[0]
        normalArray[normalIndex*3+1] = normal[1]
        normalArray[normalIndex*3+2] = normal[2]

        normalIndex+=1

    # add normal array to geometry dictionary
    geometryDict['data']['attributes']['normal']['array'] = normalArray

    geometryList.append(geometryDict)
    childrenList.append(childrenDict)

# these meshes are later added to the parent JSON Structure
class GhPythonDictionary(object):
    def __init__(self, pythonDict=None):
        if pythonDict:
            self.d = pythonDict
        else:
            self.d = {
                "material": material.d,
                "geometries": geometryList,
                "children": childrenList
            }
    def ToString(self):
        return 'GhPythonDictionary object'

mesh_object = GhPythonDictionary()

# master dictionary. all scene data goes in here

featureDict = {
    "metadata": {
        "version": 4.5,
        "type": "Object",
        "generator": "Object3D.toJSON",
    },
    "geometries":[],
    "materials":[],
    "object":{
        "uuid": "378FAA8D-0888-4249-8701-92D1C1F37C51",
        "type": "Group",
        "name": file_name,
        "matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],
        "children": []
    }
}

for i in range(len(mesh_objects)):

    for j in range(len(mesh_objects[i].d['geometries'])):
        featureDict['geometries'].append(mesh_objects[i].d['geometries'][j])

    featureDict['materials'].append(mesh_objects[i].d['material'])

    for j in range(len(mesh_objects[i].d['children'])):
        featureDict['object']['children'].append(mesh_objects[i].d['children'][j])

# file path as a string input from GH
file_path = path + '\\' + file_name + '.json'

# write file to folder path
with open(file_path, 'wb') as outfile:
    json.dump(featureDict, outfile)




// example of a mesh object created

{"uuid":"77589f14-6476-4517-b371-846920b9464b","type":"BufferGeometry","data":{"attributes":{"position":{"array":[-99.910560607910156,7.6936740875244141,211,-99.910560607910156,7.6936740875244141,207.021728515625,-100.83158111572266,7.6936740875244141,211,-100.83158111572266,7.6936740875244141,210.00543212890625,-100.83158111572266,7.6936740875244141,209.0108642578125,-100.83158111572266,7.6936740875244141,208.01629638671875,-101.75260925292969,7.6936740875244141,211,-101.75260925292969,7.6936740875244141,210.00543212890625,-101.75260925292969,7.6936740875244141,209.0108642578125,-101.75260925292969,7.6936740875244141,208.01629638671875,-102.67362976074219,7.6936740875244141,211,-102.67362976074219,7.6936740875244141,210.00543212890625,-102.67362976074219,7.6936740875244141,209.0108642578125,-102.67362976074219,7.6936740875244141,208.01629638671875,-103.59465026855469,7.6936740875244141,211,-103.59465026855469,7.6936740875244141,207.021728515625,-99.910560607910156,7.6936740875244141,207.68478393554687,-99.910560607910156,7.6936740875244141,208.34782409667969,-99.910560607910156,7.6936740875244141,209.0108642578125,-99.910560607910156,7.6936740875244141,209.67390441894531,-99.910560607910156,7.6936740875244141,210.33694458007813,-103.59465026855469,7.6936740875244141,210.33694458007813,-103.59465026855469,7.6936740875244141,209.67390441894531,-103.59465026855469,7.6936740875244141,209.0108642578125,-103.59465026855469,7.6936740875244141,208.34782409667969,-103.59465026855469,7.6936740875244141,207.68478393554687,-102.85783386230469,7.6936740875244141,207.021728515625,-102.12101745605469,7.6936740875244141,207.021728515625,-101.38420104980469,7.6936740875244141,207.021728515625,-100.64737701416016,7.6936740875244141,207.021728515625],"normalized":false,"itemSize":3,"type":"Float32Array"},"normal":{"array":[0,-1,-1,0,-1,-1,0,-1,-1,0,-1,-1,0,-1,-1,0,-1,-1,0,-1,-1,0,-1,-1,0,-1,-1,0,-1,-1,0,-1,-1,0,-1,-1,0,-1,-1,0,-1,-1,0,-1,-1,0,-1,-1,0,-1,-1,0,-1,-1,0,-1,-1,0,-1,-1,0,-1,-1,0,-1,-1,0,-1,-1,0,-1,-1,0,-1,-1],"normalized":false,"itemSize":3,"type":"Float32Array"}}}}

1 Ответ

1 голос
/ 09 ноября 2019

Как вы упомянули ThreeJS, JSON формат 4 устарел, и ObjectLoader не включен в самые последние сборки ThreeJS. Одна из причин, по которой он больше не поддерживается, заключается в том, что формат glTF стал предпочтительным вариантом для Интернета. Насколько мне известно, на момент написания этого поста экспортер glTF для Rhino / GH отсутствовал.

У вас есть несколько вариантов:

  1. добавить этот устаревший загрузчик JSON на ваш сайт
  2. выбрать тип файла, который может быть какэкспортируется из Rhino / Grasshopper и имеет загрузчик для трех файлов (например, OBJ, FBX)
  3. экспорт в формате OBJ, FBX или некоторый другой тип файла из Rhino, а затем преобразовать его в glTF с помощью другого программного обеспечения или процесса
  4. создать экспортер glTF из Rhino / GH
  5. вернуться к более старой версии threejs (до r99), которая поддерживает формат JJ Threejs 4
...