Blender V4.3
obj_importer_tests.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include <gtest/gtest.h>
6
7#include "testing/testing.h"
9
10#include "BKE_curve.hh"
11#include "BKE_customdata.hh"
12#include "BKE_main.hh"
13#include "BKE_material.h"
14#include "BKE_mesh.hh"
15#include "BKE_object.hh"
16#include "BKE_scene.hh"
17
18#include "BLI_listbase.h"
19#include "BLI_math_base.hh"
21#include "BLI_string.h"
22
23#include "BLO_readfile.hh"
24
25#include "DEG_depsgraph.hh"
27
28#include "DNA_curve_types.h"
29#include "DNA_material_types.h"
30#include "DNA_mesh_types.h"
31#include "DNA_meshdata_types.h"
32#include "DNA_scene_types.h"
33
34#include "MEM_guardedalloc.h"
35
36#include "obj_importer.hh"
37
38namespace blender::io::obj {
39
51
53 public:
67 void import_and_check(const char *path,
68 const Expectation *expect,
69 size_t expect_count,
70 int expect_mat_count,
71 int expect_image_count = 0)
72 {
73 if (!blendfile_load("io_tests" SEP_STR "blend_geometry" SEP_STR "all_quads.blend")) {
74 ADD_FAILURE();
75 return;
76 }
77
78 std::string obj_path = blender::tests::flags_test_asset_dir() +
79 SEP_STR "io_tests" SEP_STR "obj" SEP_STR + path;
80 STRNCPY(params.filepath, obj_path.c_str());
81 const size_t read_buffer_size = 650;
83
85
86 DEGObjectIterSettings deg_iter_settings{};
87 deg_iter_settings.depsgraph = depsgraph;
88 deg_iter_settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
91
92 constexpr bool print_result_scene = false;
93 if (print_result_scene) {
94 printf("Result was:\n");
95 DEG_OBJECT_ITER_BEGIN (&deg_iter_settings, object) {
96 printf(" {\"%s\", ", object->id.name);
97 if (object->type == OB_MESH) {
98 Mesh *mesh = BKE_object_get_evaluated_mesh(object);
99 const Span<float3> positions = mesh->vert_positions();
100 printf("OB_MESH, %i, %i, %i, %i, float3(%g, %g, %g), float3(%g, %g, %g)",
101 mesh->verts_num,
102 mesh->edges_num,
103 mesh->faces_num,
104 mesh->corners_num,
105 positions.first().x,
106 positions.first().y,
107 positions.first().z,
108 positions.last().x,
109 positions.last().y,
110 positions.last().z);
111 }
112 printf("},\n");
113 }
115 }
116
117 size_t object_index = 0;
118 DEG_OBJECT_ITER_BEGIN (&deg_iter_settings, object) {
119 if (object_index >= expect_count) {
120 ADD_FAILURE();
121 break;
122 }
123 const Expectation &exp = expect[object_index];
124 ASSERT_STREQ(object->id.name, exp.name.c_str());
125 EXPECT_EQ(object->type, exp.type);
126 EXPECT_V3_NEAR(object->loc, float3(0, 0, 0), 0.0001f);
127 if (!STREQ(object->id.name, "OBCube")) {
128 EXPECT_V3_NEAR(object->rot, float3(M_PI_2, 0, 0), 0.0001f);
129 }
130 EXPECT_V3_NEAR(object->scale, float3(1, 1, 1), 0.0001f);
131 if (object->type == OB_MESH) {
132 Mesh *mesh = BKE_object_get_evaluated_mesh(object);
133 EXPECT_EQ(mesh->verts_num, exp.totvert);
134 EXPECT_EQ(mesh->edges_num, exp.mesh_edges_num_or_curve_endp);
135 EXPECT_EQ(mesh->faces_num, exp.mesh_faces_num_or_curve_order);
136 EXPECT_EQ(mesh->corners_num, exp.mesh_corner_num_or_curve_cyclic);
137 const Span<float3> positions = mesh->vert_positions();
138 EXPECT_V3_NEAR(positions.first(), exp.vert_first, 0.0001f);
139 EXPECT_V3_NEAR(positions.last(), exp.vert_last, 0.0001f);
140 const float3 *corner_normals = mesh->normals_domain() == bke::MeshNormalDomain::Corner ?
141 mesh->corner_normals().data() :
142 nullptr;
143 float3 normal_first = corner_normals != nullptr ? corner_normals[0] : float3(0, 0, 0);
144 EXPECT_V3_NEAR(normal_first, exp.normal_first, 0.0001f);
145 const float2 *mloopuv = static_cast<const float2 *>(
146 CustomData_get_layer(&mesh->corner_data, CD_PROP_FLOAT2));
147 float2 uv_first = mloopuv ? *mloopuv : float2(0, 0);
148 EXPECT_V2_NEAR(uv_first, exp.uv_first, 0.0001f);
149 if (exp.color_first.x >= 0) {
150 const float4 *colors = (const float4 *)CustomData_get_layer(&mesh->vert_data,
152 EXPECT_TRUE(colors != nullptr);
153 EXPECT_V4_NEAR(colors[0], exp.color_first, 0.0001f);
154 }
155 else {
156 EXPECT_FALSE(CustomData_has_layer(&mesh->vert_data, CD_PROP_COLOR));
157 }
158 }
159 if (object->type == OB_CURVES_LEGACY) {
160 Curve *curve = static_cast<Curve *>(DEG_get_evaluated_object(depsgraph, object)->data);
161 int numVerts;
162 float(*vertexCos)[3] = BKE_curve_nurbs_vert_coords_alloc(&curve->nurb, &numVerts);
163 EXPECT_EQ(numVerts, exp.totvert);
164 EXPECT_V3_NEAR(vertexCos[0], exp.vert_first, 0.0001f);
165 EXPECT_V3_NEAR(vertexCos[numVerts - 1], exp.vert_last, 0.0001f);
166 MEM_freeN(vertexCos);
167 const Nurb *nurb = static_cast<const Nurb *>(BLI_findlink(&curve->nurb, 0));
168 int endpoint = (nurb->flagu & CU_NURB_ENDPOINT) ? 1 : 0;
169 EXPECT_EQ(nurb->orderu, exp.mesh_faces_num_or_curve_order);
170 EXPECT_EQ(endpoint, exp.mesh_edges_num_or_curve_endp);
171 /* Cyclic flag is not set by the importer yet. */
172 // int cyclic = (nurb->flagu & CU_NURB_CYCLIC) ? 1 : 0;
173 // EXPECT_EQ(cyclic, exp.mesh_corner_num_or_curve_cyclic);
174 }
175 if (!exp.first_mat.empty()) {
176 Material *mat = BKE_object_material_get(object, 1);
177 ASSERT_STREQ(mat ? mat->id.name : "<null>", exp.first_mat.c_str());
178 }
179 ++object_index;
180 }
182 EXPECT_EQ(object_index, expect_count);
183
184 /* Check number of materials & textures. */
185 const int mat_count = BLI_listbase_count(&bfile->main->materials);
186 EXPECT_EQ(mat_count, expect_mat_count);
187
188 const int ima_count = BLI_listbase_count(&bfile->main->images);
189 EXPECT_EQ(ima_count, expect_image_count);
190 }
191
193};
194
196{
197 Expectation expect[] = {
198 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
199 {"OBcube",
200 OB_MESH,
201 8,
202 12,
203 6,
204 24,
205 float3(-1, -1, 1),
206 float3(1, -1, -1),
207 float3(-0.57758f, 0.57735f, -0.57711f)},
208 };
209 import_and_check("cube.obj", expect, std::size(expect), 1);
210}
211
212TEST_F(OBJImportTest, import_cube_o_after_verts)
213{
214 Expectation expect[] = {
215 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
216 {
217 "OBActualCube",
218 OB_MESH,
219 8,
220 12,
221 6,
222 24,
223 float3(-1, -1, 1),
224 float3(1, -1, -1),
225 float3(0.57735f, -0.57735f, 0.57735f),
226 },
227 {
228 "OBSparseTri",
229 OB_MESH,
230 3,
231 3,
232 1,
233 3,
234 float3(1, -1, 1),
235 float3(-2, -2, 2),
236 float3(-0.2357f, 0.9428f, 0.2357f),
237 },
238 };
239 import_and_check("cube_o_after_verts.obj", expect, std::size(expect), 2);
240}
241
242TEST_F(OBJImportTest, import_suzanne_all_data)
243{
244 Expectation expect[] = {
245 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
246 {"OBMonkey",
247 OB_MESH,
248 505,
249 1005,
250 500,
251 1968,
252 float3(-0.4375f, 0.164062f, 0.765625f),
253 float3(0.4375f, 0.164062f, 0.765625f),
254 float3(-0.6040f, -0.5102f, 0.6122f),
255 float2(0.692094f, 0.40191f)},
256 };
257 import_and_check("suzanne_all_data.obj", expect, std::size(expect), 0);
258}
259
260TEST_F(OBJImportTest, import_nurbs)
261{
262 Expectation expect[] = {
263 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
264 {"OBnurbs",
266 12,
267 0,
268 4,
269 1,
270 float3(0.260472f, -1.477212f, -0.866025f),
271 float3(-1.5f, 2.598076f, 0)},
272 };
273 import_and_check("nurbs.obj", expect, std::size(expect), 0);
274}
275
276TEST_F(OBJImportTest, import_nurbs_curves)
277{
278 Expectation expect[] = {
279 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
280 {"OBCurveDeg3", OB_CURVES_LEGACY, 4, 0, 3, 0, float3(10, -2, 0), float3(6, -2, 0)},
281 {"OBnurbs_curves", OB_CURVES_LEGACY, 4, 0, 4, 0, float3(2, -2, 0), float3(-2, -2, 0)},
282 {"OBNurbsCurveCyclic", OB_CURVES_LEGACY, 7, 0, 4, 1, float3(-2, -2, 0), float3(-6, 2, 0)},
283 {"OBNurbsCurveDiffWeights",
285 4,
286 0,
287 4,
288 0,
289 float3(6, -2, 0),
290 float3(2, -2, 0)},
291 {"OBNurbsCurveEndpoint",
293 4,
294 1,
295 4,
296 0,
297 float3(-6, -2, 0),
298 float3(-10, -2, 0)},
299 };
300 import_and_check("nurbs_curves.obj", expect, std::size(expect), 0);
301}
302
303TEST_F(OBJImportTest, import_nurbs_cyclic)
304{
305 Expectation expect[] = {
306 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
307 {"OBnurbs_cyclic",
309 31,
310 0,
311 4,
312 1,
313 float3(2.591002f, 0, -0.794829f),
314 float3(3.280729f, 0, 3.043217f)},
315 };
316 import_and_check("nurbs_cyclic.obj", expect, std::size(expect), 0);
317}
318
319TEST_F(OBJImportTest, import_nurbs_endpoint)
320{
321 Expectation expect[] = {
322 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
323 {"OBCurveEndpointRange01",
325 15,
326 1,
327 4,
328 0,
329 float3(0.29f, 0, -0.11f),
330 float3(22.17f, 0, -5.31f)},
331 {"OBCurveEndpointRangeNon01",
333 15,
334 1,
335 4,
336 0,
337 float3(0.29f, 0, -0.11f),
338 float3(22.17f, 0, -5.31f)},
339 {"OBCurveNoEndpointRange01",
341 15,
342 0,
343 4,
344 0,
345 float3(0.29f, 0, -0.11f),
346 float3(22.17f, 0, -5.31f)},
347 };
348 import_and_check("nurbs_endpoint.obj", expect, std::size(expect), 0);
349}
350
351TEST_F(OBJImportTest, import_nurbs_manual)
352{
353 Expectation expect[] = {
354 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
355 {"OBCurve_Cyclic", OB_CURVES_LEGACY, 7, 0, 4, 1, float3(-2, 0, 2), float3(2, 0, -2)},
356 {"OBCurve_Endpoints", OB_CURVES_LEGACY, 5, 1, 4, 0, float3(-2, 0, 2), float3(-2, 0, 2)},
357 {"OBCurve_NonUniform_Parm",
359 5,
360 0,
361 4,
362 0,
363 float3(-2, 0, 2),
364 float3(-2, 0, 2)},
365 {"OBCurve_Uniform_Parm", OB_CURVES_LEGACY, 5, 0, 4, 0, float3(-2, 0, 2), float3(-2, 0, 2)},
366 };
367 import_and_check("nurbs_manual.obj", expect, std::size(expect), 0);
368}
369
370TEST_F(OBJImportTest, import_nurbs_mesh)
371{
372 Expectation expect[] = {
373 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
374 {"OBTorus_Knot",
375 OB_MESH,
376 108,
377 108,
378 0,
379 0,
380 float3(0.438725f, 1.070313f, 0.433013f),
381 float3(0.625557f, 1.040691f, 0.460328f)},
382 };
383 import_and_check("nurbs_mesh.obj", expect, std::size(expect), 0);
384}
385
386TEST_F(OBJImportTest, import_materials)
387{
388 Expectation expect[] = {
389 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
390 {"OBmaterials",
391 OB_MESH,
392 8,
393 12,
394 6,
395 24,
396 float3(-1, -1, 1),
397 float3(1, -1, -1),
398 float3(0),
399 float2(0),
400 float4(-1),
401 "MAno_textures_red"},
402 {"OBObjMtlAfter",
403 OB_MESH,
404 3,
405 3,
406 1,
407 3,
408 float3(3, 0, 0),
409 float3(5, 0, 0),
410 float3(0),
411 float2(0),
412 float4(-1),
413 "MAno_textures_red"},
414 {"OBObjMtlBefore",
415 OB_MESH,
416 3,
417 3,
418 1,
419 3,
420 float3(6, 0, 0),
421 float3(8, 0, 0),
422 float3(0),
423 float2(0),
424 float4(-1),
425 "MAClay"},
426 };
427 import_and_check("materials.obj", expect, std::size(expect), 4, 8);
428}
429
430TEST_F(OBJImportTest, import_cubes_with_textures_rel)
431{
432 Expectation expect[] = {
433 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
434 {"OBCube4Tex",
435 OB_MESH,
436 8,
437 12,
438 6,
439 24,
440 float3(1, 1, -1),
441 float3(-1, -1, 1),
442 float3(0, 1, 0),
443 float2(0.9935f, 0.0020f),
444 float4(-1),
445 "MAMat_BaseRoughEmissNormal10"},
446 {"OBCubeTexMul",
447 OB_MESH,
448 8,
449 12,
450 6,
451 24,
452 float3(4, -2, -1),
453 float3(2, -4, 1),
454 float3(0, 1, 0),
455 float2(0.9935f, 0.0020f),
456 float4(-1),
457 "MAMat_BaseMul"},
458 {"OBCubeTiledTex",
459 OB_MESH,
460 8,
461 12,
462 6,
463 24,
464 float3(4, 1, -1),
465 float3(2, -1, 1),
466 float3(0, 1, 0),
467 float2(0.9935f, 0.0020f),
468 float4(-1),
469 "MAMat_BaseTiled"},
470 {"OBCubeTiledTexFromAnotherFolder",
471 OB_MESH,
472 8,
473 12,
474 6,
475 24,
476 float3(7, 1, -1),
477 float3(5, -1, 1),
478 float3(0, 1, 0),
479 float2(0.9935f, 0.0020f),
480 float4(-1),
481 "MAMat_EmissTiledAnotherFolder"},
482 };
483 import_and_check("cubes_with_textures_rel.obj", expect, std::size(expect), 4, 4);
484}
485
486TEST_F(OBJImportTest, import_faces_invalid_or_with_holes)
487{
488 Expectation expect[] = {
489 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
490 {"OBFaceAllVerts_BecomesOneOverlappingFaceUsingAllVerts",
491 OB_MESH,
492 8,
493 8,
494 1,
495 8,
496 float3(8, 0, -2),
497 float3(11, 0, -1)},
498 {"OBFaceAllVertsDup_BecomesOneOverlappingFaceUsingAllVerts",
499 OB_MESH,
500 8,
501 8,
502 1,
503 8,
504 float3(3, 0, 3),
505 float3(6, 0, 4)},
506 {"OBFaceJustTwoVerts_IsSkipped", OB_MESH, 2, 0, 0, 0, float3(8, 0, 3), float3(8, 0, 7)},
507 {"OBFaceQuadDupSomeVerts_BecomesOneQuadUsing4Verts",
508 OB_MESH,
509 4,
510 4,
511 1,
512 4,
513 float3(3, 0, -2),
514 float3(7, 0, -2)},
515 {"OBFaceTriDupVert_Becomes1Tri", OB_MESH, 3, 3, 1, 3, float3(-2, 0, 3), float3(2, 0, 7)},
516 {"OBFaceWithHole_BecomesTwoFacesFormingAHole",
517 OB_MESH,
518 8,
519 10,
520 2,
521 12,
522 float3(-2, 0, -2),
523 float3(1, 0, -1)},
524 };
525 import_and_check("faces_invalid_or_with_holes.obj", expect, std::size(expect), 0);
526}
527
528TEST_F(OBJImportTest, import_invalid_faces)
529{
530 Expectation expect[] = {
531 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
532 {"OBTheMesh", OB_MESH, 5, 3, 1, 3, float3(-2, 0, -2), float3(0, 2, 0)},
533 };
534 import_and_check("invalid_faces.obj", expect, std::size(expect), 0);
535}
536
537TEST_F(OBJImportTest, import_invalid_indices)
538{
539 Expectation expect[] = {
540 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
541 {"OBQuad",
542 OB_MESH,
543 3,
544 3,
545 1,
546 3,
547 float3(-2, 0, -2),
548 float3(2, 0, 2),
549 float3(0, 1, 0),
550 float2(0.5f, 0.25f)},
551 };
552 import_and_check("invalid_indices.obj", expect, std::size(expect), 0);
553}
554
555TEST_F(OBJImportTest, import_invalid_syntax)
556{
557 Expectation expect[] = {
558 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
559 {"OBObjectWithAReallyLongNameToCheckHowImportHandlesNamesThatAreLon",
560 OB_MESH,
561 3,
562 3,
563 1,
564 3,
565 float3(1, 2, 3),
566 float3(7, 8, 9),
567 float3(0, 1, 0),
568 float2(0.5f, 0.25f)},
569 };
570 import_and_check("invalid_syntax.obj", expect, std::size(expect), 0);
571}
572
573TEST_F(OBJImportTest, import_all_objects)
574{
575 Expectation expect[] = {
576 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
577 /* `.obj` file has empty EmptyText and EmptyMesh objects; these are ignored and skipped. */
578 {"OBBezierCurve", OB_MESH, 13, 12, 0, 0, float3(-1, -2, 0), float3(1, -2, 0)},
579 {"OBBlankCube", OB_MESH, 8, 13, 7, 26, float3(1, 1, -1), float3(-1, 1, 1), float3(0, 0, 1)},
580 {"OBMaterialCube",
581 OB_MESH,
582 8,
583 13,
584 7,
585 26,
586 float3(28, 1, -1),
587 float3(26, 1, 1),
588 float3(-1, 0, 0),
589 float2(0),
590 float4(-1),
591 "MARed"},
592 {"OBNurbsCircle",
593 OB_MESH,
594 96,
595 96,
596 0,
597 0,
598 float3(3.292893f, -2.707107f, 0),
599 float3(3.369084f, -2.77607f, 0)},
600 {"OBNurbsCircle.001", OB_MESH, 4, 4, 0, 0, float3(2, -3, 0), float3(3, -2, 0)},
601 {"OBParticleCube",
602 OB_MESH,
603 8,
604 13,
605 7,
606 26,
607 float3(22, 1, -1),
608 float3(20, 1, 1),
609 float3(0, 0, 1)},
610 {"OBShapeKeyCube",
611 OB_MESH,
612 8,
613 13,
614 7,
615 26,
616 float3(19, 1, -1),
617 float3(17, 1, 1),
618 float3(-0.4082f, -0.4082f, 0.8165f)},
619 {"OBSmoothCube",
620 OB_MESH,
621 8,
622 13,
623 7,
624 26,
625 float3(4, 1, -1),
626 float3(2, 1, 1),
627 float3(0.5774f, 0.5773f, 0.5774f),
628 float2(0),
629 float4(-1),
630 "MAMaterial"},
631 {"OBSurface",
632 OB_MESH,
633 256,
634 480,
635 224,
636 896,
637 float3(7.292893f, -2.707107f, -1),
638 float3(7.525872f, -2.883338f, 1),
639 float3(-0.7071f, -0.7071f, 0),
640 float2(0, 0.142857f)},
641 {"OBSurfPatch",
642 OB_MESH,
643 256,
644 480,
645 225,
646 900,
647 float3(12.5f, -2.5f, 0.694444f),
648 float3(13.5f, -1.5f, 0.694444f),
649 float3(-0.3246f, -0.3531f, 0.8775f),
650 float2(0, 0.066667f)},
651 {"OBSurfSphere",
652 OB_MESH,
653 640,
654 1248,
655 608,
656 2432,
657 float3(11, -2, -1),
658 float3(11, -2, 1),
659 float3(-0.0541f, -0.0541f, -0.9971f),
660 float2(0, 1)},
661 {"OBSurfTorus.001",
662 OB_MESH,
663 1024,
664 2048,
665 1024,
666 4096,
667 float3(5.34467f, -2.65533f, -0.176777f),
668 float3(5.232792f, -2.411795f, -0.220835f),
669 float3(-0.5042f, -0.5042f, -0.7011f),
670 float2(0, 1)},
671 {"OBTaperCube",
672 OB_MESH,
673 106,
674 208,
675 104,
676 416,
677 float3(24.444445f, 0.502543f, -0.753814f),
678 float3(23.790743f, 0.460522f, -0.766546f),
679 float3(-0.0546f, 0.1716f, 0.9837f)},
680 {"OBText",
681 OB_MESH,
682 177,
683 345,
684 171,
685 513,
686 float3(1.75f, -9.458f, 0),
687 float3(0.587f, -9.406f, 0),
688 float3(0, 0, 1),
689 float2(0.017544f, 0)},
690 {"OBUVCube",
691 OB_MESH,
692 8,
693 13,
694 7,
695 26,
696 float3(7, 1, -1),
697 float3(5, 1, 1),
698 float3(0, 0, 1),
699 float2(0.654526f, 0.579873f)},
700 {"OBUVImageCube",
701 OB_MESH,
702 8,
703 13,
704 7,
705 26,
706 float3(10, 1, -1),
707 float3(8, 1, 1),
708 float3(0, 0, 1),
709 float2(0.654526f, 0.579873f)},
710 {"OBVColCube",
711 OB_MESH,
712 8,
713 13,
714 7,
715 26,
716 float3(13, 1, -1),
717 float3(11, 1, 1),
718 float3(0, 0, 1),
719 float2(0, 0),
720 float4(0.0f, 0.002125f, 1.0f, 1.0f)},
721 {"OBVGroupCube",
722 OB_MESH,
723 8,
724 13,
725 7,
726 26,
727 float3(16, 1, -1),
728 float3(14, 1, 1),
729 float3(0, 0, 1)},
730 };
731 import_and_check("all_objects.obj", expect, std::size(expect), 7);
732}
733
734TEST_F(OBJImportTest, import_cubes_vertex_colors)
735{
736 Expectation expect[] = {
737 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
738 {"OBCubeCornerByte",
739 OB_MESH,
740 8,
741 12,
742 6,
743 24,
744 float3(1.0f, 1.0f, -3.812445f),
745 float3(-1.0f, -1.0f, -1.812445f),
746 float3(0, 0, 0),
747 float2(0, 0),
748 float4(0.89627f, 0.036889f, 0.47932f, 1.0f)},
749 {"OBCubeCornerFloat",
750 OB_MESH,
751 8,
752 12,
753 6,
754 24,
755 float3(3.481967f, 1.0f, -3.812445f),
756 float3(1.481967f, -1.0f, -1.812445f),
757 float3(0, 0, 0),
758 float2(0, 0),
759 float4(1.564582f, 0.039217f, 0.664309f, 1.0f)},
760 {"OBCubeMultiColorAttribs",
761 OB_MESH,
762 8,
763 12,
764 6,
765 24,
766 float3(-4.725068f, -1.0f, 1.0f),
767 float3(-2.725068f, 1.0f, -1.0f),
768 float3(0, 0, 0),
769 float2(0, 0),
770 float4(0.270498f, 0.47932f, 0.262251f, 1.0f)},
771 {"OBCubeNoColors",
772 OB_MESH,
773 8,
774 12,
775 6,
776 24,
777 float3(-4.550208f, -1.0f, -1.918042f),
778 float3(-2.550208f, 1.0f, -3.918042f)},
779 {"OBCubeVertexByte",
780 OB_MESH,
781 8,
782 12,
783 6,
784 24,
785 float3(1.0f, 1.0f, -1.0f),
786 float3(-1.0f, -1.0f, 1.0f),
787 float3(0, 0, 0),
788 float2(0, 0),
789 float4(0.846873f, 0.027321f, 0.982123f, 1.0f)},
790 {"OBCubeVertexFloat",
791 OB_MESH,
792 8,
793 12,
794 6,
795 24,
796 float3(3.392028f, 1.0f, -1.0f),
797 float3(1.392028f, -1.0f, 1.0f),
798 float3(0, 0, 0),
799 float2(0, 0),
800 float4(49.99467f, 0.027321f, 0.982123f, 1.0f)},
801 };
802 import_and_check("cubes_vertex_colors.obj", expect, std::size(expect), 0);
803}
804
805TEST_F(OBJImportTest, import_cubes_vertex_colors_mrgb)
806{
807 Expectation expect[] = {
808 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
809 {"OBCubeMRGB",
810 OB_MESH,
811 8,
812 12,
813 6,
814 24,
815 float3(4, 1, -1),
816 float3(2, -1, 1),
817 float3(0, 0, 0),
818 float2(0, 0),
819 float4(0.8714f, 0.6308f, 0.5271f, 1.0f)},
820 {"OBCubeXYZRGB",
821 OB_MESH,
822 8,
823 12,
824 6,
825 24,
826 float3(1, 1, -1),
827 float3(-1, -1, 1),
828 float3(0, 0, 0),
829 float2(0, 0),
830 float4(0.6038f, 0.3185f, 0.1329f, 1.0f)},
831 {"OBTriMRGB",
832 OB_MESH,
833 3,
834 3,
835 1,
836 3,
837 float3(12, 1, -1),
838 float3(10, 0, -1),
839 float3(0, 0, 0),
840 float2(0, 0),
841 float4(1.0f, 0.0f, 0.0f, 1.0f)},
842 {
843 "OBTriNoColors",
844 OB_MESH,
845 3,
846 3,
847 1,
848 3,
849 float3(8, 1, -1),
850 float3(6, 0, -1),
851 },
852 };
853 import_and_check("cubes_vertex_colors_mrgb.obj", expect, std::size(expect), 0);
854}
855
856TEST_F(OBJImportTest, import_vertex_colors_non_contiguous)
857{
858 Expectation expect[] = {
859 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
860 {"OBNoColor",
861 OB_MESH,
862 3,
863 3,
864 1,
865 3,
866 float3(0, 0, 1),
867 float3(1, 0, 1),
868 float3(0, 0, 0),
869 float2(0, 0),
870 float4(-1, -1, -1, -1)},
871 {"OBRed",
872 OB_MESH,
873 3,
874 3,
875 1,
876 3,
877 float3(0, 0, 0),
878 float3(1, 0, 0),
879 float3(0, 0, 0),
880 float2(0, 0),
881 float4(1, 0, 0, 1)},
882 };
883 import_and_check("vertex_colors_non_contiguous.obj", expect, std::size(expect), 0);
884}
885
886TEST_F(OBJImportTest, import_vertices)
887{
888 Expectation expect[] = {
889 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
890 /* Loose vertices without faces or edges. */
891 {"OBCube.001", OB_MESH, 8, 0, 0, 0, float3(1, 1, -1), float3(-1, 1, 1)},
892 };
893 import_and_check("vertices.obj", expect, std::size(expect), 0);
894}
895
896TEST_F(OBJImportTest, import_split_options_by_object)
897{
898 /* Default is to split by object */
899 Expectation expect[] = {
900 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
901 {"OBBox", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, -1, 1)},
902 {"OBPyramid", OB_MESH, 5, 8, 5, 16, float3(3, 1, -1), float3(4, 0, 2)},
903 };
904 import_and_check("split_options.obj", expect, std::size(expect), 0);
905}
906
907TEST_F(OBJImportTest, import_split_options_by_group)
908{
909 params.use_split_objects = false;
910 params.use_split_groups = true;
911 Expectation expect[] = {
912 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
913 {"OBBoxOne", OB_MESH, 4, 4, 1, 4, float3(1, -1, -1), float3(-1, -1, 1)},
914 {"OBBoxTwo", OB_MESH, 6, 7, 2, 8, float3(1, 1, 1), float3(-1, -1, 1)},
915 {"OBBoxTwo.001", OB_MESH, 6, 7, 2, 8, float3(1, 1, -1), float3(-1, -1, -1)},
916 {"OBPyrBottom", OB_MESH, 4, 4, 1, 4, float3(3, 1, -1), float3(3, -1, -1)},
917 {"OBPyrSides", OB_MESH, 5, 8, 4, 12, float3(3, 1, -1), float3(4, 0, 2)},
918 {"OBsplit_options", OB_MESH, 4, 4, 1, 4, float3(1, 1, -1), float3(-1, 1, 1)},
919 };
920 import_and_check("split_options.obj", expect, std::size(expect), 0);
921}
922
923TEST_F(OBJImportTest, import_split_options_by_object_and_group)
924{
925 params.use_split_objects = true;
926 params.use_split_groups = true;
927 Expectation expect[] = {
928 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
929 {"OBBox", OB_MESH, 4, 4, 1, 4, float3(1, 1, -1), float3(-1, 1, 1)},
930 {"OBBoxOne", OB_MESH, 4, 4, 1, 4, float3(1, -1, -1), float3(-1, -1, 1)},
931 {"OBBoxTwo", OB_MESH, 6, 7, 2, 8, float3(1, 1, 1), float3(-1, -1, 1)},
932 {"OBBoxTwo.001", OB_MESH, 6, 7, 2, 8, float3(1, 1, -1), float3(-1, -1, -1)},
933 {"OBPyrBottom", OB_MESH, 4, 4, 1, 4, float3(3, 1, -1), float3(3, -1, -1)},
934 {"OBPyrSides", OB_MESH, 5, 8, 4, 12, float3(3, 1, -1), float3(4, 0, 2)},
935 };
936 import_and_check("split_options.obj", expect, std::size(expect), 0);
937}
938
939TEST_F(OBJImportTest, import_split_options_none)
940{
941 params.use_split_objects = false;
942 params.use_split_groups = false;
943 Expectation expect[] = {
944 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
945 {"OBsplit_options", OB_MESH, 13, 20, 11, 40, float3(1, 1, -1), float3(4, 0, 2)},
946 };
947 import_and_check("split_options.obj", expect, std::size(expect), 0);
948}
949
950TEST_F(OBJImportTest, import_polylines)
951{
952 Expectation expect[] = {
953 {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
954 {"OBpolylines", OB_MESH, 13, 8, 0, 0, float3(1, 0, 0), float3(.7, .7, 2)},
955 };
956 import_and_check("polylines.obj", expect, std::size(expect), 0);
957}
958
959} // namespace blender::io::obj
float(* BKE_curve_nurbs_vert_coords_alloc(const ListBase *lb, int *r_vert_len))[3]
Definition curve.cc:4555
CustomData interface, see also DNA_customdata_types.h.
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get(struct Object *ob, short act)
General operations, lookup, etc. for blender objects.
Mesh * BKE_object_get_evaluated_mesh(const Object *object_eval)
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define M_PI_2
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define STREQ(a, b)
external readfile function prototypes.
@ DAG_EVAL_VIEWPORT
#define DEG_OBJECT_ITER_BEGIN(settings_, instance_)
#define DEG_OBJECT_ITER_END
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
@ DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY
@ DEG_ITER_OBJECT_FLAG_VISIBLE
@ DEG_ITER_OBJECT_FLAG_DUPLI
@ DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET
@ CU_NURB_ENDPOINT
@ CD_PROP_COLOR
@ CD_PROP_FLOAT2
@ OB_MESH
@ OB_CURVES_LEGACY
@ IO_AXIS_Y
@ IO_AXIS_NEGATIVE_Z
Read Guarded memory(de)allocation.
virtual void depsgraph_create(eEvaluationMode depsgraph_evaluation_mode)
bool blendfile_load(const char *filepath)
void import_and_check(const char *path, const Expectation *expect, size_t expect_count, int expect_mat_count, int expect_image_count=0)
#define printf
draw_view in_light_buf[] float
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
ccl_device_inline float3 exp(float3 v)
TEST_F(OBJExportTest, filter_objects_curves_as_mesh)
void importer_main(bContext *C, const OBJImportParams &import_params)
VecBase< float, 4 > float4
VecBase< float, 2 > float2
VecBase< float, 3 > float3
ViewLayer * cur_view_layer
char name[66]
Definition DNA_ID.h:425
ListBase materials
Definition BKE_main.hh:216
ListBase images
Definition BKE_main.hh:218
short flagu
short orderu
char filepath[FILE_MAX]
float x
Definition sky_float3.h:27
#define SEP_STR
Definition unit.cc:39