43 return mesh !=
nullptr && skin !=
nullptr && skin->clusters.count > 0 &&
44 mesh->num_vertices > 0 && skin->vertices.count == mesh->num_vertices;
51 if (skin !=
nullptr) {
53 const ufbx_matrix &geom_to_world = fmesh->instances[0]->geometry_to_world;
54 ufbx_matrix world_to_geom = ufbx_matrix_invert(&geom_to_world);
55 for (
int i = 0;
i < fmesh->vertex_position.values.count;
i++) {
56 ufbx_matrix skin_mat = ufbx_get_skin_vertex_matrix(skin,
i, &geom_to_world);
57 skin_mat = ufbx_matrix_mul(&world_to_geom, &skin_mat);
58 ufbx_vec3 val = ufbx_transform_position(&skin_mat, fmesh->vertex_position.values[
i]);
59 positions[
i] =
float3(val.x, val.y, val.z);
66 BLI_assert(positions.
size() == fmesh->vertex_position.values.count);
67 for (
int i = 0;
i < fmesh->vertex_position.values.count;
i++) {
68 ufbx_vec3 val = fmesh->vertex_position.values[
i];
69 positions[
i] =
float3(val.x, val.y, val.z);
78 (face_offsets.
is_empty() && fmesh->num_faces == 0));
79 for (
int face_idx = 0; face_idx < fmesh->num_faces; face_idx++) {
81 const ufbx_face &fface = fmesh->faces[face_idx];
82 face_offsets[face_idx] = fface.index_begin;
83 for (
int i = 0;
i < fface.num_indices;
i++) {
84 int corner_idx = fface.index_begin +
i;
85 int vidx = fmesh->vertex_indices[corner_idx];
86 corner_verts[corner_idx] = vidx;
94 if (fmesh->face_material.count == fmesh->num_faces) {
97 for (
int i = 0;
i < fmesh->face_material.count;
i++) {
98 materials.
span[
i] = fmesh->face_material[
i];
107 if (fmesh->face_smoothing.count > 0 && fmesh->face_smoothing.count == fmesh->num_faces) {
110 for (
int i = 0;
i < fmesh->face_smoothing.count;
i++) {
111 smooth.
span[
i] = !fmesh->face_smoothing[
i];
123 for (
int edge_idx = 0; edge_idx < fmesh->num_edges; edge_idx++) {
124 const ufbx_edge &fedge = fmesh->edges[edge_idx];
125 int va = fmesh->vertex_indices[fedge.a];
126 int vb = fmesh->vertex_indices[fedge.b];
127 edges[edge_idx] =
int2(va, vb);
135 const bool has_edge_creases = fmesh->edge_crease.count > 0 &&
136 fmesh->edge_crease.count == fmesh->num_edges;
137 const bool has_edge_smooth = fmesh->edge_smoothing.count > 0 &&
138 fmesh->edge_smoothing.count == fmesh->num_edges;
139 if (has_edge_creases || has_edge_smooth) {
146 edge_map.
add(edges[
i],
i);
149 if (has_edge_creases) {
153 creases.
span.fill(0.0f);
154 for (
int i = 0;
i < fmesh->num_edges;
i++) {
155 const ufbx_edge &fedge = fmesh->edges[
i];
156 int va = fmesh->vertex_indices[fedge.a];
157 int vb = fmesh->vertex_indices[fedge.b];
161 creases.
span[edge_i] =
sqrtf(fmesh->edge_crease[
i]);
167 if (has_edge_smooth) {
170 sharp.
span.fill(
false);
171 for (
int i = 0;
i < fmesh->num_edges;
i++) {
172 const ufbx_edge &fedge = fmesh->edges[
i];
173 int va = fmesh->vertex_indices[fedge.a];
174 int vb = fmesh->vertex_indices[fedge.b];
177 sharp.
span[edge_i] = !fmesh->edge_smoothing[
i];
189 for (
const ufbx_uv_set &fuv_set : fmesh->uv_sets) {
194 for (
int i = 0;
i < fuv_set.vertex_uv.indices.count;
i++) {
195 int val_idx = fuv_set.vertex_uv.indices[
i];
196 const ufbx_vec2 &uv = fuv_set.vertex_uv.values[val_idx];
209 std::string first_color_name;
210 for (
const ufbx_color_set &fcol_set : fmesh->color_sets) {
212 if (first_color_name.empty()) {
213 first_color_name = attr_name;
220 BLI_assert(fcol_set.vertex_color.indices.count == cols.
span.size());
221 for (
int i = 0;
i < fcol_set.vertex_color.indices.count;
i++) {
222 int val_idx = fcol_set.vertex_color.indices[
i];
223 const ufbx_vec4 &
col = fcol_set.vertex_color.values[val_idx];
237 BLI_assert(fcol_set.vertex_color.indices.count == cols.
span.size());
238 for (
int i = 0;
i < fcol_set.vertex_color.indices.count;
i++) {
239 int val_idx = fcol_set.vertex_color.indices[
i];
240 const ufbx_vec4 &
col = fcol_set.vertex_color.values[val_idx];
249 if (!first_color_name.empty()) {
259 if (!fmesh->vertex_normal.exists) {
267 int val_idx = fmesh->vertex_normal.indices[
i];
268 const ufbx_vec3 &normal = fmesh->vertex_normal.values[val_idx];
276 const ufbx_mesh *fmesh)
279 for (
const ufbx_skin_deformer *skin : fmesh->skin_deformers) {
284 for (
const ufbx_skin_cluster *cluster : skin->clusters) {
285 if (cluster->num_weights == 0) {
290 name_set.
add(bone_name);
297 const ufbx_mesh *fmesh,
300 if (fmesh->skin_deformers.count == 0) {
313 for (
const ufbx_skin_deformer *skin : fmesh->skin_deformers) {
318 for (
const ufbx_skin_cluster *cluster : skin->clusters) {
319 if (cluster->num_weights == 0) {
323 const int group_index = bone_set.
index_of_try(bone_name);
324 if (group_index < 0) {
328 for (
int i = 0;
i < cluster->num_weights;
i++) {
329 const int vertex = cluster->vertices[
i];
330 if (vertex < dverts.
size()) {
332 dw->
weight = cluster->weights[
i];
341 const ufbx_mesh *fmesh,
344 Key *mesh_key =
nullptr;
345 for (
const ufbx_blend_deformer *fdeformer : fmesh->blend_deformers) {
346 for (
const ufbx_blend_channel *fchan : fdeformer->channels) {
349 if (fchan->target_shape ==
nullptr) {
353 if (mesh_key ==
nullptr) {
356 mesh->
key = mesh_key;
363 kb->
curval = fchan->weight;
370 for (
int i = 0;
i < fchan->target_shape->num_offsets;
i++) {
371 int idx = fchan->target_shape->offset_vertices[
i];
372 const ufbx_vec3 &delta = fchan->target_shape->position_offsets[
i];
373 kb_data[idx] +=
float3(delta.x, delta.y, delta.z);
378 return mesh_key !=
nullptr;
384 const ufbx_mesh *fmesh,
388 for (
const ufbx_blend_deformer *fdeformer : fmesh->blend_deformers) {
389 for (
const ufbx_blend_channel *fchan : fdeformer->channels) {
391 if (fchan->target_shape ==
nullptr || key ==
nullptr) {
394 if (fchan->target_shape->offset_weights.count != fchan->target_shape->num_offsets) {
407 bool all_unorm =
true;
408 for (ufbx_real
w : fchan->target_shape->offset_weights) {
416 if (all_one || !all_unorm) {
421 if (group_index < 0) {
424 if (group_index < 0) {
430 for (
int i = 0;
i < fchan->target_shape->num_offsets;
i++) {
431 const int idx = fchan->target_shape->offset_vertices[
i];
432 if (idx >= 0 && idx < dverts.
size()) {
433 const float w = fchan->target_shape->offset_weights[
i];
445 const ufbx_scene &
fbx,
452 const ufbx_mesh *fmesh = fbx.meshes.data[index];
453 if (fmesh->instances.count == 0) {
454 meshes[index] = nullptr;
460 fmesh->num_vertices, fmesh->num_edges, fmesh->num_faces, fmesh->num_indices);
473 bool has_custom_normals =
false;
474 if (
params.use_custom_normals) {
483 if (
params.validate_meshes) {
484 bool verbose_validate =
false;
486 verbose_validate =
true;
491 if (has_custom_normals) {
501 meshes[index] = mesh;
506 for (
int64_t index : meshes.index_range()) {
507 Mesh *mesh = meshes[index];
508 if (mesh ==
nullptr) {
511 const ufbx_mesh *fmesh = fbx.meshes[index];
514 Mesh *mesh_main =
static_cast<Mesh *
>(
517 meshes[index] = mesh_main;
519 if (
params.use_custom_props) {
526 for (
const ufbx_node *node : fmesh->instances) {
528 if (node->is_geometry_transform_helper) {
536 obj->
data = mesh_main;
537 if (!node->visible) {
545 bool matrix_already_set =
false;
548 if (fmesh->skin_deformers.count > 0) {
551 for (
const std::string &
name : bone_set) {
556 for (
const ufbx_skin_deformer *skin : fmesh->skin_deformers) {
560 Object *arm_obj =
nullptr;
561 for (
const ufbx_skin_cluster *cluster : skin->clusters) {
562 if (cluster->num_weights == 0) {
565 arm_obj = mapping.bone_to_armature.lookup_default(cluster->bone_node,
nullptr);
566 if (arm_obj !=
nullptr) {
571 if (arm_obj !=
nullptr) {
579 if (!matrix_already_set) {
580 matrix_already_set =
true;
586 ufbx_matrix world_to_arm = mapping.armature_world_to_arm_node_matrix.lookup_default(
587 arm_obj, ufbx_identity_matrix);
588 ufbx_matrix world_to_arm_pose = mapping.armature_world_to_arm_pose_matrix
589 .lookup_default(arm_obj, ufbx_identity_matrix);
591 ufbx_matrix mtx = ufbx_matrix_mul(&world_to_arm, &node->geometry_to_world);
596 ufbx_matrix mtx_inv = ufbx_matrix_invert(&mtx);
597 ufbx_matrix mtx_world = mapping.get_node_bind_matrix(node);
598 ufbx_matrix mtx_parent_inverse = ufbx_matrix_mul(&mtx_world, &mtx_inv);
599 mtx_parent_inverse = ufbx_matrix_mul(&world_to_arm_pose, &mtx_parent_inverse);
611 if (fmesh->materials.count > 0 && node->materials.count == fmesh->materials.count) {
613 for (
int mi = 0; mi < fmesh->materials.count; mi++) {
614 const ufbx_material *mesh_fmat = fmesh->materials[mi];
615 const ufbx_material *node_fmat = node->materials[mi];
616 Material *mesh_mat = mapping.mat_to_material.lookup_default(mesh_fmat,
nullptr);
617 Material *node_mat = mapping.mat_to_material.lookup_default(node_fmat,
nullptr);
618 if (mesh_mat !=
nullptr) {
624 if (!
ELEM(node_mat,
nullptr, mesh_mat)) {
635 if (
params.import_subdivision &&
636 fmesh->subdivision_display_mode != UFBX_SUBDIVISION_DISPLAY_DISABLED &&
637 (fmesh->subdivision_preview_levels > 0 || fmesh->subdivision_render_levels > 0))
645 ssd->
levels = fmesh->subdivision_preview_levels;
648 UFBX_SUBDIVISION_BOUNDARY_SHARP_CORNERS ?
653 if (
params.use_custom_props) {
656 if (!matrix_already_set) {
659 mapping.el_to_object.add(&node->element, obj);
660 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, bool process_shape_keys=true)
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)
MINLINE 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
#define STRNCPY_UTF8(dst, 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, AttrType 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