Skip to content

Commit

Permalink
Merge pull request #44319 from reduz/integrate-meshoptimizer
Browse files Browse the repository at this point in the history
Rework Mesh handling on scene importing.
  • Loading branch information
akien-mga authored Dec 14, 2020
2 parents b006faf + 77a045e commit fe49eaa
Show file tree
Hide file tree
Showing 33 changed files with 8,600 additions and 241 deletions.
3 changes: 3 additions & 0 deletions editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3654,6 +3654,9 @@ void EditorNode::register_editor_types() {
ClassDB::register_class<ScriptCreateDialog>();
ClassDB::register_class<EditorFeatureProfile>();
ClassDB::register_class<EditorSpinSlider>();
ClassDB::register_class<EditorSceneImporterMesh>();
ClassDB::register_class<EditorSceneImporterMeshNode>();

ClassDB::register_virtual_class<FileSystemDock>();

// FIXME: Is this stuff obsolete, or should it be ported to new APIs?
Expand Down
39 changes: 20 additions & 19 deletions editor/import/editor_import_collada.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ struct ColladaImport {

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, Ref<ArrayMesh>> mesh_cache;
Map<String, Ref<EditorSceneImporterMesh>> mesh_cache;
Map<String, Ref<Curve3D>> curve_cache;
Map<String, Ref<Material>> material_cache;
Map<Collada::Node *, Skeleton3D *> skeleton_map;
Expand All @@ -83,7 +83,7 @@ struct ColladaImport {
Error _create_scene(Collada::Node *p_node, Node3D *p_parent);
Error _create_resources(Collada::Node *p_node, bool p_use_compression);
Error _create_material(const String &p_target);
Error _create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<ArrayMesh>> p_morph_meshes = Vector<Ref<ArrayMesh>>(), bool p_use_compression = false, bool p_use_mesh_material = false);
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 Transform &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 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 create_animation(int p_clip, bool p_make_tracks_in_all_bones, bool p_import_value_tracks);
Expand Down Expand Up @@ -278,8 +278,8 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Node3D *p_parent) {
node = memnew(Path3D);
} else {
//mesh since nothing else
node = memnew(MeshInstance3D);
//Object::cast_to<MeshInstance3D>(node)->set_flag(GeometryInstance3D::FLAG_USE_BAKED_LIGHT, true);
node = memnew(EditorSceneImporterMeshNode);
//Object::cast_to<EditorSceneImporterMeshNode>(node)->set_flag(GeometryInstance3D::FLAG_USE_BAKED_LIGHT, true);
}
} break;
case Collada::Node::TYPE_SKELETON: {
Expand Down Expand Up @@ -440,7 +440,7 @@ Error ColladaImport::_create_material(const String &p_target) {
return OK;
}

Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<ArrayMesh>> p_morph_meshes, bool p_use_compression, bool p_use_mesh_material) {
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 Transform &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) {
bool local_xform_mirror = p_local_xform.basis.determinant() < 0;

if (p_morph_data) {
Expand All @@ -457,9 +457,9 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me
p_mesh->add_blend_shape(name);
}
if (p_morph_data->mode == "RELATIVE") {
p_mesh->set_blend_shape_mode(ArrayMesh::BLEND_SHAPE_MODE_RELATIVE);
p_mesh->set_blend_shape_mode(Mesh::BLEND_SHAPE_MODE_RELATIVE);
} else if (p_morph_data->mode == "NORMALIZED") {
p_mesh->set_blend_shape_mode(ArrayMesh::BLEND_SHAPE_MODE_NORMALIZED);
p_mesh->set_blend_shape_mode(Mesh::BLEND_SHAPE_MODE_NORMALIZED);
}
}

Expand Down Expand Up @@ -897,7 +897,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me
////////////////////////////

for (int mi = 0; mi < p_morph_meshes.size(); mi++) {
Array a = p_morph_meshes[mi]->surface_get_arrays(surface);
Array a = p_morph_meshes[mi]->get_surface_arrays(surface);
//add valid weight and bone arrays if they exist, TODO check if they are unique to shape (generally not)

if (has_weights) {
Expand All @@ -910,14 +910,15 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me
mr.push_back(a);
}

p_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, d, mr, Dictionary(), 0);

String surface_name;
Ref<Material> mat;
if (material.is_valid()) {
if (p_use_mesh_material) {
p_mesh->surface_set_material(surface, material);
mat = material;
}
p_mesh->surface_set_name(surface, material->get_name());
surface_name = material->get_name();
}
p_mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES, d, mr, Dictionary(), mat, surface_name);
}

/*****************/
Expand Down Expand Up @@ -1002,10 +1003,10 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres
}
}

if (Object::cast_to<MeshInstance3D>(node)) {
if (Object::cast_to<EditorSceneImporterMeshNode>(node)) {
Collada::NodeGeometry *ng2 = static_cast<Collada::NodeGeometry *>(p_node);

MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(node);
EditorSceneImporterMeshNode *mi = Object::cast_to<EditorSceneImporterMeshNode>(node);

ERR_FAIL_COND_V(!mi, ERR_BUG);

Expand All @@ -1014,7 +1015,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres
String meshid;
Transform apply_xform;
Vector<int> bone_remap;
Vector<Ref<ArrayMesh>> morphs;
Vector<Ref<EditorSceneImporterMesh>> morphs;

if (ng2->controller) {
String ngsource = ng2->source;
Expand Down Expand Up @@ -1083,10 +1084,10 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres
for (int i = 0; i < names.size(); i++) {
String meshid2 = names[i];
if (collada.state.mesh_data_map.has(meshid2)) {
Ref<ArrayMesh> mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
Ref<EditorSceneImporterMesh> mesh = Ref<EditorSceneImporterMesh>(memnew(EditorSceneImporterMesh));
const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid2];
mesh->set_name(meshdata.name);
Error err = _create_mesh_surfaces(false, mesh, ng2->material_map, meshdata, apply_xform, bone_remap, skin, nullptr, Vector<Ref<ArrayMesh>>(), false);
Error err = _create_mesh_surfaces(false, mesh, ng2->material_map, meshdata, apply_xform, bone_remap, skin, nullptr, Vector<Ref<EditorSceneImporterMesh>>(), false);
ERR_FAIL_COND_V(err, err);

morphs.push_back(mesh);
Expand All @@ -1109,15 +1110,15 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres
meshid = ng2->source;
}

Ref<ArrayMesh> mesh;
Ref<EditorSceneImporterMesh> mesh;
if (mesh_cache.has(meshid)) {
mesh = mesh_cache[meshid];
} else {
if (collada.state.mesh_data_map.has(meshid)) {
//bleh, must ignore invalid

ERR_FAIL_COND_V(!collada.state.mesh_data_map.has(meshid), ERR_INVALID_DATA);
mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
mesh = Ref<EditorSceneImporterMesh>(memnew(EditorSceneImporterMesh));
const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid];
mesh->set_name(meshdata.name);
Error err = _create_mesh_surfaces(morphs.size() == 0, mesh, ng2->material_map, meshdata, apply_xform, bone_remap, skin, morph, morphs, p_use_compression, use_mesh_builtin_materials);
Expand Down
37 changes: 21 additions & 16 deletions editor/import/editor_scene_importer_gltf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -970,15 +970,14 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
return OK;
}

uint32_t mesh_flags = 0;

Array meshes = state.json["meshes"];
for (GLTFMeshIndex i = 0; i < meshes.size(); i++) {
print_verbose("glTF: Parsing mesh: " + itos(i));
Dictionary d = meshes[i];

GLTFMesh mesh;
mesh.mesh.instance();
bool has_vertex_color = false;

ERR_FAIL_COND_V(!d.has("primitives"), ERR_PARSE_ERROR);

Expand Down Expand Up @@ -1034,6 +1033,7 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
}
if (a.has("COLOR_0")) {
array[Mesh::ARRAY_COLOR] = _decode_accessor_as_color(state, a["COLOR_0"], true);
has_vertex_color = true;
}
if (a.has("JOINTS_0")) {
array[Mesh::ARRAY_BONES] = _decode_accessor_as_ints(state, a["JOINTS_0"], true);
Expand Down Expand Up @@ -1112,7 +1112,7 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {

//ideally BLEND_SHAPE_MODE_RELATIVE since gltf2 stores in displacement
//but it could require a larger refactor?
mesh.mesh->set_blend_shape_mode(ArrayMesh::BLEND_SHAPE_MODE_NORMALIZED);
mesh.mesh->set_blend_shape_mode(Mesh::BLEND_SHAPE_MODE_NORMALIZED);

if (j == 0) {
const Array &target_names = extras.has("targetNames") ? (Array)extras["targetNames"] : Array();
Expand Down Expand Up @@ -1226,21 +1226,25 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
}

//just add it
mesh.mesh->add_surface_from_arrays(primitive, array, morphs, Dictionary(), mesh_flags);

Ref<Material> mat;
if (p.has("material")) {
const int material = p["material"];
ERR_FAIL_INDEX_V(material, state.materials.size(), ERR_FILE_CORRUPT);
const Ref<Material> &mat = state.materials[material];

mesh.mesh->surface_set_material(mesh.mesh->get_surface_count() - 1, mat);
} else {
Ref<StandardMaterial3D> mat;
mat.instance();
mat->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
Ref<StandardMaterial3D> mat3d = state.materials[material];
if (has_vertex_color) {
mat3d->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
}
mat = mat3d;

mesh.mesh->surface_set_material(mesh.mesh->get_surface_count() - 1, mat);
} else if (has_vertex_color) {
Ref<StandardMaterial3D> mat3d;
mat3d.instance();
mat3d->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
mat = mat3d;
}

mesh.mesh->add_surface(primitive, array, morphs, Dictionary(), mat);
}

mesh.blend_weights.resize(mesh.mesh->get_blend_shape_count());
Expand Down Expand Up @@ -1440,7 +1444,8 @@ Error EditorSceneImporterGLTF::_parse_materials(GLTFState &state) {
if (d.has("name")) {
material->set_name(d["name"]);
}
material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
//don't do this here only if vertex color exists
//material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);

if (d.has("pbrMetallicRoughness")) {
const Dictionary &mr = d["pbrMetallicRoughness"];
Expand Down Expand Up @@ -2586,12 +2591,12 @@ BoneAttachment3D *EditorSceneImporterGLTF::_generate_bone_attachment(GLTFState &
return bone_attachment;
}

MeshInstance3D *EditorSceneImporterGLTF::_generate_mesh_instance(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index) {
EditorSceneImporterMeshNode *EditorSceneImporterGLTF::_generate_mesh_instance(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index) {
const GLTFNode *gltf_node = state.nodes[node_index];

ERR_FAIL_INDEX_V(gltf_node->mesh, state.meshes.size(), nullptr);

MeshInstance3D *mi = memnew(MeshInstance3D);
EditorSceneImporterMeshNode *mi = memnew(EditorSceneImporterMeshNode);
print_verbose("glTF: Creating mesh for: " + gltf_node->name);

GLTFMesh &mesh = state.meshes.write[gltf_node->mesh];
Expand Down Expand Up @@ -3058,7 +3063,7 @@ void EditorSceneImporterGLTF::_process_mesh_instances(GLTFState &state, Node3D *
const GLTFSkinIndex skin_i = node->skin;

Map<GLTFNodeIndex, Node *>::Element *mi_element = state.scene_nodes.find(node_i);
MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(mi_element->get());
EditorSceneImporterMeshNode *mi = Object::cast_to<EditorSceneImporterMeshNode>(mi_element->get());
ERR_FAIL_COND(mi == nullptr);

const GLTFSkeletonIndex skel_i = state.skins[node->skin].skeleton;
Expand Down
8 changes: 4 additions & 4 deletions editor/import/editor_scene_importer_gltf.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

class AnimationPlayer;
class BoneAttachment3D;
class MeshInstance3D;
class EditorSceneImporterMeshNode;

class EditorSceneImporterGLTF : public EditorSceneImporter {
GDCLASS(EditorSceneImporterGLTF, EditorSceneImporter);
Expand Down Expand Up @@ -199,7 +199,7 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
};

struct GLTFMesh {
Ref<ArrayMesh> mesh;
Ref<EditorSceneImporterMesh> mesh;
Vector<float> blend_weights;
};

Expand Down Expand Up @@ -262,7 +262,7 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
Vector<GLTFAccessor> accessors;

Vector<GLTFMesh> meshes; //meshes are loaded directly, no reason not to.
Vector<Ref<Material>> materials;
Vector<Ref<StandardMaterial3D>> materials;

String scene_name;
Vector<int> root_nodes;
Expand Down Expand Up @@ -355,7 +355,7 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
Error _parse_animations(GLTFState &state);

BoneAttachment3D *_generate_bone_attachment(GLTFState &state, Skeleton3D *skeleton, const GLTFNodeIndex node_index);
MeshInstance3D *_generate_mesh_instance(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index);
EditorSceneImporterMeshNode *_generate_mesh_instance(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index);
Camera3D *_generate_camera(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index);
Light3D *_generate_light(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index);
Node3D *_generate_spatial(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index);
Expand Down
26 changes: 22 additions & 4 deletions editor/import/resource_importer_obj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_
String current_material_library;
String current_material;
String current_group;
uint32_t smooth_group = 0;
bool smoothing = true;

while (true) {
String l = f->get_line().strip_edges();
Expand Down Expand Up @@ -315,17 +317,26 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_
Vector3 vertex = vertices[vtx];
//if (weld_vertices)
// vertex.snap(Vector3(weld_tolerance, weld_tolerance, weld_tolerance));
if (!smoothing) {
smooth_group++;
}
surf_tool->set_smooth_group(smooth_group);
surf_tool->add_vertex(vertex);
}

face[1] = face[2];
}
} else if (l.begins_with("s ")) { //smoothing
String what = l.substr(2, l.length()).strip_edges();
bool do_smooth;
if (what == "off") {
surf_tool->add_smooth_group(false);
do_smooth = false;
} else {
surf_tool->add_smooth_group(true);
do_smooth = true;
}
if (do_smooth != smoothing) {
smooth_group++;
smoothing = do_smooth;
}
} else if (/*l.begins_with("g ") ||*/ l.begins_with("usemtl ") || (l.begins_with("o ") || f->eof_reached())) { //commit group to mesh
//groups are too annoying
Expand Down Expand Up @@ -426,8 +437,15 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
Node3D *scene = memnew(Node3D);

for (List<Ref<Mesh>>::Element *E = meshes.front(); E; E = E->next()) {
MeshInstance3D *mi = memnew(MeshInstance3D);
mi->set_mesh(E->get());
Ref<EditorSceneImporterMesh> mesh;
mesh.instance();
Ref<Mesh> m = E->get();
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));
}

EditorSceneImporterMeshNode *mi = memnew(EditorSceneImporterMeshNode);
mi->set_mesh(mesh);
mi->set_name(E->get()->get_name());
scene->add_child(mi);
mi->set_owner(scene);
Expand Down
Loading

0 comments on commit fe49eaa

Please sign in to comment.