Fix T100076: OBJ import: new importer doesn't use //relative/image/paths

The Python based importer had logic to immediately turn image paths
into relative-to-blender-file paths, if user preference for relative
paths is used (which is on by default). The new importer code did not
have that. Fixes T100076.
This commit is contained in:
Aras Pranckevicius 2022-08-01 13:39:08 +03:00
parent bea5281919
commit e2be6bc03f
Notes: blender-bot 2023-02-14 06:00:45 +01:00
Referenced by issue #100076, OBJ import: new importer doesn't use //relative/image/paths
7 changed files with 37 additions and 18 deletions

View File

@ -394,6 +394,7 @@ static int wm_obj_import_exec(bContext *C, wmOperator *op)
import_params.up_axis = RNA_enum_get(op->ptr, "up_axis");
import_params.import_vertex_groups = RNA_boolean_get(op->ptr, "import_vertex_groups");
import_params.validate_meshes = RNA_boolean_get(op->ptr, "validate_meshes");
import_params.relative_paths = ((U.flag & USER_RELPATHS) != 0);
OBJ_import(C, &import_params);

View File

@ -74,6 +74,7 @@ struct OBJImportParams {
eIOAxis up_axis;
bool import_vertex_groups;
bool validate_meshes;
bool relative_paths;
};
/**

View File

@ -57,7 +57,7 @@ Object *MeshFromGeometry::create_mesh(Main *bmain,
create_uv_verts(mesh);
create_normals(mesh);
create_colors(mesh);
create_materials(bmain, materials, created_materials, obj);
create_materials(bmain, materials, created_materials, obj, import_params.relative_paths);
if (import_params.validate_meshes || mesh_geometry_.has_invalid_polys_) {
bool verbose_validate = false;
@ -277,7 +277,8 @@ void MeshFromGeometry::create_uv_verts(Mesh *mesh)
static Material *get_or_create_material(Main *bmain,
const std::string &name,
Map<std::string, std::unique_ptr<MTLMaterial>> &materials,
Map<std::string, Material *> &created_materials)
Map<std::string, Material *> &created_materials,
bool relative_paths)
{
/* Have we created this material already? */
Material **found_mat = created_materials.lookup_ptr(name);
@ -291,7 +292,7 @@ static Material *get_or_create_material(Main *bmain,
const MTLMaterial &mtl = *materials.lookup_or_add(name, std::make_unique<MTLMaterial>());
Material *mat = BKE_material_add(bmain, name.c_str());
ShaderNodetreeWrap mat_wrap{bmain, mtl, mat};
ShaderNodetreeWrap mat_wrap{bmain, mtl, mat, relative_paths};
mat->use_nodes = true;
mat->nodetree = mat_wrap.get_nodetree();
BKE_ntree_update_main_tree(bmain, mat->nodetree, nullptr);
@ -303,10 +304,12 @@ static Material *get_or_create_material(Main *bmain,
void MeshFromGeometry::create_materials(Main *bmain,
Map<std::string, std::unique_ptr<MTLMaterial>> &materials,
Map<std::string, Material *> &created_materials,
Object *obj)
Object *obj,
bool relative_paths)
{
for (const std::string &name : mesh_geometry_.material_order_) {
Material *mat = get_or_create_material(bmain, name, materials, created_materials);
Material *mat = get_or_create_material(
bmain, name, materials, created_materials, relative_paths);
if (mat == nullptr) {
continue;
}

View File

@ -62,7 +62,8 @@ class MeshFromGeometry : NonMovable, NonCopyable {
void create_materials(Main *bmain,
Map<std::string, std::unique_ptr<MTLMaterial>> &materials,
Map<std::string, Material *> &created_materials,
Object *obj);
Object *obj,
bool relative_paths);
void create_normals(Mesh *mesh);
void create_colors(Mesh *mesh);
void create_vertex_groups(Object *obj);

View File

@ -5,10 +5,12 @@
*/
#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BLI_map.hh"
#include "BLI_math_vector.h"
#include "BLI_path_util.h"
#include "DNA_material_types.h"
#include "DNA_node_types.h"
@ -63,7 +65,8 @@ static void set_property_of_socket(eNodeSocketDatatype property_type,
static bool load_texture_image_at_path(Main *bmain,
const tex_map_XX &tex_map,
bNode *r_node,
const std::string &path)
const std::string &path,
bool relative_paths)
{
Image *tex_image = BKE_image_load_exists(bmain, path.c_str());
if (!tex_image) {
@ -71,6 +74,9 @@ static bool load_texture_image_at_path(Main *bmain,
return false;
}
fprintf(stderr, "Loaded image from: '%s'\n", path.c_str());
if (relative_paths) {
BLI_path_rel(tex_image->filepath, BKE_main_blendfile_path(bmain));
}
r_node->id = reinterpret_cast<ID *>(tex_image);
NodeTexImage *image = static_cast<NodeTexImage *>(r_node->storage);
image->projection = tex_map.projection_type;
@ -81,18 +87,21 @@ static bool load_texture_image_at_path(Main *bmain,
* Load image for Image Texture node and set the node properties.
* Return success if Image can be loaded successfully.
*/
static bool load_texture_image(Main *bmain, const tex_map_XX &tex_map, bNode *r_node)
static bool load_texture_image(Main *bmain,
const tex_map_XX &tex_map,
bNode *r_node,
bool relative_paths)
{
BLI_assert(r_node && r_node->type == SH_NODE_TEX_IMAGE);
/* First try treating texture path as relative. */
std::string tex_path{tex_map.mtl_dir_path + tex_map.image_path};
if (load_texture_image_at_path(bmain, tex_map, r_node, tex_path)) {
if (load_texture_image_at_path(bmain, tex_map, r_node, tex_path, relative_paths)) {
return true;
}
/* Then try using it directly as absolute path. */
std::string raw_path{tex_map.image_path};
if (load_texture_image_at_path(bmain, tex_map, r_node, raw_path)) {
if (load_texture_image_at_path(bmain, tex_map, r_node, raw_path, relative_paths)) {
return true;
}
/* Try removing quotes. */
@ -100,21 +109,24 @@ static bool load_texture_image(Main *bmain, const tex_map_XX &tex_map, bNode *r_
auto end_pos = std::remove(no_quote_path.begin(), no_quote_path.end(), '"');
no_quote_path.erase(end_pos, no_quote_path.end());
if (no_quote_path != tex_path &&
load_texture_image_at_path(bmain, tex_map, r_node, no_quote_path)) {
load_texture_image_at_path(bmain, tex_map, r_node, no_quote_path, relative_paths)) {
return true;
}
/* Try replacing underscores with spaces. */
std::string no_underscore_path{no_quote_path};
std::replace(no_underscore_path.begin(), no_underscore_path.end(), '_', ' ');
if (no_underscore_path != no_quote_path && no_underscore_path != tex_path &&
load_texture_image_at_path(bmain, tex_map, r_node, no_underscore_path)) {
load_texture_image_at_path(bmain, tex_map, r_node, no_underscore_path, relative_paths)) {
return true;
}
return false;
}
ShaderNodetreeWrap::ShaderNodetreeWrap(Main *bmain, const MTLMaterial &mtl_mat, Material *mat)
ShaderNodetreeWrap::ShaderNodetreeWrap(Main *bmain,
const MTLMaterial &mtl_mat,
Material *mat,
bool relative_paths)
: mtl_mat_(mtl_mat)
{
nodetree_.reset(ntreeAddTree(nullptr, "Shader Nodetree", ntreeType_Shader->idname));
@ -122,7 +134,7 @@ ShaderNodetreeWrap::ShaderNodetreeWrap(Main *bmain, const MTLMaterial &mtl_mat,
shader_output_ = add_node_to_tree(SH_NODE_OUTPUT_MATERIAL);
set_bsdf_socket_values(mat);
add_image_textures(bmain, mat);
add_image_textures(bmain, mat, relative_paths);
link_sockets(bsdf_, "BSDF", shader_output_, "Surface", 4);
nodeSetActive(nodetree_.get(), shader_output_);
@ -325,7 +337,7 @@ void ShaderNodetreeWrap::set_bsdf_socket_values(Material *mat)
}
}
void ShaderNodetreeWrap::add_image_textures(Main *bmain, Material *mat)
void ShaderNodetreeWrap::add_image_textures(Main *bmain, Material *mat, bool relative_paths)
{
for (const Map<const eMTLSyntaxElement, tex_map_XX>::Item texture_map :
mtl_mat_.texture_maps.items()) {
@ -335,7 +347,7 @@ void ShaderNodetreeWrap::add_image_textures(Main *bmain, Material *mat)
}
bNode *image_texture = add_node_to_tree(SH_NODE_TEX_IMAGE);
if (!load_texture_image(bmain, texture_map.value, image_texture)) {
if (!load_texture_image(bmain, texture_map.value, image_texture, relative_paths)) {
/* Image could not be added, so don't add or link further nodes. */
continue;
}

View File

@ -49,7 +49,7 @@ class ShaderNodetreeWrap {
* Initializes a nodetree with a p-BSDF node's BSDF socket connected to shader output node's
* surface socket.
*/
ShaderNodetreeWrap(Main *bmain, const MTLMaterial &mtl_mat, Material *mat);
ShaderNodetreeWrap(Main *bmain, const MTLMaterial &mtl_mat, Material *mat, bool relative_paths);
~ShaderNodetreeWrap();
/**
@ -87,7 +87,7 @@ class ShaderNodetreeWrap {
* Create image texture, vector and normal mapping nodes from MTL materials and link the
* nodes to p-BSDF node.
*/
void add_image_textures(Main *bmain, Material *mat);
void add_image_textures(Main *bmain, Material *mat, bool relative_paths);
};
} // namespace blender::io::obj

View File

@ -61,6 +61,7 @@ class obj_importer_test : public BlendfileLoadingBaseTest {
params.up_axis = IO_AXIS_Y;
params.validate_meshes = true;
params.import_vertex_groups = false;
params.relative_paths = true;
std::string obj_path = blender::tests::flags_test_asset_dir() + "/io_tests/obj/" + path;
strncpy(params.filepath, obj_path.c_str(), FILE_MAX - 1);