metrics io

add functions for metrics saving and loading
we need to add and remove faces. if they don't have faces, blender gltf
loader will ignore the meshes. but we want them in the end only with
vertices and edges.
This commit is contained in:
themancalledjakob 2024-08-08 11:23:08 +02:00
parent 65605aa2c0
commit 5c4ee030d3

149
butils.py
View file

@ -510,6 +510,37 @@ def completely_delete_objects(objs):
# not important
pass
def is_mesh(o):
return type(o.data) == bpy.types.Mesh
def is_metrics_object(o):
return (re.match("[\w]*_metrics$", o.name) != None or re.match("[\w]*_metrics.[\d]{3}$", o.name) != None) and is_mesh(o)
def is_glyph(o):
try:
return type(o.parent) is not type(None) \
and "glyphs" in o.parent.name \
and is_mesh(o) \
and not is_metrics_object(o)
except ReferenceError as e:
return False
# blender bound_box vertices
#
# 3------7.
# |`. | `. +y
# | `2------6 |
# | | | | |
# 0---|--4. | +--- +x
# `. | `.| `.
# `1------5 `+z
def get_glyph_advance(glyph_obj):
for c in glyph_obj.children:
if is_metrics_object(c):
return abs(c.bound_box[4][0] - c.bound_box[0][0])
return abs(glyph_obj.bound_box[4][0] - glyph_obj.bound_box[0][0])
def set_text_on_curve(text_properties):
# starttime = time.perf_counter_ns()
mom = text_properties.text_object
@ -601,35 +632,45 @@ def set_text_on_curve(text_properties):
elif distribution_type == 'CALCULATE':
location, tangent = calc_point_on_bezier_curve(mom, advance, True)
ob.location = mom.matrix_world @ (location + text_properties.translation)
mask = [0]
input_rotations = [mathutils.Vector((0.0, 0.0, 0.0))]
vectors = [tangent]
factors = [1.0]
local_main_axis = mathutils.Vector((1.0, 0.0, 0.0))
motor = align_rotations_auto_pivot(mask,
input_rotations,
vectors,
factors,
local_main_axis)
if ob.rotation_mode != 'QUATERNION':
ob.rotation_mode = 'QUATERNION'
q = mathutils.Quaternion()
q.rotate(text_properties.orientation)
ob.rotation_quaternion = (mom.matrix_world @ motor[0] @ q.to_matrix().to_4x4()).to_quaternion()
if not text_properties.ignore_orientation:
mask = [0]
input_rotations = [mathutils.Vector((0.0, 0.0, 0.0))]
vectors = [tangent]
factors = [1.0]
local_main_axis = mathutils.Vector((1.0, 0.0, 0.0))
motor = align_rotations_auto_pivot(mask,
input_rotations,
vectors,
factors,
local_main_axis)
if ob.rotation_mode != 'QUATERNION':
ob.rotation_mode = 'QUATERNION'
q = mathutils.Quaternion()
q.rotate(text_properties.orientation)
ob.rotation_quaternion = (mom.matrix_world @ motor[0] @ q.to_matrix().to_4x4()).to_quaternion()
else:
q = mathutils.Quaternion()
q.rotate(text_properties.orientation)
ob.rotation_quaternion = q
# ob.rotation_quaternion = (mom.matrix_world @ q.to_matrix().to_4x4()).to_quaternion()
scalor = 0.001 * text_properties.font_size
glyph_advance = (-1 * glyph.bound_box[0][0] + glyph.bound_box[4][0]) * scalor + text_properties.letter_spacing
glyph_advance = get_glyph_advance(glyph) * scalor + text_properties.letter_spacing
# now we need to compensate for curvature
# otherwise letters will be closer together the curvier the bezier is
# this could be done more efficiently, but whatever
curve_compensation = 0
previous_location = calc_point_on_bezier_curve(mom, advance, False)
new_location = calc_point_on_bezier_curve(mom, advance + glyph_advance, False)
while (previous_location - new_location).length < glyph_advance:
curve_compensation = curve_compensation + glyph_advance * 0.01
new_location = calc_point_on_bezier_curve(mom, advance + glyph_advance + curve_compensation, False)
if text_properties.compensate_curvature:
previous_location = calc_point_on_bezier_curve(mom, advance, False)
new_location = calc_point_on_bezier_curve(mom, advance + glyph_advance, False)
while (previous_location - new_location).length > glyph_advance:
curve_compensation = curve_compensation - glyph_advance * 0.01
new_location = calc_point_on_bezier_curve(mom, advance + glyph_advance + curve_compensation, False)
while (previous_location - new_location).length < glyph_advance:
curve_compensation = curve_compensation + glyph_advance * 0.01
new_location = calc_point_on_bezier_curve(mom, advance + glyph_advance + curve_compensation, False)
ob.scale = (scalor, scalor, scalor)
@ -695,20 +736,62 @@ def add_metrics_obj_from_bound_box(glyph, bound_box=None):
mesh.from_pydata(verts, edges, faces)
def is_mesh(o):
return type(o.data) == bpy.types.Mesh
def add_faces_to_metrics(obj):
mesh = bpy.data.meshes.new(f"{obj.name}") # add the new mesh
bound_box = bound_box_as_array(obj.bound_box)
verts = [bound_box[0],
bound_box[1],
bound_box[2],
bound_box[3],
bound_box[4],
bound_box[5],
bound_box[6],
bound_box[7],
]
edges = [[0,1],[1,2],[2,3],[3,0],
[0,4],[1,5],[2,6],[3,7],
[4,5],[5,6],[6,7],[7,4],
]
faces = [
[0,1,2], [2,3,0],
[2,6,7], [7,3,2],
[6,5,4], [4,7,6],
[4,5,1], [0,4,1],
[1,5,6], [1,6,2],
[4,0,7], [7,0,3],
]
def is_metrics_object(o):
return (re.match("[\w]*_metrics$", o.name) != None or re.match("[\w]*_metrics.[\d]{3}$", o.name) != None) and is_mesh(o)
mesh.from_pydata(verts, edges, faces)
old_mesh = obj.data
obj.data = mesh
bpy.data.meshes.remove(old_mesh)
def remove_faces_from_metrics(obj):
mesh = bpy.data.meshes.new(f"{obj.name}") # add the new mesh
bound_box = bound_box_as_array(obj.bound_box)
verts = [bound_box[0],
bound_box[1],
bound_box[2],
bound_box[3],
bound_box[4],
bound_box[5],
bound_box[6],
bound_box[7],
]
edges = [[0,1],[1,2],[2,3],[3,0],
[0,4],[1,5],[2,6],[3,7],
[4,5],[5,6],[6,7],[7,4],
]
faces = [
]
mesh.from_pydata(verts, edges, faces)
old_mesh = obj.data
obj.data = mesh
bpy.data.meshes.remove(old_mesh)
def is_glyph(o):
try:
return type(o.parent) is not type(None) \
and "glyphs" in o.parent.name \
and is_mesh(o) \
and not is_metrics_object(o)
except ReferenceError as e:
return False
# duplicate
# def remove_metrics_from_selection():
# for o in bpy.context.selected_objects: