42 return mesh !=
nullptr && skin !=
nullptr && skin->clusters.count > 0 &&
43 mesh->num_vertices > 0 && skin->vertices.count == mesh->num_vertices;
50 if (skin !=
nullptr) {
52 const ufbx_matrix &geom_to_world = fmesh->instances[0]->geometry_to_world;
53 ufbx_matrix world_to_geom = ufbx_matrix_invert(&geom_to_world);
54 for (
int i = 0;
i < fmesh->vertex_position.values.count;
i++) {
55 ufbx_matrix skin_mat = ufbx_get_skin_vertex_matrix(skin,
i, &geom_to_world);
56 skin_mat = ufbx_matrix_mul(&world_to_geom, &skin_mat);
57 ufbx_vec3 val = ufbx_transform_position(&skin_mat, fmesh->vertex_position.values[
i]);
58 positions[
i] =
float3(val.x, val.y, val.z);
65 BLI_assert(positions.
size() == fmesh->vertex_position.values.count);
66 for (
int i = 0;
i < fmesh->vertex_position.values.count;
i++) {
67 ufbx_vec3 val = fmesh->vertex_position.values[
i];
68 positions[
i] =
float3(val.x, val.y, val.z);
77 (face_offsets.
is_empty() && fmesh->num_faces == 0));
78 for (
int face_idx = 0; face_idx < fmesh->num_faces; face_idx++) {
80 const ufbx_face &fface = fmesh->faces[face_idx];
81 face_offsets[face_idx] = fface.index_begin;
82 for (
int i = 0;
i < fface.num_indices;
i++) {
83 int corner_idx = fface.index_begin +
i;
84 int vidx = fmesh->vertex_indices[corner_idx];
85 corner_verts[corner_idx] = vidx;
93 if (fmesh->face_material.count == fmesh->num_faces) {
96 for (
int i = 0;
i < fmesh->face_material.count;
i++) {
97 materials.
span[
i] = fmesh->face_material[
i];
106 if (fmesh->face_smoothing.count > 0 && fmesh->face_smoothing.count == fmesh->num_faces) {
109 for (
int i = 0;
i < fmesh->face_smoothing.count;
i++) {
110 smooth.
span[
i] = !fmesh->face_smoothing[
i];
122 for (
int edge_idx = 0; edge_idx < fmesh->num_edges; edge_idx++) {
123 const ufbx_edge &fedge = fmesh->edges[edge_idx];
124 int va = fmesh->vertex_indices[fedge.a];
125 int vb = fmesh->vertex_indices[fedge.b];
126 edges[edge_idx] =
int2(va, vb);
134 const bool has_edge_creases = fmesh->edge_crease.count > 0 &&
135 fmesh->edge_crease.count == fmesh->num_edges;
136 const bool has_edge_smooth = fmesh->edge_smoothing.count > 0 &&
137 fmesh->edge_smoothing.count == fmesh->num_edges;
138 if (has_edge_creases || has_edge_smooth) {
145 edge_map.
add(edges[
i],
i);
148 if (has_edge_creases) {
152 creases.
span.fill(0.0f);
153 for (
int i = 0;
i < fmesh->num_edges;
i++) {
154 const ufbx_edge &fedge = fmesh->edges[
i];
155 int va = fmesh->vertex_indices[fedge.a];
156 int vb = fmesh->vertex_indices[fedge.b];
160 creases.
span[edge_i] =
sqrtf(fmesh->edge_crease[
i]);
166 if (has_edge_smooth) {
169 sharp.
span.fill(
false);
170 for (
int i = 0;
i < fmesh->num_edges;
i++) {
171 const ufbx_edge &fedge = fmesh->edges[
i];
172 int va = fmesh->vertex_indices[fedge.a];
173 int vb = fmesh->vertex_indices[fedge.b];
176 sharp.
span[edge_i] = !fmesh->edge_smoothing[
i];
188 for (
const ufbx_uv_set &fuv_set : fmesh->uv_sets) {
193 for (
int i = 0;
i < fuv_set.vertex_uv.indices.count;
i++) {
194 int val_idx = fuv_set.vertex_uv.indices[
i];
195 const ufbx_vec2 &uv = fuv_set.vertex_uv.values[val_idx];
208 std::string first_color_name;
209 for (
const ufbx_color_set &fcol_set : fmesh->color_sets) {
211 if (first_color_name.empty()) {
212 first_color_name = attr_name;
219 BLI_assert(fcol_set.vertex_color.indices.count == cols.
span.size());
220 for (
int i = 0;
i < fcol_set.vertex_color.indices.count;
i++) {
221 int val_idx = fcol_set.vertex_color.indices[
i];
222 const ufbx_vec4 &
col = fcol_set.vertex_color.values[val_idx];
236 BLI_assert(fcol_set.vertex_color.indices.count == cols.
span.size());
237 for (
int i = 0;
i < fcol_set.vertex_color.indices.count;
i++) {
238 int val_idx = fcol_set.vertex_color.indices[
i];
239 const ufbx_vec4 &
col = fcol_set.vertex_color.values[val_idx];
248 if (!first_color_name.empty()) {
258 if (!fmesh->vertex_normal.exists) {
266 int val_idx = fmesh->vertex_normal.indices[
i];
267 const ufbx_vec3 &normal = fmesh->vertex_normal.values[val_idx];
275 const ufbx_mesh *fmesh)
278 for (
const ufbx_skin_deformer *skin : fmesh->skin_deformers) {
283 for (
const ufbx_skin_cluster *cluster : skin->clusters) {
284 if (cluster->num_weights == 0) {
289 name_set.
add(bone_name);
296 const ufbx_mesh *fmesh,
299 if (fmesh->skin_deformers.count == 0) {
312 for (
const ufbx_skin_deformer *skin : fmesh->skin_deformers) {
317 for (
const ufbx_skin_cluster *cluster : skin->clusters) {
318 if (cluster->num_weights == 0) {
322 const int group_index = bone_set.
index_of_try(bone_name);
323 if (group_index < 0) {
327 for (
int i = 0;
i < cluster->num_weights;
i++) {
328 const int vertex = cluster->vertices[
i];
329 if (vertex < dverts.
size()) {
331 dw->
weight = cluster->weights[
i];
340 const ufbx_mesh *fmesh,
343 Key *mesh_key =
nullptr;
344 for (
const ufbx_blend_deformer *fdeformer : fmesh->blend_deformers) {
345 for (
const ufbx_blend_channel *fchan : fdeformer->channels) {
348 if (fchan->target_shape ==
nullptr) {
352 if (mesh_key ==
nullptr) {
355 mesh->
key = mesh_key;
362 kb->
curval = fchan->weight;
369 for (
int i = 0;
i < fchan->target_shape->num_offsets;
i++) {
370 int idx = fchan->target_shape->offset_vertices[
i];
371 const ufbx_vec3 &delta = fchan->target_shape->position_offsets[
i];
372 kb_data[idx] +=
float3(delta.x, delta.y, delta.z);
377 return mesh_key !=
nullptr;
383 const ufbx_mesh *fmesh,
387 for (
const ufbx_blend_deformer *fdeformer : fmesh->blend_deformers) {
388 for (
const ufbx_blend_channel *fchan : fdeformer->channels) {
390 if (fchan->target_shape ==
nullptr || key ==
nullptr) {
393 if (fchan->target_shape->offset_weights.count != fchan->target_shape->num_offsets) {
406 bool all_unorm =
true;
407 for (ufbx_real
w : fchan->target_shape->offset_weights) {
415 if (all_one || !all_unorm) {
420 if (group_index < 0) {
423 if (group_index < 0) {
429 for (
int i = 0;
i < fchan->target_shape->num_offsets;
i++) {
430 const int idx = fchan->target_shape->offset_vertices[
i];
431 if (idx >= 0 && idx < dverts.
size()) {
432 const float w = fchan->target_shape->offset_weights[
i];
444 const ufbx_scene &
fbx,
451 const ufbx_mesh *fmesh = fbx.meshes.data[index];
452 if (fmesh->instances.count == 0) {
453 meshes[index] = nullptr;
459 fmesh->num_vertices, fmesh->num_edges, fmesh->num_faces, fmesh->num_indices);
472 bool has_custom_normals =
false;
473 if (
params.use_custom_normals) {
482 if (
params.validate_meshes) {
483 bool verbose_validate =
false;
485 verbose_validate =
true;
490 if (has_custom_normals) {
500 meshes[index] = mesh;
505 for (
int64_t index : meshes.index_range()) {
506 Mesh *mesh = meshes[index];
507 if (mesh ==
nullptr) {
510 const ufbx_mesh *fmesh = fbx.meshes[index];
513 Mesh *mesh_main =
static_cast<Mesh *
>(
516 meshes[index] = mesh_main;
518 if (
params.use_custom_props) {
525 for (
const ufbx_node *node : fmesh->instances) {
527 if (node->is_geometry_transform_helper) {
529 name =
get_fbx_name(node->parent->name) + std::string(
"_GeomAdjust");
535 obj->
data = mesh_main;
536 if (!node->visible) {
544 bool matrix_already_set =
false;
547 if (fmesh->skin_deformers.count > 0) {
550 for (
const std::string &name : bone_set) {
555 for (
const ufbx_skin_deformer *skin : fmesh->skin_deformers) {
559 Object *arm_obj =
nullptr;
560 for (
const ufbx_skin_cluster *cluster : skin->clusters) {
561 if (cluster->num_weights == 0) {
564 arm_obj = mapping.bone_to_armature.lookup_default(cluster->bone_node,
nullptr);
565 if (arm_obj !=
nullptr) {
570 if (arm_obj !=
nullptr) {
578 if (!matrix_already_set) {
579 matrix_already_set =
true;
585 ufbx_matrix world_to_arm = mapping.armature_world_to_arm_node_matrix.lookup_default(
586 arm_obj, ufbx_identity_matrix);
587 ufbx_matrix world_to_arm_pose = mapping.armature_world_to_arm_pose_matrix
588 .lookup_default(arm_obj, ufbx_identity_matrix);
590 ufbx_matrix mtx = ufbx_matrix_mul(&world_to_arm, &node->geometry_to_world);
595 ufbx_matrix mtx_inv = ufbx_matrix_invert(&mtx);
596 ufbx_matrix mtx_world = mapping.get_node_bind_matrix(node);
597 ufbx_matrix mtx_parent_inverse = ufbx_matrix_mul(&mtx_world, &mtx_inv);
598 mtx_parent_inverse = ufbx_matrix_mul(&world_to_arm_pose, &mtx_parent_inverse);
610 if (fmesh->materials.count > 0 && node->materials.count == fmesh->materials.count) {
612 for (
int mi = 0; mi < fmesh->materials.count; mi++) {
613 const ufbx_material *mesh_fmat = fmesh->materials[mi];
614 const ufbx_material *node_fmat = node->materials[mi];
615 Material *mesh_mat = mapping.mat_to_material.lookup_default(mesh_fmat,
nullptr);
616 Material *node_mat = mapping.mat_to_material.lookup_default(node_fmat,
nullptr);
617 if (mesh_mat !=
nullptr) {
623 if (!
ELEM(node_mat,
nullptr, mesh_mat)) {
634 if (
params.import_subdivision &&
635 fmesh->subdivision_display_mode != UFBX_SUBDIVISION_DISPLAY_DISABLED &&
636 (fmesh->subdivision_preview_levels > 0 || fmesh->subdivision_render_levels > 0))
644 ssd->
levels = fmesh->subdivision_preview_levels;
647 UFBX_SUBDIVISION_BOUNDARY_SHARP_CORNERS ?
652 if (
params.use_custom_props) {
655 if (!matrix_already_set) {
658 mapping.el_to_object.add(&node->element, obj);
659 mapping.imported_objects.add(obj);
std::string BKE_attribute_calc_unique_name(const AttributeOwner &owner, blender::StringRef name)
Key * BKE_key_add(Main *bmain, ID *id)
KeyBlock * BKE_keyblock_add(Key *key, const char *name)
void BKE_keyblock_convert_from_mesh(const Mesh *mesh, const Key *key, KeyBlock *kb)
KeyBlock * BKE_keyblock_find_name(Key *key, const char name[])
const char * BKE_id_name(const ID &id)
General operations, lookup, etc. for materials.
void BKE_object_material_assign_single_obdata(Main *bmain, Object *ob, Material *ma, short act)
void BKE_object_material_assign(Main *bmain, Object *ob, Material *ma, short act, int assign_type)
bool BKE_mesh_validate(Mesh *mesh, bool do_verbose, bool cddata_check_mask)
Mesh * BKE_mesh_new_nomain(int verts_num, int edges_num, int faces_num, int corners_num)
void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob)
void BKE_modifiers_persistent_uid_init(const Object &object, ModifierData &md)
ModifierData * BKE_modifier_new(int type)
General operations, lookup, etc. for blender objects.
void * BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name) ATTR_NONNULL(1)
Object * BKE_object_add_only_object(Main *bmain, int type, const char *name) ATTR_RETURNS_NONNULL
#define BLI_assert_unreachable()
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void rgba_float_to_uchar(unsigned char r_col[4], const float col_f[4])
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
char * STRNCPY(char(&dst)[N], const char *src)
@ SUBSURF_TYPE_CATMULL_CLARK
@ SUBSURF_BOUNDARY_SMOOTH_ALL
@ SUBSURF_BOUNDARY_SMOOTH_PRESERVE_CORNERS
struct ModifierData ModifierData
struct SubsurfModifierData SubsurfModifierData
struct ArmatureModifierData ArmatureModifierData
Object is a sort of wrapper for general info.
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
static AttributeOwner from_id(ID *id)
bool add(const Key &key, const Value &value)
Value lookup_default(const Key &key, const Value &default_value) const
bool add(const Key &key, const Value &value)
Value lookup_default(const Key &key, const Value &default_value) const
constexpr int64_t size() const
constexpr bool is_empty() const
constexpr int64_t size() const
constexpr IndexRange index_range() const
int64_t index_of_try(const Key &key) const
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type)
static float normals[][3]
void mesh_calc_edges(Mesh &mesh, bool keep_existing_edges, bool select_new_edges)
void mesh_set_custom_normals(Mesh &mesh, MutableSpan< float3 > corner_normals)
static VectorSet< std::string > get_skin_bone_name_set(const FbxElementMapping &mapping, const ufbx_mesh *fmesh)
void ufbx_matrix_to_obj(const ufbx_matrix &mtx, Object *obj)
static void import_blend_shape_full_weights(const FbxElementMapping &mapping, const ufbx_mesh *fmesh, Mesh *mesh, Object *obj)
static void import_colors(const ufbx_mesh *fmesh, Mesh *mesh, bke::MutableAttributeAccessor &attributes, AttributeOwner attr_owner, eFBXVertexColorMode color_mode)
const char * get_fbx_name(const ufbx_string &name, const char *def)
static bool import_blend_shapes(Main &bmain, FbxElementMapping &mapping, const ufbx_mesh *fmesh, Mesh *mesh)
void read_custom_properties(const ufbx_props &props, ID &id, bool enums_as_strings)
void node_matrix_to_obj(const ufbx_node *node, Object *obj, const FbxElementMapping &mapping)
static bool is_skin_deformer_usable(const ufbx_mesh *mesh, const ufbx_skin_deformer *skin)
static constexpr const char * temp_custom_normals_name
void matrix_to_m44(const ufbx_matrix &src, float dst[4][4])
static void import_skin_vertex_groups(const FbxElementMapping &mapping, const ufbx_mesh *fmesh, Mesh *mesh)
static void import_uvs(const ufbx_mesh *fmesh, bke::MutableAttributeAccessor &attributes, AttributeOwner attr_owner)
static void import_face_smoothing(const ufbx_mesh *fmesh, bke::MutableAttributeAccessor &attributes)
static void import_faces(const ufbx_mesh *fmesh, Mesh *mesh)
static void import_face_material_indices(const ufbx_mesh *fmesh, bke::MutableAttributeAccessor &attributes)
static void import_vertex_positions(const ufbx_mesh *fmesh, Mesh *mesh)
static void import_edges(const ufbx_mesh *fmesh, Mesh *mesh, bke::MutableAttributeAccessor &attributes)
static bool import_normals_into_temp_attribute(const ufbx_mesh *fmesh, Mesh *mesh, bke::MutableAttributeAccessor &attributes)
void import_meshes(Main &bmain, const ufbx_scene &fbx, FbxElementMapping &mapping, const FBXImportParams ¶ms)
void parallel_for_each(Range &&range, const Function &function)
blender::VecBase< uint8_t, 4 > uchar4
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
VecBase< float, 3 > float3
ColorSceneLinearByteEncoded4b< eAlpha::Premultiplied > ColorGeometry4b
char * default_color_attribute
ListBase vertex_group_names
char * active_color_attribute
MutableVArraySpan< T > span
Map< const ufbx_node *, std::string > node_to_name
Map< const ufbx_element *, Key * > el_to_shape_key