GeometryValidityTestingExample.cpp

<< 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;
    }