Blender V5.0
fbx_import_material.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2025 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "BKE_image.hh"
10#include "BKE_lib_id.hh"
11#include "BKE_material.hh"
13#include "BKE_node_runtime.hh"
15
16#include "BLI_math_vector.hh"
17#include "BLI_path_utils.hh"
18#include "BLI_string.h"
19#include "BLI_string_utf8.h"
20
21#include "DNA_material_types.h"
22
23#include "NOD_shader.h"
24
26#include "IMB_imbuf_types.hh"
27
29
30#include "ufbx.h"
31
32namespace blender::io::fbx {
33
34/* Nodes are arranged in columns by type, with manually placed x coordinates
35 * based on node widths. */
36static constexpr float node_locx_texcoord = -880.0f;
37static constexpr float node_locx_mapping = -680.0f;
38static constexpr float node_locx_image = -480.0f;
39static constexpr float node_locx_normalmap = -200.0f;
40static constexpr float node_locx_bsdf = 0.0f;
41static constexpr float node_locx_output = 280.0f;
42
43/* Nodes are arranged in rows; one row for each image being used. */
44static constexpr float node_locy_top = 300.0f;
45static constexpr float node_locy_step = 300.0f;
46
47/* Add a node of the given type at the given location. */
48static bNode *add_node(bNodeTree *ntree, int type, float x, float y)
49{
50 bNode *node = bke::node_add_static_node(nullptr, *ntree, type);
51 node->location[0] = x;
52 node->location[1] = y;
53 return node;
54}
55
56static void link_sockets(bNodeTree *ntree,
57 bNode *from_node,
58 const char *from_node_id,
59 bNode *to_node,
60 const char *to_node_id)
61{
62 bNodeSocket *from_sock{bke::node_find_socket(*from_node, SOCK_OUT, from_node_id)};
63 bNodeSocket *to_sock{bke::node_find_socket(*to_node, SOCK_IN, to_node_id)};
64 BLI_assert(from_sock && to_sock);
65 bke::node_add_link(*ntree, *from_node, *from_sock, *to_node, *to_sock);
66}
67
68static void set_socket_float(const char *socket_id, const float value, bNode *node)
69{
70 bNodeSocket *socket{bke::node_find_socket(*node, SOCK_IN, socket_id)};
71 BLI_assert(socket && socket->type == SOCK_FLOAT);
72 bNodeSocketValueFloat *dst = socket->default_value_typed<bNodeSocketValueFloat>();
73 dst->value = value;
74}
75
76static void set_socket_rgb(const char *socket_id, float vr, float vg, float vb, bNode *node)
77{
78 bNodeSocket *socket{bke::node_find_socket(*node, SOCK_IN, socket_id)};
79 BLI_assert(socket && socket->type == SOCK_RGBA);
80 bNodeSocketValueRGBA *dst = socket->default_value_typed<bNodeSocketValueRGBA>();
81 dst->value[0] = vr;
82 dst->value[1] = vg;
83 dst->value[2] = vb;
84 dst->value[3] = 1.0f;
85}
86
87static void set_socket_vector(const char *socket_id, float vx, float vy, float vz, bNode *node)
88{
89 bNodeSocket *socket{bke::node_find_socket(*node, SOCK_IN, socket_id)};
90 BLI_assert(socket && socket->type == SOCK_VECTOR);
91 bNodeSocketValueVector *dst = socket->default_value_typed<bNodeSocketValueVector>();
92 dst->value[0] = vx;
93 dst->value[1] = vy;
94 dst->value[2] = vz;
95}
96
97static float set_bsdf_float_param(bNode *bsdf,
98 const ufbx_material_map &umap,
99 const char *socket,
100 float def,
101 float min = 0.0f,
102 float max = 1.0f,
103 float multiplier = 1.0f)
104{
105 if (!umap.has_value) {
106 return def * multiplier;
107 }
108 float value = umap.value_real * multiplier;
109 value = math::clamp(value, min, max);
110 set_socket_float(socket, value, bsdf);
111 return value;
112}
113
115 const ufbx_material_map &umap,
116 const char *socket,
117 float3 def,
118 float3 min = float3(0.0f),
119 float3 max = float3(1.0f))
120{
121 if (!umap.has_value || umap.value_components < 3) {
122 return def;
123 }
124 float3 value = float3(umap.value_vec3.x, umap.value_vec3.y, umap.value_vec3.z);
125 value = math::clamp(value, min, max);
126 set_socket_rgb(socket, value.x, value.y, value.z, bsdf);
127 return value;
128}
129
130static void set_bsdf_socket_values(bNode *bsdf, Material *mat, const ufbx_material &fmat)
131{
132 float3 base_color = set_bsdf_color_param(bsdf, fmat.pbr.base_color, "Base Color", float3(0.8f));
133 mat->r = base_color.x;
134 mat->g = base_color.y;
135 mat->b = base_color.z;
136
137 float roughness = set_bsdf_float_param(bsdf, fmat.pbr.roughness, "Roughness", 0.5f);
138 mat->roughness = roughness;
139
140 float metallic = set_bsdf_float_param(bsdf, fmat.pbr.metalness, "Metallic", 0.0f);
141 mat->metallic = metallic;
142
143 set_bsdf_float_param(bsdf, fmat.pbr.specular_ior, "IOR", 1.5f, 1.0f, 1000.0f);
144
145 set_bsdf_float_param(bsdf, fmat.pbr.opacity, "Alpha", 1.0f);
146
147 set_bsdf_float_param(bsdf, fmat.pbr.diffuse_roughness, "Diffuse Roughness", 0.0f);
148
149 set_bsdf_float_param(bsdf, fmat.pbr.subsurface_factor, "Subsurface Weight", 0.0f);
150 set_bsdf_float_param(bsdf, fmat.pbr.subsurface_scale, "Subsurface Scale", 0.05f);
151 set_bsdf_float_param(bsdf, fmat.pbr.subsurface_anisotropy, "Subsurface Anisotropy", 0.0f);
152
153 if (fmat.features.specular.enabled) {
154 float spec = set_bsdf_float_param(
155 bsdf, fmat.pbr.specular_factor, "Specular IOR Level", 0.25f, 0.0f, 1.0f, 2.0f);
156 mat->spec = spec;
157 set_bsdf_color_param(bsdf, fmat.pbr.specular_color, "Specular Tint", float3(1.0f));
158 set_bsdf_float_param(bsdf, fmat.pbr.specular_anisotropy, "Anisotropic", 0.0f);
159 set_bsdf_float_param(bsdf, fmat.pbr.specular_rotation, "Anisotropic Rotation", 0.0f);
160 }
161
162 if (ELEM(fmat.shader_type,
163 UFBX_SHADER_OSL_STANDARD_SURFACE,
164 UFBX_SHADER_ARNOLD_STANDARD_SURFACE,
165 UFBX_SHADER_3DS_MAX_PHYSICAL_MATERIAL,
166 UFBX_SHADER_3DS_MAX_PBR_METAL_ROUGH,
167 UFBX_SHADER_3DS_MAX_PBR_SPEC_GLOSS,
168 UFBX_SHADER_GLTF_MATERIAL,
169 UFBX_SHADER_BLENDER_PHONG) &&
170 fmat.features.transmission.enabled)
171 {
172 set_bsdf_float_param(bsdf, fmat.pbr.transmission_factor, "Transmission Weight", 0.0f);
173 }
174
175 if (fmat.features.coat.enabled) {
176 set_bsdf_float_param(bsdf, fmat.pbr.coat_factor, "Coat Weight", 0.0f);
177 set_bsdf_float_param(bsdf, fmat.pbr.coat_roughness, "Coat Roughness", 0.03f);
178 set_bsdf_float_param(bsdf, fmat.pbr.coat_ior, "Coat IOR", 1.5f, 1.0f, 4.0f);
179 set_bsdf_color_param(bsdf, fmat.pbr.coat_color, "Coat Tint", float3(1.0f));
180 }
181
182 if (fmat.features.sheen.enabled) {
183 set_bsdf_float_param(bsdf, fmat.pbr.sheen_factor, "Sheen Weight", 0.0f);
184 set_bsdf_float_param(bsdf, fmat.pbr.sheen_roughness, "Sheen Roughness", 0.5f);
185 set_bsdf_color_param(bsdf, fmat.pbr.sheen_color, "Sheen Tint", float3(1.0f));
186 }
187
189 bsdf, fmat.pbr.emission_factor, "Emission Strength", 0.0f, 0.0f, 1000000.0f);
191 fmat.pbr.emission_color,
192 "Emission Color",
193 float3(0.0f),
194 float3(0.0f),
195 float3(1000000.0f));
196
198 bsdf, fmat.pbr.thin_film_thickness, "Thin Film Thickness", 0.0f, 0.0f, 100000.0f);
199 set_bsdf_float_param(bsdf, fmat.pbr.thin_film_ior, "Thin Film IOR", 1.33f, 1.0f, 1000.0f);
200}
201
202static Image *create_placeholder_image(Main *bmain, const std::string &path)
203{
204 const float color[4] = {0, 0, 0, 1};
205 const char *name = BLI_path_basename(path.c_str());
207 bmain, 32, 32, name, 24, false, IMA_GENTYPE_BLANK, color, false, false, false);
208 STRNCPY(image->filepath, path.c_str());
209 image->source = IMA_SRC_FILE;
210 return image;
211}
212
213static Image *load_texture_image(Main *bmain, const std::string &file_dir, const ufbx_texture &tex)
214{
215 /* Check with filename directly. */
216 Image *image = BKE_image_load_exists(bmain, tex.filename.data);
217 /* Try loading as a relative path. */
218 if (image == nullptr) {
219 std::string path = file_dir + "/" + tex.filename.data;
220 image = BKE_image_load_exists(bmain, path.c_str());
221 }
222 /* Try loading with absolute path from FBX. */
223 if (image == nullptr) {
224 image = BKE_image_load_exists(bmain, tex.absolute_filename.data);
225 }
226
227 /* If still not found, try taking progressively longer parts of the absolute path,
228 * as relative to the file. */
229 if (image == nullptr) {
230 size_t pos = tex.absolute_filename.length;
231 do {
232 const char *parent_path = BLI_path_parent_dir_end(tex.absolute_filename.data, pos);
233 if (parent_path == nullptr) {
234 break;
235 }
236 char path[FILE_MAX];
237 BLI_path_join(path, sizeof(path), file_dir.c_str(), parent_path);
238 BLI_path_normalize(path);
239 image = BKE_image_load_exists(bmain, path);
240 pos = parent_path - tex.absolute_filename.data;
241 } while (image == nullptr);
242 }
243
244 /* Create dummy/placeholder image. */
245 if (image == nullptr) {
246 image = create_placeholder_image(bmain, tex.filename.data);
247 }
248
249 /* Use embedded data for this image, if we haven't done that yet. */
250 if (tex.content.size > 0 && (image == nullptr || !BKE_image_has_packedfile(image))) {
251 BKE_image_free_buffers(image); /* Free cached placeholder images. */
252 char *data_dup = MEM_malloc_arrayN<char>(tex.content.size, __func__);
253 memcpy(data_dup, tex.content.data, tex.content.size);
254 BKE_image_packfiles_from_mem(nullptr, image, data_dup, tex.content.size);
255
256 /* Make sure the image is not marked as "generated". */
257 image->source = IMA_SRC_FILE;
258 image->type = IMA_TYPE_IMAGE;
259 }
260
261 return image;
262}
263
265 ufbx_material_pbr_map slot;
266 const char *socket;
267};
269 {UFBX_MATERIAL_PBR_BASE_COLOR, "Base Color"},
270 {UFBX_MATERIAL_PBR_ROUGHNESS, "Roughness"},
271 {UFBX_MATERIAL_PBR_METALNESS, "Metallic"},
272 {UFBX_MATERIAL_PBR_DIFFUSE_ROUGHNESS, "Diffuse Roughness"},
273 {UFBX_MATERIAL_PBR_SPECULAR_FACTOR, "Specular IOR Level"},
274 {UFBX_MATERIAL_PBR_SPECULAR_COLOR, "Specular Tint"},
275 {UFBX_MATERIAL_PBR_SPECULAR_IOR, "IOR"},
276 {UFBX_MATERIAL_PBR_SPECULAR_ANISOTROPY, "Anisotropic"},
277 {UFBX_MATERIAL_PBR_SPECULAR_ROTATION, "Anisotropic Rotation"},
278 {UFBX_MATERIAL_PBR_TRANSMISSION_FACTOR, "Transmission Weight"},
279 {UFBX_MATERIAL_PBR_SUBSURFACE_FACTOR, "Subsurface Weight"},
280 {UFBX_MATERIAL_PBR_SUBSURFACE_SCALE, "Subsurface Scale"},
281 {UFBX_MATERIAL_PBR_SUBSURFACE_ANISOTROPY, "Subsurface Anisotropy"},
282 {UFBX_MATERIAL_PBR_SHEEN_FACTOR, "Sheen Weight"},
283 {UFBX_MATERIAL_PBR_SHEEN_COLOR, "Sheen Tint"},
284 {UFBX_MATERIAL_PBR_SHEEN_ROUGHNESS, "Sheen Roughness"},
285 {UFBX_MATERIAL_PBR_COAT_FACTOR, "Coat Weight"},
286 {UFBX_MATERIAL_PBR_COAT_COLOR, "Coat Tint"},
287 {UFBX_MATERIAL_PBR_COAT_ROUGHNESS, "Coat Roughness"},
288 {UFBX_MATERIAL_PBR_COAT_IOR, "Coat IOR"},
289 {UFBX_MATERIAL_PBR_COAT_NORMAL, "Coat Normal"},
290 {UFBX_MATERIAL_PBR_THIN_FILM_THICKNESS, "Thin Film Thickness"},
291 {UFBX_MATERIAL_PBR_THIN_FILM_IOR, "Thin Film IOR"},
292 {UFBX_MATERIAL_PBR_EMISSION_FACTOR, "Emission Strength"},
293 {UFBX_MATERIAL_PBR_EMISSION_COLOR, "Emission Color"},
294 {UFBX_MATERIAL_PBR_OPACITY, "Alpha"},
295 {UFBX_MATERIAL_PBR_NORMAL_MAP, "Normal"},
296 {UFBX_MATERIAL_PBR_TANGENT_MAP, "Tangent"},
297};
298
300 ufbx_material_fbx_map slot;
301 const char *socket;
302};
304 {UFBX_MATERIAL_FBX_TRANSPARENCY_FACTOR, "Alpha"},
305 {UFBX_MATERIAL_FBX_TRANSPARENCY_COLOR, "Alpha"},
306 {UFBX_MATERIAL_FBX_BUMP, "Normal"},
307};
308
309static void add_image_texture(Main *bmain,
310 const std::string &file_dir,
311 bNodeTree *ntree,
312 bNode *bsdf,
313 const ufbx_material &fmat,
314 const ufbx_texture *ftex,
315 const char *socket_name,
316 float node_locy,
317 Set<StringRefNull> &done_bsdf_inputs)
318{
319 Image *image = load_texture_image(bmain, file_dir, *ftex);
320 BLI_assert(image != nullptr);
321
322 /* Set "non-color" color space for all "data" textures. */
323 if (!STR_ELEM(
324 socket_name, "Base Color", "Specular Tint", "Sheen Tint", "Coat Tint", "Emission Color"))
325 {
328 }
329
330 /* Add texture node and any UV transformations if needed. */
331 bNode *image_node = add_node(ntree, SH_NODE_TEX_IMAGE, node_locx_image, node_locy);
332 BLI_assert(image_node);
333 image_node->id = &image->id;
334 NodeTexImage *tex_image = static_cast<NodeTexImage *>(image_node->storage);
335
336 /* Wrap mode. */
338 if (ftex->wrap_u == UFBX_WRAP_CLAMP || ftex->wrap_v == UFBX_WRAP_CLAMP) {
340 }
341
342 /* UV transform. */
343 if (ftex->has_uv_transform) {
344 /* TODO: which UV set to use. */
345 bNode *uvmap = add_node(ntree, SH_NODE_UVMAP, node_locx_texcoord, node_locy);
346 bNode *mapping = add_node(ntree, SH_NODE_MAPPING, node_locx_mapping, node_locy);
347 mapping->custom1 = TEXMAP_TYPE_TEXTURE;
348 set_socket_vector("Location",
349 ftex->uv_transform.translation.x,
350 ftex->uv_transform.translation.y,
351 ftex->uv_transform.translation.z,
352 mapping);
353 ufbx_vec3 rot = ufbx_quat_to_euler(ftex->uv_transform.rotation, UFBX_ROTATION_ORDER_XYZ);
354 set_socket_vector("Rotation", -rot.x, -rot.y, -rot.z, mapping);
355 set_socket_vector("Scale",
356 1.0f / ftex->uv_transform.scale.x,
357 1.0f / ftex->uv_transform.scale.y,
358 1.0f / ftex->uv_transform.scale.z,
359 mapping);
360
361 link_sockets(ntree, uvmap, "UV", mapping, "Vector");
362 link_sockets(ntree, mapping, "Vector", image_node, "Vector");
363 }
364
365 done_bsdf_inputs.add(socket_name);
366 if (STREQ(socket_name, "Normal")) {
367 bNode *normal_node = add_node(ntree, SH_NODE_NORMAL_MAP, node_locx_normalmap, node_locy);
368 link_sockets(ntree, image_node, "Color", normal_node, "Color");
369 link_sockets(ntree, normal_node, "Normal", bsdf, "Normal");
370
371 /* Normal strength: Blender exports it as BumpFactor in FBX built-in properties. */
372 float normal_strength = 1.0f;
373 if (fmat.fbx.bump_factor.has_value) {
374 normal_strength = fmat.fbx.bump_factor.value_real;
375 }
376 set_socket_float("Strength", normal_strength, normal_node);
377 }
378 else {
379 link_sockets(ntree, image_node, "Color", bsdf, socket_name);
380
381 if (STREQ(socket_name, "Base Color") && !done_bsdf_inputs.contains("Alpha")) {
382 /* Link base color alpha (if we have one) to output alpha. */
383 void *lock;
384 ImBuf *ibuf = BKE_image_acquire_ibuf(image, nullptr, &lock);
385 bool has_alpha = ibuf != nullptr && ibuf->planes == R_IMF_PLANES_RGBA;
386 BKE_image_release_ibuf(image, ibuf, lock);
387
388 if (has_alpha) {
389 link_sockets(ntree, image_node, "Alpha", bsdf, "Alpha");
390 done_bsdf_inputs.add("Alpha");
391 }
392 }
393 }
394}
395
396static void add_image_textures(Main *bmain,
397 const std::string &file_dir,
398 bNodeTree *ntree,
399 bNode *bsdf,
400 const ufbx_material &fmat)
401{
402 float node_locy = node_locy_top;
403 Set<StringRefNull> done_bsdf_inputs;
404
405 /* We primarily use images from "PBR" FBX mapping. */
406 for (const FbxPbrTextureToSocket &entry : fbx_pbr_to_socket) {
407 BLI_assert(entry.socket != nullptr);
408 if (done_bsdf_inputs.contains(entry.socket)) {
409 continue; /* Already connected. */
410 }
411
412 const ufbx_texture *ftex = fmat.pbr.maps[entry.slot].texture;
413 if (ftex == nullptr || !fmat.pbr.maps[entry.slot].texture_enabled) {
414 /* No texture used for this slot. */
415 continue;
416 }
417
419 bmain, file_dir, ntree, bsdf, fmat, ftex, entry.socket, node_locy, done_bsdf_inputs);
420 node_locy -= node_locy_step;
421 }
422
423 /* But also support several from the legacy/standard "FBX" material model,
424 * mostly to match behavior of python importer. */
425 for (const FbxStdTextureToSocket &entry : fbx_std_to_socket) {
426 BLI_assert(entry.socket != nullptr);
427 if (done_bsdf_inputs.contains(entry.socket)) {
428 continue; /* Already connected. */
429 }
430
431 const ufbx_texture *ftex = fmat.fbx.maps[entry.slot].texture;
432 if (ftex == nullptr || !fmat.fbx.maps[entry.slot].texture_enabled) {
433 /* No texture used for this slot. */
434 continue;
435 }
436
438 bmain, file_dir, ntree, bsdf, fmat, ftex, entry.socket, node_locy, done_bsdf_inputs);
439 node_locy -= node_locy_step;
440 }
441}
442
443Material *import_material(Main *bmain, const std::string &base_dir, const ufbx_material &fmat)
444{
445 Material *mat = BKE_material_add(bmain, fmat.name.data);
446 id_us_min(&mat->id);
447
449 nullptr, &mat->id, "Shader Nodetree", ntreeType_Shader->idname);
452 set_bsdf_socket_values(bsdf, mat, fmat);
453 add_image_textures(bmain, base_dir, ntree, bsdf, fmat);
454 link_sockets(ntree, bsdf, "BSDF", output, "Surface");
456
457 mat->nodetree = ntree;
458
460
461 return mat;
462}
463
464} // namespace blender::io::fbx
ImBuf * BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
Image * BKE_image_load_exists(Main *bmain, const char *filepath, bool *r_exists=nullptr)
bool BKE_image_has_packedfile(const Image *image)
void BKE_image_packfiles_from_mem(ReportList *reports, Image *ima, char *data, size_t data_len)
Image * BKE_image_add_generated(Main *bmain, unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, const float color[4], bool stereo3d, bool is_data, bool tiled)
void id_us_min(ID *id)
Definition lib_id.cc:366
General operations, lookup, etc. for materials.
Material * BKE_material_add(Main *bmain, const char *name)
#define SH_NODE_UVMAP
#define SH_NODE_TEX_IMAGE
#define SH_NODE_BSDF_PRINCIPLED
#define SH_NODE_NORMAL_MAP
#define SH_NODE_OUTPUT_MATERIAL
#define SH_NODE_MAPPING
void BKE_ntree_update_after_single_tree_change(Main &bmain, bNodeTree &modified_tree, const NodeTreeUpdateExtraParams &params={})
#define BLI_assert(a)
Definition BLI_assert.h:46
void void void const char * BLI_path_basename(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
#define FILE_MAX
int BLI_path_normalize(char *path) ATTR_NONNULL(1)
#define BLI_path_join(...)
const char * BLI_path_parent_dir_end(const char *path, size_t path_len) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
#define STR_ELEM(...)
Definition BLI_string.h:661
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
#define STRNCPY_UTF8(dst, src)
#define ELEM(...)
#define STREQ(a, b)
@ IMA_SRC_FILE
@ IMA_GENTYPE_BLANK
@ IMA_TYPE_IMAGE
@ SHD_IMAGE_EXTENSION_REPEAT
@ SHD_IMAGE_EXTENSION_EXTEND
@ SOCK_OUT
@ SOCK_IN
@ SOCK_VECTOR
@ SOCK_FLOAT
@ SOCK_RGBA
@ R_IMF_PLANES_RGBA
@ TEXMAP_TYPE_TEXTURE
@ COLOR_ROLE_DATA
const char * IMB_colormanagement_role_colorspace_name_get(int role)
struct blender::bke::bNodeTreeType * ntreeType_Shader
volatile int lock
bool contains(const Key &key) const
Definition BLI_set.hh:310
bool add(const Key &key)
Definition BLI_set.hh:248
#define rot(x, k)
uint pos
#define output
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
bNodeTree * node_tree_add_tree_embedded(Main *bmain, ID *owner_id, StringRefNull name, StringRefNull idname)
Definition node.cc:4098
bNodeSocket * node_find_socket(bNode &node, eNodeSocketInOut in_out, StringRef identifier)
Definition node.cc:2532
bNode * node_add_static_node(const bContext *C, bNodeTree &ntree, int type)
Definition node.cc:3500
bNodeLink & node_add_link(bNodeTree &ntree, bNode &fromnode, bNodeSocket &fromsock, bNode &tonode, bNodeSocket &tosock)
Definition node.cc:3810
void node_set_active(bNodeTree &ntree, bNode &node)
Definition node.cc:4724
static void add_image_texture(Main *bmain, const std::string &file_dir, bNodeTree *ntree, bNode *bsdf, const ufbx_material &fmat, const ufbx_texture *ftex, const char *socket_name, float node_locy, Set< StringRefNull > &done_bsdf_inputs)
static constexpr float node_locx_bsdf
Material * import_material(Main *bmain, const std::string &base_dir, const ufbx_material &fmat)
static constexpr float node_locy_top
static float set_bsdf_float_param(bNode *bsdf, const ufbx_material_map &umap, const char *socket, float def, float min=0.0f, float max=1.0f, float multiplier=1.0f)
static void link_sockets(bNodeTree *ntree, bNode *from_node, const char *from_node_id, bNode *to_node, const char *to_node_id)
static constexpr float node_locx_image
static bNode * add_node(bNodeTree *ntree, int type, float x, float y)
static const FbxPbrTextureToSocket fbx_pbr_to_socket[]
static const FbxStdTextureToSocket fbx_std_to_socket[]
static void set_bsdf_socket_values(bNode *bsdf, Material *mat, const ufbx_material &fmat)
static Image * create_placeholder_image(Main *bmain, const std::string &path)
static float3 set_bsdf_color_param(bNode *bsdf, const ufbx_material_map &umap, const char *socket, float3 def, float3 min=float3(0.0f), float3 max=float3(1.0f))
static constexpr float node_locx_mapping
static void set_socket_rgb(const char *socket_id, float vr, float vg, float vb, bNode *node)
static void add_image_textures(Main *bmain, const std::string &file_dir, bNodeTree *ntree, bNode *bsdf, const ufbx_material &fmat)
static constexpr float node_locx_output
static void set_socket_vector(const char *socket_id, float vx, float vy, float vz, bNode *node)
static Image * load_texture_image(Main *bmain, const std::string &file_dir, const ufbx_texture &tex)
static void set_socket_float(const char *socket_id, const float value, bNode *node)
static constexpr float node_locy_step
static constexpr float node_locx_texcoord
static constexpr float node_locx_normalmap
T clamp(const T &a, const T &min, const T &max)
VecBase< float, 3 > float3
const char * name
#define min(a, b)
Definition sort.cc:36
unsigned char planes
ColorManagedColorspaceSettings colorspace_settings
char filepath[1024]
short source
struct bNodeTree * nodetree
float location[2]
int16_t custom1
struct ID * id
void * storage
void * BKE_image_free_buffers
Definition stubs.c:35
max
Definition text_draw.cc:251