Blender  V3.3
stl_import.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include <cstdio>
8 
9 #include "BKE_customdata.h"
10 #include "BKE_layer.h"
11 #include "BKE_mesh.h"
12 #include "BKE_object.h"
13 
14 #include "DNA_collection_types.h"
15 #include "DNA_scene_types.h"
16 
17 #include "BLI_fileops.hh"
18 #include "BLI_math_vector.h"
19 #include "BLI_memory_utils.hh"
20 
21 #include "DNA_object_types.h"
22 
23 #include "DEG_depsgraph.h"
24 #include "DEG_depsgraph_build.h"
25 
26 #include "stl_import.hh"
29 
30 namespace blender::io::stl {
31 
33 {
34  fprintf(stderr, "STL Importer: failed to read file");
35  if (feof(file)) {
36  fprintf(stderr, ", end of file reached.\n");
37  }
38  else if (ferror(file)) {
39  perror("Error");
40  }
41 }
42 
43 void importer_main(bContext *C, const STLImportParams &import_params)
44 {
45  Main *bmain = CTX_data_main(C);
47  ViewLayer *view_layer = CTX_data_view_layer(C);
48  importer_main(bmain, scene, view_layer, import_params);
49 }
50 
51 void importer_main(Main *bmain,
52  Scene *scene,
53  ViewLayer *view_layer,
54  const STLImportParams &import_params)
55 {
56  FILE *file = BLI_fopen(import_params.filepath, "rb");
57  if (!file) {
58  fprintf(stderr, "Failed to open STL file:'%s'.\n", import_params.filepath);
59  return;
60  }
61  BLI_SCOPED_DEFER([&]() { fclose(file); });
62 
63  /* Detect STL file type by comparing file size with expected file size,
64  * could check if file starts with "solid", but some files do not adhere,
65  * this is the same as the old Python importer.
66  */
67  uint32_t num_tri = 0;
68  size_t file_size = BLI_file_size(import_params.filepath);
69  fseek(file, BINARY_HEADER_SIZE, SEEK_SET);
70  if (fread(&num_tri, sizeof(uint32_t), 1, file) != 1) {
72  return;
73  }
74  bool is_ascii_stl = (file_size != (BINARY_HEADER_SIZE + 4 + BINARY_STRIDE * num_tri));
75 
76  /* Name used for both mesh and object. */
77  char ob_name[FILE_MAX];
78  BLI_strncpy(ob_name, BLI_path_basename(import_params.filepath), FILE_MAX);
80 
81  Mesh *mesh = nullptr;
82  if (is_ascii_stl) {
83  mesh = read_stl_ascii(import_params.filepath, bmain, ob_name, import_params.use_facet_normal);
84  }
85  else {
86  mesh = read_stl_binary(file, bmain, ob_name, import_params.use_facet_normal);
87  }
88 
89  if (mesh == nullptr) {
90  fprintf(stderr, "STL Importer: Failed to import mesh '%s'\n", import_params.filepath);
91  return;
92  }
93 
94  if (import_params.use_mesh_validate) {
95  bool verbose_validate = false;
96 #ifdef DEBUG
97  verbose_validate = true;
98 #endif
99  BKE_mesh_validate(mesh, verbose_validate, false);
100  }
101 
104  Object *obj = BKE_object_add_only_object(bmain, OB_MESH, ob_name);
105  BKE_mesh_assign_object(bmain, obj, mesh);
106  BKE_collection_object_add(bmain, lc->collection, obj);
107  Base *base = BKE_view_layer_base_find(view_layer, obj);
109 
110  float global_scale = import_params.global_scale;
111  if ((scene->unit.system != USER_UNIT_NONE) && import_params.use_scene_unit) {
112  global_scale *= scene->unit.scale_length;
113  }
114  float scale_vec[3] = {global_scale, global_scale, global_scale};
115  float obmat3x3[3][3];
116  unit_m3(obmat3x3);
117  float obmat4x4[4][4];
118  unit_m4(obmat4x4);
119  /* +Y-forward and +Z-up are the Blender's default axis settings. */
121  IO_AXIS_Y, IO_AXIS_Z, import_params.forward_axis, import_params.up_axis, obmat3x3);
122  copy_m4_m3(obmat4x4, obmat3x3);
123  rescale_m4(obmat4x4, scale_vec);
124  BKE_object_apply_mat4(obj, obmat4x4, true, false);
125 
129  DEG_id_tag_update_ex(bmain, &obj->id, flags);
132 }
133 } // namespace blender::io::stl
bool BKE_collection_object_add(struct Main *bmain, struct Collection *collection, struct Object *ob)
Definition: collection.c:1125
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1100
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
CustomData interface, see also DNA_customdata_types.h.
struct LayerCollection * BKE_layer_collection_get_active(struct ViewLayer *view_layer)
Definition: layer.c:636
void BKE_view_layer_base_deselect_all(struct ViewLayer *view_layer)
Definition: layer.c:388
struct Base * BKE_view_layer_base_find(struct ViewLayer *view_layer, struct Object *ob)
Definition: layer.c:379
void BKE_view_layer_base_select_and_set_active(struct ViewLayer *view_layer, struct Base *selbase)
Definition: layer.c:397
void BKE_mesh_assign_object(struct Main *bmain, struct Object *ob, struct Mesh *me)
Definition: mesh.cc:1377
bool BKE_mesh_validate(struct Mesh *me, bool do_verbose, bool cddata_check_mask)
General operations, lookup, etc. for blender objects.
void BKE_object_apply_mat4(struct Object *ob, const float mat[4][4], bool use_compat, bool use_parent)
Definition: object.cc:3575
struct Object * BKE_object_add_only_object(struct Main *bmain, int type, const char *name) ATTR_RETURNS_NONNULL
Definition: object.cc:2241
FILE * BLI_fopen(const char *filepath, const char *mode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: fileops.c:906
size_t BLI_file_size(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: storage.c:187
File and directory operations.
void unit_m3(float m[3][3])
Definition: math_matrix.c:40
void unit_m4(float m[4][4])
Definition: rct.c:1090
void copy_m4_m3(float m1[4][4], const float m2[3][3])
Definition: math_matrix.c:102
void rescale_m4(float mat[4][4], const float scale[3])
Definition: math_matrix.c:2362
bool mat3_from_axis_conversion(int src_forward, int src_up, int dst_forward, int dst_up, float r_mat[3][3])
#define BLI_SCOPED_DEFER(function_to_defer)
const char * BLI_path_basename(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:1653
#define FILE_MAX
bool BLI_path_extension_replace(char *path, size_t maxlen, const char *ext) ATTR_NONNULL()
Definition: path_util.c:1393
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
void DEG_id_tag_update_ex(struct Main *bmain, struct ID *id, int flag)
void DEG_id_tag_update(struct ID *id, int flag)
void DEG_relations_tag_update(struct Main *bmain)
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:771
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:834
@ ID_RECALC_ANIMATION
Definition: DNA_ID.h:794
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
@ ID_RECALC_BASE_FLAGS
Definition: DNA_ID.h:821
Object groups, one object can be in many groups at once.
Object is a sort of wrapper for general info.
@ OB_MESH
#define USER_UNIT_NONE
@ IO_AXIS_Y
Definition: IO_orientation.h:9
@ IO_AXIS_Z
#define C
Definition: RandGen.cpp:25
FILE * file
Scene scene
void importer_main(bContext *C, const STLImportParams &import_params)
Definition: stl_import.cc:43
Mesh * read_stl_ascii(const char *filepath, Main *bmain, char *mesh_name, bool use_custom_normals)
Mesh * read_stl_binary(FILE *file, Main *bmain, char *mesh_name, bool use_custom_normals)
void stl_import_report_error(FILE *file)
Definition: stl_import.cc:32
unsigned int uint32_t
Definition: stdint.h:80
struct Collection * collection
Definition: BKE_main.h:121
eIOAxis up_axis
Definition: IO_stl.h:21
bool use_mesh_validate
Definition: IO_stl.h:25
float global_scale
Definition: IO_stl.h:24
eIOAxis forward_axis
Definition: IO_stl.h:20
char filepath[FILE_MAX]
Definition: IO_stl.h:19
bool use_facet_normal
Definition: IO_stl.h:22
bool use_scene_unit
Definition: IO_stl.h:23
struct UnitSettings unit