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