GeometryGroupingExample.cpp

<< Click to Display Table of Contents >>

Navigation:  Simplygon 7.1 examples >

GeometryGroupingExample.cpp

///////////////////////////////////////////////////////////////////////////
//
//  System:    Simplygon
//  File:      GeometryGroupingExample.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#
//
//  Four patches are generated, border to border with each other making up a square, but
//  each with a different group id. Three of the geometries are combined into a single
//  geometry. The resulting geometry and the fourth patch are added to scene mesh nodes
//  in a scene, and processed with the reduction processor to demonstrate how to keep
//  group borders as well as borders between scene mesh geometries during reduction.
//
///////////////////////////////////////////////////////////////////////////
#include "../Common/Example.h"
void RunExample();
bool GeneratePatch(int n, float x_mult, float y_mult, rid groupId, IGeometryData* _geom);
int main( int argc , char* argv[] )
    {
    InitExample();
    // Run the example code
    RunExample();
    DeinitExample();
    return 0;
    }
void RunExample()
    {
    // Create the Geometries. All geometry data will be loaded into these objects
    spGeometryData geom1 = sg->CreateGeometryData();
    spGeometryData geom2 = sg->CreateGeometryData();
    spGeometryData geom3 = sg->CreateGeometryData();
    spGeometryData geom4 = sg->CreateGeometryData();
    // This will generate 4 patches placed next to each other
    if(!GeneratePatch(20, 1, 1, 0, geom1))
        return;
    if(!GeneratePatch(39, -0.5, 0.5, 0, geom2))
        return;
    if(!GeneratePatch(39, 0.5, -0.5, 1, geom3))
        return;
    if(!GeneratePatch(20, -1, -1, 2, geom4))
        return;
    // Combine three geometries into single geometry
    geom1->AppendGeometry( geom3 );
    geom1->AppendGeometry( geom4 );
    // Create Scene and insert geometry into it
    spScene scene = sg->CreateScene();
    spSceneMesh sceneMesh1 = sg->CreateSceneMesh();
    sceneMesh1->SetGeometry( geom1 );
    scene->GetRootNode()->AddChild( sceneMesh1 );
    spSceneMesh sceneMesh2 = sg->CreateSceneMesh();
    sceneMesh2->SetGeometry( geom2 );
    scene->GetRootNode()->AddChild( sceneMesh2 );
    // Export original scene
    spWavefrontExporter objexp = sg->CreateWavefrontExporter();
    std::string outputPath = GetExecutablePath() + "originalgeometries.obj";
    objexp->SetExportFilePath( outputPath.c_str() );
    objexp->SetScene(scene);
    objexp->RunExport();
    // Create the reduction processor. Set the geometry that is to be processed
    spReductionProcessor reducer = sg->CreateReductionProcessor();
    reducer->SetScene(scene);
    ///////////////////////////////////////////////////
    //
    // Set the Repair Settings. Default settings will mean that all visual gaps will remain in the geometry and thus
    // hinder the reduction on geometries that contains gaps, holes and tjunctions.
    // By setting the Tjunc distance to 0.3, the gaps between the differently-sized patches will be stitched together.
    spRepairSettings repair_settings = reducer->GetRepairSettings();
    // Only vertices that actually share the same position will be welded together
    repair_settings->SetWeldDist( 0.0f );
    // All gaps in the example patches will be stitched together before reduction proceeds.
    repair_settings->SetTjuncDist( 0.3f );
    ///////////////////////////////////////////////////
    //
    // Set the Reduction Settings.
    spReductionSettings reduction_settings = reducer->GetReductionSettings();
    // These importance values will make the reduction process respect group boundaries.
    reduction_settings->SetEdgeSetImportance(0.0f);
    reduction_settings->SetGroupImportance(1.0f);
    reduction_settings->SetMaterialImportance(0.0f);
    reduction_settings->SetShadingImportance(0.0f);
    reduction_settings->SetSkinningImportance(0.0f);
    reduction_settings->SetTextureImportance(0.0f);
    reduction_settings->SetVertexColorImportance(0.0f);
    // Reduce to 10% triangles.
    reduction_settings->SetTriangleRatio( 0.1f );
    ///////////////////////////////////////////////////
    //
    // Set the Normal Calculation Settings.
    spNormalCalculationSettings normal_settings = reducer->GetNormalCalculationSettings();
    // Will completely recalculate the normals.
    normal_settings->SetReplaceNormals( true );
    normal_settings->SetHardEdgeAngleInRadians( 3.141590f*90.f/180.0f );   
    // Run the process
    reducer->RunProcessing();   
    // Output reduced geometries, where the group borders are kept as intact as possible.
    outputPath = GetExecutablePath() + "reducedgeometries.obj";
    objexp->SetExportFilePath( outputPath.c_str() );
    objexp->SetScene(scene);
    objexp->RunExport();
    }
// GeneratePatch generates a waved triangle patch of size (n x n) vertices.
bool GeneratePatch(int n, float x_mult, float y_mult, rid groupId, IGeometryData* geom)
    {
    if(n < 2 || x_mult == 0.0f || y_mult == 0.0f)
        return false;
    int vertex_count = n*n;
    int triangle_count = (n-1)*(n-1)*2;
    float *vertex_coordinates = new float[ vertex_count * 3 ];
    int index;
    for(int x = 0; x < n; x++)
        {
        for(int y = 0; y < n; y++)
            {
            index = x*n + y;
            // x-value
            vertex_coordinates[index*3 + 0] = float(x)*x_mult;
            // y-value
            vertex_coordinates[index*3 + 1] = float(y)*y_mult;
            // z-value
            vertex_coordinates[index*3 + 2] =  vertex_coordinates[index*3 + 0] * vertex_coordinates[index*3 + 0] * 0.02f +
                vertex_coordinates[index*3 + 1] * vertex_coordinates[index*3 + 1] * 0.02f;
            }
        }
    int *corner_ids = new int[ triangle_count*3 ];
    for(int x = 0; x < n-1; x++)
        {
        for(int y = 0; y < n-1; y++)
            {
            index = (x*(n-1) + y) * 2;
            corner_ids[ index*3 + 0] = y*n + x;
            corner_ids[ index*3 + 1] = y*n + x + 1;
            corner_ids[ index*3 + 2] = (y+1)*n + x;
            corner_ids[ (index + 1)*3 + 0] = (y+1)*n + x;
            corner_ids[ (index + 1)*3 + 1] = y*n + x + 1;
            corner_ids[ (index + 1)*3 + 2] = (y+1)*n + x + 1;
            }
        }
    // Array with vertex-coordinates. Will contain 3 real-values for each vertex in the geometry.
    spRealArray coords = geom->GetCoords();
    // Array with triangle-data. Will contain 3 ids for each corner of each triangle, so the triangles know what vertices to use.
    spRidArray vertex_ids = geom->GetVertexIds();
    // Add GroupIds field. Contains 1 id for each corner.
    geom->AddGroupIds();
    spRidArray group_ids = geom->GetGroupIds();
    // Set vertex- and triangle-counts for the Geometry.
    // NOTE: The number of vertices and triangles has to be set before vertex- and triangle-data is loaded into the GeometryData.
    geom->SetVertexCount(vertex_count);
    geom->SetTriangleCount(triangle_count);
    // add vertex-coordinates to the Geometry. Each tuple contains the 3 coordinates for each vertex. X, y and z values.
    for( int i=0; i<vertex_count; ++i )
        {
        coords->SetTuple( i , &vertex_coordinates[i*3] );
        }
    // add triangles to the Geometry. Each triangle contains the 3 ids for what vertices each triangle uses.
    // SetTuple can also be used, but since the TupleSize of the vertex_ids array is 1, it would make no difference.
    for( int i=0; i<triangle_count; ++i )
        {
        vertex_ids->SetItem( i*3+0 , corner_ids[i*3+0] );
        vertex_ids->SetItem( i*3+1 , corner_ids[i*3+1] );
        vertex_ids->SetItem( i*3+2 , corner_ids[i*3+2] );
        group_ids->SetItem( i, groupId );
        }
    delete [] corner_ids;
    delete [] vertex_coordinates;
    return true;
    }