GLTF for game templates.

Convert GLTF Document to use ImporterMeshInstance3D.

Add a GLTFDocument extension list and an extension for converting the importer mesh instance 3d to mesh instance 3d.

Use GLTF module when the editor tools are disabled.

Modified the render server to be less restrictive on matching blend arrays and have more logging.

Misc bugs with multimesh.

Always index the meshes.
This commit is contained in:
K. S. Ernest (iFire) Lee 2021-09-20 18:24:31 -07:00
parent 84e4cfbcbe
commit 1463fc889b
40 changed files with 800 additions and 315 deletions

View file

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<class name="EditorSceneImporterMesh" inherits="Resource" version="4.0"> <class name="ImporterMesh" inherits="Resource" version="4.0">
<brief_description> <brief_description>
A [Resource] that contains vertex array-based geometry during the import process. A [Resource] that contains vertex array-based geometry during the import process.
</brief_description> </brief_description>
<description> <description>
EditorSceneImporterMesh is a type of [Resource] analogous to [ArrayMesh]. It contains vertex array-based geometry, divided in [i]surfaces[/i]. Each surface contains a completely separate array and a material used to draw it. Design wise, a mesh with multiple surfaces is preferred to a single surface, because objects created in 3D editing software commonly contain multiple materials. ImporterMesh is a type of [Resource] analogous to [ArrayMesh]. It contains vertex array-based geometry, divided in [i]surfaces[/i]. Each surface contains a completely separate array and a material used to draw it. Design wise, a mesh with multiple surfaces is preferred to a single surface, because objects created in 3D editing software commonly contain multiple materials.
Unlike its runtime counterpart, [EditorSceneImporterMesh] contains mesh data before various import steps, such as lod and shadow mesh generation, have taken place. Modify surface data by calling [method clear], followed by [method add_surface] for each surface. Unlike its runtime counterpart, [ImporterMesh] contains mesh data before various import steps, such as lod and shadow mesh generation, have taken place. Modify surface data by calling [method clear], followed by [method add_surface] for each surface.
</description> </description>
<tutorials> <tutorials>
</tutorials> </tutorials>
@ -37,7 +37,7 @@
<method name="clear"> <method name="clear">
<return type="void" /> <return type="void" />
<description> <description>
Removes all surfaces and blend shapes from this [EditorSceneImporterMesh]. Removes all surfaces and blend shapes from this [ImporterMesh].
</description> </description>
</method> </method>
<method name="get_blend_shape_count" qualifiers="const"> <method name="get_blend_shape_count" qualifiers="const">
@ -69,7 +69,7 @@
<return type="ArrayMesh" /> <return type="ArrayMesh" />
<argument index="0" name="base_mesh" type="ArrayMesh" default="null" /> <argument index="0" name="base_mesh" type="ArrayMesh" default="null" />
<description> <description>
Returns the mesh data represented by this [EditorSceneImporterMesh] as a usable [ArrayMesh]. Returns the mesh data represented by this [ImporterMesh] as a usable [ArrayMesh].
This method caches the returned mesh, and subsequent calls will return the cached data until [method clear] is called. This method caches the returned mesh, and subsequent calls will return the cached data until [method clear] is called.
If not yet cached and [code]base_mesh[/code] is provided, [code]base_mesh[/code] will be used and mutated. If not yet cached and [code]base_mesh[/code] is provided, [code]base_mesh[/code] will be used and mutated.
</description> </description>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<class name="EditorSceneImporterMeshNode3D" inherits="Node3D" version="4.0"> <class name="ImporterMeshInstance3D" inherits="Node3D" version="4.0">
<brief_description> <brief_description>
</brief_description> </brief_description>
<description> <description>
@ -7,7 +7,7 @@
<tutorials> <tutorials>
</tutorials> </tutorials>
<members> <members>
<member name="mesh" type="EditorSceneImporterMesh" setter="set_mesh" getter="get_mesh"> <member name="mesh" type="ImporterMesh" setter="set_mesh" getter="get_mesh">
</member> </member>
<member name="skeleton_path" type="NodePath" setter="set_skeleton_path" getter="get_skeleton_path" default="NodePath(&quot;&quot;)"> <member name="skeleton_path" type="NodePath" setter="set_skeleton_path" getter="get_skeleton_path" default="NodePath(&quot;&quot;)">
</member> </member>

View file

@ -49,6 +49,7 @@
#include "core/version.h" #include "core/version.h"
#include "core/version_hash.gen.h" #include "core/version_hash.gen.h"
#include "main/main.h" #include "main/main.h"
#include "scene/3d/importer_mesh_instance_3d.h"
#include "scene/gui/center_container.h" #include "scene/gui/center_container.h"
#include "scene/gui/control.h" #include "scene/gui/control.h"
#include "scene/gui/dialogs.h" #include "scene/gui/dialogs.h"
@ -113,7 +114,6 @@
#include "editor/import/resource_importer_texture_atlas.h" #include "editor/import/resource_importer_texture_atlas.h"
#include "editor/import/resource_importer_wav.h" #include "editor/import/resource_importer_wav.h"
#include "editor/import/scene_import_settings.h" #include "editor/import/scene_import_settings.h"
#include "editor/import/scene_importer_mesh_node_3d.h"
#include "editor/import_dock.h" #include "editor/import_dock.h"
#include "editor/multi_node_edit.h" #include "editor/multi_node_edit.h"
#include "editor/node_dock.h" #include "editor/node_dock.h"
@ -3852,8 +3852,6 @@ void EditorNode::register_editor_types() {
GDREGISTER_CLASS(EditorSpinSlider); GDREGISTER_CLASS(EditorSpinSlider);
GDREGISTER_CLASS(EditorResourcePicker); GDREGISTER_CLASS(EditorResourcePicker);
GDREGISTER_CLASS(EditorScriptPicker); GDREGISTER_CLASS(EditorScriptPicker);
GDREGISTER_CLASS(EditorSceneImporterMesh);
GDREGISTER_CLASS(EditorSceneImporterMeshNode3D);
GDREGISTER_VIRTUAL_CLASS(FileSystemDock); GDREGISTER_VIRTUAL_CLASS(FileSystemDock);

View file

@ -33,8 +33,8 @@
#include "core/os/os.h" #include "core/os/os.h"
#include "editor/editor_node.h" #include "editor/editor_node.h"
#include "editor/import/collada.h" #include "editor/import/collada.h"
#include "editor/import/scene_importer_mesh_node_3d.h"
#include "scene/3d/camera_3d.h" #include "scene/3d/camera_3d.h"
#include "scene/3d/importer_mesh_instance_3d.h"
#include "scene/3d/light_3d.h" #include "scene/3d/light_3d.h"
#include "scene/3d/mesh_instance_3d.h" #include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/node_3d.h" #include "scene/3d/node_3d.h"
@ -42,6 +42,7 @@
#include "scene/3d/skeleton_3d.h" #include "scene/3d/skeleton_3d.h"
#include "scene/animation/animation_player.h" #include "scene/animation/animation_player.h"
#include "scene/resources/animation.h" #include "scene/resources/animation.h"
#include "scene/resources/importer_mesh.h"
#include "scene/resources/packed_scene.h" #include "scene/resources/packed_scene.h"
#include "scene/resources/surface_tool.h" #include "scene/resources/surface_tool.h"
@ -68,7 +69,7 @@ struct ColladaImport {
Map<String, NodeMap> node_map; //map from collada node to engine node Map<String, NodeMap> node_map; //map from collada node to engine node
Map<String, String> node_name_map; //map from collada node to engine node Map<String, String> node_name_map; //map from collada node to engine node
Map<String, Ref<EditorSceneImporterMesh>> mesh_cache; Map<String, Ref<ImporterMesh>> mesh_cache;
Map<String, Ref<Curve3D>> curve_cache; Map<String, Ref<Curve3D>> curve_cache;
Map<String, Ref<Material>> material_cache; Map<String, Ref<Material>> material_cache;
Map<Collada::Node *, Skeleton3D *> skeleton_map; Map<Collada::Node *, Skeleton3D *> skeleton_map;
@ -87,7 +88,7 @@ struct ColladaImport {
Error _create_scene(Collada::Node *p_node, Node3D *p_parent); Error _create_scene(Collada::Node *p_node, Node3D *p_parent);
Error _create_resources(Collada::Node *p_node, bool p_use_compression); Error _create_resources(Collada::Node *p_node, bool p_use_compression);
Error _create_material(const String &p_target); Error _create_material(const String &p_target);
Error _create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImporterMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform3D &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<EditorSceneImporterMesh>> p_morph_meshes = Vector<Ref<EditorSceneImporterMesh>>(), bool p_use_compression = false, bool p_use_mesh_material = false); Error _create_mesh_surfaces(bool p_optimize, Ref<ImporterMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform3D &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<ImporterMesh>> p_morph_meshes = Vector<Ref<ImporterMesh>>(), bool p_use_compression = false, bool p_use_mesh_material = false);
Error load(const String &p_path, int p_flags, bool p_force_make_tangents = false, bool p_use_compression = false); Error load(const String &p_path, int p_flags, bool p_force_make_tangents = false, bool p_use_compression = false);
void _fix_param_animation_tracks(); void _fix_param_animation_tracks();
void create_animation(int p_clip, bool p_make_tracks_in_all_bones, bool p_import_value_tracks); void create_animation(int p_clip, bool p_make_tracks_in_all_bones, bool p_import_value_tracks);
@ -282,8 +283,8 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Node3D *p_parent) {
node = memnew(Path3D); node = memnew(Path3D);
} else { } else {
//mesh since nothing else //mesh since nothing else
node = memnew(EditorSceneImporterMeshNode3D); node = memnew(ImporterMeshInstance3D);
//Object::cast_to<EditorSceneImporterMeshNode3D>(node)->set_flag(GeometryInstance3D::FLAG_USE_BAKED_LIGHT, true); //Object::cast_to<ImporterMeshInstance3D>(node)->set_flag(GeometryInstance3D::FLAG_USE_BAKED_LIGHT, true);
} }
} break; } break;
case Collada::Node::TYPE_SKELETON: { case Collada::Node::TYPE_SKELETON: {
@ -457,7 +458,7 @@ Error ColladaImport::_create_material(const String &p_target) {
return OK; return OK;
} }
Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImporterMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform3D &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<EditorSceneImporterMesh>> p_morph_meshes, bool p_use_compression, bool p_use_mesh_material) { Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ImporterMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform3D &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<ImporterMesh>> p_morph_meshes, bool p_use_compression, bool p_use_mesh_material) {
bool local_xform_mirror = p_local_xform.basis.determinant() < 0; bool local_xform_mirror = p_local_xform.basis.determinant() < 0;
if (p_morph_data) { if (p_morph_data) {
@ -1087,10 +1088,10 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres
} }
} }
if (Object::cast_to<EditorSceneImporterMeshNode3D>(node)) { if (Object::cast_to<ImporterMeshInstance3D>(node)) {
Collada::NodeGeometry *ng2 = static_cast<Collada::NodeGeometry *>(p_node); Collada::NodeGeometry *ng2 = static_cast<Collada::NodeGeometry *>(p_node);
EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(node); ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(node);
ERR_FAIL_COND_V(!mi, ERR_BUG); ERR_FAIL_COND_V(!mi, ERR_BUG);
@ -1099,7 +1100,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres
String meshid; String meshid;
Transform3D apply_xform; Transform3D apply_xform;
Vector<int> bone_remap; Vector<int> bone_remap;
Vector<Ref<EditorSceneImporterMesh>> morphs; Vector<Ref<ImporterMesh>> morphs;
if (ng2->controller) { if (ng2->controller) {
String ngsource = ng2->source; String ngsource = ng2->source;
@ -1168,10 +1169,10 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres
for (int i = 0; i < names.size(); i++) { for (int i = 0; i < names.size(); i++) {
String meshid2 = names[i]; String meshid2 = names[i];
if (collada.state.mesh_data_map.has(meshid2)) { if (collada.state.mesh_data_map.has(meshid2)) {
Ref<EditorSceneImporterMesh> mesh = Ref<EditorSceneImporterMesh>(memnew(EditorSceneImporterMesh)); Ref<ImporterMesh> mesh = Ref<ImporterMesh>(memnew(ImporterMesh));
const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid2]; const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid2];
mesh->set_name(meshdata.name); mesh->set_name(meshdata.name);
Error err = _create_mesh_surfaces(false, mesh, ng2->material_map, meshdata, apply_xform, bone_remap, skin, nullptr, Vector<Ref<EditorSceneImporterMesh>>(), false); Error err = _create_mesh_surfaces(false, mesh, ng2->material_map, meshdata, apply_xform, bone_remap, skin, nullptr, Vector<Ref<ImporterMesh>>(), false);
ERR_FAIL_COND_V(err, err); ERR_FAIL_COND_V(err, err);
morphs.push_back(mesh); morphs.push_back(mesh);
@ -1194,7 +1195,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres
meshid = ng2->source; meshid = ng2->source;
} }
Ref<EditorSceneImporterMesh> mesh; Ref<ImporterMesh> mesh;
if (mesh_cache.has(meshid)) { if (mesh_cache.has(meshid)) {
mesh = mesh_cache[meshid]; mesh = mesh_cache[meshid];
} else { } else {
@ -1202,7 +1203,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres
//bleh, must ignore invalid //bleh, must ignore invalid
ERR_FAIL_COND_V(!collada.state.mesh_data_map.has(meshid), ERR_INVALID_DATA); ERR_FAIL_COND_V(!collada.state.mesh_data_map.has(meshid), ERR_INVALID_DATA);
mesh = Ref<EditorSceneImporterMesh>(memnew(EditorSceneImporterMesh)); mesh = Ref<ImporterMesh>(memnew(ImporterMesh));
const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid]; const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid];
String name = meshdata.name; String name = meshdata.name;
if (name == "") { if (name == "") {

View file

@ -33,8 +33,8 @@
#include "core/error/error_list.h" #include "core/error/error_list.h"
#include "core/error/error_macros.h" #include "core/error/error_macros.h"
#include "core/math/transform_3d.h" #include "core/math/transform_3d.h"
#include "editor/import/scene_importer_mesh_node_3d.h"
#include "resource_importer_scene.h" #include "resource_importer_scene.h"
#include "scene/3d/importer_mesh_instance_3d.h"
#include "scene/3d/mesh_instance_3d.h" #include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/node_3d.h" #include "scene/3d/node_3d.h"
#include "scene/3d/skeleton_3d.h" #include "scene/3d/skeleton_3d.h"
@ -71,7 +71,7 @@ void BakeReset::_bake_animation_pose(Node *scene, const String &p_bake_anim) {
while (!queue.is_empty()) { while (!queue.is_empty()) {
List<Node *>::Element *E = queue.front(); List<Node *>::Element *E = queue.front();
Node *node = E->get(); Node *node = E->get();
EditorSceneImporterMeshNode3D *editor_mesh_3d = scene->cast_to<EditorSceneImporterMeshNode3D>(node); ImporterMeshInstance3D *editor_mesh_3d = scene->cast_to<ImporterMeshInstance3D>(node);
MeshInstance3D *mesh_3d = scene->cast_to<MeshInstance3D>(node); MeshInstance3D *mesh_3d = scene->cast_to<MeshInstance3D>(node);
if (scene->cast_to<Skeleton3D>(node)) { if (scene->cast_to<Skeleton3D>(node)) {
Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(node); Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(node);

View file

@ -32,10 +32,10 @@
#include "core/io/file_access.h" #include "core/io/file_access.h"
#include "core/io/resource_saver.h" #include "core/io/resource_saver.h"
#include "editor/import/scene_importer_mesh.h" #include "scene/3d/importer_mesh_instance_3d.h"
#include "editor/import/scene_importer_mesh_node_3d.h"
#include "scene/3d/mesh_instance_3d.h" #include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/node_3d.h" #include "scene/3d/node_3d.h"
#include "scene/resources/importer_mesh.h"
#include "scene/resources/mesh.h" #include "scene/resources/mesh.h"
#include "scene/resources/surface_tool.h" #include "scene/resources/surface_tool.h"
@ -439,13 +439,13 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
Node3D *scene = memnew(Node3D); Node3D *scene = memnew(Node3D);
for (const Ref<Mesh> &m : meshes) { for (const Ref<Mesh> &m : meshes) {
Ref<EditorSceneImporterMesh> mesh; Ref<ImporterMesh> mesh;
mesh.instantiate(); mesh.instantiate();
for (int i = 0; i < m->get_surface_count(); i++) { for (int i = 0; i < m->get_surface_count(); i++) {
mesh->add_surface(m->surface_get_primitive_type(i), m->surface_get_arrays(i), Array(), Dictionary(), m->surface_get_material(i)); mesh->add_surface(m->surface_get_primitive_type(i), m->surface_get_arrays(i), Array(), Dictionary(), m->surface_get_material(i));
} }
EditorSceneImporterMeshNode3D *mi = memnew(EditorSceneImporterMeshNode3D); ImporterMeshInstance3D *mi = memnew(ImporterMeshInstance3D);
mi->set_mesh(mesh); mi->set_mesh(mesh);
mi->set_name(m->get_name()); mi->set_name(m->get_name());
scene->add_child(mi); scene->add_child(mi);

View file

@ -34,9 +34,9 @@
#include "editor/editor_node.h" #include "editor/editor_node.h"
#include "editor/import/editor_importer_bake_reset.h" #include "editor/import/editor_importer_bake_reset.h"
#include "editor/import/scene_import_settings.h" #include "editor/import/scene_import_settings.h"
#include "editor/import/scene_importer_mesh_node_3d.h"
#include "scene/3d/area_3d.h" #include "scene/3d/area_3d.h"
#include "scene/3d/collision_shape_3d.h" #include "scene/3d/collision_shape_3d.h"
#include "scene/3d/importer_mesh_instance_3d.h"
#include "scene/3d/mesh_instance_3d.h" #include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/navigation_region_3d.h" #include "scene/3d/navigation_region_3d.h"
#include "scene/3d/physics_body_3d.h" #include "scene/3d/physics_body_3d.h"
@ -44,6 +44,7 @@
#include "scene/animation/animation_player.h" #include "scene/animation/animation_player.h"
#include "scene/resources/animation.h" #include "scene/resources/animation.h"
#include "scene/resources/box_shape_3d.h" #include "scene/resources/box_shape_3d.h"
#include "scene/resources/importer_mesh.h"
#include "scene/resources/packed_scene.h" #include "scene/resources/packed_scene.h"
#include "scene/resources/resource_format_text.h" #include "scene/resources/resource_format_text.h"
#include "scene/resources/separation_ray_shape_3d.h" #include "scene/resources/separation_ray_shape_3d.h"
@ -233,7 +234,7 @@ static String _fixstr(const String &p_what, const String &p_str) {
return what; return what;
} }
static void _pre_gen_shape_list(Ref<EditorSceneImporterMesh> &mesh, Vector<Ref<Shape3D>> &r_shape_list, bool p_convex) { static void _pre_gen_shape_list(Ref<ImporterMesh> &mesh, Vector<Ref<Shape3D>> &r_shape_list, bool p_convex) {
ERR_FAIL_NULL_MSG(mesh, "Cannot generate shape list with null mesh value"); ERR_FAIL_NULL_MSG(mesh, "Cannot generate shape list with null mesh value");
if (!p_convex) { if (!p_convex) {
Ref<Shape3D> shape = mesh->create_trimesh_shape(); Ref<Shape3D> shape = mesh->create_trimesh_shape();
@ -249,7 +250,7 @@ static void _pre_gen_shape_list(Ref<EditorSceneImporterMesh> &mesh, Vector<Ref<S
} }
} }
Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> &collision_map) { Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map) {
// children first // children first
for (int i = 0; i < p_node->get_child_count(); i++) { for (int i = 0; i < p_node->get_child_count(); i++) {
Node *r = _pre_fix_node(p_node->get_child(i), p_root, collision_map); Node *r = _pre_fix_node(p_node->get_child(i), p_root, collision_map);
@ -267,10 +268,10 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E
return nullptr; return nullptr;
} }
if (Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) { if (Object::cast_to<ImporterMeshInstance3D>(p_node)) {
EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(p_node);
Ref<EditorSceneImporterMesh> m = mi->get_mesh(); Ref<ImporterMesh> m = mi->get_mesh();
if (m.is_valid()) { if (m.is_valid()) {
for (int i = 0; i < m->get_surface_count(); i++) { for (int i = 0; i < m->get_surface_count(); i++) {
@ -331,9 +332,9 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E
if (isroot) { if (isroot) {
return p_node; return p_node;
} }
EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(p_node);
if (mi) { if (mi) {
Ref<EditorSceneImporterMesh> mesh = mi->get_mesh(); Ref<ImporterMesh> mesh = mi->get_mesh();
if (mesh.is_valid()) { if (mesh.is_valid()) {
Vector<Ref<Shape3D>> shapes; Vector<Ref<Shape3D>> shapes;
@ -398,13 +399,13 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E
colshape->set_owner(sb->get_owner()); colshape->set_owner(sb->get_owner());
} }
} else if (_teststr(name, "rigid") && Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) { } else if (_teststr(name, "rigid") && Object::cast_to<ImporterMeshInstance3D>(p_node)) {
if (isroot) { if (isroot) {
return p_node; return p_node;
} }
EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(p_node);
Ref<EditorSceneImporterMesh> mesh = mi->get_mesh(); Ref<ImporterMesh> mesh = mi->get_mesh();
if (mesh.is_valid()) { if (mesh.is_valid()) {
Vector<Ref<Shape3D>> shapes; Vector<Ref<Shape3D>> shapes;
@ -426,10 +427,10 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E
_add_shapes(rigid_body, shapes); _add_shapes(rigid_body, shapes);
} }
} else if ((_teststr(name, "col") || (_teststr(name, "convcol"))) && Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) { } else if ((_teststr(name, "col") || (_teststr(name, "convcol"))) && Object::cast_to<ImporterMeshInstance3D>(p_node)) {
EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(p_node);
Ref<EditorSceneImporterMesh> mesh = mi->get_mesh(); Ref<ImporterMesh> mesh = mi->get_mesh();
if (mesh.is_valid()) { if (mesh.is_valid()) {
Vector<Ref<Shape3D>> shapes; Vector<Ref<Shape3D>> shapes;
@ -465,14 +466,14 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E
} }
} }
} else if (_teststr(name, "navmesh") && Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) { } else if (_teststr(name, "navmesh") && Object::cast_to<ImporterMeshInstance3D>(p_node)) {
if (isroot) { if (isroot) {
return p_node; return p_node;
} }
EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(p_node);
Ref<EditorSceneImporterMesh> mesh = mi->get_mesh(); Ref<ImporterMesh> mesh = mi->get_mesh();
ERR_FAIL_COND_V(mesh.is_null(), nullptr); ERR_FAIL_COND_V(mesh.is_null(), nullptr);
NavigationRegion3D *nmi = memnew(NavigationRegion3D); NavigationRegion3D *nmi = memnew(NavigationRegion3D);
@ -484,12 +485,12 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E
memdelete(p_node); memdelete(p_node);
p_node = nmi; p_node = nmi;
} else if (Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) { } else if (Object::cast_to<ImporterMeshInstance3D>(p_node)) {
//last attempt, maybe collision inside the mesh data //last attempt, maybe collision inside the mesh data
EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(p_node);
Ref<EditorSceneImporterMesh> mesh = mi->get_mesh(); Ref<ImporterMesh> mesh = mi->get_mesh();
if (!mesh.is_null()) { if (!mesh.is_null()) {
Vector<Ref<Shape3D>> shapes; Vector<Ref<Shape3D>> shapes;
if (collision_map.has(mesh)) { if (collision_map.has(mesh)) {
@ -517,7 +518,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E
return p_node; return p_node;
} }
Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Set<Ref<EditorSceneImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps) { Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Set<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps) {
// children first // children first
for (int i = 0; i < p_node->get_child_count(); i++) { for (int i = 0; i < p_node->get_child_count(); i++) {
Node *r = _post_fix_node(p_node->get_child(i), p_root, collision_map, r_scanned_meshes, p_node_data, p_material_data, p_animation_data, p_animation_fps); Node *r = _post_fix_node(p_node->get_child(i), p_root, collision_map, r_scanned_meshes, p_node_data, p_material_data, p_animation_data, p_animation_fps);
@ -546,10 +547,10 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<
return nullptr; return nullptr;
} }
if (Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) { if (Object::cast_to<ImporterMeshInstance3D>(p_node)) {
EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(p_node);
Ref<EditorSceneImporterMesh> m = mi->get_mesh(); Ref<ImporterMesh> m = mi->get_mesh();
if (m.is_valid()) { if (m.is_valid()) {
if (!r_scanned_meshes.has(m)) { if (!r_scanned_meshes.has(m)) {
@ -669,10 +670,10 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<
} }
//navmesh (node may have changed type above) //navmesh (node may have changed type above)
if (Object::cast_to<EditorSceneImporterMeshNode3D>(p_node)) { if (Object::cast_to<ImporterMeshInstance3D>(p_node)) {
EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(p_node);
Ref<EditorSceneImporterMesh> m = mi->get_mesh(); Ref<ImporterMesh> m = mi->get_mesh();
if (m.is_valid()) { if (m.is_valid()) {
if (node_settings.has("generate/navmesh")) { if (node_settings.has("generate/navmesh")) {
@ -1247,7 +1248,7 @@ Ref<Animation> ResourceImporterScene::import_animation_from_other_importer(Edito
} }
void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_mesh_data, bool p_generate_lods, bool p_create_shadow_meshes, LightBakeMode p_light_bake_mode, float p_lightmap_texel_size, const Vector<uint8_t> &p_src_lightmap_cache, Vector<Vector<uint8_t>> &r_lightmap_caches) { void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_mesh_data, bool p_generate_lods, bool p_create_shadow_meshes, LightBakeMode p_light_bake_mode, float p_lightmap_texel_size, const Vector<uint8_t> &p_src_lightmap_cache, Vector<Vector<uint8_t>> &r_lightmap_caches) {
EditorSceneImporterMeshNode3D *src_mesh_node = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); ImporterMeshInstance3D *src_mesh_node = Object::cast_to<ImporterMeshInstance3D>(p_node);
if (src_mesh_node) { if (src_mesh_node) {
//is mesh //is mesh
MeshInstance3D *mesh_node = memnew(MeshInstance3D); MeshInstance3D *mesh_node = memnew(MeshInstance3D);
@ -1452,7 +1453,7 @@ Node *ResourceImporterScene::pre_import(const String &p_source_file) {
return nullptr; return nullptr;
} }
Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> collision_map; Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> collision_map;
_pre_fix_node(scene, scene, collision_map); _pre_fix_node(scene, scene, collision_map);
@ -1527,8 +1528,8 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
animation_data = subresources["animations"]; animation_data = subresources["animations"];
} }
Set<Ref<EditorSceneImporterMesh>> scanned_meshes; Set<Ref<ImporterMesh>> scanned_meshes;
Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> collision_map; Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> collision_map;
_pre_fix_node(scene, scene, collision_map); _pre_fix_node(scene, scene, collision_map);
_post_fix_node(scene, scene, collision_map, scanned_meshes, node_data, material_data, animation_data, fps); _post_fix_node(scene, scene, collision_map, scanned_meshes, node_data, material_data, animation_data, fps);

View file

@ -41,7 +41,7 @@
class Material; class Material;
class AnimationPlayer; class AnimationPlayer;
class EditorSceneImporterMesh; class ImporterMesh;
class EditorSceneImporter : public RefCounted { class EditorSceneImporter : public RefCounted {
GDCLASS(EditorSceneImporter, RefCounted); GDCLASS(EditorSceneImporter, RefCounted);
@ -181,8 +181,8 @@ public:
// Import scenes *after* everything else (such as textures). // Import scenes *after* everything else (such as textures).
virtual int get_import_order() const override { return ResourceImporter::IMPORT_ORDER_SCENE; } virtual int get_import_order() const override { return ResourceImporter::IMPORT_ORDER_SCENE; }
Node *_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> &collision_map); Node *_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map);
Node *_post_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Set<Ref<EditorSceneImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps); Node *_post_fix_node(Node *p_node, Node *p_root, Map<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Set<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps);
Ref<Animation> _save_animation_to_file(Ref<Animation> anim, bool p_save_to_file, String p_save_to_path, bool p_keep_custom_tracks); Ref<Animation> _save_animation_to_file(Ref<Animation> anim, bool p_save_to_file, String p_save_to_path, bool p_keep_custom_tracks);
void _create_clips(AnimationPlayer *anim, const Array &p_clips, bool p_bake_all); void _create_clips(AnimationPlayer *anim, const Array &p_clips, bool p_bake_all);

View file

@ -31,7 +31,8 @@
#include "scene_import_settings.h" #include "scene_import_settings.h"
#include "editor/editor_node.h" #include "editor/editor_node.h"
#include "editor/editor_scale.h" #include "editor/editor_scale.h"
#include "editor/import/scene_importer_mesh_node_3d.h" #include "scene/3d/importer_mesh_instance_3d.h"
#include "scene/resources/importer_mesh.h"
#include "scene/resources/surface_tool.h" #include "scene/resources/surface_tool.h"
class SceneImportSettingsData : public Object { class SceneImportSettingsData : public Object {
@ -240,7 +241,7 @@ void SceneImportSettings::_fill_scene(Node *p_node, TreeItem *p_parent_item) {
p_node->set_meta("import_id", import_id); p_node->set_meta("import_id", import_id);
} }
EditorSceneImporterMeshNode3D *src_mesh_node = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); ImporterMeshInstance3D *src_mesh_node = Object::cast_to<ImporterMeshInstance3D>(p_node);
if (src_mesh_node) { if (src_mesh_node) {
MeshInstance3D *mesh_node = memnew(MeshInstance3D); MeshInstance3D *mesh_node = memnew(MeshInstance3D);
@ -249,7 +250,7 @@ void SceneImportSettings::_fill_scene(Node *p_node, TreeItem *p_parent_item) {
mesh_node->set_skin(src_mesh_node->get_skin()); mesh_node->set_skin(src_mesh_node->get_skin());
mesh_node->set_skeleton_path(src_mesh_node->get_skeleton_path()); mesh_node->set_skeleton_path(src_mesh_node->get_skeleton_path());
if (src_mesh_node->get_mesh().is_valid()) { if (src_mesh_node->get_mesh().is_valid()) {
Ref<EditorSceneImporterMesh> editor_mesh = src_mesh_node->get_mesh(); Ref<ImporterMesh> editor_mesh = src_mesh_node->get_mesh();
mesh_node->set_mesh(editor_mesh->get_mesh()); mesh_node->set_mesh(editor_mesh->get_mesh());
} }

View file

@ -31,6 +31,7 @@
#include "fbx_mesh_data.h" #include "fbx_mesh_data.h"
#include "core/templates/local_vector.h" #include "core/templates/local_vector.h"
#include "scene/resources/importer_mesh.h"
#include "scene/resources/mesh.h" #include "scene/resources/mesh.h"
#include "scene/resources/surface_tool.h" #include "scene/resources/surface_tool.h"
@ -101,7 +102,7 @@ HashMap<int, Vector2> collect_uv(const Vector<VertexData<Vector2>> *p_data, Hash
return collection; return collection;
} }
EditorSceneImporterMeshNode3D *FBXMeshData::create_fbx_mesh(const ImportState &state, const FBXDocParser::MeshGeometry *p_mesh_geometry, const FBXDocParser::Model *model, bool use_compression) { ImporterMeshInstance3D *FBXMeshData::create_fbx_mesh(const ImportState &state, const FBXDocParser::MeshGeometry *p_mesh_geometry, const FBXDocParser::Model *model, bool use_compression) {
mesh_geometry = p_mesh_geometry; mesh_geometry = p_mesh_geometry;
// todo: make this just use a uint64_t FBX ID this is a copy of our original materials unfortunately. // todo: make this just use a uint64_t FBX ID this is a copy of our original materials unfortunately.
const std::vector<const FBXDocParser::Material *> &material_lookup = model->GetMaterials(); const std::vector<const FBXDocParser::Material *> &material_lookup = model->GetMaterials();
@ -344,7 +345,7 @@ EditorSceneImporterMeshNode3D *FBXMeshData::create_fbx_mesh(const ImportState &s
} }
// Phase 6. Compose the mesh and return it. // Phase 6. Compose the mesh and return it.
Ref<EditorSceneImporterMesh> mesh; Ref<ImporterMesh> mesh;
mesh.instantiate(); mesh.instantiate();
// Add blend shape info. // Add blend shape info.
@ -380,7 +381,7 @@ EditorSceneImporterMeshNode3D *FBXMeshData::create_fbx_mesh(const ImportState &s
in_mesh_surface_id += 1; in_mesh_surface_id += 1;
} }
EditorSceneImporterMeshNode3D *godot_mesh = memnew(EditorSceneImporterMeshNode3D); ImporterMeshInstance3D *godot_mesh = memnew(ImporterMeshInstance3D);
godot_mesh->set_mesh(mesh); godot_mesh->set_mesh(mesh);
const String name = ImportUtils::FBXNodeToName(model->Name()); const String name = ImportUtils::FBXNodeToName(model->Name());
godot_mesh->set_name(name); // hurry up compiling >.< godot_mesh->set_name(name); // hurry up compiling >.<

View file

@ -35,7 +35,7 @@
#include "core/templates/local_vector.h" #include "core/templates/local_vector.h"
#include "core/templates/ordered_hash_map.h" #include "core/templates/ordered_hash_map.h"
#include "editor/import/resource_importer_scene.h" #include "editor/import/resource_importer_scene.h"
#include "editor/import/scene_importer_mesh_node_3d.h" #include "scene/3d/importer_mesh_instance_3d.h"
#include "scene/3d/mesh_instance_3d.h" #include "scene/3d/mesh_instance_3d.h"
#include "scene/resources/surface_tool.h" #include "scene/resources/surface_tool.h"
@ -98,7 +98,7 @@ struct FBXMeshData : RefCounted {
// translate fbx mesh data from document context to FBX Mesh Geometry Context // translate fbx mesh data from document context to FBX Mesh Geometry Context
bool valid_weight_indexes = false; bool valid_weight_indexes = false;
EditorSceneImporterMeshNode3D *create_fbx_mesh(const ImportState &state, const FBXDocParser::MeshGeometry *p_mesh_geometry, const FBXDocParser::Model *model, bool use_compression); ImporterMeshInstance3D *create_fbx_mesh(const ImportState &state, const FBXDocParser::MeshGeometry *p_mesh_geometry, const FBXDocParser::Model *model, bool use_compression);
void gen_weight_info(Ref<SurfaceTool> st, int vertex_id) const; void gen_weight_info(Ref<SurfaceTool> st, int vertex_id) const;
@ -107,7 +107,7 @@ struct FBXMeshData : RefCounted {
int max_weight_count = 0; int max_weight_count = 0;
uint64_t armature_id = 0; uint64_t armature_id = 0;
bool valid_armature_id = false; bool valid_armature_id = false;
EditorSceneImporterMeshNode3D *godot_mesh_instance = nullptr; ImporterMeshInstance3D *godot_mesh_instance = nullptr;
private: private:
void sanitize_vertex_weights(const ImportState &state); void sanitize_vertex_weights(const ImportState &state);

View file

@ -40,9 +40,9 @@
#include "editor/editor_log.h" #include "editor/editor_log.h"
#include "editor/editor_node.h" #include "editor/editor_node.h"
#include "editor/import/resource_importer_scene.h" #include "editor/import/resource_importer_scene.h"
#include "editor/import/scene_importer_mesh_node_3d.h"
#include "scene/3d/bone_attachment_3d.h" #include "scene/3d/bone_attachment_3d.h"
#include "scene/3d/camera_3d.h" #include "scene/3d/camera_3d.h"
#include "scene/3d/importer_mesh_instance_3d.h"
#include "scene/3d/light_3d.h" #include "scene/3d/light_3d.h"
#include "scene/main/node.h" #include "scene/main/node.h"
#include "scene/resources/material.h" #include "scene/resources/material.h"
@ -627,7 +627,7 @@ Node3D *EditorSceneImporterFBX::_generate_scene(
node_element; node_element;
node_element = node_element->next()) { node_element = node_element->next()) {
Ref<FBXNode> fbx_node = node_element->get(); Ref<FBXNode> fbx_node = node_element->get();
EditorSceneImporterMeshNode3D *mesh_node = nullptr; ImporterMeshInstance3D *mesh_node = nullptr;
Ref<FBXMeshData> mesh_data_precached; Ref<FBXMeshData> mesh_data_precached;
// check for valid geometry // check for valid geometry
@ -768,7 +768,7 @@ Node3D *EditorSceneImporterFBX::_generate_scene(
for (KeyValue<uint64_t, Ref<FBXMeshData>> &mesh_data : state.renderer_mesh_data) { for (KeyValue<uint64_t, Ref<FBXMeshData>> &mesh_data : state.renderer_mesh_data) {
Ref<FBXMeshData> mesh = mesh_data.value; Ref<FBXMeshData> mesh = mesh_data.value;
const uint64_t mesh_id = mesh_data.key; const uint64_t mesh_id = mesh_data.key;
EditorSceneImporterMeshNode3D *mesh_instance = mesh->godot_mesh_instance; ImporterMeshInstance3D *mesh_instance = mesh->godot_mesh_instance;
const int mesh_weights = mesh->max_weight_count; const int mesh_weights = mesh->max_weight_count;
Ref<FBXSkeleton> skeleton; Ref<FBXSkeleton> skeleton;
const bool valid_armature = mesh->valid_armature_id; const bool valid_armature = mesh->valid_armature_id;

View file

@ -1,5 +1,5 @@
def can_build(env, platform): def can_build(env, platform):
return env["tools"] and not env["disable_3d"] return not env["disable_3d"]
def configure(env): def configure(env):
@ -22,6 +22,8 @@ def get_doc_classes():
"GLTFSpecGloss", "GLTFSpecGloss",
"GLTFState", "GLTFState",
"GLTFTexture", "GLTFTexture",
"GLTFDocumentExtension",
"GLTFDocumentExtensionConvertImporterMesh",
] ]

View file

@ -30,4 +30,8 @@
</description> </description>
</method> </method>
</methods> </methods>
<members>
<member name="extensions" type="GLTFDocumentExtension[]" setter="set_extensions" getter="get_extensions" default="[Object(GLTFDocumentExtensionConvertImporterMesh,&quot;resource_local_to_scene&quot;:false,&quot;resource_name&quot;:&quot;&quot;,&quot;script&quot;:null)]">
</member>
</members>
</class> </class>

View file

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="GLTFDocumentExtension" inherits="Resource" version="4.0">
<brief_description>
</brief_description>
<description>
</description>
<tutorials>
</tutorials>
<methods>
<method name="export_post">
<return type="int" enum="Error" />
<argument index="0" name="document" type="GLTFDocument" />
<description>
</description>
</method>
<method name="export_preflight">
<return type="int" enum="Error" />
<argument index="0" name="document" type="GLTFDocument" />
<argument index="1" name="node" type="Node" />
<description>
</description>
</method>
<method name="get_export_setting" qualifiers="const">
<return type="Variant" />
<argument index="0" name="key" type="StringName" />
<description>
</description>
</method>
<method name="get_export_setting_keys" qualifiers="const">
<return type="Array" />
<description>
</description>
</method>
<method name="get_import_setting" qualifiers="const">
<return type="Variant" />
<argument index="0" name="key" type="StringName" />
<description>
</description>
</method>
<method name="get_import_setting_keys" qualifiers="const">
<return type="Array" />
<description>
</description>
</method>
<method name="import_post">
<return type="int" enum="Error" />
<argument index="0" name="document" type="GLTFDocument" />
<argument index="1" name="node" type="Node" />
<description>
</description>
</method>
<method name="import_preflight">
<return type="int" enum="Error" />
<argument index="0" name="document" type="GLTFDocument" />
<description>
</description>
</method>
<method name="set_export_setting">
<return type="void" />
<argument index="0" name="key" type="StringName" />
<argument index="1" name="value" type="Variant" />
<description>
</description>
</method>
<method name="set_import_setting">
<return type="void" />
<argument index="0" name="key" type="StringName" />
<argument index="1" name="value" type="Variant" />
<description>
</description>
</method>
</methods>
</class>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="GLTFDocumentExtensionConvertImporterMesh" inherits="GLTFDocumentExtension" version="4.0">
<brief_description>
</brief_description>
<description>
</description>
<tutorials>
</tutorials>
</class>

View file

@ -9,7 +9,7 @@
<members> <members>
<member name="blend_weights" type="PackedFloat32Array" setter="set_blend_weights" getter="get_blend_weights" default="PackedFloat32Array()"> <member name="blend_weights" type="PackedFloat32Array" setter="set_blend_weights" getter="get_blend_weights" default="PackedFloat32Array()">
</member> </member>
<member name="mesh" type="EditorSceneImporterMesh" setter="set_mesh" getter="get_mesh"> <member name="mesh" type="ImporterMesh" setter="set_mesh" getter="get_mesh">
</member> </member>
</members> </members>
</class> </class>

View file

@ -28,6 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/ /*************************************************************************/
#if TOOLS_ENABLED
#include "editor_scene_exporter_gltf_plugin.h" #include "editor_scene_exporter_gltf_plugin.h"
#include "core/config/project_settings.h" #include "core/config/project_settings.h"
#include "core/error/error_list.h" #include "core/error/error_list.h"
@ -93,3 +94,5 @@ void SceneExporterGLTFPlugin::convert_scene_to_gltf2() {
file_export_lib->set_current_file(filename + String(".gltf")); file_export_lib->set_current_file(filename + String(".gltf"));
file_export_lib->popup_centered_ratio(); file_export_lib->popup_centered_ratio();
} }
#endif // TOOLS_ENABLED

View file

@ -31,7 +31,9 @@
#ifndef EDITOR_SCENE_EXPORTER_GLTF_PLUGIN_H #ifndef EDITOR_SCENE_EXPORTER_GLTF_PLUGIN_H
#define EDITOR_SCENE_EXPORTER_GLTF_PLUGIN_H #define EDITOR_SCENE_EXPORTER_GLTF_PLUGIN_H
#if TOOLS_ENABLED
#include "editor/editor_plugin.h" #include "editor/editor_plugin.h"
#include "editor_scene_importer_gltf.h" #include "editor_scene_importer_gltf.h"
class SceneExporterGLTFPlugin : public EditorPlugin { class SceneExporterGLTFPlugin : public EditorPlugin {
@ -47,5 +49,5 @@ public:
bool has_main_screen() const override; bool has_main_screen() const override;
SceneExporterGLTFPlugin(class EditorNode *p_node); SceneExporterGLTFPlugin(class EditorNode *p_node);
}; };
#endif // TOOLS_ENABLED
#endif // EDITOR_SCENE_EXPORTER_GLTF_PLUGIN_H #endif // EDITOR_SCENE_EXPORTER_GLTF_PLUGIN_H

View file

@ -28,6 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/ /*************************************************************************/
#if TOOLS_ENABLED
#include "editor_scene_importer_gltf.h" #include "editor_scene_importer_gltf.h"
#include "gltf_document.h" #include "gltf_document.h"
@ -60,3 +61,5 @@ Ref<Animation> EditorSceneImporterGLTF::import_animation(const String &p_path,
int p_bake_fps) { int p_bake_fps) {
return Ref<Animation>(); return Ref<Animation>();
} }
#endif // TOOLS_ENABLED

View file

@ -30,16 +30,17 @@
#ifndef EDITOR_SCENE_IMPORTER_GLTF_H #ifndef EDITOR_SCENE_IMPORTER_GLTF_H
#define EDITOR_SCENE_IMPORTER_GLTF_H #define EDITOR_SCENE_IMPORTER_GLTF_H
#ifdef TOOLS_ENABLED
#include "gltf_state.h" #include "gltf_state.h"
#include "gltf_document_extension.h"
#include "editor/import/resource_importer_scene.h" #include "editor/import/resource_importer_scene.h"
#include "scene/main/node.h" #include "scene/main/node.h"
#include "scene/resources/packed_scene.h" #include "scene/resources/packed_scene.h"
class Animation; class Animation;
#ifdef TOOLS_ENABLED
class EditorSceneImporterGLTF : public EditorSceneImporter { class EditorSceneImporterGLTF : public EditorSceneImporter {
GDCLASS(EditorSceneImporterGLTF, EditorSceneImporter); GDCLASS(EditorSceneImporterGLTF, EditorSceneImporter);
@ -50,5 +51,5 @@ public:
virtual Ref<Animation> import_animation(const String &p_path, virtual Ref<Animation> import_animation(const String &p_path,
uint32_t p_flags, int p_bake_fps) override; uint32_t p_flags, int p_bake_fps) override;
}; };
#endif #endif // TOOLS_ENABLED
#endif // EDITOR_SCENE_IMPORTER_GLTF_H #endif // EDITOR_SCENE_IMPORTER_GLTF_H

View file

@ -30,6 +30,8 @@
#include "gltf_accessor.h" #include "gltf_accessor.h"
#include "gltf_document_extension.h"
void GLTFAccessor::_bind_methods() { void GLTFAccessor::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_buffer_view"), &GLTFAccessor::get_buffer_view); ClassDB::bind_method(D_METHOD("get_buffer_view"), &GLTFAccessor::get_buffer_view);
ClassDB::bind_method(D_METHOD("set_buffer_view", "buffer_view"), &GLTFAccessor::set_buffer_view); ClassDB::bind_method(D_METHOD("set_buffer_view", "buffer_view"), &GLTFAccessor::set_buffer_view);

View file

@ -32,7 +32,9 @@
#define GLTF_ACCESSOR_H #define GLTF_ACCESSOR_H
#include "core/io/resource.h" #include "core/io/resource.h"
#include "gltf_document.h" #include "gltf_document.h"
#include "gltf_document_extension.h"
struct GLTFAccessor : public Resource { struct GLTFAccessor : public Resource {
GDCLASS(GLTFAccessor, Resource); GDCLASS(GLTFAccessor, Resource);

View file

@ -30,6 +30,8 @@
#include "gltf_buffer_view.h" #include "gltf_buffer_view.h"
#include "gltf_document_extension.h"
void GLTFBufferView::_bind_methods() { void GLTFBufferView::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_buffer"), &GLTFBufferView::get_buffer); ClassDB::bind_method(D_METHOD("get_buffer"), &GLTFBufferView::get_buffer);
ClassDB::bind_method(D_METHOD("set_buffer", "buffer"), &GLTFBufferView::set_buffer); ClassDB::bind_method(D_METHOD("set_buffer", "buffer"), &GLTFBufferView::set_buffer);

View file

@ -33,6 +33,8 @@
#include "gltf_accessor.h" #include "gltf_accessor.h"
#include "gltf_animation.h" #include "gltf_animation.h"
#include "gltf_camera.h" #include "gltf_camera.h"
#include "gltf_document_extension.h"
#include "gltf_document_extension_convert_importer_mesh.h"
#include "gltf_light.h" #include "gltf_light.h"
#include "gltf_mesh.h" #include "gltf_mesh.h"
#include "gltf_node.h" #include "gltf_node.h"
@ -49,6 +51,7 @@
#include "core/io/json.h" #include "core/io/json.h"
#include "core/math/disjoint_set.h" #include "core/math/disjoint_set.h"
#include "core/math/vector2.h" #include "core/math/vector2.h"
#include "core/variant/dictionary.h"
#include "core/variant/typed_array.h" #include "core/variant/typed_array.h"
#include "core/variant/variant.h" #include "core/variant/variant.h"
#include "core/version.h" #include "core/version.h"
@ -57,8 +60,12 @@
#include "editor/import/resource_importer_scene.h" #include "editor/import/resource_importer_scene.h"
#include "scene/2d/node_2d.h" #include "scene/2d/node_2d.h"
#include "scene/3d/camera_3d.h" #include "scene/3d/camera_3d.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/multimesh_instance_3d.h" #include "scene/3d/multimesh_instance_3d.h"
#include "scene/animation/animation_player.h" #include "scene/animation/animation_player.h"
#include "scene/resources/importer_mesh.h"
#include "scene/resources/mesh.h"
#include "scene/resources/multimesh.h"
#include "scene/resources/surface_tool.h" #include "scene/resources/surface_tool.h"
#include "modules/modules_enabled.gen.h" #include "modules/modules_enabled.gen.h"
@ -2101,7 +2108,7 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
Array meshes; Array meshes;
for (GLTFMeshIndex gltf_mesh_i = 0; gltf_mesh_i < state->meshes.size(); gltf_mesh_i++) { for (GLTFMeshIndex gltf_mesh_i = 0; gltf_mesh_i < state->meshes.size(); gltf_mesh_i++) {
print_verbose("glTF: Serializing mesh: " + itos(gltf_mesh_i)); print_verbose("glTF: Serializing mesh: " + itos(gltf_mesh_i));
Ref<EditorSceneImporterMesh> import_mesh = state->meshes.write[gltf_mesh_i]->get_mesh(); Ref<ImporterMesh> import_mesh = state->meshes.write[gltf_mesh_i]->get_mesh();
if (import_mesh.is_null()) { if (import_mesh.is_null()) {
continue; continue;
} }
@ -2493,7 +2500,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
Array primitives = d["primitives"]; Array primitives = d["primitives"];
const Dictionary &extras = d.has("extras") ? (Dictionary)d["extras"] : const Dictionary &extras = d.has("extras") ? (Dictionary)d["extras"] :
Dictionary(); Dictionary();
Ref<EditorSceneImporterMesh> import_mesh; Ref<ImporterMesh> import_mesh;
import_mesh.instantiate(); import_mesh.instantiate();
String mesh_name = "mesh"; String mesh_name = "mesh";
if (d.has("name") && !String(d["name"]).is_empty()) { if (d.has("name") && !String(d["name"]).is_empty()) {
@ -2732,17 +2739,18 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
bool generate_tangents = (primitive == Mesh::PRIMITIVE_TRIANGLES && !a.has("TANGENT") && a.has("TEXCOORD_0") && a.has("NORMAL")); bool generate_tangents = (primitive == Mesh::PRIMITIVE_TRIANGLES && !a.has("TANGENT") && a.has("TEXCOORD_0") && a.has("NORMAL"));
Ref<SurfaceTool> mesh_surface_tool;
mesh_surface_tool.instantiate();
mesh_surface_tool->create_from_triangle_arrays(array);
if (a.has("JOINTS_0") && a.has("JOINTS_1")) {
mesh_surface_tool->set_skin_weight_count(SurfaceTool::SKIN_8_WEIGHTS);
}
mesh_surface_tool->index();
if (generate_tangents) { if (generate_tangents) {
//must generate mikktspace tangents.. ergh.. //must generate mikktspace tangents.. ergh..
Ref<SurfaceTool> st; mesh_surface_tool->generate_tangents();
st.instantiate();
st->create_from_triangle_arrays(array);
if (a.has("JOINTS_0") && a.has("JOINTS_1")) {
st->set_skin_weight_count(SurfaceTool::SKIN_8_WEIGHTS);
}
st->generate_tangents();
array = st->commit_to_arrays();
} }
array = mesh_surface_tool->commit_to_arrays();
Array morphs; Array morphs;
//blend shapes //blend shapes
@ -2772,8 +2780,6 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
array_copy[l] = array[l]; array_copy[l] = array[l];
} }
array_copy[Mesh::ARRAY_INDEX] = Variant();
if (t.has("POSITION")) { if (t.has("POSITION")) {
Vector<Vector3> varr = _decode_accessor_as_vec3(state, t["POSITION"], true); Vector<Vector3> varr = _decode_accessor_as_vec3(state, t["POSITION"], true);
const Vector<Vector3> src_varr = array[Mesh::ARRAY_VERTEX]; const Vector<Vector3> src_varr = array[Mesh::ARRAY_VERTEX];
@ -2852,17 +2858,17 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
array_copy[Mesh::ARRAY_TANGENT] = tangents_v4; array_copy[Mesh::ARRAY_TANGENT] = tangents_v4;
} }
if (generate_tangents) { Ref<SurfaceTool> blend_surface_tool;
Ref<SurfaceTool> st; blend_surface_tool.instantiate();
st.instantiate(); blend_surface_tool->create_from_triangle_arrays(array_copy);
st->create_from_triangle_arrays(array_copy); if (a.has("JOINTS_0") && a.has("JOINTS_1")) {
if (a.has("JOINTS_0") && a.has("JOINTS_1")) { blend_surface_tool->set_skin_weight_count(SurfaceTool::SKIN_8_WEIGHTS);
st->set_skin_weight_count(SurfaceTool::SKIN_8_WEIGHTS);
}
st->deindex();
st->generate_tangents();
array_copy = st->commit_to_arrays();
} }
blend_surface_tool->index();
if (generate_tangents) {
blend_surface_tool->generate_tangents();
}
array_copy = blend_surface_tool->commit_to_arrays();
morphs.push_back(array_copy); morphs.push_back(array_copy);
} }
@ -2875,19 +2881,23 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
const int material = p["material"]; const int material = p["material"];
ERR_FAIL_INDEX_V(material, state->materials.size(), ERR_FILE_CORRUPT); ERR_FAIL_INDEX_V(material, state->materials.size(), ERR_FILE_CORRUPT);
Ref<BaseMaterial3D> mat3d = state->materials[material]; Ref<BaseMaterial3D> mat3d = state->materials[material];
ERR_FAIL_NULL_V(mat3d, ERR_FILE_CORRUPT);
if (has_vertex_color) { if (has_vertex_color) {
mat3d->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); mat3d->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
} }
mat = mat3d; mat = mat3d;
} else if (has_vertex_color) { } else {
Ref<StandardMaterial3D> mat3d; Ref<StandardMaterial3D> mat3d;
mat3d.instantiate(); mat3d.instantiate();
mat3d->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); if (has_vertex_color) {
mat3d->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
}
mat = mat3d; mat = mat3d;
} }
ERR_FAIL_NULL_V(mat, ERR_FILE_CORRUPT);
import_mesh->add_surface(primitive, array, morphs, Dictionary(), mat, mat.is_valid() ? mat->get_name() : String(), flags); import_mesh->add_surface(primitive, array, morphs,
Dictionary(), mat, mat->get_name(), flags);
} }
Vector<float> blend_weights; Vector<float> blend_weights;
@ -3610,7 +3620,6 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) {
material->set_cull_mode(BaseMaterial3D::CULL_DISABLED); material->set_cull_mode(BaseMaterial3D::CULL_DISABLED);
} }
} }
if (d.has("alphaMode")) { if (d.has("alphaMode")) {
const String &am = d["alphaMode"]; const String &am = d["alphaMode"];
if (am == "BLEND") { if (am == "BLEND") {
@ -5007,72 +5016,65 @@ GLTFMeshIndex GLTFDocument::_convert_mesh_to_gltf(Ref<GLTFState> state, MeshInst
if (p_mesh_instance->get_mesh().is_null()) { if (p_mesh_instance->get_mesh().is_null()) {
return -1; return -1;
} }
Ref<EditorSceneImporterMesh> import_mesh; Ref<ImporterMesh> current_mesh;
import_mesh.instantiate(); current_mesh.instantiate();
Ref<Mesh> godot_mesh = p_mesh_instance->get_mesh();
if (godot_mesh.is_null()) {
return -1;
}
Vector<float> blend_weights; Vector<float> blend_weights;
Vector<String> blend_names; {
int32_t blend_count = godot_mesh->get_blend_shape_count(); Ref<Mesh> import_mesh = p_mesh_instance->get_mesh();
blend_names.resize(blend_count); Ref<ArrayMesh> import_array_mesh = p_mesh_instance->get_mesh();
blend_weights.resize(blend_count); if (import_mesh->get_blend_shape_count()) {
for (int32_t blend_i = 0; blend_i < godot_mesh->get_blend_shape_count(); blend_i++) { ArrayMesh::BlendShapeMode shape_mode = ArrayMesh::BLEND_SHAPE_MODE_NORMALIZED;
String blend_name = godot_mesh->get_blend_shape_name(blend_i); if (import_array_mesh.is_valid()) {
blend_names.write[blend_i] = blend_name; shape_mode = import_array_mesh->get_blend_shape_mode();
import_mesh->add_blend_shape(blend_name); }
} current_mesh->set_blend_shape_mode(shape_mode);
for (int32_t surface_i = 0; surface_i < godot_mesh->get_surface_count(); surface_i++) { for (int morph_i = 0; morph_i < import_mesh->get_blend_shape_count(); morph_i++) {
Mesh::PrimitiveType primitive_type = godot_mesh->surface_get_primitive_type(surface_i); current_mesh->add_blend_shape(import_mesh->get_blend_shape_name(morph_i));
Array arrays = godot_mesh->surface_get_arrays(surface_i); }
Array blend_shape_arrays = godot_mesh->surface_get_blend_shape_arrays(surface_i);
Ref<Material> mat = godot_mesh->surface_get_material(surface_i);
Ref<ArrayMesh> godot_array_mesh = godot_mesh;
String surface_name;
if (godot_array_mesh.is_valid()) {
surface_name = godot_array_mesh->surface_get_name(surface_i);
} }
if (p_mesh_instance->get_surface_override_material(surface_i).is_valid()) { for (int32_t surface_i = 0; surface_i < import_mesh->get_surface_count(); surface_i++) {
mat = p_mesh_instance->get_surface_override_material(surface_i); Array array = import_mesh->surface_get_arrays(surface_i);
Ref<Material> mat = import_mesh->surface_get_material(surface_i);
String mat_name;
if (mat.is_valid()) {
mat_name = mat->get_name();
}
current_mesh->add_surface(import_mesh->surface_get_primitive_type(surface_i),
array, import_mesh->surface_get_blend_shape_arrays(surface_i), import_mesh->surface_get_lods(surface_i), mat,
mat_name, import_mesh->surface_get_format(surface_i));
} }
if (p_mesh_instance->get_material_override().is_valid()) { int32_t blend_count = import_mesh->get_blend_shape_count();
mat = p_mesh_instance->get_material_override(); blend_weights.resize(blend_count);
for (int32_t blend_i = 0; blend_i < blend_count; blend_i++) {
blend_weights.write[blend_i] = 0.0f;
} }
import_mesh->add_surface(primitive_type, arrays, blend_shape_arrays, Dictionary(), mat, surface_name, godot_mesh->surface_get_format(surface_i));
}
for (int32_t blend_i = 0; blend_i < blend_count; blend_i++) {
blend_weights.write[blend_i] = 0.0f;
} }
Ref<GLTFMesh> gltf_mesh; Ref<GLTFMesh> gltf_mesh;
gltf_mesh.instantiate(); gltf_mesh.instantiate();
gltf_mesh->set_mesh(import_mesh); gltf_mesh->set_mesh(current_mesh);
gltf_mesh->set_blend_weights(blend_weights); gltf_mesh->set_blend_weights(blend_weights);
GLTFMeshIndex mesh_i = state->meshes.size(); GLTFMeshIndex mesh_i = state->meshes.size();
state->meshes.push_back(gltf_mesh); state->meshes.push_back(gltf_mesh);
return mesh_i; return mesh_i;
} }
EditorSceneImporterMeshNode3D *GLTFDocument::_generate_mesh_instance(Ref<GLTFState> state, Node *scene_parent, const GLTFNodeIndex node_index) { ImporterMeshInstance3D *GLTFDocument::_generate_mesh_instance(Ref<GLTFState> state, Node *parent_node, const GLTFNodeIndex node_index) {
Ref<GLTFNode> gltf_node = state->nodes[node_index]; Ref<GLTFNode> gltf_node = state->nodes[node_index];
ERR_FAIL_INDEX_V(gltf_node->mesh, state->meshes.size(), nullptr); ERR_FAIL_INDEX_V(gltf_node->mesh, state->meshes.size(), nullptr);
EditorSceneImporterMeshNode3D *mi = memnew(EditorSceneImporterMeshNode3D); ImporterMeshInstance3D *mi = memnew(ImporterMeshInstance3D);
print_verbose("glTF: Creating mesh for: " + gltf_node->get_name()); print_verbose("glTF: Creating mesh for: " + gltf_node->get_name());
Ref<GLTFMesh> mesh = state->meshes.write[gltf_node->mesh]; Ref<GLTFMesh> mesh = state->meshes.write[gltf_node->mesh];
if (mesh.is_null()) { if (mesh.is_null()) {
return mi; return mi;
} }
Ref<EditorSceneImporterMesh> import_mesh = mesh->get_mesh(); Ref<ImporterMesh> import_mesh = mesh->get_mesh();
if (import_mesh.is_null()) { if (import_mesh.is_null()) {
return mi; return mi;
} }
mi->set_mesh(import_mesh); mi->set_mesh(import_mesh);
for (int i = 0; i < mesh->get_blend_weights().size(); i++) {
mi->set("blend_shapes/" + mesh->get_mesh()->get_blend_shape_name(i), mesh->get_blend_weights()[i]);
}
return mi; return mi;
} }
@ -5241,7 +5243,7 @@ void GLTFDocument::_convert_scene_node(Ref<GLTFState> state, Node *p_current, co
return; return;
} else if (cast_to<MultiMeshInstance3D>(p_current)) { } else if (cast_to<MultiMeshInstance3D>(p_current)) {
MultiMeshInstance3D *multi = cast_to<MultiMeshInstance3D>(p_current); MultiMeshInstance3D *multi = cast_to<MultiMeshInstance3D>(p_current);
_convert_mult_mesh_instance_to_gltf(multi, p_gltf_parent, p_gltf_root, gltf_node, state); _convert_multi_mesh_instance_to_gltf(multi, p_gltf_parent, p_gltf_root, gltf_node, state);
#ifdef MODULE_CSG_ENABLED #ifdef MODULE_CSG_ENABLED
} else if (cast_to<CSGShape3D>(p_current)) { } else if (cast_to<CSGShape3D>(p_current)) {
CSGShape3D *shape = cast_to<CSGShape3D>(p_current); CSGShape3D *shape = cast_to<CSGShape3D>(p_current);
@ -5292,13 +5294,8 @@ void GLTFDocument::_convert_csg_shape_to_gltf(CSGShape3D *p_current, GLTFNodeInd
} }
Ref<GLTFMesh> gltf_mesh; Ref<GLTFMesh> gltf_mesh;
gltf_mesh.instantiate(); gltf_mesh.instantiate();
Ref<EditorSceneImporterMesh> import_mesh; Ref<ImporterMesh> array_mesh = csg->get_meshes()[1];
import_mesh.instantiate(); gltf_mesh->set_mesh(array_mesh);
Ref<ArrayMesh> array_mesh = csg->get_meshes()[1];
for (int32_t surface_i = 0; surface_i < array_mesh->get_surface_count(); surface_i++) {
import_mesh->add_surface(Mesh::PrimitiveType::PRIMITIVE_TRIANGLES, array_mesh->surface_get_arrays(surface_i), Array(), Dictionary(), mat, array_mesh->surface_get_name(surface_i));
}
gltf_mesh->set_mesh(import_mesh);
GLTFMeshIndex mesh_i = state->meshes.size(); GLTFMeshIndex mesh_i = state->meshes.size();
state->meshes.push_back(gltf_mesh); state->meshes.push_back(gltf_mesh);
gltf_node->mesh = mesh_i; gltf_node->mesh = mesh_i;
@ -5364,7 +5361,7 @@ void GLTFDocument::_convert_grid_map_to_gltf(GridMap *p_grid_map, GLTFNodeIndex
Vector3 cell_location = cells[k]; Vector3 cell_location = cells[k];
int32_t cell = p_grid_map->get_cell_item( int32_t cell = p_grid_map->get_cell_item(
Vector3(cell_location.x, cell_location.y, cell_location.z)); Vector3(cell_location.x, cell_location.y, cell_location.z));
EditorSceneImporterMeshNode3D *import_mesh_node = memnew(EditorSceneImporterMeshNode3D); ImporterMeshInstance3D *import_mesh_node = memnew(ImporterMeshInstance3D);
import_mesh_node->set_mesh(p_grid_map->get_mesh_library()->get_item_mesh(cell)); import_mesh_node->set_mesh(p_grid_map->get_mesh_library()->get_item_mesh(cell));
Transform3D cell_xform; Transform3D cell_xform;
cell_xform.basis.set_orthogonal_index( cell_xform.basis.set_orthogonal_index(
@ -5386,50 +5383,73 @@ void GLTFDocument::_convert_grid_map_to_gltf(GridMap *p_grid_map, GLTFNodeIndex
} }
#endif // MODULE_GRIDMAP_ENABLED #endif // MODULE_GRIDMAP_ENABLED
void GLTFDocument::_convert_mult_mesh_instance_to_gltf(MultiMeshInstance3D *p_multi_mesh_instance, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref<GLTFNode> gltf_node, Ref<GLTFState> state) { void GLTFDocument::_convert_multi_mesh_instance_to_gltf(
MultiMeshInstance3D *p_multi_mesh_instance,
GLTFNodeIndex p_parent_node_index,
GLTFNodeIndex p_root_node_index,
Ref<GLTFNode> gltf_node, Ref<GLTFState> state) {
ERR_FAIL_COND(!p_multi_mesh_instance);
Ref<MultiMesh> multi_mesh = p_multi_mesh_instance->get_multimesh(); Ref<MultiMesh> multi_mesh = p_multi_mesh_instance->get_multimesh();
if (multi_mesh.is_valid()) { if (multi_mesh.is_null()) {
for (int32_t instance_i = 0; instance_i < multi_mesh->get_instance_count(); return;
instance_i++) { }
GLTFNode *new_gltf_node = memnew(GLTFNode); Ref<GLTFMesh> gltf_mesh;
Transform3D transform; gltf_mesh.instantiate();
if (multi_mesh->get_transform_format() == MultiMesh::TRANSFORM_2D) { Ref<Mesh> mesh = multi_mesh->get_mesh();
Transform2D xform_2d = multi_mesh->get_instance_transform_2d(instance_i); if (mesh.is_null()) {
transform.origin = return;
Vector3(xform_2d.get_origin().x, 0, xform_2d.get_origin().y); }
real_t rotation = xform_2d.get_rotation(); gltf_mesh->set_name(multi_mesh->get_name());
Quaternion quaternion(Vector3(0, 1, 0), rotation); Ref<ImporterMesh> importer_mesh;
Size2 scale = xform_2d.get_scale(); importer_mesh.instantiate();
transform.basis.set_quaternion_scale(quaternion, Ref<ArrayMesh> array_mesh = multi_mesh->get_mesh();
Vector3(scale.x, 0, scale.y)); if (array_mesh.is_valid()) {
transform = importer_mesh->set_blend_shape_mode(array_mesh->get_blend_shape_mode());
p_multi_mesh_instance->get_transform() * transform; for (int32_t blend_i = 0; blend_i < array_mesh->get_blend_shape_count(); blend_i++) {
} else if (multi_mesh->get_transform_format() == MultiMesh::TRANSFORM_3D) { importer_mesh->add_blend_shape(array_mesh->get_blend_shape_name(blend_i));
transform = p_multi_mesh_instance->get_transform() *
multi_mesh->get_instance_transform(instance_i);
}
Ref<ArrayMesh> mm = multi_mesh->get_mesh();
if (mm.is_valid()) {
Ref<EditorSceneImporterMesh> mesh;
mesh.instantiate();
for (int32_t surface_i = 0; surface_i < mm->get_surface_count(); surface_i++) {
Array surface = mm->surface_get_arrays(surface_i);
mesh->add_surface(mm->surface_get_primitive_type(surface_i), surface, Array(), Dictionary(),
mm->surface_get_material(surface_i), mm->get_name());
}
Ref<GLTFMesh> gltf_mesh;
gltf_mesh.instantiate();
gltf_mesh->set_name(multi_mesh->get_name());
gltf_mesh->set_mesh(mesh);
new_gltf_node->mesh = state->meshes.size();
state->meshes.push_back(gltf_mesh);
}
new_gltf_node->xform = transform;
new_gltf_node->set_name(_gen_unique_name(state, p_multi_mesh_instance->get_name()));
gltf_node->children.push_back(state->nodes.size());
state->nodes.push_back(new_gltf_node);
} }
} }
for (int32_t surface_i = 0; surface_i < mesh->get_surface_count(); surface_i++) {
Ref<Material> mat = mesh->surface_get_material(surface_i);
String material_name;
if (mat.is_valid()) {
material_name = mat->get_name();
}
Array blend_arrays;
if (array_mesh.is_valid()) {
blend_arrays = array_mesh->surface_get_blend_shape_arrays(surface_i);
}
importer_mesh->add_surface(mesh->surface_get_primitive_type(surface_i), mesh->surface_get_arrays(surface_i),
blend_arrays, mesh->surface_get_lods(surface_i), mat, material_name, mesh->surface_get_format(surface_i));
}
gltf_mesh->set_mesh(importer_mesh);
GLTFMeshIndex mesh_index = state->meshes.size();
state->meshes.push_back(gltf_mesh);
for (int32_t instance_i = 0; instance_i < multi_mesh->get_instance_count();
instance_i++) {
Transform3D transform;
if (multi_mesh->get_transform_format() == MultiMesh::TRANSFORM_2D) {
Transform2D xform_2d = multi_mesh->get_instance_transform_2d(instance_i);
transform.origin =
Vector3(xform_2d.get_origin().x, 0, xform_2d.get_origin().y);
real_t rotation = xform_2d.get_rotation();
Quaternion quaternion(Vector3(0, 1, 0), rotation);
Size2 scale = xform_2d.get_scale();
transform.basis.set_quaternion_scale(quaternion,
Vector3(scale.x, 0, scale.y));
transform = p_multi_mesh_instance->get_transform() * transform;
} else if (multi_mesh->get_transform_format() == MultiMesh::TRANSFORM_3D) {
transform = p_multi_mesh_instance->get_transform() *
multi_mesh->get_instance_transform(instance_i);
}
Ref<GLTFNode> new_gltf_node;
new_gltf_node.instantiate();
new_gltf_node->mesh = mesh_index;
new_gltf_node->xform = transform;
new_gltf_node->set_name(_gen_unique_name(state, p_multi_mesh_instance->get_name()));
gltf_node->children.push_back(state->nodes.size());
state->nodes.push_back(new_gltf_node);
}
} }
void GLTFDocument::_convert_skeleton_to_gltf(Skeleton3D *p_skeleton3d, Ref<GLTFState> state, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref<GLTFNode> gltf_node) { void GLTFDocument::_convert_skeleton_to_gltf(Skeleton3D *p_skeleton3d, Ref<GLTFState> state, GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_node_index, Ref<GLTFNode> gltf_node) {
@ -6106,8 +6126,8 @@ void GLTFDocument::_process_mesh_instances(Ref<GLTFState> state, Node *scene_roo
Map<GLTFNodeIndex, Node *>::Element *mi_element = state->scene_nodes.find(node_i); Map<GLTFNodeIndex, Node *>::Element *mi_element = state->scene_nodes.find(node_i);
ERR_CONTINUE_MSG(mi_element == nullptr, vformat("Unable to find node %d", node_i)); ERR_CONTINUE_MSG(mi_element == nullptr, vformat("Unable to find node %d", node_i));
EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(mi_element->get()); ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(mi_element->get());
ERR_CONTINUE_MSG(mi == nullptr, vformat("Unable to cast node %d of type %s to EditorSceneImporterMeshNode3D", node_i, mi_element->get()->get_class_name())); ERR_CONTINUE_MSG(mi == nullptr, vformat("Unable to cast node %d of type %s to ImporterMeshInstance3D", node_i, mi_element->get()->get_class_name()));
const GLTFSkeletonIndex skel_i = state->skins.write[node->skin]->skeleton; const GLTFSkeletonIndex skel_i = state->skins.write[node->skin]->skeleton;
Ref<GLTFSkeleton> gltf_skeleton = state->skeletons.write[skel_i]; Ref<GLTFSkeleton> gltf_skeleton = state->skeletons.write[skel_i];
@ -6748,10 +6768,25 @@ Error GLTFDocument::save_scene(Node *p_node, const String &p_path,
Ref<GLTFDocument> gltf_document; Ref<GLTFDocument> gltf_document;
gltf_document.instantiate(); gltf_document.instantiate();
for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
ERR_CONTINUE(ext.is_null());
Error err = ext->export_preflight(this, p_node);
ERR_FAIL_COND_V(err != OK, err);
}
if (r_state == Ref<GLTFState>()) { if (r_state == Ref<GLTFState>()) {
r_state.instantiate(); r_state.instantiate();
} }
return gltf_document->serialize(r_state, p_node, p_path); Error err = gltf_document->serialize(r_state, p_node, p_path);
ERR_FAIL_COND_V(err != OK, err);
for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
ERR_CONTINUE(ext.is_null());
err = ext->export_post(this);
ERR_FAIL_COND_V(err != OK, err);
}
return OK;
} }
Node *GLTFDocument::import_scene_gltf(const String &p_path, uint32_t p_flags, int32_t p_bake_fps, Ref<GLTFState> r_state, List<String> *r_missing_deps, Error *r_err) { Node *GLTFDocument::import_scene_gltf(const String &p_path, uint32_t p_flags, int32_t p_bake_fps, Ref<GLTFState> r_state, List<String> *r_missing_deps, Error *r_err) {
@ -6764,6 +6799,15 @@ Node *GLTFDocument::import_scene_gltf(const String &p_path, uint32_t p_flags, in
Ref<GLTFDocument> gltf_document; Ref<GLTFDocument> gltf_document;
gltf_document.instantiate(); gltf_document.instantiate();
for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
ERR_CONTINUE(ext.is_null());
Error err = ext->import_preflight(this);
if (r_err) {
*r_err = err;
}
ERR_FAIL_COND_V(err != OK, nullptr);
}
Error err = gltf_document->parse(r_state, p_path); Error err = gltf_document->parse(r_state, p_path);
if (r_err) { if (r_err) {
*r_err = err; *r_err = err;
@ -6783,7 +6827,15 @@ Node *GLTFDocument::import_scene_gltf(const String &p_path, uint32_t p_flags, in
gltf_document->_import_animation(r_state, ap, i, p_bake_fps); gltf_document->_import_animation(r_state, ap, i, p_bake_fps);
} }
} }
for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
ERR_CONTINUE(ext.is_null());
err = ext->import_post(this, root);
if (r_err) {
*r_err = err;
}
ERR_FAIL_COND_V(err != OK, nullptr);
}
return root; return root;
} }
@ -6792,6 +6844,14 @@ void GLTFDocument::_bind_methods() {
&GLTFDocument::save_scene, DEFVAL(0), DEFVAL(30), DEFVAL(Ref<GLTFState>())); &GLTFDocument::save_scene, DEFVAL(0), DEFVAL(30), DEFVAL(Ref<GLTFState>()));
ClassDB::bind_method(D_METHOD("import_scene", "path", "flags", "bake_fps", "state"), ClassDB::bind_method(D_METHOD("import_scene", "path", "flags", "bake_fps", "state"),
&GLTFDocument::import_scene, DEFVAL(0), DEFVAL(30), DEFVAL(Ref<GLTFState>())); &GLTFDocument::import_scene, DEFVAL(0), DEFVAL(30), DEFVAL(Ref<GLTFState>()));
ClassDB::bind_method(D_METHOD("set_extensions", "extensions"),
&GLTFDocument::set_extensions);
ClassDB::bind_method(D_METHOD("get_extensions"),
&GLTFDocument::get_extensions);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "extensions", PROPERTY_HINT_ARRAY_TYPE,
vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "GLTFDocumentExtension"),
PROPERTY_USAGE_DEFAULT),
"set_extensions", "get_extensions");
} }
void GLTFDocument::_build_parent_hierachy(Ref<GLTFState> state) { void GLTFDocument::_build_parent_hierachy(Ref<GLTFState> state) {
@ -6817,3 +6877,20 @@ Node *GLTFDocument::import_scene(const String &p_path, uint32_t p_flags, int32_t
} }
return node; return node;
} }
void GLTFDocument::set_extensions(TypedArray<GLTFDocumentExtension> p_extensions) {
document_extensions = p_extensions;
}
TypedArray<GLTFDocumentExtension> GLTFDocument::get_extensions() const {
return document_extensions;
}
GLTFDocument::GLTFDocument() {
if (!::Engine::get_singleton()->is_editor_hint()) {
return;
}
Ref<GLTFDocumentExtensionConvertImporterMesh> extension_editor;
extension_editor.instantiate();
document_extensions.push_back(extension_editor);
}

View file

@ -33,8 +33,11 @@
#include "gltf_animation.h" #include "gltf_animation.h"
#include "editor/import/scene_importer_mesh_node_3d.h" #include "core/variant/dictionary.h"
#include "core/variant/variant.h"
#include "gltf_document_extension_convert_importer_mesh.h"
#include "scene/3d/bone_attachment_3d.h" #include "scene/3d/bone_attachment_3d.h"
#include "scene/3d/importer_mesh_instance_3d.h"
#include "scene/3d/light_3d.h" #include "scene/3d/light_3d.h"
#include "scene/3d/mesh_instance_3d.h" #include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/node_3d.h" #include "scene/3d/node_3d.h"
@ -54,6 +57,7 @@ class GLTFSkeleton;
class CSGShape3D; class CSGShape3D;
class GridMap; class GridMap;
class MultiMeshInstance3D; class MultiMeshInstance3D;
class GLTFDocumentExtension;
using GLTFAccessorIndex = int; using GLTFAccessorIndex = int;
using GLTFAnimationIndex = int; using GLTFAnimationIndex = int;
@ -74,11 +78,13 @@ class GLTFDocument : public Resource {
friend class GLTFState; friend class GLTFState;
friend class GLTFSkin; friend class GLTFSkin;
friend class GLTFSkeleton; friend class GLTFSkeleton;
TypedArray<GLTFDocumentExtension> document_extensions;
private: private:
const float BAKE_FPS = 30.0f; const float BAKE_FPS = 30.0f;
public: public:
GLTFDocument();
const int32_t JOINT_GROUP_SIZE = 4; const int32_t JOINT_GROUP_SIZE = 4;
enum GLTFType { enum GLTFType {
TYPE_SCALAR, TYPE_SCALAR,
@ -118,6 +124,8 @@ public:
Error save_scene(Node *p_node, const String &p_path, Error save_scene(Node *p_node, const String &p_path,
const String &p_src_path, uint32_t p_flags, const String &p_src_path, uint32_t p_flags,
float p_bake_fps, Ref<GLTFState> r_state); float p_bake_fps, Ref<GLTFState> r_state);
void set_extensions(TypedArray<GLTFDocumentExtension> p_extensions);
TypedArray<GLTFDocumentExtension> get_extensions() const;
private: private:
template <class T> template <class T>
@ -280,12 +288,10 @@ private:
Skeleton3D *skeleton, Skeleton3D *skeleton,
const GLTFNodeIndex node_index, const GLTFNodeIndex node_index,
const GLTFNodeIndex bone_index); const GLTFNodeIndex bone_index);
EditorSceneImporterMeshNode3D *_generate_mesh_instance(Ref<GLTFState> state, Node *scene_parent, const GLTFNodeIndex node_index); ImporterMeshInstance3D *_generate_mesh_instance(Ref<GLTFState> state, Node *parent_node, const GLTFNodeIndex node_index);
Camera3D *_generate_camera(Ref<GLTFState> state, Node *scene_parent, Camera3D *_generate_camera(Ref<GLTFState> state, Node *parent_node, const GLTFNodeIndex node_index);
const GLTFNodeIndex node_index); Node3D *_generate_light(Ref<GLTFState> state, Node *parent_node, const GLTFNodeIndex node_index);
Node3D *_generate_light(Ref<GLTFState> state, Node *scene_parent, const GLTFNodeIndex node_index); Node3D *_generate_spatial(Ref<GLTFState> state, Node *parent_node, const GLTFNodeIndex node_index);
Node3D *_generate_spatial(Ref<GLTFState> state, Node *scene_parent,
const GLTFNodeIndex node_index);
void _assign_scene_names(Ref<GLTFState> state); void _assign_scene_names(Ref<GLTFState> state);
template <class T> template <class T>
T _interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, T _interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values,
@ -420,8 +426,8 @@ public:
GLTFNodeIndex p_root_node_index, GLTFNodeIndex p_root_node_index,
Ref<GLTFNode> gltf_node, Ref<GLTFState> state); Ref<GLTFNode> gltf_node, Ref<GLTFState> state);
#endif // MODULE_GRIDMAP_ENABLED #endif // MODULE_GRIDMAP_ENABLED
void _convert_mult_mesh_instance_to_gltf( void _convert_multi_mesh_instance_to_gltf(
MultiMeshInstance3D *p_scene_parent, MultiMeshInstance3D *p_multi_mesh_instance,
GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_parent_node_index,
GLTFNodeIndex p_root_node_index, GLTFNodeIndex p_root_node_index,
Ref<GLTFNode> gltf_node, Ref<GLTFState> state); Ref<GLTFNode> gltf_node, Ref<GLTFState> state);

View file

@ -0,0 +1,88 @@
/*************************************************************************/
/* gltf_document_extension.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "gltf_document_extension.h"
#include "gltf_document.h"
void GLTFDocumentExtension::_bind_methods() {
// Import
ClassDB::bind_method(D_METHOD("get_import_setting_keys"),
&GLTFDocumentExtension::get_import_setting_keys);
ClassDB::bind_method(D_METHOD("import_preflight", "document"),
&GLTFDocumentExtension::import_preflight);
ClassDB::bind_method(D_METHOD("get_import_setting", "key"),
&GLTFDocumentExtension::get_import_setting);
ClassDB::bind_method(D_METHOD("set_import_setting", "key", "value"),
&GLTFDocumentExtension::set_import_setting);
ClassDB::bind_method(D_METHOD("import_post", "document", "node"),
&GLTFDocumentExtension::import_post);
// Export
ClassDB::bind_method(D_METHOD("get_export_setting_keys"),
&GLTFDocumentExtension::get_export_setting_keys);
ClassDB::bind_method(D_METHOD("get_export_setting", "key"),
&GLTFDocumentExtension::get_export_setting);
ClassDB::bind_method(D_METHOD("set_export_setting", "key", "value"),
&GLTFDocumentExtension::set_export_setting);
ClassDB::bind_method(D_METHOD("export_preflight", "document", "node"),
&GLTFDocumentExtension::export_preflight);
ClassDB::bind_method(D_METHOD("export_post", "document"),
&GLTFDocumentExtension::export_post);
}
Array GLTFDocumentExtension::get_import_setting_keys() const {
return import_settings.keys();
}
Variant GLTFDocumentExtension::get_import_setting(const StringName &p_key) const {
if (!import_settings.has(p_key)) {
return Variant();
}
return import_settings[p_key];
}
void GLTFDocumentExtension::set_import_setting(const StringName &p_key, Variant p_var) {
import_settings[p_key] = p_var;
}
Array GLTFDocumentExtension::get_export_setting_keys() const {
return import_settings.keys();
}
Variant GLTFDocumentExtension::get_export_setting(const StringName &p_key) const {
if (!import_settings.has(p_key)) {
return Variant();
}
return import_settings[p_key];
}
void GLTFDocumentExtension::set_export_setting(const StringName &p_key, Variant p_var) {
import_settings[p_key] = p_var;
}

View file

@ -0,0 +1,63 @@
/*************************************************************************/
/* gltf_document_extension.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef GLTF_DOCUMENT_EXTENSION_H
#define GLTF_DOCUMENT_EXTENSION_H
#include "core/io/resource.h"
#include "core/variant/dictionary.h"
#include "core/variant/typed_array.h"
#include "core/variant/variant.h"
class GLTFDocument;
class GLTFDocumentExtension : public Resource {
GDCLASS(GLTFDocumentExtension, Resource);
Dictionary import_settings;
Dictionary export_settings;
protected:
static void _bind_methods();
public:
virtual Array get_import_setting_keys() const;
virtual Variant get_import_setting(const StringName &p_key) const;
virtual void set_import_setting(const StringName &p_key, Variant p_var);
virtual Error import_preflight(Ref<GLTFDocument> p_document) { return OK; }
virtual Error import_post(Ref<GLTFDocument> p_document, Node *p_node) { return OK; }
public:
virtual Array get_export_setting_keys() const;
virtual Variant get_export_setting(const StringName &p_key) const;
virtual void set_export_setting(const StringName &p_key, Variant p_var);
virtual Error export_preflight(Ref<GLTFDocument> p_document, Node *p_node) { return OK; }
virtual Error export_post(Ref<GLTFDocument> p_document) { return OK; }
};
#endif // GLTF_DOCUMENT_EXTENSION_H

View file

@ -0,0 +1,79 @@
/*************************************************************************/
/* gltf_document_extension_convert_importer_mesh.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "gltf_document_extension_convert_importer_mesh.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/resources/importer_mesh.h"
#include <cstddef>
void GLTFDocumentExtensionConvertImporterMesh::_bind_methods() {
}
Error GLTFDocumentExtensionConvertImporterMesh::import_post(Ref<GLTFDocument> p_document, Node *p_node) {
List<Node *> queue;
queue.push_back(p_node);
List<Node *> delete_queue;
while (!queue.is_empty()) {
List<Node *>::Element *E = queue.front();
Node *node = E->get();
{
ImporterMeshInstance3D *mesh_3d = cast_to<ImporterMeshInstance3D>(node);
if (mesh_3d) {
MeshInstance3D *mesh_instance_node_3d = memnew(MeshInstance3D);
Ref<ImporterMesh> mesh = mesh_3d->get_mesh();
if (mesh.is_valid()) {
Ref<ArrayMesh> array_mesh = mesh->get_mesh();
mesh_instance_node_3d->set_name(node->get_name());
mesh_instance_node_3d->set_transform(mesh_3d->get_transform());
mesh_instance_node_3d->set_mesh(array_mesh);
mesh_instance_node_3d->set_skin(mesh_3d->get_skin());
mesh_instance_node_3d->set_skeleton_path(mesh_3d->get_skeleton_path());
node->replace_by(mesh_instance_node_3d);
delete_queue.push_back(node);
} else {
memdelete(mesh_instance_node_3d);
}
}
}
int child_count = node->get_child_count();
for (int i = 0; i < child_count; i++) {
queue.push_back(node->get_child(i));
}
queue.pop_front();
}
while (!queue.is_empty()) {
List<Node *>::Element *E = delete_queue.front();
Node *node = E->get();
memdelete(node);
delete_queue.pop_front();
}
return OK;
}

View file

@ -0,0 +1,55 @@
/*************************************************************************/
/* gltf_document_extension_convert_importer_mesh.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef GLTF_EXTENSION_EDITOR_H
#define GLTF_EXTENSION_EDITOR_H
#include "core/io/resource.h"
#include "core/variant/dictionary.h"
#include "gltf_document.h"
#include "gltf_document_extension.h"
#include "scene/3d/importer_mesh_instance_3d.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/main/node.h"
#include "scene/resources/importer_mesh.h"
class GLTFDocumentExtension;
class GLTFDocument;
class GLTFDocumentExtensionConvertImporterMesh : public GLTFDocumentExtension {
GDCLASS(GLTFDocumentExtensionConvertImporterMesh, GLTFDocumentExtension);
protected:
static void _bind_methods();
public:
Error import_post(Ref<GLTFDocument> p_document, Node *p_node) override;
};
#endif // GLTF_EXTENSION_EDITOR_H

View file

@ -29,7 +29,7 @@
/*************************************************************************/ /*************************************************************************/
#include "gltf_mesh.h" #include "gltf_mesh.h"
#include "editor/import/scene_importer_mesh.h" #include "scene/resources/importer_mesh.h"
void GLTFMesh::_bind_methods() { void GLTFMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_mesh"), &GLTFMesh::get_mesh); ClassDB::bind_method(D_METHOD("get_mesh"), &GLTFMesh::get_mesh);
@ -41,11 +41,11 @@ void GLTFMesh::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::PACKED_FLOAT32_ARRAY, "blend_weights"), "set_blend_weights", "get_blend_weights"); // Vector<float> ADD_PROPERTY(PropertyInfo(Variant::PACKED_FLOAT32_ARRAY, "blend_weights"), "set_blend_weights", "get_blend_weights"); // Vector<float>
} }
Ref<EditorSceneImporterMesh> GLTFMesh::get_mesh() { Ref<ImporterMesh> GLTFMesh::get_mesh() {
return mesh; return mesh;
} }
void GLTFMesh::set_mesh(Ref<EditorSceneImporterMesh> p_mesh) { void GLTFMesh::set_mesh(Ref<ImporterMesh> p_mesh) {
mesh = p_mesh; mesh = p_mesh;
} }

View file

@ -33,22 +33,23 @@
#include "core/io/resource.h" #include "core/io/resource.h"
#include "editor/import/resource_importer_scene.h" #include "editor/import/resource_importer_scene.h"
#include "editor/import/scene_importer_mesh.h" #include "scene/3d/importer_mesh_instance_3d.h"
#include "scene/resources/importer_mesh.h"
#include "scene/resources/mesh.h" #include "scene/resources/mesh.h"
class GLTFMesh : public Resource { class GLTFMesh : public Resource {
GDCLASS(GLTFMesh, Resource); GDCLASS(GLTFMesh, Resource);
private: private:
Ref<EditorSceneImporterMesh> mesh; Ref<ImporterMesh> mesh;
Vector<float> blend_weights; Vector<float> blend_weights;
protected: protected:
static void _bind_methods(); static void _bind_methods();
public: public:
Ref<EditorSceneImporterMesh> get_mesh(); Ref<ImporterMesh> get_mesh();
void set_mesh(Ref<EditorSceneImporterMesh> p_mesh); void set_mesh(Ref<ImporterMesh> p_mesh);
Vector<float> get_blend_weights(); Vector<float> get_blend_weights();
void set_blend_weights(Vector<float> p_blend_weights); void set_blend_weights(Vector<float> p_blend_weights);
}; };

View file

@ -36,6 +36,7 @@
#include "gltf_buffer_view.h" #include "gltf_buffer_view.h"
#include "gltf_camera.h" #include "gltf_camera.h"
#include "gltf_document.h" #include "gltf_document.h"
#include "gltf_document_extension.h"
#include "gltf_light.h" #include "gltf_light.h"
#include "gltf_mesh.h" #include "gltf_mesh.h"
#include "gltf_node.h" #include "gltf_node.h"

View file

@ -38,6 +38,8 @@
#include "gltf_buffer_view.h" #include "gltf_buffer_view.h"
#include "gltf_camera.h" #include "gltf_camera.h"
#include "gltf_document.h" #include "gltf_document.h"
#include "gltf_document_extension.h"
#include "gltf_document_extension_convert_importer_mesh.h"
#include "gltf_light.h" #include "gltf_light.h"
#include "gltf_mesh.h" #include "gltf_mesh.h"
#include "gltf_node.h" #include "gltf_node.h"
@ -79,6 +81,8 @@ void register_gltf_types() {
GDREGISTER_CLASS(GLTFCamera); GDREGISTER_CLASS(GLTFCamera);
GDREGISTER_CLASS(GLTFLight); GDREGISTER_CLASS(GLTFLight);
GDREGISTER_CLASS(GLTFState); GDREGISTER_CLASS(GLTFState);
GDREGISTER_CLASS(GLTFDocumentExtensionConvertImporterMesh);
GDREGISTER_CLASS(GLTFDocumentExtension);
GDREGISTER_CLASS(GLTFDocument); GDREGISTER_CLASS(GLTFDocument);
#endif #endif
} }

View file

@ -1,5 +1,5 @@
/*************************************************************************/ /*************************************************************************/
/* scene_importer_mesh_node_3d.cpp */ /* importer_mesh_instance_3d.cpp */
/*************************************************************************/ /*************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@ -28,23 +28,25 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/ /*************************************************************************/
#include "scene_importer_mesh_node_3d.h" #include "importer_mesh_instance_3d.h"
void EditorSceneImporterMeshNode3D::set_mesh(const Ref<EditorSceneImporterMesh> &p_mesh) { #include "scene/resources/importer_mesh.h"
void ImporterMeshInstance3D::set_mesh(const Ref<ImporterMesh> &p_mesh) {
mesh = p_mesh; mesh = p_mesh;
} }
Ref<EditorSceneImporterMesh> EditorSceneImporterMeshNode3D::get_mesh() const { Ref<ImporterMesh> ImporterMeshInstance3D::get_mesh() const {
return mesh; return mesh;
} }
void EditorSceneImporterMeshNode3D::set_skin(const Ref<Skin> &p_skin) { void ImporterMeshInstance3D::set_skin(const Ref<Skin> &p_skin) {
skin = p_skin; skin = p_skin;
} }
Ref<Skin> EditorSceneImporterMeshNode3D::get_skin() const { Ref<Skin> ImporterMeshInstance3D::get_skin() const {
return skin; return skin;
} }
void EditorSceneImporterMeshNode3D::set_surface_material(int p_idx, const Ref<Material> &p_material) { void ImporterMeshInstance3D::set_surface_material(int p_idx, const Ref<Material> &p_material) {
ERR_FAIL_COND(p_idx < 0); ERR_FAIL_COND(p_idx < 0);
if (p_idx >= surface_materials.size()) { if (p_idx >= surface_materials.size()) {
surface_materials.resize(p_idx + 1); surface_materials.resize(p_idx + 1);
@ -52,7 +54,7 @@ void EditorSceneImporterMeshNode3D::set_surface_material(int p_idx, const Ref<Ma
surface_materials.write[p_idx] = p_material; surface_materials.write[p_idx] = p_material;
} }
Ref<Material> EditorSceneImporterMeshNode3D::get_surface_material(int p_idx) const { Ref<Material> ImporterMeshInstance3D::get_surface_material(int p_idx) const {
ERR_FAIL_COND_V(p_idx < 0, Ref<Material>()); ERR_FAIL_COND_V(p_idx < 0, Ref<Material>());
if (p_idx >= surface_materials.size()) { if (p_idx >= surface_materials.size()) {
return Ref<Material>(); return Ref<Material>();
@ -60,24 +62,24 @@ Ref<Material> EditorSceneImporterMeshNode3D::get_surface_material(int p_idx) con
return surface_materials[p_idx]; return surface_materials[p_idx];
} }
void EditorSceneImporterMeshNode3D::set_skeleton_path(const NodePath &p_path) { void ImporterMeshInstance3D::set_skeleton_path(const NodePath &p_path) {
skeleton_path = p_path; skeleton_path = p_path;
} }
NodePath EditorSceneImporterMeshNode3D::get_skeleton_path() const { NodePath ImporterMeshInstance3D::get_skeleton_path() const {
return skeleton_path; return skeleton_path;
} }
void EditorSceneImporterMeshNode3D::_bind_methods() { void ImporterMeshInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &EditorSceneImporterMeshNode3D::set_mesh); ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &ImporterMeshInstance3D::set_mesh);
ClassDB::bind_method(D_METHOD("get_mesh"), &EditorSceneImporterMeshNode3D::get_mesh); ClassDB::bind_method(D_METHOD("get_mesh"), &ImporterMeshInstance3D::get_mesh);
ClassDB::bind_method(D_METHOD("set_skin", "skin"), &EditorSceneImporterMeshNode3D::set_skin); ClassDB::bind_method(D_METHOD("set_skin", "skin"), &ImporterMeshInstance3D::set_skin);
ClassDB::bind_method(D_METHOD("get_skin"), &EditorSceneImporterMeshNode3D::get_skin); ClassDB::bind_method(D_METHOD("get_skin"), &ImporterMeshInstance3D::get_skin);
ClassDB::bind_method(D_METHOD("set_skeleton_path", "skeleton_path"), &EditorSceneImporterMeshNode3D::set_skeleton_path); ClassDB::bind_method(D_METHOD("set_skeleton_path", "skeleton_path"), &ImporterMeshInstance3D::set_skeleton_path);
ClassDB::bind_method(D_METHOD("get_skeleton_path"), &EditorSceneImporterMeshNode3D::get_skeleton_path); ClassDB::bind_method(D_METHOD("get_skeleton_path"), &ImporterMeshInstance3D::get_skeleton_path);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "EditorSceneImporterMesh"), "set_mesh", "get_mesh"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "ImporterMesh"), "set_mesh", "get_mesh");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skin", PROPERTY_HINT_RESOURCE_TYPE, "Skin"), "set_skin", "get_skin"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skin", PROPERTY_HINT_RESOURCE_TYPE, "Skin"), "set_skin", "get_skin");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Skeleton"), "set_skeleton_path", "get_skeleton_path"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Skeleton"), "set_skeleton_path", "get_skeleton_path");
} }

View file

@ -1,5 +1,5 @@
/*************************************************************************/ /*************************************************************************/
/* scene_importer_mesh_node_3d.h */ /* importer_mesh_instance_3d.h */
/*************************************************************************/ /*************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@ -28,19 +28,19 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/ /*************************************************************************/
#ifndef EDITOR_SCENE_IMPORTER_MESH_NODE_3D_H #ifndef SCENE_IMPORTER_MESH_INSTANCE_3D_H
#define EDITOR_SCENE_IMPORTER_MESH_NODE_3D_H #define SCENE_IMPORTER_MESH_INSTANCE_3D_H
#include "editor/import/scene_importer_mesh.h"
#include "scene/3d/node_3d.h" #include "scene/3d/node_3d.h"
#include "scene/resources/immediate_mesh.h"
#include "scene/resources/skin.h" #include "scene/resources/skin.h"
class EditorSceneImporterMesh; class ImporterMesh;
class EditorSceneImporterMeshNode3D : public Node3D { class ImporterMeshInstance3D : public Node3D {
GDCLASS(EditorSceneImporterMeshNode3D, Node3D) GDCLASS(ImporterMeshInstance3D, Node3D)
Ref<EditorSceneImporterMesh> mesh; Ref<ImporterMesh> mesh;
Ref<Skin> skin; Ref<Skin> skin;
NodePath skeleton_path; NodePath skeleton_path;
Vector<Ref<Material>> surface_materials; Vector<Ref<Material>> surface_materials;
@ -49,8 +49,8 @@ protected:
static void _bind_methods(); static void _bind_methods();
public: public:
void set_mesh(const Ref<EditorSceneImporterMesh> &p_mesh); void set_mesh(const Ref<ImporterMesh> &p_mesh);
Ref<EditorSceneImporterMesh> get_mesh() const; Ref<ImporterMesh> get_mesh() const;
void set_skin(const Ref<Skin> &p_skin); void set_skin(const Ref<Skin> &p_skin);
Ref<Skin> get_skin() const; Ref<Skin> get_skin() const;

View file

@ -215,6 +215,7 @@
#include "scene/3d/decal.h" #include "scene/3d/decal.h"
#include "scene/3d/gpu_particles_3d.h" #include "scene/3d/gpu_particles_3d.h"
#include "scene/3d/gpu_particles_collision_3d.h" #include "scene/3d/gpu_particles_collision_3d.h"
#include "scene/3d/importer_mesh_instance_3d.h"
#include "scene/3d/joint_3d.h" #include "scene/3d/joint_3d.h"
#include "scene/3d/light_3d.h" #include "scene/3d/light_3d.h"
#include "scene/3d/lightmap_gi.h" #include "scene/3d/lightmap_gi.h"
@ -244,6 +245,7 @@
#include "scene/3d/world_environment.h" #include "scene/3d/world_environment.h"
#include "scene/3d/xr_nodes.h" #include "scene/3d/xr_nodes.h"
#include "scene/resources/environment.h" #include "scene/resources/environment.h"
#include "scene/resources/importer_mesh.h"
#include "scene/resources/mesh_library.h" #include "scene/resources/mesh_library.h"
#endif #endif
@ -441,6 +443,8 @@ void register_scene_types() {
GDREGISTER_CLASS(Skin); GDREGISTER_CLASS(Skin);
GDREGISTER_VIRTUAL_CLASS(SkinReference); GDREGISTER_VIRTUAL_CLASS(SkinReference);
GDREGISTER_CLASS(Skeleton3D); GDREGISTER_CLASS(Skeleton3D);
GDREGISTER_CLASS(ImporterMesh);
GDREGISTER_CLASS(ImporterMeshInstance3D);
GDREGISTER_VIRTUAL_CLASS(VisualInstance3D); GDREGISTER_VIRTUAL_CLASS(VisualInstance3D);
GDREGISTER_VIRTUAL_CLASS(GeometryInstance3D); GDREGISTER_VIRTUAL_CLASS(GeometryInstance3D);
GDREGISTER_CLASS(Camera3D); GDREGISTER_CLASS(Camera3D);

View file

@ -1,5 +1,5 @@
/*************************************************************************/ /*************************************************************************/
/* scene_importer_mesh.cpp */ /* importer_mesh.cpp */
/*************************************************************************/ /*************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/ /*************************************************************************/
#include "scene_importer_mesh.h" #include "importer_mesh.h"
#include "core/math/random_pcg.h" #include "core/math/random_pcg.h"
#include "core/math/static_raycaster.h" #include "core/math/static_raycaster.h"
@ -36,7 +36,7 @@
#include <cstdint> #include <cstdint>
void EditorSceneImporterMesh::Surface::split_normals(const LocalVector<int> &p_indices, const LocalVector<Vector3> &p_normals) { void ImporterMesh::Surface::split_normals(const LocalVector<int> &p_indices, const LocalVector<Vector3> &p_normals) {
ERR_FAIL_COND(arrays.size() != RS::ARRAY_MAX); ERR_FAIL_COND(arrays.size() != RS::ARRAY_MAX);
const PackedVector3Array &vertices = arrays[RS::ARRAY_VERTEX]; const PackedVector3Array &vertices = arrays[RS::ARRAY_VERTEX];
@ -124,29 +124,29 @@ void EditorSceneImporterMesh::Surface::split_normals(const LocalVector<int> &p_i
} }
} }
void EditorSceneImporterMesh::add_blend_shape(const String &p_name) { void ImporterMesh::add_blend_shape(const String &p_name) {
ERR_FAIL_COND(surfaces.size() > 0); ERR_FAIL_COND(surfaces.size() > 0);
blend_shapes.push_back(p_name); blend_shapes.push_back(p_name);
} }
int EditorSceneImporterMesh::get_blend_shape_count() const { int ImporterMesh::get_blend_shape_count() const {
return blend_shapes.size(); return blend_shapes.size();
} }
String EditorSceneImporterMesh::get_blend_shape_name(int p_blend_shape) const { String ImporterMesh::get_blend_shape_name(int p_blend_shape) const {
ERR_FAIL_INDEX_V(p_blend_shape, blend_shapes.size(), String()); ERR_FAIL_INDEX_V(p_blend_shape, blend_shapes.size(), String());
return blend_shapes[p_blend_shape]; return blend_shapes[p_blend_shape];
} }
void EditorSceneImporterMesh::set_blend_shape_mode(Mesh::BlendShapeMode p_blend_shape_mode) { void ImporterMesh::set_blend_shape_mode(Mesh::BlendShapeMode p_blend_shape_mode) {
blend_shape_mode = p_blend_shape_mode; blend_shape_mode = p_blend_shape_mode;
} }
Mesh::BlendShapeMode EditorSceneImporterMesh::get_blend_shape_mode() const { Mesh::BlendShapeMode ImporterMesh::get_blend_shape_mode() const {
return blend_shape_mode; return blend_shape_mode;
} }
void EditorSceneImporterMesh::add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, const Ref<Material> &p_material, const String &p_name, const uint32_t p_flags) { void ImporterMesh::add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, const Ref<Material> &p_material, const String &p_name, const uint32_t p_flags) {
ERR_FAIL_COND(p_blend_shapes.size() != blend_shapes.size()); ERR_FAIL_COND(p_blend_shapes.size() != blend_shapes.size());
ERR_FAIL_COND(p_arrays.size() != Mesh::ARRAY_MAX); ERR_FAIL_COND(p_arrays.size() != Mesh::ARRAY_MAX);
Surface s; Surface s;
@ -186,67 +186,67 @@ void EditorSceneImporterMesh::add_surface(Mesh::PrimitiveType p_primitive, const
mesh.unref(); mesh.unref();
} }
int EditorSceneImporterMesh::get_surface_count() const { int ImporterMesh::get_surface_count() const {
return surfaces.size(); return surfaces.size();
} }
Mesh::PrimitiveType EditorSceneImporterMesh::get_surface_primitive_type(int p_surface) { Mesh::PrimitiveType ImporterMesh::get_surface_primitive_type(int p_surface) {
ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Mesh::PRIMITIVE_MAX); ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Mesh::PRIMITIVE_MAX);
return surfaces[p_surface].primitive; return surfaces[p_surface].primitive;
} }
Array EditorSceneImporterMesh::get_surface_arrays(int p_surface) const { Array ImporterMesh::get_surface_arrays(int p_surface) const {
ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array()); ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array());
return surfaces[p_surface].arrays; return surfaces[p_surface].arrays;
} }
String EditorSceneImporterMesh::get_surface_name(int p_surface) const { String ImporterMesh::get_surface_name(int p_surface) const {
ERR_FAIL_INDEX_V(p_surface, surfaces.size(), String()); ERR_FAIL_INDEX_V(p_surface, surfaces.size(), String());
return surfaces[p_surface].name; return surfaces[p_surface].name;
} }
void EditorSceneImporterMesh::set_surface_name(int p_surface, const String &p_name) { void ImporterMesh::set_surface_name(int p_surface, const String &p_name) {
ERR_FAIL_INDEX(p_surface, surfaces.size()); ERR_FAIL_INDEX(p_surface, surfaces.size());
surfaces.write[p_surface].name = p_name; surfaces.write[p_surface].name = p_name;
mesh.unref(); mesh.unref();
} }
Array EditorSceneImporterMesh::get_surface_blend_shape_arrays(int p_surface, int p_blend_shape) const { Array ImporterMesh::get_surface_blend_shape_arrays(int p_surface, int p_blend_shape) const {
ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array()); ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array());
ERR_FAIL_INDEX_V(p_blend_shape, surfaces[p_surface].blend_shape_data.size(), Array()); ERR_FAIL_INDEX_V(p_blend_shape, surfaces[p_surface].blend_shape_data.size(), Array());
return surfaces[p_surface].blend_shape_data[p_blend_shape].arrays; return surfaces[p_surface].blend_shape_data[p_blend_shape].arrays;
} }
int EditorSceneImporterMesh::get_surface_lod_count(int p_surface) const { int ImporterMesh::get_surface_lod_count(int p_surface) const {
ERR_FAIL_INDEX_V(p_surface, surfaces.size(), 0); ERR_FAIL_INDEX_V(p_surface, surfaces.size(), 0);
return surfaces[p_surface].lods.size(); return surfaces[p_surface].lods.size();
} }
Vector<int> EditorSceneImporterMesh::get_surface_lod_indices(int p_surface, int p_lod) const { Vector<int> ImporterMesh::get_surface_lod_indices(int p_surface, int p_lod) const {
ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Vector<int>()); ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Vector<int>());
ERR_FAIL_INDEX_V(p_lod, surfaces[p_surface].lods.size(), Vector<int>()); ERR_FAIL_INDEX_V(p_lod, surfaces[p_surface].lods.size(), Vector<int>());
return surfaces[p_surface].lods[p_lod].indices; return surfaces[p_surface].lods[p_lod].indices;
} }
float EditorSceneImporterMesh::get_surface_lod_size(int p_surface, int p_lod) const { float ImporterMesh::get_surface_lod_size(int p_surface, int p_lod) const {
ERR_FAIL_INDEX_V(p_surface, surfaces.size(), 0); ERR_FAIL_INDEX_V(p_surface, surfaces.size(), 0);
ERR_FAIL_INDEX_V(p_lod, surfaces[p_surface].lods.size(), 0); ERR_FAIL_INDEX_V(p_lod, surfaces[p_surface].lods.size(), 0);
return surfaces[p_surface].lods[p_lod].distance; return surfaces[p_surface].lods[p_lod].distance;
} }
uint32_t EditorSceneImporterMesh::get_surface_format(int p_surface) const { uint32_t ImporterMesh::get_surface_format(int p_surface) const {
ERR_FAIL_INDEX_V(p_surface, surfaces.size(), 0); ERR_FAIL_INDEX_V(p_surface, surfaces.size(), 0);
return surfaces[p_surface].flags; return surfaces[p_surface].flags;
} }
Ref<Material> EditorSceneImporterMesh::get_surface_material(int p_surface) const { Ref<Material> ImporterMesh::get_surface_material(int p_surface) const {
ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Ref<Material>()); ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Ref<Material>());
return surfaces[p_surface].material; return surfaces[p_surface].material;
} }
void EditorSceneImporterMesh::set_surface_material(int p_surface, const Ref<Material> &p_material) { void ImporterMesh::set_surface_material(int p_surface, const Ref<Material> &p_material) {
ERR_FAIL_INDEX(p_surface, surfaces.size()); ERR_FAIL_INDEX(p_surface, surfaces.size());
surfaces.write[p_surface].material = p_material; surfaces.write[p_surface].material = p_material;
mesh.unref(); mesh.unref();
} }
void EditorSceneImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_split_angle) { void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_split_angle) {
if (!SurfaceTool::simplify_scale_func) { if (!SurfaceTool::simplify_scale_func) {
return; return;
} }
@ -608,11 +608,11 @@ void EditorSceneImporterMesh::generate_lods(float p_normal_merge_angle, float p_
} }
} }
bool EditorSceneImporterMesh::has_mesh() const { bool ImporterMesh::has_mesh() const {
return mesh.is_valid(); return mesh.is_valid();
} }
Ref<ArrayMesh> EditorSceneImporterMesh::get_mesh(const Ref<ArrayMesh> &p_base) { Ref<ArrayMesh> ImporterMesh::get_mesh(const Ref<ArrayMesh> &p_base) {
ERR_FAIL_COND_V(surfaces.size() == 0, Ref<ArrayMesh>()); ERR_FAIL_COND_V(surfaces.size() == 0, Ref<ArrayMesh>());
if (mesh.is_null()) { if (mesh.is_null()) {
@ -664,13 +664,13 @@ Ref<ArrayMesh> EditorSceneImporterMesh::get_mesh(const Ref<ArrayMesh> &p_base) {
return mesh; return mesh;
} }
void EditorSceneImporterMesh::clear() { void ImporterMesh::clear() {
surfaces.clear(); surfaces.clear();
blend_shapes.clear(); blend_shapes.clear();
mesh.unref(); mesh.unref();
} }
void EditorSceneImporterMesh::create_shadow_mesh() { void ImporterMesh::create_shadow_mesh() {
if (shadow_mesh.is_valid()) { if (shadow_mesh.is_valid()) {
shadow_mesh.unref(); shadow_mesh.unref();
} }
@ -763,11 +763,11 @@ void EditorSceneImporterMesh::create_shadow_mesh() {
} }
} }
Ref<EditorSceneImporterMesh> EditorSceneImporterMesh::get_shadow_mesh() const { Ref<ImporterMesh> ImporterMesh::get_shadow_mesh() const {
return shadow_mesh; return shadow_mesh;
} }
void EditorSceneImporterMesh::_set_data(const Dictionary &p_data) { void ImporterMesh::_set_data(const Dictionary &p_data) {
clear(); clear();
if (p_data.has("blend_shape_names")) { if (p_data.has("blend_shape_names")) {
blend_shapes = p_data["blend_shape_names"]; blend_shapes = p_data["blend_shape_names"];
@ -805,7 +805,7 @@ void EditorSceneImporterMesh::_set_data(const Dictionary &p_data) {
} }
} }
} }
Dictionary EditorSceneImporterMesh::_get_data() const { Dictionary ImporterMesh::_get_data() const {
Dictionary data; Dictionary data;
if (blend_shapes.size()) { if (blend_shapes.size()) {
data["blend_shape_names"] = blend_shapes; data["blend_shape_names"] = blend_shapes;
@ -848,7 +848,7 @@ Dictionary EditorSceneImporterMesh::_get_data() const {
return data; return data;
} }
Vector<Face3> EditorSceneImporterMesh::get_faces() const { Vector<Face3> ImporterMesh::get_faces() const {
Vector<Face3> faces; Vector<Face3> faces;
for (int i = 0; i < surfaces.size(); i++) { for (int i = 0; i < surfaces.size(); i++) {
if (surfaces[i].primitive == Mesh::PRIMITIVE_TRIANGLES) { if (surfaces[i].primitive == Mesh::PRIMITIVE_TRIANGLES) {
@ -877,7 +877,7 @@ Vector<Face3> EditorSceneImporterMesh::get_faces() const {
return faces; return faces;
} }
Vector<Ref<Shape3D>> EditorSceneImporterMesh::convex_decompose(const Mesh::ConvexDecompositionSettings &p_settings) const { Vector<Ref<Shape3D>> ImporterMesh::convex_decompose(const Mesh::ConvexDecompositionSettings &p_settings) const {
ERR_FAIL_COND_V(!Mesh::convex_decomposition_function, Vector<Ref<Shape3D>>()); ERR_FAIL_COND_V(!Mesh::convex_decomposition_function, Vector<Ref<Shape3D>>());
const Vector<Face3> faces = get_faces(); const Vector<Face3> faces = get_faces();
@ -924,7 +924,7 @@ Vector<Ref<Shape3D>> EditorSceneImporterMesh::convex_decompose(const Mesh::Conve
return ret; return ret;
} }
Ref<Shape3D> EditorSceneImporterMesh::create_trimesh_shape() const { Ref<Shape3D> ImporterMesh::create_trimesh_shape() const {
Vector<Face3> faces = get_faces(); Vector<Face3> faces = get_faces();
if (faces.size() == 0) { if (faces.size() == 0) {
return Ref<Shape3D>(); return Ref<Shape3D>();
@ -945,7 +945,7 @@ Ref<Shape3D> EditorSceneImporterMesh::create_trimesh_shape() const {
return shape; return shape;
} }
Ref<NavigationMesh> EditorSceneImporterMesh::create_navigation_mesh() { Ref<NavigationMesh> ImporterMesh::create_navigation_mesh() {
Vector<Face3> faces = get_faces(); Vector<Face3> faces = get_faces();
if (faces.size() == 0) { if (faces.size() == 0) {
return Ref<NavigationMesh>(); return Ref<NavigationMesh>();
@ -1000,7 +1000,7 @@ struct EditorSceneImporterMeshLightmapSurface {
String name; String name;
}; };
Error EditorSceneImporterMesh::lightmap_unwrap_cached(const Transform3D &p_base_transform, float p_texel_size, const Vector<uint8_t> &p_src_cache, Vector<uint8_t> &r_dst_cache) { Error ImporterMesh::lightmap_unwrap_cached(const Transform3D &p_base_transform, float p_texel_size, const Vector<uint8_t> &p_src_cache, Vector<uint8_t> &r_dst_cache) {
ERR_FAIL_COND_V(!array_mesh_lightmap_unwrap_callback, ERR_UNCONFIGURED); ERR_FAIL_COND_V(!array_mesh_lightmap_unwrap_callback, ERR_UNCONFIGURED);
ERR_FAIL_COND_V_MSG(blend_shapes.size() != 0, ERR_UNAVAILABLE, "Can't unwrap mesh with blend shapes."); ERR_FAIL_COND_V_MSG(blend_shapes.size() != 0, ERR_UNAVAILABLE, "Can't unwrap mesh with blend shapes.");
@ -1197,46 +1197,46 @@ Error EditorSceneImporterMesh::lightmap_unwrap_cached(const Transform3D &p_base_
return OK; return OK;
} }
void EditorSceneImporterMesh::set_lightmap_size_hint(const Size2i &p_size) { void ImporterMesh::set_lightmap_size_hint(const Size2i &p_size) {
lightmap_size_hint = p_size; lightmap_size_hint = p_size;
} }
Size2i EditorSceneImporterMesh::get_lightmap_size_hint() const { Size2i ImporterMesh::get_lightmap_size_hint() const {
return lightmap_size_hint; return lightmap_size_hint;
} }
void EditorSceneImporterMesh::_bind_methods() { void ImporterMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_blend_shape", "name"), &EditorSceneImporterMesh::add_blend_shape); ClassDB::bind_method(D_METHOD("add_blend_shape", "name"), &ImporterMesh::add_blend_shape);
ClassDB::bind_method(D_METHOD("get_blend_shape_count"), &EditorSceneImporterMesh::get_blend_shape_count); ClassDB::bind_method(D_METHOD("get_blend_shape_count"), &ImporterMesh::get_blend_shape_count);
ClassDB::bind_method(D_METHOD("get_blend_shape_name", "blend_shape_idx"), &EditorSceneImporterMesh::get_blend_shape_name); ClassDB::bind_method(D_METHOD("get_blend_shape_name", "blend_shape_idx"), &ImporterMesh::get_blend_shape_name);
ClassDB::bind_method(D_METHOD("set_blend_shape_mode", "mode"), &EditorSceneImporterMesh::set_blend_shape_mode); ClassDB::bind_method(D_METHOD("set_blend_shape_mode", "mode"), &ImporterMesh::set_blend_shape_mode);
ClassDB::bind_method(D_METHOD("get_blend_shape_mode"), &EditorSceneImporterMesh::get_blend_shape_mode); ClassDB::bind_method(D_METHOD("get_blend_shape_mode"), &ImporterMesh::get_blend_shape_mode);
ClassDB::bind_method(D_METHOD("add_surface", "primitive", "arrays", "blend_shapes", "lods", "material", "name", "flags"), &EditorSceneImporterMesh::add_surface, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(Ref<Material>()), DEFVAL(String()), DEFVAL(0)); ClassDB::bind_method(D_METHOD("add_surface", "primitive", "arrays", "blend_shapes", "lods", "material", "name", "flags"), &ImporterMesh::add_surface, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(Ref<Material>()), DEFVAL(String()), DEFVAL(0));
ClassDB::bind_method(D_METHOD("get_surface_count"), &EditorSceneImporterMesh::get_surface_count); ClassDB::bind_method(D_METHOD("get_surface_count"), &ImporterMesh::get_surface_count);
ClassDB::bind_method(D_METHOD("get_surface_primitive_type", "surface_idx"), &EditorSceneImporterMesh::get_surface_primitive_type); ClassDB::bind_method(D_METHOD("get_surface_primitive_type", "surface_idx"), &ImporterMesh::get_surface_primitive_type);
ClassDB::bind_method(D_METHOD("get_surface_name", "surface_idx"), &EditorSceneImporterMesh::get_surface_name); ClassDB::bind_method(D_METHOD("get_surface_name", "surface_idx"), &ImporterMesh::get_surface_name);
ClassDB::bind_method(D_METHOD("get_surface_arrays", "surface_idx"), &EditorSceneImporterMesh::get_surface_arrays); ClassDB::bind_method(D_METHOD("get_surface_arrays", "surface_idx"), &ImporterMesh::get_surface_arrays);
ClassDB::bind_method(D_METHOD("get_surface_blend_shape_arrays", "surface_idx", "blend_shape_idx"), &EditorSceneImporterMesh::get_surface_blend_shape_arrays); ClassDB::bind_method(D_METHOD("get_surface_blend_shape_arrays", "surface_idx", "blend_shape_idx"), &ImporterMesh::get_surface_blend_shape_arrays);
ClassDB::bind_method(D_METHOD("get_surface_lod_count", "surface_idx"), &EditorSceneImporterMesh::get_surface_lod_count); ClassDB::bind_method(D_METHOD("get_surface_lod_count", "surface_idx"), &ImporterMesh::get_surface_lod_count);
ClassDB::bind_method(D_METHOD("get_surface_lod_size", "surface_idx", "lod_idx"), &EditorSceneImporterMesh::get_surface_lod_size); ClassDB::bind_method(D_METHOD("get_surface_lod_size", "surface_idx", "lod_idx"), &ImporterMesh::get_surface_lod_size);
ClassDB::bind_method(D_METHOD("get_surface_lod_indices", "surface_idx", "lod_idx"), &EditorSceneImporterMesh::get_surface_lod_indices); ClassDB::bind_method(D_METHOD("get_surface_lod_indices", "surface_idx", "lod_idx"), &ImporterMesh::get_surface_lod_indices);
ClassDB::bind_method(D_METHOD("get_surface_material", "surface_idx"), &EditorSceneImporterMesh::get_surface_material); ClassDB::bind_method(D_METHOD("get_surface_material", "surface_idx"), &ImporterMesh::get_surface_material);
ClassDB::bind_method(D_METHOD("get_surface_format", "surface_idx"), &EditorSceneImporterMesh::get_surface_format); ClassDB::bind_method(D_METHOD("get_surface_format", "surface_idx"), &ImporterMesh::get_surface_format);
ClassDB::bind_method(D_METHOD("set_surface_name", "surface_idx", "name"), &EditorSceneImporterMesh::set_surface_name); ClassDB::bind_method(D_METHOD("set_surface_name", "surface_idx", "name"), &ImporterMesh::set_surface_name);
ClassDB::bind_method(D_METHOD("set_surface_material", "surface_idx", "material"), &EditorSceneImporterMesh::set_surface_material); ClassDB::bind_method(D_METHOD("set_surface_material", "surface_idx", "material"), &ImporterMesh::set_surface_material);
ClassDB::bind_method(D_METHOD("get_mesh", "base_mesh"), &EditorSceneImporterMesh::get_mesh, DEFVAL(Ref<ArrayMesh>())); ClassDB::bind_method(D_METHOD("get_mesh", "base_mesh"), &ImporterMesh::get_mesh, DEFVAL(Ref<ArrayMesh>()));
ClassDB::bind_method(D_METHOD("clear"), &EditorSceneImporterMesh::clear); ClassDB::bind_method(D_METHOD("clear"), &ImporterMesh::clear);
ClassDB::bind_method(D_METHOD("_set_data", "data"), &EditorSceneImporterMesh::_set_data); ClassDB::bind_method(D_METHOD("_set_data", "data"), &ImporterMesh::_set_data);
ClassDB::bind_method(D_METHOD("_get_data"), &EditorSceneImporterMesh::_get_data); ClassDB::bind_method(D_METHOD("_get_data"), &ImporterMesh::_get_data);
ClassDB::bind_method(D_METHOD("set_lightmap_size_hint", "size"), &EditorSceneImporterMesh::set_lightmap_size_hint); ClassDB::bind_method(D_METHOD("set_lightmap_size_hint", "size"), &ImporterMesh::set_lightmap_size_hint);
ClassDB::bind_method(D_METHOD("get_lightmap_size_hint"), &EditorSceneImporterMesh::get_lightmap_size_hint); ClassDB::bind_method(D_METHOD("get_lightmap_size_hint"), &ImporterMesh::get_lightmap_size_hint);
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_data", "_get_data"); ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_data", "_get_data");
} }

View file

@ -1,5 +1,5 @@
/*************************************************************************/ /*************************************************************************/
/* scene_importer_mesh.h */ /* importer_mesh.h */
/*************************************************************************/ /*************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/ /*************************************************************************/
#ifndef EDITOR_SCENE_IMPORTER_MESH_H #ifndef SCENE_IMPORTER_MESH_H
#define EDITOR_SCENE_IMPORTER_MESH_H #define SCENE_IMPORTER_MESH_H
#include "core/io/resource.h" #include "core/io/resource.h"
#include "core/templates/local_vector.h" #include "core/templates/local_vector.h"
@ -44,8 +44,8 @@
// so the data is not registered (hence, quality loss), importing happens faster and // so the data is not registered (hence, quality loss), importing happens faster and
// its easier to modify before saving // its easier to modify before saving
class EditorSceneImporterMesh : public Resource { class ImporterMesh : public Resource {
GDCLASS(EditorSceneImporterMesh, Resource) GDCLASS(ImporterMesh, Resource)
struct Surface { struct Surface {
Mesh::PrimitiveType primitive; Mesh::PrimitiveType primitive;
@ -77,7 +77,7 @@ class EditorSceneImporterMesh : public Resource {
Ref<ArrayMesh> mesh; Ref<ArrayMesh> mesh;
Ref<EditorSceneImporterMesh> shadow_mesh; Ref<ImporterMesh> shadow_mesh;
Size2i lightmap_size_hint; Size2i lightmap_size_hint;
@ -114,7 +114,7 @@ public:
void generate_lods(float p_normal_merge_angle, float p_normal_split_angle); void generate_lods(float p_normal_merge_angle, float p_normal_split_angle);
void create_shadow_mesh(); void create_shadow_mesh();
Ref<EditorSceneImporterMesh> get_shadow_mesh() const; Ref<ImporterMesh> get_shadow_mesh() const;
Vector<Face3> get_faces() const; Vector<Face3> get_faces() const;
Vector<Ref<Shape3D>> convex_decompose(const Mesh::ConvexDecompositionSettings &p_settings) const; Vector<Ref<Shape3D>> convex_decompose(const Mesh::ConvexDecompositionSettings &p_settings) const;
@ -129,4 +129,4 @@ public:
Ref<ArrayMesh> get_mesh(const Ref<ArrayMesh> &p_base = Ref<ArrayMesh>()); Ref<ArrayMesh> get_mesh(const Ref<ArrayMesh> &p_base = Ref<ArrayMesh>());
void clear(); void clear();
}; };
#endif // EDITOR_SCENE_IMPORTER_MESH_H #endif // SCENE_IMPORTER_MESH_H

View file

@ -934,7 +934,7 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
} }
} }
ERR_FAIL_COND_V((bsformat) != (format & (RS::ARRAY_FORMAT_INDEX - 1)), ERR_INVALID_PARAMETER); ERR_FAIL_COND_V_MSG((bsformat) != (format & (ARRAY_FORMAT_VERTEX | ARRAY_FORMAT_NORMAL | ARRAY_FORMAT_TANGENT)), ERR_INVALID_PARAMETER, "Blend shape format must match the main array format for Vertex, Normal and Tangent arrays.");
} }
} }