///////////////////////////////////////////////////////////////////////////
//
// System: Simplygon
// File: SceneDataExample.cpp
// Language: C++
//
// Copyright (c) 2019 Microsoft. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////
//
// #Description# This example shows how to use the simplygon scene data.
// First we create a scene. We fetch the scene's material table and add
// a red diffuse and a red specular material. We then create two cube geometries
// with one assigned the diffuse material and the other the specular material.
// Two scene mesh nodes are created that refer to the cubes. The scene meshes
// are then added to the scene's root node as children.
//
///////////////////////////////////////////////////////////////////////////
#include "../Common/Example.h"
#include "../Common/Vector3D.h"
#include "../Common/Matrix4x4.h"
/////////////////////////////////////////////////////////////////////
// Main function with startup and shutdown code
void RunExample();
void save_scene_to_file( spScene scene, const std::string& obj_filepath, const std::string& mat_filepath );
spGeometryData generate_cube( rid matId );
int main( int argc, char* argv[] )
{
try
{
// init SDK
InitExample();
// Run the example code
RunExample();
// deinit SDK
DeinitExample();
}
catch (const std::exception& ex)
{
std::cerr << ex.what() << std::endl;
return -1;
}
return 0;
}
// This function runs the example by creating a simplygon scene and generating
// two materials. The materials are stored in the scene's material table.
// Two cubes are generated which refer to the materials created earlier.
// Two scene mesh nodes are created which refer to the cube geometries created
// earlier. One of the scene meshes is transformed using the transform3 class.
// Finally the scene meshes are added as children to the root node of the scene
// and exported to a wavefront file along with corresponding material file.
void RunExample()
{
//create a simplygon scene
spScene scene = sg->CreateScene();
//get material table from the scene
spMaterialTable matTable = scene->GetMaterialTable();
//create a red diffuse material and a red specular material
spShadingColorNode redNode = sg->CreateShadingColorNode();
redNode->SetColor( 0.5f, 0.f, 0.f, 0.f );
spMaterial diffuseRed = sg->CreateMaterial();
diffuseRed->SetName( "red_diffuse" );
diffuseRed->SetShadingNetwork( SG_MATERIAL_CHANNEL_DIFFUSE, redNode );
diffuseRed->SetShadingNetwork( SG_MATERIAL_CHANNEL_AMBIENT, redNode );
spMaterial specRed = sg->CreateMaterial();
specRed->SetName( "red_spec" );
specRed->SetShadingNetwork( SG_MATERIAL_CHANNEL_DIFFUSE, redNode );
specRed->SetShadingNetwork( SG_MATERIAL_CHANNEL_SPECULAR, redNode );
//add the materials to the material table
rid d_mat_id = matTable->AddMaterial( diffuseRed );
rid s_mat_id = matTable->AddMaterial( specRed );
//create two scene mesh objects
spSceneMesh cube_one = sg->CreateSceneMesh();
spSceneMesh cube_two = sg->CreateSceneMesh();
//set name on the scene meshes
cube_one->SetName( "cube_one" );
cube_one->SetOriginalName( "cube_one" );
cube_two->SetName( "cube_two" );
cube_two->SetOriginalName( "cube_two" );
cube_one->SetGeometry( generate_cube( s_mat_id ) );
cube_two->SetGeometry( generate_cube( d_mat_id ) );
//add the two scene meshes as child to the root node of the scene
scene->GetRootNode()->AddChild( cube_one );
scene->GetRootNode()->AddChild( cube_two );
//create a transform node
spTransform3 xform = sg->CreateTransform3();
//set the transform to use premultiply
xform->PreMultiply();
//add rotations and translations
xform->AddRotation( GetRadFromDegrees( 45 ), 0, 1, 0 );
xform->AddRotation( GetRadFromDegrees( 45 ), 1, 0, 0 );
xform->AddTranslation( 0, 5.0, 0.0 );
//access the node for cube_two in the scene
spSceneMesh node = Cast<ISceneMesh>( scene->GetNodeFromPath( "Root/cube_two" ) );
//apply transformation on the node
node->GetRelativeTransform()->DeepCopy( xform->GetMatrix() );
std::string outputObjPath = GetExecutablePath() + "cubes.obj";
std::string outputMtlPath = GetExecutablePath() + "cubes.mtl";
//store the scene and material to file
save_scene_to_file( scene, outputObjPath, outputMtlPath );
}
// This function stores the data into an .obj file and materials in .mtl file
void save_scene_to_file( spScene scene, const std::string& filepath, const std::string& mat_filepath )
{
// create the wavefront exporter
spWavefrontExporter exp = sg->CreateWavefrontExporter();
// set the geometries
exp->SetScene( scene );
// set file paths
exp->SetExportFilePath( filepath.c_str() );
exp->SetMaterialFilePath( mat_filepath.c_str() );
// export to file
exp->RunExport();
}
//this function generates a fixed cube
spGeometryData generate_cube( rid matId )
{
const int vertex_count = 8;
const int triangle_count = 12;
const int corner_count = triangle_count * 3;
// 4 triangles x 3 indices ( or 3 corners )
int corner_ids[corner_count * 1] = { 0, 1, 4,
4, 1, 5,
5, 1, 6,
1, 2, 6,
6, 2, 3,
6, 3, 7,
7, 3, 0,
7, 0, 4,
0, 2, 1,
0, 3, 2,
4, 5, 6,
4, 6, 7 };
// 12 vertices with values for the x, y and z coordinates.
float vertex_coordinates[vertex_count * 3] = { 1.0, -1.0, 1.0,
1.0, -1.0, -1.0,
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
-1.0, 1.0, -1.0,
-1.0, 1.0, 1.0 };
spGeometryData geom = sg->CreateGeometryData();
//add material data
//materials are assigned per triangle
geom->AddMaterialIds();
spRealArray coords = geom->GetCoords();
spRidArray vertex_ids = geom->GetVertexIds();
spRidArray matIds = geom->GetMaterialIds();
geom->SetVertexCount( vertex_count );
geom->SetTriangleCount( triangle_count );
for( int i = 0; i < vertex_count; ++i )
{
coords->SetTuple( i, &vertex_coordinates[i * 3] );
}
for( int i = 0; i < corner_count; ++i )
{
vertex_ids->SetItem( i, corner_ids[i] );
}
//loop through all the triangles an assign material
for( int i = 0; i < triangle_count; ++i )
{
matIds->SetItem( i, matId );
}
return geom;
}