openglobus/blender.py
2023-04-11 20:04:05 +04:00

85 lines
2.3 KiB
Python

import bpy
import bmesh
import os
import sys
import json
import math
import mathutils
filepath = bpy.data.filepath
[path, name] = os.path.split(filepath)
[filename, ext] = name.split('.')
filename += '.json'
try:
args = list(reversed(sys.argv))
idx = args.index("--")
params = args[:idx][::-1]
except ValueError:
params = []
if len(params) > 0:
filename = params[0]
vertices = []
normals = []
indices = []
texcoords = []
vertex_index_offset = 0
def triangulate_object(obj):
bm = bmesh.new()
me = obj.data
bm.from_mesh(me)
bpy.ops.object.mode_set(mode='OBJECT')
bmesh.ops.triangulate(bm, faces=bm.faces[:])
bm.to_mesh(me)
bm.free()
for collection in bpy.data.collections:
for obj in collection.all_objects:
obj.rotation_euler[2] += math.radians(-90)
if obj.type == "MESH":
triangulate_object(obj)
matrix = obj.matrix_world
maxIndex = max(indices) + 1 if len(indices) > 0 else 0
bm = bmesh.new()
bm.from_mesh(obj.data)
bm.normal_update()
for face in bm.faces:
for vert, loop in zip(face.verts, face.loops):
indices.append(loop.index + vertex_index_offset)
vertex = matrix @ vert.co
vertices.append(vertex.x)
vertices.append(vertex.z)
vertices.append(-vertex.y)
# average the normals of each adjacent face to get vertex normal
normal = mathutils.Vector()
for other_face in vert.link_faces:
if other_face.normal.dot(face.normal) > 0:
normal += other_face.normal
if normal.length_squared > 0:
normal.normalize()
normals.append(normal.x)
normals.append(normal.z)
normals.append(-normal.y)
uv_layer = obj.data.uv_layers.active.data[loop.index]
texcoords.append(uv_layer.uv.x)
texcoords.append(1 - uv_layer.uv.y)
vertex_index_offset += maxIndex
data = {
"indices": indices,
"vertices": vertices,
"normals": normals,
"texCoords" : texcoords
}
with open(filename, "w") as outfile:
json.dump(data, outfile)