1
2 //
3 // This source file is part of appleseed.
4 // Visit https://appleseedhq.net/ for additional information and resources.
5 //
6 // This software is released under the MIT license.
7 //
8 // Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
9 // Copyright (c) 2014-2018 Francois Beaune, The appleseedhq Organization
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining a copy
12 // of this software and associated documentation files (the "Software"), to deal
13 // in the Software without restriction, including without limitation the rights
14 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 // copies of the Software, and to permit persons to whom the Software is
16 // furnished to do so, subject to the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be included in
19 // all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 // THE SOFTWARE.
28 //
29
30 // appleseed.foundation headers.
31 #include "foundation/math/vector.h"
32 #include "foundation/mesh/meshbuilderbase.h"
33 #include "foundation/mesh/objmeshfilereader.h"
34 #include "foundation/platform/compiler.h"
35 #include "foundation/utility/test.h"
36
37 // Standard headers.
38 #include <cstddef>
39 #include <string>
40 #include <vector>
41
42 using namespace foundation;
43 using namespace std;
44
TEST_SUITE(Foundation_Mesh_OBJMeshFileReader)45 TEST_SUITE(Foundation_Mesh_OBJMeshFileReader)
46 {
47 struct Face
48 {
49 vector<size_t> m_vertices;
50 };
51
52 struct Mesh
53 {
54 string m_name;
55 vector<Vector3d> m_vertices;
56 vector<Vector3d> m_vertex_normals;
57 vector<Vector2d> m_tex_coords;
58 vector<Face> m_faces;
59 };
60
61 struct MeshBuilder
62 : public MeshBuilderBase
63 {
64 vector<Mesh> m_meshes;
65
66 void begin_mesh(const char* name) override
67 {
68 m_meshes.emplace_back();
69 m_meshes.back().m_name = name;
70 }
71
72 size_t push_vertex(const Vector3d& v) override
73 {
74 assert(!m_meshes.empty());
75 m_meshes.back().m_vertices.push_back(v);
76 return m_meshes.back().m_vertices.size() - 1;
77 }
78
79 size_t push_vertex_normal(const Vector3d& v) override
80 {
81 assert(!m_meshes.empty());
82 m_meshes.back().m_vertex_normals.push_back(safe_normalize(v));
83 return m_meshes.back().m_vertex_normals.size() - 1;
84 }
85
86 size_t push_tex_coords(const Vector2d& v) override
87 {
88 assert(!m_meshes.empty());
89 m_meshes.back().m_tex_coords.push_back(v);
90 return m_meshes.back().m_tex_coords.size() - 1;
91 }
92
93 void begin_face(const size_t vertex_count) override
94 {
95 assert(!m_meshes.empty());
96 m_meshes.back().m_faces.emplace_back();
97 Face& face = m_meshes.back().m_faces.back();
98 face.m_vertices.resize(vertex_count);
99 }
100
101 void set_face_vertices(const size_t vertices[]) override
102 {
103 assert(!m_meshes.empty());
104 assert(!m_meshes.back().m_faces.empty());
105 Face& face = m_meshes.back().m_faces.back();
106 for (size_t i = 0, e = face.m_vertices.size(); i < e; ++i)
107 face.m_vertices[i] = vertices[i];
108 }
109 };
110
111 TEST_CASE(ReadCubeMeshFile)
112 {
113 OBJMeshFileReader reader("unit tests/inputs/test_objmeshfilereader_cube.obj");
114 MeshBuilder builder;
115 reader.read(builder);
116
117 EXPECT_EQ(1, builder.m_meshes.size());
118
119 Mesh& mesh = builder.m_meshes.front();
120 EXPECT_EQ("", mesh.m_name);
121 EXPECT_EQ(20, mesh.m_vertices.size());
122 EXPECT_EQ(6, mesh.m_vertex_normals.size());
123 EXPECT_EQ(20, mesh.m_tex_coords.size());
124 EXPECT_EQ(12, mesh.m_faces.size());
125 }
126
127 TEST_CASE(ReadQuadMeshFile)
128 {
129 OBJMeshFileReader reader("unit tests/inputs/test_objmeshfilereader_quad.obj");
130 MeshBuilder builder;
131 reader.read(builder);
132
133 EXPECT_EQ(1, builder.m_meshes.size());
134
135 Mesh& mesh = builder.m_meshes.front();
136 EXPECT_EQ("quad", mesh.m_name);
137 EXPECT_EQ(4, mesh.m_vertices.size());
138 EXPECT_EQ(0, mesh.m_vertex_normals.size());
139 EXPECT_EQ(4, mesh.m_tex_coords.size());
140 EXPECT_EQ(1, mesh.m_faces.size());
141 }
142
143 #if 0
144
145 TEST_CASE(OBJFileToCPPFile)
146 {
147 OBJMeshFileReader reader("input.obj");
148 MeshBuilder builder;
149 reader.read(builder);
150
151 assert(builder.m_meshes.size() == 1);
152
153 FILE* f = fopen("output.cpp", "wt");
154 assert(f);
155
156 const Mesh& m = builder.m_meshes.front();
157
158 fprintf(f, "static const float Vertices[] =\n{\n");
159 for (const auto& v : m.m_vertices)
160 {
161 fprintf(f, " %.7ff, %.7ff, %.7ff,\n", v.x, v.y, v.z);
162 }
163 fprintf(f, "};\n\n");
164
165 fprintf(f, "static const size_t Triangles[] =\n{\n");
166 for (const auto& face : m.m_faces)
167 {
168 fprintf(
169 f,
170 " " FMT_SIZE_T ", " FMT_SIZE_T ", " FMT_SIZE_T ",\n",
171 face.m_vertices[0], face.m_vertices[1], face.m_vertices[2]);
172 }
173 fprintf(f, "};\n");
174
175 fclose(f);
176 }
177
178 #endif
179 }
180