mirror of
https://github.com/godotengine/godot-blender-exporter.git
synced 2026-01-05 18:10:04 +03:00
Refactor CollisionShape generating in physics
1. Remove triangulating in exporting any convex CollisionShape 2. Add utils to reuse mesh exporting related functions in CollisionShape exporting
This commit is contained in:
@@ -1,15 +1,15 @@
|
||||
"""Exports a normal triangle mesh"""
|
||||
import logging
|
||||
import bpy
|
||||
import bmesh
|
||||
import mathutils
|
||||
|
||||
from .material import export_material
|
||||
from ..structures import (
|
||||
Array, NodeTemplate, InternalResource, Map, gamma_correct)
|
||||
from . import physics
|
||||
from . import armature
|
||||
from . import animation
|
||||
from .utils import MeshConverter, MeshResourceKey
|
||||
from .physics import has_physics, export_physics_properties
|
||||
from .armature import generate_bones_mapping
|
||||
from .animation import export_animation_data
|
||||
|
||||
MAX_BONE_PER_VERTEX = 4
|
||||
|
||||
@@ -21,8 +21,8 @@ def export_mesh_node(escn_file, export_settings, obj, parent_gd_node):
|
||||
# If this mesh object has physics properties, we need to export them first
|
||||
# because they need to be higher in the scene-tree
|
||||
|
||||
if physics.has_physics(obj):
|
||||
parent_gd_node = physics.export_physics_properties(
|
||||
if has_physics(obj):
|
||||
parent_gd_node = export_physics_properties(
|
||||
escn_file, export_settings, obj, parent_gd_node
|
||||
)
|
||||
# skip wire mesh which is used as collision mesh
|
||||
@@ -59,7 +59,7 @@ def export_mesh_node(escn_file, export_settings, obj, parent_gd_node):
|
||||
|
||||
# Transform of rigid mesh is moved up to its collision
|
||||
# shapes.
|
||||
if physics.has_physics(obj):
|
||||
if has_physics(obj):
|
||||
mesh_node['transform'] = mathutils.Matrix.Identity(4)
|
||||
else:
|
||||
mesh_node['transform'] = obj.matrix_local
|
||||
@@ -69,25 +69,13 @@ def export_mesh_node(escn_file, export_settings, obj, parent_gd_node):
|
||||
# export shape key animation
|
||||
if (export_settings['use_export_shape_key'] and
|
||||
has_shape_keys(obj.data)):
|
||||
animation.export_animation_data(
|
||||
export_animation_data(
|
||||
escn_file, export_settings, mesh_node,
|
||||
obj.data.shape_keys, 'shapekey')
|
||||
|
||||
return mesh_node
|
||||
|
||||
|
||||
def triangulate_mesh(mesh):
|
||||
"""Triangulate a mesh"""
|
||||
tri_mesh = bmesh.new()
|
||||
tri_mesh.from_mesh(mesh)
|
||||
bmesh.ops.triangulate(
|
||||
tri_mesh, faces=tri_mesh.faces, quad_method="ALTERNATE")
|
||||
tri_mesh.to_mesh(mesh)
|
||||
tri_mesh.free()
|
||||
|
||||
mesh.update(calc_loop_triangles=True)
|
||||
|
||||
|
||||
def fix_vertex(vtx):
|
||||
"""Changes a single position vector from y-up to z-up"""
|
||||
return mathutils.Vector((vtx.x, vtx.z, -vtx.y))
|
||||
@@ -119,85 +107,12 @@ def export_object_link_material(escn_file, export_settings, mesh_object,
|
||||
)
|
||||
|
||||
|
||||
def get_applicable_modifiers(obj, export_settings):
|
||||
"""Returns a list of all the modifiers that'll be applied to the final
|
||||
godot mesh"""
|
||||
ignore_modifiers = []
|
||||
if not export_settings['use_mesh_modifiers']:
|
||||
return []
|
||||
if "ARMATURE" in export_settings['object_types']:
|
||||
ignore_modifiers.append(bpy.types.ArmatureModifier)
|
||||
ignore_modifiers = tuple(ignore_modifiers)
|
||||
return [m for m in obj.modifiers if not isinstance(m, ignore_modifiers)
|
||||
and m.show_viewport]
|
||||
|
||||
|
||||
def record_modifier_config(obj):
|
||||
"""Returns modifiers viewport visibility config"""
|
||||
modifier_config_cache = []
|
||||
for mod in obj.modifiers:
|
||||
modifier_config_cache.append(mod.show_viewport)
|
||||
return modifier_config_cache
|
||||
|
||||
|
||||
def restore_modifier_config(obj, modifier_config_cache):
|
||||
"""Applies modifiers viewport visibility config"""
|
||||
for i, mod in enumerate(obj.modifiers):
|
||||
mod.show_viewport = modifier_config_cache[i]
|
||||
|
||||
|
||||
def has_shape_keys(object_data):
|
||||
"""Determine if object data has shape keys"""
|
||||
return (hasattr(object_data, "shape_keys") and
|
||||
object_data.shape_keys is not None)
|
||||
|
||||
|
||||
class MeshResourceKey:
|
||||
"""Produces a key based on an mesh object's data, every different
|
||||
Mesh Resource would have a unique key"""
|
||||
|
||||
def __init__(self, rsc_type, obj, export_settings):
|
||||
mesh_data = obj.data
|
||||
|
||||
# Resource type included because same blender mesh may be used as
|
||||
# MeshResource or CollisionShape, but they are different resource
|
||||
gd_rsc_type = rsc_type
|
||||
|
||||
# Here collect info of all the modifiers applied on the mesh.
|
||||
# Modifiers along with the original mesh data would determine
|
||||
# the evaluated mesh.
|
||||
mod_info_list = list()
|
||||
for modifier in get_applicable_modifiers(obj, export_settings):
|
||||
# Modifier name indicates its type, its an identifier
|
||||
mod_info_list.append(modifier.name)
|
||||
|
||||
# First property is always 'rna_type', skip it
|
||||
for prop in modifier.bl_rna.properties.keys()[1:]:
|
||||
# Note that Property may be `BoolProperty`,
|
||||
# `CollectionProperty`, `EnumProperty`, `FloatProperty`,
|
||||
# `IntProperty`, `PointerProperty`, `StringProperty`"
|
||||
# Most of them are primary type when accessed with `getattr`,
|
||||
# so they are fine to be hashed.
|
||||
# For `PointerProperty`, it is mostly an bpy.types.ID, hash it
|
||||
# would get its python object identifier, which is also good.
|
||||
# For `CollectionProperty`, it would make more sense to
|
||||
# traversal it, however, we cut down it here to allow
|
||||
# some of mesh resource not be shared because of simplicity
|
||||
mod_info_list.append(getattr(modifier, prop))
|
||||
|
||||
self._data = tuple([mesh_data, gd_rsc_type] + mod_info_list)
|
||||
# Precalculate the hash now for better efficiency later
|
||||
self._hash = hash(self._data)
|
||||
|
||||
def __hash__(self):
|
||||
return self._hash
|
||||
|
||||
def __eq__(self, other):
|
||||
# pylint: disable=protected-access
|
||||
return (self.__class__ == other.__class__ and
|
||||
self._data == other._data)
|
||||
|
||||
|
||||
class ArrayMeshResource(InternalResource):
|
||||
"""Godot ArrayMesh resource, containing surfaces"""
|
||||
|
||||
@@ -232,8 +147,7 @@ class ArrayMeshResourceExporter:
|
||||
if armature_obj is None:
|
||||
return
|
||||
|
||||
bones_mapping = armature.generate_bones_mapping(export_settings,
|
||||
armature_obj)
|
||||
bones_mapping = generate_bones_mapping(export_settings, armature_obj)
|
||||
for bl_bone_name, gd_bone_id in bones_mapping.items():
|
||||
group = self.object.vertex_groups.get(bl_bone_name)
|
||||
if group is not None:
|
||||
@@ -310,7 +224,7 @@ class ArrayMeshResourceExporter:
|
||||
)
|
||||
|
||||
mesh_converter = MeshConverter(self.object, export_settings)
|
||||
shape_key_mesh = mesh_converter.to_mesh(index)
|
||||
shape_key_mesh = mesh_converter.to_mesh(shape_key_index=index)
|
||||
|
||||
surfaces_morph_data = self.intialize_surfaces_morph_data(surfaces)
|
||||
|
||||
@@ -675,68 +589,3 @@ class Vertex:
|
||||
self.uv = []
|
||||
self.bones = []
|
||||
self.weights = []
|
||||
|
||||
|
||||
class MeshConverter:
|
||||
"""MeshConverter evaulates and converts objects to meshes, triangulates
|
||||
and calculates tangents"""
|
||||
|
||||
def __init__(self, obj, export_settings):
|
||||
self.object = obj
|
||||
self.eval_object = None
|
||||
self.use_mesh_modifiers = export_settings["use_mesh_modifiers"]
|
||||
self.use_export_shape_key = export_settings['use_export_shape_key']
|
||||
self.has_tangents = False
|
||||
|
||||
def to_mesh(self, shape_key_index=0, calculate_tangents=True):
|
||||
"""Evaluates object & converts to final mesh, ready for export.
|
||||
The mesh is only temporary, call to_mesh_clear() afterwards."""
|
||||
# set shape key to basis key which would have index 0
|
||||
orig_shape_key_index = self.object.active_shape_key_index
|
||||
self.object.show_only_shape_key = True
|
||||
self.object.active_shape_key_index = shape_key_index
|
||||
|
||||
self.eval_object = self.object
|
||||
|
||||
modifier_config_cache = None
|
||||
if not self.use_mesh_modifiers:
|
||||
modifier_config_cache = record_modifier_config(self.object)
|
||||
for mod in self.object.modifiers:
|
||||
mod.show_viewport = False
|
||||
|
||||
depsgraph = bpy.context.view_layer.depsgraph
|
||||
depsgraph.update()
|
||||
self.eval_object = self.object.evaluated_get(depsgraph)
|
||||
|
||||
# These parameters are required for preserving vertex groups.
|
||||
mesh = self.eval_object.to_mesh(
|
||||
preserve_all_data_layers=True, depsgraph=depsgraph)
|
||||
|
||||
if not self.use_mesh_modifiers:
|
||||
restore_modifier_config(self.object, modifier_config_cache)
|
||||
|
||||
self.has_tangents = False
|
||||
|
||||
# mesh result can be none if the source geometry has no faces, so we
|
||||
# need to consider this if we want a robust exporter.
|
||||
if mesh is not None:
|
||||
triangulate_mesh(mesh)
|
||||
|
||||
self.has_tangents = mesh.uv_layers and mesh.polygons
|
||||
if calculate_tangents:
|
||||
if self.has_tangents:
|
||||
mesh.calc_tangents()
|
||||
else:
|
||||
mesh.calc_normals_split()
|
||||
|
||||
self.object.show_only_shape_key = False
|
||||
self.object.active_shape_key_index = orig_shape_key_index
|
||||
|
||||
return mesh
|
||||
|
||||
def to_mesh_clear(self):
|
||||
"""Clears the temporary generated mesh from memory"""
|
||||
if self.object is None:
|
||||
return
|
||||
self.eval_object.to_mesh_clear()
|
||||
self.object = self.eval_object = None
|
||||
|
||||
@@ -7,6 +7,7 @@ physics owns the object.
|
||||
import logging
|
||||
import mathutils
|
||||
from ..structures import NodeTemplate, InternalResource, Array, _AXIS_CORRECT
|
||||
from .utils import MeshConverter, MeshResourceKey
|
||||
|
||||
PHYSICS_TYPES = {'KinematicBody', 'RigidBody', 'StaticBody'}
|
||||
|
||||
@@ -72,10 +73,17 @@ def export_collision_shape(escn_file, export_settings, node, parent_gd_node,
|
||||
col_shape = None
|
||||
if rbd.collision_shape in ("CONVEX_HULL", "MESH"):
|
||||
is_convex = rbd.collision_shape == "CONVEX_HULL"
|
||||
shape_id = generate_shape_mesh(
|
||||
escn_file, export_settings,
|
||||
node, is_convex
|
||||
)
|
||||
if rbd.collision_shape == "CONVEX_HULL":
|
||||
shape_id = generate_convex_shape(
|
||||
escn_file, export_settings, node
|
||||
)
|
||||
else: # "MESH"
|
||||
shape_id = generate_concave_shape(
|
||||
escn_file, export_settings, node
|
||||
)
|
||||
|
||||
if shape_id is not None:
|
||||
col_node['shape'] = "SubResource({})".format(shape_id)
|
||||
else:
|
||||
bounds = get_extents(node)
|
||||
if rbd.collision_shape == "BOX":
|
||||
@@ -96,56 +104,95 @@ def export_collision_shape(escn_file, export_settings, node, parent_gd_node,
|
||||
else:
|
||||
logging.warning("Unable to export physics shape for %s", node.name)
|
||||
|
||||
col_node['shape'] = "SubResource({})".format(shape_id)
|
||||
if col_shape is not None and rbd.use_margin:
|
||||
col_shape['margin'] = rbd.collision_margin
|
||||
|
||||
if shape_id is not None:
|
||||
col_node['shape'] = "SubResource({})".format(shape_id)
|
||||
escn_file.add_node(col_node)
|
||||
|
||||
return col_node
|
||||
|
||||
|
||||
def generate_shape_mesh(escn_file, export_settings, node, is_convex):
|
||||
"""Generates godots PolygonShape from a blender mesh object"""
|
||||
# pylint: disable-msg=cyclic-import
|
||||
from .mesh import (MeshConverter, MeshResourceKey)
|
||||
class MeshCollisionShapeKey:
|
||||
"""Produces a resource key based on an mesh object's data and rigid
|
||||
propertys"""
|
||||
def __init__(self, shape_type, bl_object, export_settings):
|
||||
assert shape_type in ("ConvexPolygonShape", "ConcavePolygonShape")
|
||||
|
||||
margin = 0
|
||||
if node.rigid_body.use_margin:
|
||||
margin = node.rigid_body.collision_margin
|
||||
mesh_data_key = MeshResourceKey(shape_type, bl_object, export_settings)
|
||||
# margin is the property that stores in CollisionShape in Godot
|
||||
margin = 0
|
||||
if bl_object.rigid_body.use_margin:
|
||||
margin = bl_object.rigid_body.collision_margin
|
||||
|
||||
# Build the Shape resource hash key with rigid margin and mesh data
|
||||
if is_convex:
|
||||
shape_rsc_type = "ConvexPolygonShape"
|
||||
else:
|
||||
shape_rsc_type = "ConcavePolygonShape"
|
||||
mesh_data_key = MeshResourceKey(shape_rsc_type, node, export_settings)
|
||||
shape_rsc_key = (margin, mesh_data_key)
|
||||
self._data = tuple((margin, mesh_data_key))
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self._data)
|
||||
|
||||
def __eq__(self, other):
|
||||
# pylint: disable=protected-access
|
||||
return (self.__class__ == other.__class__ and
|
||||
self._data == other._data)
|
||||
|
||||
|
||||
def generate_convex_shape(escn_file, export_settings, bl_object):
|
||||
"""Generates godots ConvexCollisionShape from a blender mesh object"""
|
||||
shape_rsc_key = MeshCollisionShapeKey(
|
||||
"ConvexPolygonShape", bl_object, export_settings)
|
||||
shape_id = escn_file.get_internal_resource(shape_rsc_key)
|
||||
if shape_id is not None:
|
||||
return shape_id
|
||||
|
||||
# No cached Shape found, build new one
|
||||
col_shape = None
|
||||
mesh_converter = MeshConverter(node, export_settings)
|
||||
mesh = mesh_converter.to_mesh(calculate_tangents=False)
|
||||
mesh_converter = MeshConverter(bl_object, export_settings)
|
||||
mesh = mesh_converter.to_mesh(
|
||||
triangulate=False,
|
||||
preserve_vertex_groups=False,
|
||||
calculate_tangents=False
|
||||
)
|
||||
if mesh is not None:
|
||||
vert_array = [vert.co for vert in mesh.vertices]
|
||||
col_shape = InternalResource("ConvexPolygonShape", mesh.name)
|
||||
col_shape['points'] = Array("PoolVector3Array(", values=vert_array)
|
||||
if bl_object.rigid_body.use_margin:
|
||||
col_shape['margin'] = bl_object.rigid_body.collision_margin
|
||||
|
||||
shape_id = escn_file.add_internal_resource(col_shape, shape_rsc_key)
|
||||
|
||||
mesh_converter.to_mesh_clear()
|
||||
|
||||
return shape_id
|
||||
|
||||
|
||||
def generate_concave_shape(escn_file, export_settings, bl_object):
|
||||
"""Generates godots ConcaveCollisionShape from a blender mesh object"""
|
||||
shape_rsc_key = MeshCollisionShapeKey(
|
||||
"ConcavePolygonShape", bl_object, export_settings)
|
||||
shape_id = escn_file.get_internal_resource(shape_rsc_key)
|
||||
if shape_id is not None:
|
||||
return shape_id
|
||||
|
||||
# No cached Shape found, build new one
|
||||
col_shape = None
|
||||
mesh_converter = MeshConverter(bl_object, export_settings)
|
||||
mesh = mesh_converter.to_mesh(
|
||||
triangulate=True,
|
||||
preserve_vertex_groups=False,
|
||||
calculate_tangents=False
|
||||
)
|
||||
if mesh is not None and mesh.polygons:
|
||||
vert_array = list()
|
||||
for poly in mesh.polygons:
|
||||
for vert_id in poly.vertices:
|
||||
vert_array.append(list(mesh.vertices[vert_id].co))
|
||||
|
||||
if is_convex:
|
||||
col_shape = InternalResource("ConvexPolygonShape", mesh.name)
|
||||
col_shape['points'] = Array("PoolVector3Array(", values=vert_array)
|
||||
else:
|
||||
col_shape = InternalResource("ConcavePolygonShape", mesh.name)
|
||||
col_shape['data'] = Array("PoolVector3Array(", values=vert_array)
|
||||
col_shape = InternalResource("ConcavePolygonShape", mesh.name)
|
||||
col_shape['data'] = Array("PoolVector3Array(", values=vert_array)
|
||||
|
||||
if node.rigid_body.use_margin:
|
||||
col_shape['margin'] = node.rigid_body.collision_margin
|
||||
if bl_object.rigid_body.use_margin:
|
||||
col_shape['margin'] = bl_object.rigid_body.collision_margin
|
||||
|
||||
shape_id = escn_file.add_internal_resource(col_shape, shape_rsc_key)
|
||||
|
||||
|
||||
158
io_scene_godot/converters/utils.py
Normal file
158
io_scene_godot/converters/utils.py
Normal file
@@ -0,0 +1,158 @@
|
||||
"""Util functions and structs shared by multiple resource converters"""
|
||||
|
||||
import bpy
|
||||
import bmesh
|
||||
|
||||
|
||||
def get_applicable_modifiers(obj, export_settings):
|
||||
"""Returns a list of all the modifiers that'll be applied to the final
|
||||
godot mesh"""
|
||||
ignore_modifiers = []
|
||||
if not export_settings['use_mesh_modifiers']:
|
||||
return []
|
||||
if "ARMATURE" in export_settings['object_types']:
|
||||
ignore_modifiers.append(bpy.types.ArmatureModifier)
|
||||
ignore_modifiers = tuple(ignore_modifiers)
|
||||
return [m for m in obj.modifiers if not isinstance(m, ignore_modifiers)
|
||||
and m.show_viewport]
|
||||
|
||||
|
||||
def record_modifier_config(obj):
|
||||
"""Returns modifiers viewport visibility config"""
|
||||
modifier_config_cache = []
|
||||
for mod in obj.modifiers:
|
||||
modifier_config_cache.append(mod.show_viewport)
|
||||
return modifier_config_cache
|
||||
|
||||
|
||||
def restore_modifier_config(obj, modifier_config_cache):
|
||||
"""Applies modifiers viewport visibility config"""
|
||||
for i, mod in enumerate(obj.modifiers):
|
||||
mod.show_viewport = modifier_config_cache[i]
|
||||
|
||||
|
||||
def triangulate_mesh(mesh):
|
||||
"""Triangulate a mesh"""
|
||||
tri_mesh = bmesh.new()
|
||||
tri_mesh.from_mesh(mesh)
|
||||
bmesh.ops.triangulate(
|
||||
tri_mesh, faces=tri_mesh.faces, quad_method="ALTERNATE")
|
||||
tri_mesh.to_mesh(mesh)
|
||||
tri_mesh.free()
|
||||
|
||||
mesh.update(calc_loop_triangles=True)
|
||||
|
||||
|
||||
class MeshResourceKey:
|
||||
"""Produces a key based on an mesh object's data, every different
|
||||
Mesh Resource would have a unique key"""
|
||||
|
||||
def __init__(self, rsc_type, obj, export_settings):
|
||||
mesh_data = obj.data
|
||||
|
||||
# Resource type included because same blender mesh may be used as
|
||||
# MeshResource or CollisionShape, but they are different resource
|
||||
gd_rsc_type = rsc_type
|
||||
|
||||
# Here collect info of all the modifiers applied on the mesh.
|
||||
# Modifiers along with the original mesh data would determine
|
||||
# the evaluated mesh.
|
||||
mod_info_list = list()
|
||||
for modifier in get_applicable_modifiers(obj, export_settings):
|
||||
# Modifier name indicates its type, its an identifier
|
||||
mod_info_list.append(modifier.name)
|
||||
|
||||
# First property is always 'rna_type', skip it
|
||||
for prop in modifier.bl_rna.properties.keys()[1:]:
|
||||
# Note that Property may be `BoolProperty`,
|
||||
# `CollectionProperty`, `EnumProperty`, `FloatProperty`,
|
||||
# `IntProperty`, `PointerProperty`, `StringProperty`"
|
||||
# Most of them are primary type when accessed with `getattr`,
|
||||
# so they are fine to be hashed.
|
||||
# For `PointerProperty`, it is mostly an bpy.types.ID, hash it
|
||||
# would get its python object identifier, which is also good.
|
||||
# For `CollectionProperty`, it would make more sense to
|
||||
# traversal it, however, we cut down it here to allow
|
||||
# some of mesh resource not be shared because of simplicity
|
||||
mod_info_list.append(getattr(modifier, prop))
|
||||
|
||||
self._data = tuple([mesh_data, gd_rsc_type] + mod_info_list)
|
||||
# Precalculate the hash now for better efficiency later
|
||||
self._hash = hash(self._data)
|
||||
|
||||
def __hash__(self):
|
||||
return self._hash
|
||||
|
||||
def __eq__(self, other):
|
||||
# pylint: disable=protected-access
|
||||
return (self.__class__ == other.__class__ and
|
||||
self._data == other._data)
|
||||
|
||||
|
||||
class MeshConverter:
|
||||
"""MeshConverter evaulates and converts objects to meshes, triangulates
|
||||
and calculates tangents"""
|
||||
|
||||
def __init__(self, obj, export_settings):
|
||||
self.object = obj
|
||||
self.eval_object = None
|
||||
self.use_mesh_modifiers = export_settings["use_mesh_modifiers"]
|
||||
self.use_export_shape_key = export_settings['use_export_shape_key']
|
||||
self.has_tangents = False
|
||||
|
||||
def to_mesh(self, triangulate=True, preserve_vertex_groups=True,
|
||||
calculate_tangents=True, shape_key_index=0):
|
||||
"""Evaluates object & converts to final mesh, ready for export.
|
||||
The mesh is only temporary, call to_mesh_clear() afterwards."""
|
||||
# set shape key to basis key which would have index 0
|
||||
orig_shape_key_index = self.object.active_shape_key_index
|
||||
self.object.show_only_shape_key = True
|
||||
self.object.active_shape_key_index = shape_key_index
|
||||
|
||||
self.eval_object = self.object
|
||||
|
||||
modifier_config_cache = None
|
||||
if not self.use_mesh_modifiers:
|
||||
modifier_config_cache = record_modifier_config(self.object)
|
||||
for mod in self.object.modifiers:
|
||||
mod.show_viewport = False
|
||||
|
||||
depsgraph = bpy.context.view_layer.depsgraph
|
||||
depsgraph.update()
|
||||
self.eval_object = self.object.evaluated_get(depsgraph)
|
||||
|
||||
# These parameters are required for preserving vertex groups.
|
||||
mesh = self.eval_object.to_mesh(
|
||||
preserve_all_data_layers=preserve_vertex_groups,
|
||||
depsgraph=depsgraph
|
||||
)
|
||||
|
||||
if not self.use_mesh_modifiers:
|
||||
restore_modifier_config(self.object, modifier_config_cache)
|
||||
|
||||
self.has_tangents = False
|
||||
|
||||
# mesh result can be none if the source geometry has no faces, so we
|
||||
# need to consider this if we want a robust exporter.
|
||||
if mesh is not None:
|
||||
if triangulate:
|
||||
triangulate_mesh(mesh)
|
||||
|
||||
self.has_tangents = mesh.uv_layers and mesh.polygons
|
||||
if calculate_tangents:
|
||||
if self.has_tangents:
|
||||
mesh.calc_tangents()
|
||||
else:
|
||||
mesh.calc_normals_split()
|
||||
|
||||
self.object.show_only_shape_key = False
|
||||
self.object.active_shape_key_index = orig_shape_key_index
|
||||
|
||||
return mesh
|
||||
|
||||
def to_mesh_clear(self):
|
||||
"""Clears the temporary generated mesh from memory"""
|
||||
if self.object is None:
|
||||
return
|
||||
self.eval_object.to_mesh_clear()
|
||||
self.object = self.eval_object = None
|
||||
@@ -3,7 +3,7 @@
|
||||
[sub_resource id=1 type="ConvexPolygonShape"]
|
||||
|
||||
resource_name = "Cube"
|
||||
points = PoolVector3Array(1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 4.09789, 0.999999, -1.0, 4.09789, 1.0, 0.999999, 4.09789, 1.0, 0.999999, 4.09789, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 0.999999, -1.0, 4.09789, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 4.09789, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 4.09789, 1.0, 0.999999, 4.09789, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 4.09789, -1.0, -1.0, 4.09789, 0.999999, -1.0, 4.09789, 1.0, 0.999999, 4.09789, 0.999999, -1.0, 4.09789, 1.0, -1.0, -1.0, 0.999999, -1.0, 4.09789, -1.0, -1.0, 4.09789, -1.0, -1.0, -1.0, -1.0, -1.0, 4.09789, -1.0, 1.0, 4.09789, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 4.09789)
|
||||
points = PoolVector3Array(1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 0.999999, 4.09789, 0.999999, -1.0, 4.09789, -1.0, -1.0, 4.09789, -1.0, 1.0, 4.09789)
|
||||
|
||||
[sub_resource id=2 type="ArrayMesh"]
|
||||
|
||||
@@ -27,7 +27,7 @@ surfaces/0 = {
|
||||
[sub_resource id=3 type="ConvexPolygonShape"]
|
||||
|
||||
resource_name = "Cube003"
|
||||
points = PoolVector3Array(1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 4.09789, 0.999999, -1.0, 4.09789, 1.0, 0.999999, 4.09789, 1.0, 0.999999, 4.09789, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 0.999999, -1.0, 4.09789, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 4.09789, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 4.09789, 1.0, 0.999999, 4.09789, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 4.09789, -1.0, -1.0, 4.09789, 0.999999, -1.0, 4.09789, 1.0, 0.999999, 4.09789, 0.999999, -1.0, 4.09789, 1.0, -1.0, -1.0, 0.999999, -1.0, 4.09789, -1.0, -1.0, 4.09789, -1.0, -1.0, -1.0, -1.0, -1.0, 4.09789, -1.0, 1.0, 4.09789, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 4.09789)
|
||||
points = PoolVector3Array(1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 0.999999, 4.09789, 0.999999, -1.0, 4.09789, -1.0, -1.0, 4.09789, -1.0, 1.0, 4.09789)
|
||||
|
||||
[sub_resource id=4 type="Animation"]
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
[sub_resource id=1 type="ConvexPolygonShape"]
|
||||
|
||||
resource_name = "Cube002"
|
||||
points = PoolVector3Array(-0.8, -0.8, 1.2, -0.8, 0.8, -1.2, -0.8, -0.8, -1.2, -0.8, 0.8, 1.2, 0.8, 0.8, -1.2, -0.8, 0.8, -1.2, 0.8, 0.8, 1.2, 0.8, -0.8, -1.2, 0.8, 0.8, -1.2, 0.8, -0.8, 1.2, -0.8, -0.8, -1.2, 0.8, -0.8, -1.2, 0.8, 0.8, -1.2, -0.8, -0.8, -1.2, -0.8, 0.8, -1.2, -0.8, 0.8, 1.2, 0.8, -0.8, 1.2, 0.8, 0.8, 1.2, -0.8, -0.8, 1.2, -0.8, 0.8, 1.2, -0.8, 0.8, -1.2, -0.8, 0.8, 1.2, 0.8, 0.8, 1.2, 0.8, 0.8, -1.2, 0.8, 0.8, 1.2, 0.8, -0.8, 1.2, 0.8, -0.8, -1.2, 0.8, -0.8, 1.2, -0.8, -0.8, 1.2, -0.8, -0.8, -1.2, 0.8, 0.8, -1.2, 0.8, -0.8, -1.2, -0.8, -0.8, -1.2, -0.8, 0.8, 1.2, -0.8, -0.8, 1.2, 0.8, -0.8, 1.2)
|
||||
points = PoolVector3Array(-0.8, -0.8, -1.2, -0.8, -0.8, 1.2, -0.8, 0.8, -1.2, -0.8, 0.8, 1.2, 0.8, -0.8, -1.2, 0.8, -0.8, 1.2, 0.8, 0.8, -1.2, 0.8, 0.8, 1.2)
|
||||
|
||||
[sub_resource id=2 type="ArrayMesh"]
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
[sub_resource id=1 type="ConvexPolygonShape"]
|
||||
|
||||
resource_name = "Cube002"
|
||||
points = PoolVector3Array(-4.0, 1.33333, 0.3, -4.0, 4.0, -0.3, -4.0, 1.33333, -0.3, 1.33333, 4.0, 0.3, 4.0, 4.0, -0.3, 1.33333, 4.0, -0.3, 4.0, -1.33333, 0.3, 4.0, -4.0, -0.3, 4.0, -1.33333, -0.3, -1.33333, -4.0, 0.3, -4.0, -4.0, -0.3, -1.33333, -4.0, -0.3, 4.0, -1.33333, -0.3, 1.33333, -4.0, -0.3, 1.33333, -1.33333, -0.3, -4.0, -1.33333, 0.3, -1.33333, -4.0, 0.3, -1.33333, -1.33333, 0.3, 1.33333, -1.33333, 0.3, 4.0, -4.0, 0.3, 4.0, -1.33333, 0.3, -1.33333, -1.33333, 0.3, 1.33333, -4.0, 0.3, 1.33333, -1.33333, 0.3, 1.33333, 4.0, 0.3, 4.0, 1.33333, 0.3, 4.0, 4.0, 0.3, 1.33333, 1.33333, 0.3, 4.0, -1.33333, 0.3, 4.0, 1.33333, 0.3, -1.33333, 4.0, 0.3, 1.33333, 1.33333, 0.3, 1.33333, 4.0, 0.3, -1.33333, -1.33333, -0.3, -1.33333, 1.33333, 0.3, -1.33333, -1.33333, 0.3, -4.0, 4.0, 0.3, -1.33333, 1.33333, 0.3, -1.33333, 4.0, 0.3, -4.0, 1.33333, 0.3, -1.33333, -1.33333, 0.3, -1.33333, 1.33333, 0.3, -1.33333, -1.33333, -0.3, -4.0, -4.0, -0.3, -4.0, -1.33333, -0.3, 1.33333, -1.33333, -0.3, -1.33333, -4.0, -0.3, -1.33333, -1.33333, -0.3, -1.33333, 4.0, -0.3, -4.0, 1.33333, -0.3, -4.0, 4.0, -0.3, -1.33333, 1.33333, -0.3, -4.0, -1.33333, -0.3, -4.0, 1.33333, -0.3, 1.33333, 4.0, -0.3, -1.33333, 1.33333, -0.3, -1.33333, 4.0, -0.3, 1.33333, -1.33333, -0.3, -1.33333, -1.33333, 0.3, 1.33333, -1.33333, 0.3, 4.0, 4.0, -0.3, 1.33333, 1.33333, -0.3, 1.33333, 4.0, -0.3, 4.0, 1.33333, -0.3, 1.33333, -1.33333, -0.3, 1.33333, 1.33333, -0.3, 4.0, -4.0, 0.3, 1.33333, -4.0, -0.3, 4.0, -4.0, -0.3, 1.33333, -4.0, 0.3, -1.33333, -4.0, -0.3, 1.33333, -4.0, -0.3, 4.0, 4.0, 0.3, 4.0, 1.33333, -0.3, 4.0, 4.0, -0.3, 4.0, 1.33333, 0.3, 4.0, -1.33333, -0.3, 4.0, 1.33333, -0.3, -4.0, 4.0, 0.3, -1.33333, 4.0, -0.3, -4.0, 4.0, -0.3, -1.33333, 4.0, 0.3, 1.33333, 4.0, -0.3, -1.33333, 4.0, -0.3, -4.0, -4.0, 0.3, -4.0, -1.33333, -0.3, -4.0, -4.0, -0.3, -4.0, -1.33333, 0.3, -4.0, 1.33333, -0.3, -4.0, -1.33333, -0.3, -1.33333, 1.33333, -0.3, 1.33333, 1.33333, 0.3, -1.33333, 1.33333, 0.3, 1.33333, 1.33333, -0.3, 1.33333, -1.33333, 0.3, 1.33333, 1.33333, 0.3, -4.0, 1.33333, 0.3, -4.0, 4.0, 0.3, -4.0, 4.0, -0.3, 1.33333, 4.0, 0.3, 4.0, 4.0, 0.3, 4.0, 4.0, -0.3, 4.0, -1.33333, 0.3, 4.0, -4.0, 0.3, 4.0, -4.0, -0.3, -1.33333, -4.0, 0.3, -4.0, -4.0, 0.3, -4.0, -4.0, -0.3, 4.0, -1.33333, -0.3, 4.0, -4.0, -0.3, 1.33333, -4.0, -0.3, -4.0, -1.33333, 0.3, -4.0, -4.0, 0.3, -1.33333, -4.0, 0.3, 1.33333, -1.33333, 0.3, 1.33333, -4.0, 0.3, 4.0, -4.0, 0.3, -1.33333, -1.33333, 0.3, -1.33333, -4.0, 0.3, 1.33333, -4.0, 0.3, 1.33333, 4.0, 0.3, 1.33333, 1.33333, 0.3, 4.0, 1.33333, 0.3, 1.33333, 1.33333, 0.3, 1.33333, -1.33333, 0.3, 4.0, -1.33333, 0.3, -1.33333, 4.0, 0.3, -1.33333, 1.33333, 0.3, 1.33333, 1.33333, 0.3, -1.33333, -1.33333, -0.3, -1.33333, 1.33333, -0.3, -1.33333, 1.33333, 0.3, -4.0, 4.0, 0.3, -4.0, 1.33333, 0.3, -1.33333, 1.33333, 0.3, -4.0, 1.33333, 0.3, -4.0, -1.33333, 0.3, -1.33333, -1.33333, 0.3, -1.33333, -1.33333, -0.3, -1.33333, -4.0, -0.3, -4.0, -4.0, -0.3, 1.33333, -1.33333, -0.3, 1.33333, -4.0, -0.3, -1.33333, -4.0, -0.3, -1.33333, 4.0, -0.3, -1.33333, 1.33333, -0.3, -4.0, 1.33333, -0.3, -1.33333, 1.33333, -0.3, -1.33333, -1.33333, -0.3, -4.0, -1.33333, -0.3, 1.33333, 4.0, -0.3, 1.33333, 1.33333, -0.3, -1.33333, 1.33333, -0.3, 1.33333, -1.33333, -0.3, -1.33333, -1.33333, -0.3, -1.33333, -1.33333, 0.3, 4.0, 4.0, -0.3, 4.0, 1.33333, -0.3, 1.33333, 1.33333, -0.3, 4.0, 1.33333, -0.3, 4.0, -1.33333, -0.3, 1.33333, -1.33333, -0.3, 4.0, -4.0, 0.3, 1.33333, -4.0, 0.3, 1.33333, -4.0, -0.3, 1.33333, -4.0, 0.3, -1.33333, -4.0, 0.3, -1.33333, -4.0, -0.3, 4.0, 4.0, 0.3, 4.0, 1.33333, 0.3, 4.0, 1.33333, -0.3, 4.0, 1.33333, 0.3, 4.0, -1.33333, 0.3, 4.0, -1.33333, -0.3, -4.0, 4.0, 0.3, -1.33333, 4.0, 0.3, -1.33333, 4.0, -0.3, -1.33333, 4.0, 0.3, 1.33333, 4.0, 0.3, 1.33333, 4.0, -0.3, -4.0, -4.0, 0.3, -4.0, -1.33333, 0.3, -4.0, -1.33333, -0.3, -4.0, -1.33333, 0.3, -4.0, 1.33333, 0.3, -4.0, 1.33333, -0.3, -1.33333, 1.33333, -0.3, 1.33333, 1.33333, -0.3, 1.33333, 1.33333, 0.3, 1.33333, 1.33333, -0.3, 1.33333, -1.33333, -0.3, 1.33333, -1.33333, 0.3)
|
||||
points = PoolVector3Array(-4.0, -4.0, -0.3, -4.0, -4.0, 0.3, -4.0, 4.0, -0.3, -4.0, 4.0, 0.3, 4.0, -4.0, -0.3, 4.0, -4.0, 0.3, 4.0, 4.0, -0.3, 4.0, 4.0, 0.3, -4.0, 1.33333, -0.3, -4.0, -1.33333, -0.3, -4.0, -1.33333, 0.3, -4.0, 1.33333, 0.3, 1.33333, 4.0, -0.3, -1.33333, 4.0, -0.3, -1.33333, 4.0, 0.3, 1.33333, 4.0, 0.3, 4.0, -1.33333, -0.3, 4.0, 1.33333, -0.3, 4.0, 1.33333, 0.3, 4.0, -1.33333, 0.3, -1.33333, -4.0, -0.3, 1.33333, -4.0, -0.3, 1.33333, -4.0, 0.3, -1.33333, -4.0, 0.3, 1.33333, 1.33333, 0.3, 1.33333, -1.33333, 0.3, -1.33333, 1.33333, 0.3, -1.33333, -1.33333, 0.3, -1.33333, 1.33333, -0.3, -1.33333, -1.33333, -0.3, 1.33333, 1.33333, -0.3, 1.33333, -1.33333, -0.3)
|
||||
|
||||
[sub_resource id=2 type="ArrayMesh"]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user