Developer Documentation
MeshCompiler_test.cc
1 /*===========================================================================*\
2  * *
3  * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40 \*===========================================================================*/
41 
42 /*
43  * BSP_test.cc
44  *
45  * Created on: 28.12.2013
46  * Author: tenter
47  */
48 
49 #include <gtest/gtest.h>
50 
51 #include <ACG/GL/VertexDeclaration.hh>
52 #include <ACG/GL/MeshCompiler.hh>
53 
54 #include "MeshCompiler_testData.hh"
55 
56 
57 // Importer for custom binary file format developed to debug/profe MeshCompiler
58 
60 {
61 public:
62  SBFReader(const char* szObjFile);
63  virtual ~SBFReader(void) {}
64 
65  int getNumVertices() {return m_Vertices.size() / 3;}
66  int getNumTexcoords() {return m_TexCoords.size() / 2;}
67  int getNumNormals() {return m_Normals.size() / 3;}
68 
69  float* getVertices() {return m_Vertices.empty() ? 0 : &m_Vertices[0];}
70  float* getNormals() {return m_Normals.empty() ? 0 : &m_Normals[0];}
71  float* getTexCoords() {return m_TexCoords.empty() ? 0 : &m_TexCoords[0];}
72 
73  virtual int getVertexAdjCount(const int _vertexID) const
74  {
75  if (m_AdjVertexCount.size()) return m_AdjVertexCount[_vertexID];
76  else return -1;
77  }
78  virtual int getVertexAdjFace(const int _vertexID, const int _k) const
79  {
80  if (m_AdjVertexOffset.size()) return m_AdjVertexBuf[m_AdjVertexOffset[_vertexID] + _k];
81  else return -1;
82  }
83  virtual int getFaceAdjCount(int _faceID)
84  {
85  if (m_AdjFaceCount.size()) return m_AdjFaceCount[_faceID];
86  else return -1;
87  }
88  virtual int getFaceAdjFace(int _faceID, int _k)
89  {
90  if (m_AdjFaceOffset.size()) return m_AdjFaceBuf[m_AdjFaceOffset[_faceID] + _k];
91  else return -1;
92  }
93 
94  void writeFile(const char* szFile);
95 
96 private:
97 
98  int m_NumVerts,
99  m_NumNormals,
100  m_NumTexCoords;
101 
102 
103  std::vector<float> m_Vertices;
104  std::vector<float> m_Normals;
105  std::vector<float> m_TexCoords;
106 
107  int m_PosAttrID,
108  m_NormAttrID,
109  m_TexCAttrID;
110 
111 
112 
113  // adjacency
114  std::vector<unsigned char> m_AdjVertexCount;
115  std::vector<int> m_AdjVertexOffset;
116  std::vector<int> m_AdjVertexBuf;
117 
118  std::vector<int> m_AdjFaceOffset;
119  std::vector<unsigned char> m_AdjFaceCount;
120  std::vector<int> m_AdjFaceBuf;
121 };
122 
123 SBFReader::SBFReader(const char* szObjFile)
124  : MeshCompilerDefaultFaceInput(0, 0),
125  m_NumVerts(0), m_NumNormals(0), m_NumTexCoords(0),
126  m_PosAttrID(0), m_NormAttrID(-1), m_TexCAttrID(-1)
127 {
128  if (szObjFile)
129  {
130  FILE* pFile = fopen(szObjFile, "rb");
131 
132  // count # tris, verts
133 
134  numFaces_ = 0;
135  m_NumVerts = 0; m_NumNormals = 0; m_NumTexCoords = 0;
136 
137  if (pFile)
138  {
139  fread(&numFaces_, 4, 1, pFile);
140  fread(&m_NumVerts, 4, 1, pFile);
141  fread(&m_NumNormals, 4, 1, pFile);
142  fread(&m_NumTexCoords, 4, 1, pFile);
143 
144  int faceBufSize = 0;
145  fread(&faceBufSize, 4, 1, pFile);
146 
147 
148  m_Vertices.resize(m_NumVerts * 3);
149  m_Normals.resize(m_NumNormals * 3);
150  m_TexCoords.resize(m_NumTexCoords * 3);
151  faceOffset_.resize(numFaces_);
152  faceSize_.resize(numFaces_);
153 
154  fread(&faceSize_[0], 4, numFaces_, pFile);
155 
156  faceOffset_[0] = 0;
157  for (int i = 1; i < numFaces_; ++i)
158  faceOffset_[i] = faceOffset_[i-1] + faceSize_[i-1];
159 
160  if (m_NumVerts)
161  {
162  faceData_[m_PosAttrID].resize(faceBufSize);
163  fread(&faceData_[m_PosAttrID][0], 4, faceBufSize, pFile);
164  }
165 
166  if (m_NumTexCoords)
167  {
168  m_TexCAttrID = 1;
169  faceData_[m_TexCAttrID].resize(faceBufSize);
170  fread(&faceData_[m_TexCAttrID][0], 4, faceBufSize, pFile);
171  }
172 
173  if (m_NumNormals)
174  {
175  m_NormAttrID = m_TexCAttrID >= 0 ? m_TexCAttrID + 1 : m_PosAttrID + 1;
176  faceData_[m_NormAttrID].resize(faceBufSize);
177  fread(&faceData_[m_NormAttrID][0], 4, faceBufSize, pFile);
178  }
179 
180 
181  if (m_NumVerts)
182  fread(&m_Vertices[0], 12, m_NumVerts, pFile);
183 
184  if (m_NumTexCoords)
185  fread(&m_TexCoords[0], 8, m_NumTexCoords, pFile);
186 
187  if (m_NumNormals)
188  fread(&m_Normals[0], 12, m_NumNormals, pFile);
189 
190 
191  int numVertAdj, numFaceAdj, vertAdjSize, faceAdjSize;
192 
193  if (fread(&numVertAdj, 4, 1, pFile) == 1)
194  {
195  fread(&vertAdjSize, 4, 1, pFile);
196 
197  m_AdjVertexOffset.resize(numVertAdj);
198  m_AdjVertexCount.resize(numVertAdj);
199  m_AdjVertexBuf.resize(vertAdjSize);
200 
201  fread(&m_AdjVertexOffset[0], 4, numVertAdj, pFile);
202  fread(&m_AdjVertexCount[0], 1, numVertAdj, pFile);
203  fread(&m_AdjVertexBuf[0], 4, vertAdjSize, pFile);
204 
205  if (fread(&numFaceAdj, 4, 1, pFile) == 1)
206  {
207  fread(&faceAdjSize, 4, 1, pFile);
208 
209  m_AdjFaceOffset.resize(numFaceAdj);
210  m_AdjFaceCount.resize(numFaceAdj);
211  m_AdjFaceBuf.resize(faceAdjSize);
212 
213  fread(&m_AdjFaceOffset[0], 4, numFaceAdj, pFile);
214  fread(&m_AdjFaceCount[0], 1, numFaceAdj, pFile);
215  fread(&m_AdjFaceBuf[0], 4, faceAdjSize, pFile);
216  }
217  }
218 
219  fclose(pFile);
220  }
221 
222  }
223 
224 }
225 
226 
227 
228 class MeshCompilerTest : public testing::Test {
229 
230 public:
232  {
233  // create mesh 0
234  MeshTestData input0;
235  MeshCompilerTest_GetInput0(&input0);
236  mesh0_ = CreateMesh(input0);
237 
238  // create mesh 1
239  MeshTestData input1;
240  MeshCompilerTest_GetInput1(&input1);
241  mesh1_ = CreateMesh(input1);
242  }
243 
244 protected:
245 
246  // This function is called before each test is run
247  virtual void SetUp() {
248 
249  }
250 
251  // This function is called after all tests are through
252  virtual void TearDown() {
253 
254  delete mesh0_; mesh0_ = 0;
255  delete mesh1_; mesh1_ = 0;
256  }
257 
258 
259  ACG::MeshCompiler* CreateMesh(const MeshTestData& input) {
260 
262  decl.addElement(GL_FLOAT, 3, ACG::VERTEX_USAGE_POSITION);
263  if (input.numTexcoords_)
264  decl.addElement(GL_FLOAT, 2, ACG::VERTEX_USAGE_TEXCOORD);
265  if (input.numNormals_)
266  decl.addElement(GL_FLOAT, 3, ACG::VERTEX_USAGE_NORMAL);
267 
268 
269  ACG::MeshCompiler* mesh = new ACG::MeshCompiler(decl);
270 
271  // vertex data input
272  mesh->setVertices(input.numVerts_, input.vdata_pos);
273  mesh->setTexCoords(input.numTexcoords_, input.vdata_t);
274  mesh->setNormals(input.numNormals_, input.vdata_n);
275 
276  // face input
277  mesh->setNumFaces(input.numFaces_, input.numIndices_);
278 
279  int offset = 0;
280  for (int i = 0; i < input.numFaces_; ++i)
281  {
282  int fsize = input.fsize_[i];
283  mesh->setFaceVerts(i, fsize, ((int*)input.fdata_pos) + offset);
284 
285  if (input.numTexcoords_ && input.fdata_t)
286  mesh->setFaceTexCoords(i, fsize, ((int*)input.fdata_t) + offset);
287 
288  if (input.numNormals_ && input.fdata_n)
289  mesh->setFaceNormals(i, fsize, ((int*)input.fdata_n) + offset);
290 
291  offset += fsize;
292  }
293 
294  // test group id sorting
295 
296  const int numGroups = 5;
297 
298  //srand(GetTickCount());
299 
300  for (int i = 0; i < input.numFaces_; ++i)
301  mesh->setFaceGroup(i, rand()% numGroups);
302 
303  return mesh;
304  }
305 
306 
307  ACG::MeshCompiler* mesh0_;
308  ACG::MeshCompiler* mesh1_;
309 
310 };
311 
312 
313 TEST_F(MeshCompilerTest, npoly_vpos__fff ) {
314 
315  mesh0_->build(false, false, false);
316  EXPECT_EQ(mesh0_->dbgVerify(0), true) << "compiled mesh contains errors";
317 }
318 
319 TEST_F(MeshCompilerTest, npoly_vpos__tff ) {
320 
321  mesh0_->build(true, false, false);
322 
323  EXPECT_EQ(mesh0_->dbgVerify(0), true) << "compiled mesh contains errors";
324 }
325 
326 TEST_F(MeshCompilerTest, npoly_vpos__ftf ) {
327 
328  mesh0_->build(false, true, false);
329 
330  EXPECT_EQ(mesh0_->dbgVerify(0), true) << "compiled mesh contains errors";
331 }
332 
333 TEST_F(MeshCompilerTest, npoly_vpos__ttf ) {
334 
335  mesh0_->build(true, true, false);
336 
337  EXPECT_EQ(mesh0_->dbgVerify(0), true) << "compiled mesh contains errors";
338 }
339 
340 
341 
342 
343 
344 TEST_F(MeshCompilerTest, npoly_vpos__fft ) {
345 
346  mesh0_->build(false, false, true);
347 
348  EXPECT_EQ(mesh0_->dbgVerify(0), true) << "compiled mesh contains errors";
349 }
350 
351 TEST_F(MeshCompilerTest, npoly_vpos__tft ) {
352 
353  mesh0_->build(true, false, true);
354 
355  EXPECT_EQ(mesh0_->dbgVerify(0), true) << "compiled mesh contains errors";
356 }
357 
358 TEST_F(MeshCompilerTest, npoly_vpos__ftt ) {
359 
360  mesh0_->build(false, true, true);
361 
362  EXPECT_EQ(mesh0_->dbgVerify(0), true) << "compiled mesh contains errors";
363 }
364 
365 TEST_F(MeshCompilerTest, npoly_vpos__ttt ) {
366 
367  mesh0_->build(true, true, true);
368 
369  EXPECT_EQ(mesh0_->dbgVerify(0), true) << "compiled mesh contains errors";
370 }
371 
372 
373 
374 
375 
376 TEST_F(MeshCompilerTest, tri_vpos_texc__fff ) {
377 
378  mesh1_->build(false, false, false);
379 
380  EXPECT_EQ(mesh1_->dbgVerify(0), true) << "compiled mesh contains errors";
381 }
382 
383 TEST_F(MeshCompilerTest, tri_vpos_texc__tff ) {
384 
385  mesh1_->build(true, false, false);
386 
387  EXPECT_EQ(mesh1_->dbgVerify(0), true) << "compiled mesh contains errors";
388 }
389 
390 TEST_F(MeshCompilerTest, tri_vpos_texc__ftf ) {
391 
392  mesh1_->build(false, true, false);
393 
394  EXPECT_EQ(mesh1_->dbgVerify(0), true) << "compiled mesh contains errors";
395 }
396 
397 TEST_F(MeshCompilerTest, tri_vpos_texc__ttf ) {
398 
399  mesh1_->build(true, true, false);
400 
401  EXPECT_EQ(mesh1_->dbgVerify(0), true) << "compiled mesh contains errors";
402 }
403 
404 
405 
406 
407 
408 TEST_F(MeshCompilerTest, tri_vpos_texc__fft ) {
409 
410  mesh1_->build(false, false, true);
411 
412  EXPECT_EQ(mesh1_->dbgVerify(0), true) << "compiled mesh contains errors";
413 }
414 
415 TEST_F(MeshCompilerTest, tri_vpos_texc__tft ) {
416 
417  mesh1_->build(true, false, true);
418 
419  EXPECT_EQ(mesh1_->dbgVerify(0), true) << "compiled mesh contains errors";
420 }
421 
422 TEST_F(MeshCompilerTest, tri_vpos_texc__ftt ) {
423 
424  mesh1_->build(false, true, true);
425 
426  EXPECT_EQ(mesh1_->dbgVerify(0), true) << "compiled mesh contains errors";
427 }
428 
429 TEST_F(MeshCompilerTest, tri_vpos_texc__ttt ) {
430 
431  mesh1_->build(true, true, true);
432 
433  EXPECT_EQ(mesh1_->dbgVerify(0), true) << "compiled mesh contains errors";
434 }
void setFaceNormals(int _i, int _v0, int _v1, int _v2)
Set normal ids per triangle.
virtual int getVertexAdjCount(const int _vertexID) const
Class to define the vertex input layout.
void setFaceTexCoords(int _i, int _v0, int _v1, int _v2)
Set texcoord ids per triangle.
void setNumFaces(const int _numFaces, const int _numIndices)
Set number of faces and indices if known by user.
void setVertices(int _num, const void *_data, int _stride=0, bool _internalCopy=false, GLuint _fmt=0, int _elementSize=-1)
void setNormals(int _num, const void *_data, int _stride=0, bool _internalCopy=false, GLuint _fmt=0, int _elementSize=-1)
virtual int getVertexAdjFace(const int _vertexID, const int _k) const
void addElement(const VertexElement *_pElement)
void setFaceVerts(int _i, int _v0, int _v1, int _v2)
Set vertex ids per triangle.
void setFaceGroup(int _i, short _groupID)
Specify face groups.
void setTexCoords(int _num, const void *_data, int _stride=0, bool _internalCopy=false, GLuint _fmt=0, int _elementSize=-1)