Blender V4.5
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
20#include "DNA_material_types.h"
21
22#include "NOD_shader.h"
23
25#include "IMB_imbuf_types.hh"
26
28
29#include "ufbx.h"
30
31namespace blender::io::fbx {
32
33/* Nodes are arranged in columns by type, with manually placed x coordinates
34 * based on node widths. */
35static constexpr float node_locx_texcoord = -880.0f;
36static constexpr float node_locx_mapping = -680.0f;
37static constexpr float node_locx_image = -480.0f;
38static constexpr float node_locx_normalmap = -200.0f;
39static constexpr float node_locx_bsdf = 0.0f;
40static constexpr float node_locx_output = 280.0f;
41
42/* Nodes are arranged in rows; one row for each image being used. */
43static constexpr float node_locy_top = 300.0f;
44static constexpr float node_locy_step = 300.0f;
45
46/* Add a node of the given type at the given location. */
47static bNode *add_node(bNodeTree *ntree, int type, float x, float y)
48{
49 bNode *node = bke::node_add_static_node(nullptr, *ntree, type);
50 node->location[0] = x;
51 node->location[1] = y;
52 return node;
53}
54
55static void link_sockets(bNodeTree *ntree,
56 bNode *from_node,
57 const char *from_node_id,
58 bNode *to_node,
59 const char *to_node_id)
60{
61 bNodeSocket *from_sock{bke::node_find_socket(*from_node, SOCK_OUT, from_node_id)};
62 bNodeSocket *to_sock{bke::node_find_socket(*to_node, SOCK_IN, to_node_id)};
63 BLI_assert(from_sock && to_sock);
64 bke::node_add_link(*ntree, *from_node, *from_sock, *to_node, *to_sock);
65}
66
67static void set_socket_float(const char *socket_id, const float value, bNode *node)
68{
69 bNodeSocket *socket{bke::node_find_socket(*node, SOCK_IN, socket_id)};
70 BLI_assert(socket && socket->type == SOCK_FLOAT);
71 bNodeSocketValueFloat *dst = socket->default_value_typed<bNodeSocketValueFloat>();
72 dst->value = value;
73}
74
75static void set_socket_rgb(const char *socket_id, float vr, float vg, float vb, bNode *node)
76{
77 bNodeSocket *socket{bke::node_find_socket(*node, SOCK_IN, socket_id)};
78 BLI_assert(socket && socket->type == SOCK_RGBA);
79 bNodeSocketValueRGBA *dst = socket->default_value_typed<bNodeSocketValueRGBA>();
80 dst->value[0] = vr;
81 dst->value[1] = vg;
82 dst->value[2] = vb;
83 dst->value[3] = 1.0f;
84}
85
86static void set_socket_vector(const char *socket_id, float vx, float vy, float vz, bNode *node)
87{
88 bNodeSocket *socket{bke::node_find_socket(*node, SOCK_IN, socket_id)};
89 BLI_assert(socket && socket->type == SOCK_VECTOR);
90 bNodeSocketValueVector *dst = socket->default_value_typed<bNodeSocketValueVector>();
91 dst->value[0] = vx;
92 dst->value[1] = vy;
93 dst->value[2] = vz;
94}
95
96static float set_bsdf_float_param(bNode *bsdf,
97 const ufbx_material_map &umap,
98 const char *socket,
99 float def,
100 float min = 0.0f,
101 float max = 1.0f,
102 float multiplier = 1.0f)
103{
104 if (!umap.has_value) {
105 return def * multiplier;
106 }
107 float value = umap.value_real * multiplier;
108 value = math::clamp(value, min, max);
109 set_socket_float(socket, value, bsdf);
110 return value;
111}
112
114 const ufbx_material_map &umap,
115 const char *socket,
116 float3 def,
117 float3 min = float3(0.0f),
118 float3 max = float3(1.0f))
119{
120 if (!umap.has_value || umap.value_components < 3) {
121 return def;
122 }
123 float3 value = float3(umap.value_vec3.x, umap.value_vec3.y, umap.value_vec3.z);
124 value = math::clamp(value, min, max);
125 set_socket_rgb(socket, value.x, value.y, value.z, bsdf);
126 return value;
127}
128
129static void set_bsdf_socket_values(bNode *bsdf, Material *mat, const ufbx_material &fmat)
130{
131 float3 base_color = set_bsdf_color_param(bsdf, fmat.pbr.base_color, "Base Color", float3(0.8f));
132 mat->r = base_color.x;
133 mat->g = base_color.y;
134 mat->b = base_color.z;
135
136 float roughness = set_bsdf_float_param(bsdf, fmat.pbr.roughness, "Roughness", 0.5f);
137 mat->roughness = roughness;
138
139 float metallic = set_bsdf_float_param(bsdf, fmat.pbr.metalness, "Metallic", 0.0f);
140 mat->metallic = metallic;
141
142 set_bsdf_float_param(bsdf, fmat.pbr.specular_ior, "IOR", 1.5f, 1.0f, 1000.0f);
143
144 set_bsdf_float_param(bsdf, fmat.pbr.opacity, "Alpha", 1.0f);
145
146 set_bsdf_float_param(bsdf, fmat.pbr.diffuse_roughness, "Diffuse Roughness", 0.0f);
147
148 set_bsdf_float_param(bsdf, fmat.pbr.subsurface_factor, "Subsurface Weight", 0.0f);
149 set_bsdf_float_param(bsdf, fmat.pbr.subsurface_scale, "Subsurface Scale", 0.05f);
150 set_bsdf_float_param(bsdf, fmat.pbr.subsurface_anisotropy, "Subsurface Anisotropy", 0.0f);
151
152 if (fmat.features.specular.enabled) {
153 float spec = set_bsdf_float_param(
154 bsdf, fmat.pbr.specular_factor, "Specular IOR Level", 0.25f, 0.0f, 1.0f, 2.0f);
155 mat->spec = spec;
156 set_bsdf_color_param(bsdf, fmat.pbr.specular_color, "Specular Tint", float3(1.0f));
157 set_bsdf_float_param(bsdf, fmat.pbr.specular_anisotropy, "Anisotropic", 0.0f);
158 set_bsdf_float_param(bsdf, fmat.pbr.specular_rotation, "Anisotropic Rotation", 0.0f);
159 }
160
161 if (ELEM(fmat.shader_type,
162 UFBX_SHADER_OSL_STANDARD_SURFACE,
163 UFBX_SHADER_ARNOLD_STANDARD_SURFACE,
164 UFBX_SHADER_3DS_MAX_PHYSICAL_MATERIAL,
165 UFBX_SHADER_3DS_MAX_PBR_METAL_ROUGH,
166 UFBX_SHADER_3DS_MAX_PBR_SPEC_GLOSS,
167 UFBX_SHADER_GLTF_MATERIAL,
168 UFBX_SHADER_BLENDER_PHONG) &&
169 fmat.features.transmission.enabled)
170 {
171 set_bsdf_float_param(bsdf, fmat.pbr.transmission_factor, "Transmission Weight", 0.0f);
172 }
173
174 if (fmat.features.coat.enabled) {
175 set_bsdf_float_param(bsdf, fmat.pbr.coat_factor, "Coat Weight", 0.0f);
176 set_bsdf_float_param(bsdf, fmat.pbr.coat_roughness, "Coat Roughness", 0.03f);
177 set_bsdf_float_param(bsdf, fmat.pbr.coat_ior, "Coat IOR", 1.5f, 1.0f, 4.0f);
178 set_bsdf_color_param(bsdf, fmat.pbr.coat_color, "Coat Tint", float3(1.0f));
179 }
180
181 if (fmat.features.sheen.enabled) {
182 set_bsdf_float_param(bsdf, fmat.pbr.sheen_factor, "Sheen Weight", 0.0f);
183 set_bsdf_float_param(bsdf, fmat.pbr.sheen_roughness, "Sheen Roughness", 0.5f);
184 set_bsdf_color_param(bsdf, fmat.pbr.sheen_color, "Sheen Tint", float3(1.0f));
185 }
186
188 bsdf, fmat.pbr.emission_factor, "Emission Strength", 0.0f, 0.0f, 1000000.0f);
190 fmat.pbr.emission_color,
191 "Emission Color",
192 float3(0.0f),
193 float3(0.0f),
194 float3(1000000.0f));
195
197 bsdf, fmat.pbr.thin_film_thickness, "Thin Film Thickness", 0.0f, 0.0f, 100000.0f);
198 set_bsdf_float_param(bsdf, fmat.pbr.thin_film_ior, "Thin Film IOR", 1.33f, 1.0f, 1000.0f);
199}
200
201static Image *create_placeholder_image(Main *bmain, const std::string &path)
202{
203 const float color[4] = {0, 0, 0, 1};
204 const char *name = BLI_path_basename(path.c_str());
206 bmain, 32, 32, name, 24, false, IMA_GENTYPE_BLANK, color, false, false, false);
207 STRNCPY(image->filepath, path.c_str());
208 image->source = IMA_SRC_FILE;
209 return image;
210}
211
212static Image *load_texture_image(Main *bmain, const std::string &file_dir, const ufbx_texture &tex)
213{
214 /* Check with filename directly. */
215 Image *image = BKE_image_load_exists(bmain, tex.filename.data);
216 /* Try loading as a relative path. */
217 if (image == nullptr) {
218 std::string path = file_dir + "/" + tex.filename.data;
219 image = BKE_image_load_exists(bmain, path.c_str());
220 }
221 /* Try loading with absolute path from FBX. */
222 if (image == nullptr) {
223 image = BKE_image_load_exists(bmain, tex.absolute_filename.data);
224 }
225
226 /* If still not found, try taking progressively longer parts of the absolute path,
227 * as relative to the file. */
228 if (image == nullptr) {
229 size_t pos = tex.absolute_filename.length;
230 do {
231 const char *parent_path = BLI_path_parent_dir_end(tex.absolute_filename.data, pos);
232 if (parent_path == nullptr) {
233 break;
234 }
235 char path[FILE_MAX];
236 BLI_path_join(path, sizeof(path), file_dir.c_str(), parent_path);
237 BLI_path_normalize(path);
238 image = BKE_image_load_exists(bmain, path);
239 pos = parent_path - tex.absolute_filename.data;
240 } while (image == nullptr);
241 }
242
243 /* Create dummy/placeholder image. */
244 if (image == nullptr) {
245 image = create_placeholder_image(bmain, tex.filename.data);
246 }
247
248 /* Use embedded data for this image, if we haven't done that yet. */
249 if (tex.content.size > 0 && (image == nullptr || !BKE_image_has_packedfile(image))) {
250 BKE_image_free_buffers(image); /* Free cached placeholder images. */
251 char *data_dup = MEM_malloc_arrayN<char>(tex.content.size, __func__);
252 memcpy(data_dup, tex.content.data, tex.content.size);
253 BKE_image_packfiles_from_mem(nullptr, image, data_dup, tex.content.size);
254
255 /* Make sure the image is not marked as "generated". */
256 image->source = IMA_SRC_FILE;
257 image->type = IMA_TYPE_IMAGE;
258 }
259
260 return image;
261}
262
264 ufbx_material_pbr_map slot;
265 const char *socket;
266};
268 {UFBX_MATERIAL_PBR_BASE_COLOR, "Base Color"},
269 {UFBX_MATERIAL_PBR_ROUGHNESS, "Roughness"},
270 {UFBX_MATERIAL_PBR_METALNESS, "Metallic"},
271 {UFBX_MATERIAL_PBR_DIFFUSE_ROUGHNESS, "Diffuse Roughness"},
272 {UFBX_MATERIAL_PBR_SPECULAR_FACTOR, "Specular IOR Level"},
273 {UFBX_MATERIAL_PBR_SPECULAR_COLOR, "Specular Tint"},
274 {UFBX_MATERIAL_PBR_SPECULAR_IOR, "IOR"},
275 {UFBX_MATERIAL_PBR_SPECULAR_ANISOTROPY, "Anisotropic"},
276 {UFBX_MATERIAL_PBR_SPECULAR_ROTATION, "Anisotropic Rotation"},
277 {UFBX_MATERIAL_PBR_TRANSMISSION_FACTOR, "Transmission Weight"},
278 {UFBX_MATERIAL_PBR_SUBSURFACE_FACTOR, "Subsurface Weight"},
279 {UFBX_MATERIAL_PBR_SUBSURFACE_SCALE, "Subsurface Scale"},
280 {UFBX_MATERIAL_PBR_SUBSURFACE_ANISOTROPY, "Subsurface Anisotropy"},
281 {UFBX_MATERIAL_PBR_SHEEN_FACTOR, "Sheen Weight"},
282 {UFBX_MATERIAL_PBR_SHEEN_COLOR, "Sheen Tint"},
283 {UFBX_MATERIAL_PBR_SHEEN_ROUGHNESS, "Sheen Roughness"},
284 {UFBX_MATERIAL_PBR_COAT_FACTOR, "Coat Weight"},
285 {UFBX_MATERIAL_PBR_COAT_COLOR, "Coat Tint"},
286 {UFBX_MATERIAL_PBR_COAT_ROUGHNESS, "Coat Roughness"},
287 {UFBX_MATERIAL_PBR_COAT_IOR, "Coat IOR"},
288 {UFBX_MATERIAL_PBR_COAT_NORMAL, "Coat Normal"},
289 {UFBX_MATERIAL_PBR_THIN_FILM_THICKNESS, "Thin Film Thickness"},
290 {UFBX_MATERIAL_PBR_THIN_FILM_IOR, "Thin Film IOR"},
291 {UFBX_MATERIAL_PBR_EMISSION_FACTOR, "Emission Strength"},
292 {UFBX_MATERIAL_PBR_EMISSION_COLOR, "Emission Color"},
293 {UFBX_MATERIAL_PBR_OPACITY, "Alpha"},
294 {UFBX_MATERIAL_PBR_NORMAL_MAP, "Normal"},
295 {UFBX_MATERIAL_PBR_TANGENT_MAP, "Tangent"},
296};
297
299 ufbx_material_fbx_map slot;
300 const char *socket;
301};
303 {UFBX_MATERIAL_FBX_TRANSPARENCY_FACTOR, "Alpha"},
304 {UFBX_MATERIAL_FBX_TRANSPARENCY_COLOR, "Alpha"},
305 {UFBX_MATERIAL_FBX_BUMP, "Normal"},
306};
307
308static void add_image_texture(Main *bmain,
309 const std::string &file_dir,
310 bNodeTree *ntree,
311 bNode *bsdf,
312 const ufbx_material &fmat,
313 const ufbx_texture *ftex,
314 const char *socket_name,
315 float node_locy,
316 Set<StringRefNull> &done_bsdf_inputs)
317{
318 Image *image = load_texture_image(bmain, file_dir, *ftex);
319 BLI_assert(image != nullptr);
320
321 /* Set "non-color" color space for all "data" textures. */
322 if (!STREQ(socket_name, "Base Color") && !STREQ(socket_name, "Specular Tint") &&
323 !STREQ(socket_name, "Sheen Tint") && !STREQ(socket_name, "Coat Tint") &&
324 !STREQ(socket_name, "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
448 mat->use_nodes = true;
450 nullptr, &mat->id, "Shader Nodetree", ntreeType_Shader->idname);
453 set_bsdf_socket_values(bsdf, mat, fmat);
454 add_image_textures(bmain, base_dir, ntree, bsdf, fmat);
455 link_sockets(ntree, bsdf, "BSDF", output, "Surface");
457
458 mat->nodetree = ntree;
459
461
462 return mat;
463}
464
465} // 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:361
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
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
#define ELEM(...)
#define STREQ(a, b)
@ IMA_SRC_FILE
@ IMA_GENTYPE_BLANK
@ IMA_TYPE_IMAGE
@ SOCK_OUT
@ SOCK_IN
@ SOCK_VECTOR
@ SOCK_FLOAT
@ SOCK_RGBA
@ SHD_IMAGE_EXTENSION_REPEAT
@ SHD_IMAGE_EXTENSION_EXTEND
@ 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:4375
bNodeSocket * node_find_socket(bNode &node, eNodeSocketInOut in_out, StringRef identifier)
Definition node.cc:2864
bNode * node_add_static_node(const bContext *C, bNodeTree &ntree, int type)
Definition node.cc:3804
bNodeLink & node_add_link(bNodeTree &ntree, bNode &fromnode, bNodeSocket &fromsock, bNode &tonode, bNodeSocket &tosock)
Definition node.cc:4087
void node_set_active(bNodeTree &ntree, bNode &node)
Definition node.cc:4996
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
#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