Initial code commit

This commit is contained in:
Colin Basnett
2021-02-06 00:03:27 -08:00
parent ac4abe99bc
commit 0bb81b35e6
7 changed files with 453 additions and 0 deletions

110
src/builder.py Normal file
View File

@@ -0,0 +1,110 @@
from .ase import *
import bpy
import bmesh
import math
from mathutils import Matrix
class ASEBuilderError(Exception):
pass
class ASEBuilderOptions(object):
def __init__(self):
self.scale = 1.0
class ASEBuilder(object):
def build(self, context, options: ASEBuilderOptions):
ase = ASE()
main_geometry_object = None
for obj in context.selected_objects:
if obj is None or obj.type != 'MESH':
continue
mesh_data = obj.data
if not is_collision_name(obj.name) and main_geometry_object is not None:
geometry_object = main_geometry_object
else:
geometry_object = ASEGeometryObject()
geometry_object.name = obj.name
if not geometry_object.is_collision:
main_geometry_object = geometry_object
ase.geometry_objects.append(geometry_object)
if not geometry_object.is_collision and len(mesh_data.materials) == 0:
raise ASEBuilderError(f'Mesh \'{obj.name}\' must have at least one material')
geometry_object.vertex_offset += len(geometry_object.vertices)
vertex_transform = Matrix.Scale(options.scale, 4) @ Matrix.Rotation(math.pi, 4, 'Z') @ obj.matrix_world
for vertex_index, vertex in enumerate(mesh_data.vertices):
geometry_object.vertices.append(vertex_transform @ vertex.co)
material_indices = []
if not geometry_object.is_collision:
for mesh_material_index, material in enumerate(mesh_data.materials):
if material is None:
raise ASEBuilderError(f'Material slot {mesh_material_index + 1} for mesh \'{obj.name}\' cannot be empty')
try:
# Reuse existing material entries for duplicates
material_index = ase.materials.index(material.name)
except ValueError:
material_index = len(ase.materials)
ase.materials.append(material.name)
material_indices.append(material_index)
mesh_data.calc_loop_triangles()
mesh_data.calc_normals_split()
poly_groups, groups = mesh_data.calc_smooth_groups(use_bitflags=False)
# Faces
for face_index, loop_triangle in enumerate(mesh_data.loop_triangles):
face = ASEFace()
face.a = geometry_object.vertex_offset + mesh_data.loops[loop_triangle.loops[0]].vertex_index
face.b = geometry_object.vertex_offset + mesh_data.loops[loop_triangle.loops[1]].vertex_index
face.c = geometry_object.vertex_offset + mesh_data.loops[loop_triangle.loops[2]].vertex_index
if not geometry_object.is_collision:
face.material_index = material_indices[loop_triangle.material_index]
face.smoothing = poly_groups[loop_triangle.polygon_index]
geometry_object.faces.append(face)
# Normals
if not geometry_object.is_collision:
for face_index, loop_triangle in enumerate(mesh_data.loop_triangles):
face_normal = ASEFaceNormal()
face_normal.normal = loop_triangle.normal
face_normal.vertex_normals = []
for i in range(3):
vertex_normal = ASEVertexNormal()
vertex_normal.vertex_index = geometry_object.vertex_offset + mesh_data.loops[loop_triangle.loops[i]].vertex_index
vertex_normal.normal = loop_triangle.split_normals[i]
face_normal.vertex_normals.append(vertex_normal)
geometry_object.face_normals.append(face_normal)
uv_layer = mesh_data.uv_layers.active.data
# Texture Coordinates
geometry_object.texture_vertex_offset += len(geometry_object.texture_vertices)
if not geometry_object.is_collision:
for loop_index, loop in enumerate(mesh_data.loops):
u, v = uv_layer[loop_index].uv
geometry_object.texture_vertices.append((u, v, 0.0))
# Texture Faces
if not geometry_object.is_collision:
for loop_triangle in mesh_data.loop_triangles:
geometry_object.texture_vertex_faces.append((
geometry_object.texture_vertex_offset + loop_triangle.loops[0],
geometry_object.texture_vertex_offset + loop_triangle.loops[1],
geometry_object.texture_vertex_offset + loop_triangle.loops[2]
))
if len(ase.geometry_objects) == 0:
raise ASEBuilderError('At least one mesh object must be selected')
if main_geometry_object is None:
raise ASEBuilderError('At least one non-collision mesh must be exported')
return ase