Export Curve objects as Godot Path nodes. (#380)

* Export Curve objects as Godot Path nodes.

Fixes #330.
Relates to godotengine/godot-proposals#527.

Previously, curves in blender were exported to meshes in Godot.

Now, a bezier curve created in blender will be exported as a Path node
with a Curve3D resource matching the blender data. The curve will have a
child MeshInstance that renders the bevel.

Only bezier curves are exported to Godot Path nodes. Other curves, such
as Nurbs, export only as meshes as they did previously.

* Export all splines but only assign the active one.

* Remove curve test scenes for now.

They are generated with too recent of a blender version. We'll add them
again after bumping the blender CI version.

* Fix pylint warnings.
This commit is contained in:
Ryan Roden-Corrent
2020-12-16 09:01:53 -05:00
committed by GitHub
parent 0619f241ee
commit 3e66e12d7c
2 changed files with 67 additions and 3 deletions

View File

@@ -30,7 +30,7 @@ BLENDER_TYPE_TO_EXPORTER = {
"CAMERA": export_camera_node,
"LIGHT": export_light_node,
"EMPTY": export_empty_node,
"CURVE": export_mesh_node,
"CURVE": export_curve_node,
"SURFACE": export_mesh_node,
"META": export_mesh_node,
"FONT": export_mesh_node

View File

@@ -3,12 +3,15 @@ Any exporters that can be written in a single function can go in here.
Anything more complex should go in it's own file
"""
import math
import logging
import math
import mathutils
from ..structures import (
NodeTemplate, fix_directional_transform, gamma_correct
NodeTemplate, fix_directional_transform, gamma_correct, InternalResource,
Map, Array
)
from .animation import export_animation_data, AttributeConvertInfo
from .mesh import export_mesh_node
def export_empty_node(escn_file, export_settings, node, parent_gd_node):
@@ -165,3 +168,64 @@ def export_light_node(escn_file, export_settings, node, parent_gd_node):
light_node, node.data, 'light')
return light_node
def _export_spline(escn_file, spline, name):
points = Array("PoolVector3Array(")
tilts = Array("PoolRealArray(")
axis_correct = mathutils.Matrix((
(1, 0, 0), # X in blender is X in Godot
(0, 0, -1), # Y in blender is -Z in Godot
(0, 1, 0), # Z in blender is Y in Godot
)).normalized()
src_points = spline.bezier_points
if spline.use_cyclic_u:
# Godot fakes a closed path by adding the start point at the end
# https://github.com/godotengine/godot-proposals/issues/527
src_points = [*src_points, src_points[0]]
for point in src_points:
# blender handles are absolute
# godot handles are relative to the control point
points.extend((point.handle_left - point.co) @ axis_correct)
points.extend((point.handle_right - point.co) @ axis_correct)
points.extend(point.co @ axis_correct)
tilts.append(point.tilt)
data = Map()
data["points"] = points
data["tilts"] = tilts
curve_resource = InternalResource("Curve3D", name)
curve_resource["_data"] = data
curve_id = escn_file.get_internal_resource(spline)
if curve_id is None:
return escn_file.add_internal_resource(curve_resource, spline)
return escn_file.get_internal_resource(spline)
def export_curve_node(escn_file, export_settings, node, parent_gd_node):
"""Export a curve to a Path node, with a child mesh."""
splines = node.data.splines
path_node = NodeTemplate(node.name, "Path", parent_gd_node)
path_node["transform"] = node.matrix_local
escn_file.add_node(path_node)
for spline in splines:
# https://docs.blender.org/manual/en/latest/modeling/curves/editing/curve.html#set-spline-type
# Godot only supports bezier, and blender cannot convert losslessly
if spline.type == "BEZIER":
curve_id = _export_spline(escn_file, splines[0], node.data.name)
if spline == splines.active:
path_node["curve"] = "SubResource({})".format(curve_id)
# Create child MeshInstance renders the bevel for any curve type
mesh_node = export_mesh_node(
escn_file, export_settings, node, path_node
)
# The transform is already set on the path, don't duplicate it
mesh_node["transform"] = mathutils.Matrix.Identity(4)
return path_node