<< Click to Display Table of Contents >> Navigation: Simplygon 7.1 examples > GeometryValidityTestingExample.cpp |
///////////////////////////////////////////////////////////////////////////
//
// System: Simplygon
// File: GeometryValidityTestingExample.cpp
// Language: C++
//
// Copyright (c) 2015 Donya Labs AB. All rights reserved.
//
// This is private property, and it is illegal to copy or distribute in
// any form, without written authorization by the copyright owner(s).
//
///////////////////////////////////////////////////////////////////////////
//
// #Description#
//
// This example demonstrates how to look through a GeometryData-object and
// make sure all stored data inside is valid, and that it is stored
// correctly. The local function ValidateGeometry() gives an example of how
// the geometry can be validated manually.
//
// The IGeometryValidator class is also used on the geometry to display
// how you can simply use it to validate your geometries and get a string
// error message with description of any non-valid parts with the geometry.
//
///////////////////////////////////////////////////////////////////////////
#include "../Common/Example.h"
void RunExample(const std::string& readFrom);
bool CheckArray(IValueArray* arr, unsigned int tuplecount, unsigned int tuplesize);
bool CheckGeometry(IGeometryData* geom);
void ValidateGeometry(IGeometryData* geom);
int main( int argc , char* argv[] )
{
// Initiate
InitExample();
// Run the example code
std::string assetPath = GetAssetPath();
RunExample( assetPath + "testobject.obj" );
// Deinitialize the SDK
DeinitExample();
return 0;
}
void RunExample(const std::string& readFrom)
{
// Load from file
spWavefrontImporter objReader = sg->CreateWavefrontImporter();
objReader->SetImportFilePath( readFrom.c_str() );
if( !objReader->RunImport() )
{
std::cout << "Failed to load file" << std::endl;
}
// Get the scene from the importer
spScene scene = objReader->GetScene();
// First running the loaded scene. Should be ok!
if(true)
{
std::cout << "Validating the original geometry." << std::endl;
spGeometryData geometry = scene->GetCombinedGeometry()->NewCopy(true);
ValidateGeometry( geometry );
//Using the IGeometryValidator class
spGeometryValidator geometryValidator = sg->CreateGeometryValidator();
geometryValidator->ValidateGeometry( geometry );
rid error_value = geometryValidator->GetErrorValue();
rstring error_string = geometryValidator->GetErrorString();
printf( "\nIGeometryValidator: %s\n\n\n", error_string->GetText());
}
// Now we mess up the Geometry some.
// Here we set the vertex index to an invalid index.
if(true)
{
std::cout << "\nValidating the geometry with invalid index." << std::endl;
spGeometryData geometry = scene->GetCombinedGeometry()->NewCopy(true);
geometry->GetVertexIds()->SetItem( 73, geometry->GetVertexCount()+1 );
// Lets validate again!
ValidateGeometry( geometry );
//Using the IGeometryValidator class
spGeometryValidator geometryValidator = sg->CreateGeometryValidator();
geometryValidator->ValidateGeometry( geometry );
rid error_value = geometryValidator->GetErrorValue();
rstring error_string = geometryValidator->GetErrorString();
printf( "\nIGeometryValidator: %s\n\n\n", error_string->GetText());
}
// Another way to mess up the Geometry.
// This time we set an illegal tuplesize.
if(true)
{
std::cout << "\nValidating the geometry with invalid tuplesize." << std::endl;
spGeometryData geometry = scene->GetCombinedGeometry()->NewCopy(true);
geometry->GetCoords()->SetTupleSize( 4 );
// Lets validate again!
ValidateGeometry( geometry );
//Using the IGeometryValidator class
spGeometryValidator geometryValidator = sg->CreateGeometryValidator();
geometryValidator->ValidateGeometry( geometry );
rid error_value = geometryValidator->GetErrorValue();
rstring error_string = geometryValidator->GetErrorString();
printf( "\nIGeometryValidator: %s\n\n\n", error_string->GetText());
}
// Another way to mess up the Geometry.
// Create a degenerate triangle where two vertices in the triangle are the same vertex
if(true)
{
std::cout << "\nValidating the geometry with a degenerate triangle." << std::endl;
spGeometryData geometry = scene->GetCombinedGeometry()->NewCopy(true);
geometry->GetVertexIds()->SetItem( 10*3 + 0 , geometry->GetVertexIds()->GetItem( 10*3 + 1 ) );
//Using the IGeometryValidator class
spGeometryValidator geometryValidator = sg->CreateGeometryValidator();
geometryValidator->ValidateGeometry( geometry );
rid error_value = geometryValidator->GetErrorValue();
rstring error_string = geometryValidator->GetErrorString();
printf( "\nIGeometryValidator: %s\n\n\n", error_string->GetText());
}
// Another way to mess up the Geometry.
// Create a zero area triangle
if(true)
{
std::cout << "\nValidating the geometry with a zero area triangle." << std::endl;
spGeometryData geometry = scene->GetCombinedGeometry()->NewCopy(true);
geometry->GetCoords()->SetItem( 0, geometry->GetCoords()->GetItem( 3 ) );
geometry->GetCoords()->SetItem( 1, geometry->GetCoords()->GetItem( 4 ) );
geometry->GetCoords()->SetItem( 2, geometry->GetCoords()->GetItem( 5 ) );
//Using the IGeometryValidator class
spGeometryValidator geometryValidator = sg->CreateGeometryValidator();
geometryValidator->ValidateGeometry( geometry );
rid error_value = geometryValidator->GetErrorValue();
rstring error_string = geometryValidator->GetErrorString();
printf( "\nIGeometryValidator: %s\n\n\n", error_string->GetText());
}
}
void ValidateGeometry(IGeometryData* geom)
{
//bool passedtest = CheckGeometry( geom );
spGeometryValidator validator = sg->CreateGeometryValidator();
bool passedtest = validator->ValidateGeometry(geom);
if(!passedtest)
std::cout << "Geometry failed test" << std::endl;
else
std::cout << "Geometry passed test" << std::endl;
}
bool CheckGeometry(IGeometryData* geom)
{
// Check geometry for consistency
unsigned int vertex_count = geom->GetVertexCount();
unsigned int triangle_count = geom->GetTriangleCount();
unsigned int corner_count = triangle_count * 3;
if( triangle_count < 1 || vertex_count < 3)
{
std::cout << "Illegal mesh: too few vertices or triangles" << std::endl;
return false;
}
// Load indices for the vertices belonging to the 3 corners of each triangle.
// It should have the size 3 x triangle_count.
// TupleCount should be same as number of triangle-corners in the geometry, i.e 3 x triangle_count,
// and TupleSize should be 1. This one might be confusing, because its stored per-corner-basis, and not on
// per-triangle-basis, and that is why tuplesize is 1 and not 3.
spRidArray VertexIds = geom->GetVertexIds();
if( !CheckArray( VertexIds , corner_count, 1) )
return false;
// Check that the Coords-array is of correct size
spRealArray Coords = geom->GetCoords();
if( !CheckArray( Coords , vertex_count, 3) )
return false;
// Check that all VertexIds has correct index, i.e 0 <= index < vertex_count;
std::cout << "Checking if the indices contains valid values..." << std::endl;
rid index[3];
for( unsigned int i = 0; i < triangle_count; i++)
{
for(int n = 0; n < 3; n++)
{
index[n] = VertexIds->GetItem( i*3+n );
if( index[n] < 0 || rid(vertex_count) <= index[n] )
{
std::cout << "error: Index for triangle: " << i << ", corner: " << n << " out of bounds!" << std::endl;
return false;
}
}
if( index[0] == index[1] ||
index[0] == index[2] ||
index[1] == index[2] )
{
std::cout << "warning: Triangle " << i << " contains same vertices atleast twice" << std::endl;
}
}
// Check texcoords, levels 0-3
spRealArray texcoordsarray;
for(int i = 0; i < 4; i++)
{
texcoordsarray = geom->GetTexCoords( i );
if( !texcoordsarray.IsNull() )
{
if( !CheckArray( texcoordsarray , corner_count, 2) )
return false;
}
}
//Check normals
spRealArray Normals = geom->GetNormals();
if( !Normals.IsNull() )
{
if( !CheckArray( Normals , corner_count, 3) )
return false;
}
//Check material-ids
spRidArray Materials = geom->GetMaterialIds();
if( !Materials.IsNull() )
{
if( !CheckArray( Materials , triangle_count, 1) )
return false;
}
//Check group-ids
spRidArray Groups = geom->GetGroupIds();
if( !Groups.IsNull() )
{
if( !CheckArray( Groups , triangle_count, 1) )
return false;
}
return true;
}
bool CheckArray(IValueArray* arr, unsigned int tuplecount, unsigned int tuplesize)
{
rstring name = arr->GetName();
std::cout << "Checking size information on: " << name.GetText() << std::endl;
unsigned int count = arr->GetTupleCount();
if( tuplecount != count )
{
std::cout << "error: " << name.GetText() << " does not contain correct number of tuples" << std::endl;
std::cout << "tuplecount should be " << tuplecount << " but was " << count << std::endl;
return false;
}
count = arr->GetTupleSize();
if( tuplesize != count )
{
std::cout << "error: " << name.GetText() << " does not have the correct tuple-size" << std::endl;
std::cout << "tuplesize should be " << tuplesize << " but was " << count << std::endl;
return false;
}
count = arr->GetItemCount();
if( tuplecount * tuplesize != count )
{
std::cout << "error: " << name.GetText() << " does not contain correct number of items" << std::endl;
std::cout << "itemcount should be " << tuplecount * tuplesize << " but was " << count << std::endl;
return false;
}
return true;
}