#include "gltf-scene.h"
using namespace Dali;
-using Dali::Toolkit::TextLabel;
namespace
{
Shader shader;
Geometry geometry;
};
+using ModelPtr = std::unique_ptr<Model>;
+
+using ActorContainer = std::vector<Actor>;
+using CameraContainer = std::vector<CameraActor>;
+using ModelContainer = std::vector<ModelPtr>;
+using TextureSetContainer = std::vector<TextureSet>;
+
+const Vector3 DEFAULT_LIGHT_DIRECTION( 0.5, 0.5, -1 );
template<class T>
bool LoadFile( const std::string& filename, std::vector<T>& bytes )
return Shader::New( std::string(vshShaderSource.data()), std::string(fshShaderSource.data()) );
}
-std::unique_ptr<Model> CreateModel( glTF& gltf,
- const glTF_Mesh* mesh,
- const std::string& vertexShaderSource,
- const std::string& fragmentShaderSource )
+ModelPtr CreateModel(
+ glTF& gltf,
+ const glTF_Mesh* mesh,
+ const std::string& vertexShaderSource,
+ const std::string& fragmentShaderSource )
{
/*
* Obtain interleaved buffer for first mesh with position and normal attributes
auto indexBuffer = gltf.GetMeshIndexBuffer( mesh );
geometry.SetIndexBuffer( indexBuffer.data(), indexBuffer.size() );
geometry.SetType( Geometry::Type::TRIANGLES );
- std::unique_ptr<Model> retval( new Model() );
+ ModelPtr retval( new Model() );
retval->shader = CreateShader( vertexShaderSource, fragmentShaderSource );
retval->geometry = geometry;
return retval;
renderer.SetShader( shader );
}
+void CreateTextureSetsFromGLTF( glTF* gltf, const std::string& basePath, TextureSetContainer& textureSets )
+{
+ const auto& materials = gltf->GetMaterials();
+ const auto& textures = gltf->GetTextures();
+
+ std::map<std::string, Texture> textureCache{};
+
+ for(const auto& material : materials )
+ {
+ TextureSet textureSet;
+ if(material.pbrMetallicRoughness.enabled)
+ {
+ textureSet = TextureSet::New();
+ std::string filename( basePath );
+ filename += '/';
+ filename += textures[material.pbrMetallicRoughness.baseTextureColor.index].uri;
+ Dali::PixelData pixelData = Dali::Toolkit::SyncImageLoader::Load( filename );
+
+ auto cacheKey = textures[material.pbrMetallicRoughness.baseTextureColor.index].uri;
+ auto iter = textureCache.find(cacheKey);
+ Texture texture;
+ if(iter == textureCache.end())
+ {
+ texture = Texture::New(TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(),
+ pixelData.GetHeight());
+ texture.Upload(pixelData);
+ texture.GenerateMipmaps();
+ textureCache[cacheKey] = texture;
+ }
+ else
+ {
+ texture = iter->second;
+ }
+ textureSet.SetTexture( 0, texture );
+ Dali::Sampler sampler = Dali::Sampler::New();
+ sampler.SetWrapMode( Dali::WrapMode::REPEAT, Dali::WrapMode::REPEAT, Dali::WrapMode::REPEAT );
+ sampler.SetFilterMode( Dali::FilterMode::LINEAR_MIPMAP_LINEAR, Dali::FilterMode::LINEAR );
+ textureSet.SetSampler( 0, sampler );
+ }
+ textureSets.emplace_back( textureSet );
+ }
+}
+
+
+/**
+ * Creates models from glTF
+ */
+void CreateModelsFromGLTF( glTF* gltf, ModelContainer& models )
+{
+ const auto& meshes = gltf->GetMeshes();
+ for( const auto& mesh : meshes )
+ {
+ // change shader to use texture if material indicates that
+ if(mesh->material != 0xffffffff && gltf->GetMaterials()[mesh->material].pbrMetallicRoughness.enabled)
+ {
+ models.emplace_back( CreateModel( *gltf, mesh, VERTEX_SHADER, TEXTURED_FRAGMENT_SHADER ) );
+ }
+ else
+ {
+ models.emplace_back( CreateModel( *gltf, mesh, VERTEX_SHADER, FRAGMENT_SHADER ) );
+ }
+ }
+}
+
+Actor CreateSceneFromGLTF(
+ Window window,
+ glTF* gltf,
+ ModelContainer& models,
+ ActorContainer& actors,
+ CameraContainer& cameras,
+ TextureSetContainer& textureSets )
+{
+ const auto& nodes = gltf->GetNodes();
+
+ Vector3 cameraPosition;
+
+ // for each node create nodes and children
+ // resolve parents later
+ actors.reserve( nodes.size() );
+ for( const auto& node : nodes )
+ {
+ auto actor = node.cameraId != 0xffffffff ? CameraActor::New( window.GetSize() ) : Actor::New();
+
+ actor.SetProperty( Actor::Property::SIZE, Vector3( 1, 1, 1 ) );
+ actor.SetProperty( Dali::Actor::Property::NAME, node.name );
+ actor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
+ actor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
+ actor.SetProperty( Actor::Property::POSITION, Vector3( node.translation[0], node.translation[1], node.translation[2] ));
+ actor.SetProperty( Actor::Property::SCALE, Vector3( node.scale[0], node.scale[1], node.scale[2] ) );
+ actor.SetProperty( Actor::Property::ORIENTATION, Quaternion(node.rotationQuaternion[3],
+ node.rotationQuaternion[0],
+ node.rotationQuaternion[1],
+ node.rotationQuaternion[2]));
+
+ actors.emplace_back( actor );
+
+ // Initially add each actor to the very first one
+ if(actors.size() > 1)
+ {
+ actors[0].Add(actor);
+ }
+
+ // If mesh, create and add renderer
+ if(node.meshId != 0xffffffff)
+ {
+ const auto& model = models[node.meshId].get();
+ auto renderer = Renderer::New( model->geometry, model->shader );
+
+ // if textured, add texture set
+ auto materialId = gltf->GetMeshes()[node.meshId]->material;
+ if( materialId != 0xffffffff )
+ {
+ if( gltf->GetMaterials()[materialId].pbrMetallicRoughness.enabled )
+ {
+ renderer.SetTextures( textureSets[materialId] );
+ }
+ }
+
+ actor.AddRenderer( renderer );
+ }
+
+ // Reset and attach main camera
+ if( node.cameraId != 0xffffffff )
+ {
+ cameraPosition = Vector3(node.translation[0], node.translation[1], node.translation[2]);
+ auto quatY = Quaternion( Degree(180.0f), Vector3( 0.0, 1.0, 0.0) );
+ auto cameraActor = CameraActor::DownCast( actor );
+ cameraActor.SetProperty( Actor::Property::ORIENTATION, Quaternion(node.rotationQuaternion[3],
+ node.rotationQuaternion[0],
+ node.rotationQuaternion[1],
+ node.rotationQuaternion[2] )
+ * quatY
+ );
+ cameraActor.SetProjectionMode( Camera::PERSPECTIVE_PROJECTION );
+
+ const auto camera = gltf->GetCameras()[node.cameraId];
+ cameraActor.SetNearClippingPlane( camera->znear );
+ cameraActor.SetFarClippingPlane( camera->zfar );
+ cameraActor.SetFieldOfView( camera->yfov );
+
+ cameraActor.SetProperty( CameraActor::Property::INVERT_Y_AXIS, true);
+ cameraActor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
+ cameraActor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
+
+ cameras.emplace_back( cameraActor );
+ }
+ }
+
+ // Resolve hierarchy dependencies
+ auto i = 0u;
+ for( const auto& node : nodes )
+ {
+ if(!node.children.empty())
+ {
+ for(const auto& childId : node.children)
+ {
+ actors[i].Add( actors[childId+1] );
+ }
+ }
+ ++i;
+ }
+
+ for( auto& actor : actors )
+ {
+ actor.RegisterProperty( "lightDir", DEFAULT_LIGHT_DIRECTION );
+ actor.RegisterProperty( "eyePos", cameraPosition );
+ }
+
+ return actors[0];
+}
+
} // unnamed namespace
// This example shows how to create and display mirrored reflection using CameraActor
auto gltf = glTF(DEMO_GAME_DIR "/reflection");
// Define direction of light
- mLightDir = Vector3( 0.5, 0.5, -1 );
/**
* Instantiate texture sets
*/
- CreateTextureSetsFromGLTF( &gltf, DEMO_GAME_DIR );
+ CreateTextureSetsFromGLTF( &gltf, DEMO_GAME_DIR, mTextureSets );
/**
* Create models
*/
- CreateModelsFromGLTF( &gltf );
+ CreateModelsFromGLTF( &gltf, mModels );
/**
- * Create scene nodes
+ * Create scene nodes & add to 3D Layer
*/
- CreateSceneFromGLTF( window, &gltf );
+ mLayer3D.Add( CreateSceneFromGLTF( window, &gltf, mModels, mActors, mCameras, mTextureSets ) );
auto planeActor = mLayer3D.FindChildByName( "Plane" );
auto solarActor = mLayer3D.FindChildByName( "solar_root" );
mTickTimer.Start();
}
- void CreateSceneFromGLTF( Window window, glTF* gltf )
- {
- const auto& nodes = gltf->GetNodes();
-
- // for each node create nodes and children
- // resolve parents later
- std::vector<Actor> actors;
- actors.reserve( nodes.size() );
- for( const auto& node : nodes )
- {
- auto actor = node.cameraId != 0xffffffff ? CameraActor::New( window.GetSize() ) : Actor::New();
-
- actor.SetProperty( Actor::Property::SIZE, Vector3( 1, 1, 1 ) );
- actor.SetProperty( Dali::Actor::Property::NAME, node.name );
- actor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
- actor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
- actor.SetProperty( Actor::Property::POSITION, Vector3( node.translation[0], node.translation[1], node.translation[2] ));
- actor.SetProperty( Actor::Property::SCALE, Vector3( node.scale[0], node.scale[1], node.scale[2] ) );
- actor.SetProperty( Actor::Property::ORIENTATION, Quaternion(node.rotationQuaternion[3],
- node.rotationQuaternion[0],
- node.rotationQuaternion[1],
- node.rotationQuaternion[2]));
-
- actors.emplace_back( actor );
-
- // Initially add each actor to the very first one
- if(actors.size() > 1)
- {
- actors[0].Add(actor);
- }
-
- // If mesh, create and add renderer
- if(node.meshId != 0xffffffff)
- {
- const auto& model = mModels[node.meshId].get();
- auto renderer = Renderer::New( model->geometry, model->shader );
-
- // if textured, add texture set
- auto materialId = gltf->GetMeshes()[node.meshId]->material;
- if( materialId != 0xffffffff )
- {
- if( gltf->GetMaterials()[materialId].pbrMetallicRoughness.enabled )
- {
- renderer.SetTextures( mTextureSets[materialId] );
- }
- }
-
- actor.AddRenderer( renderer );
- }
-
- // Reset and attach main camera
- if( node.cameraId != 0xffffffff )
- {
- mCameraPos = Vector3(node.translation[0], node.translation[1], node.translation[2]);
- auto quatY = Quaternion( Degree(180.0f), Vector3( 0.0, 1.0, 0.0) );
- auto cameraActor = CameraActor::DownCast( actor );
- cameraActor.SetProperty( Actor::Property::ORIENTATION, Quaternion(node.rotationQuaternion[3],
- node.rotationQuaternion[0],
- node.rotationQuaternion[1],
- node.rotationQuaternion[2] )
- * quatY
- );
- cameraActor.SetProjectionMode( Camera::PERSPECTIVE_PROJECTION );
-
- const auto camera = gltf->GetCameras()[node.cameraId];
- cameraActor.SetNearClippingPlane( camera->znear );
- cameraActor.SetFarClippingPlane( camera->zfar );
- cameraActor.SetFieldOfView( camera->yfov );
-
- cameraActor.SetProperty( CameraActor::Property::INVERT_Y_AXIS, true);
- cameraActor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
- cameraActor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
-
- mCameras.emplace_back( cameraActor );
- }
- }
-
- // Resolve hierarchy dependencies
- auto i = 0u;
- for( const auto& node : nodes )
- {
- if(!node.children.empty())
- {
- for(const auto& childId : node.children)
- {
- actors[i].Add( actors[childId+1] );
- }
- }
- ++i;
- }
-
- mActors = std::move(actors);
-
- // Add root actor to the window
- mLayer3D.Add( mActors[0] );
-
- for( auto& actor : mActors )
- {
- actor.RegisterProperty( "lightDir", mLightDir );
- actor.RegisterProperty( "eyePos", mCameraPos );
- }
-
- }
-
- /**
- * Creates models from glTF
- */
- void CreateModelsFromGLTF( glTF* gltf )
- {
- const auto& meshes = gltf->GetMeshes();
- for( const auto& mesh : meshes )
- {
- // change shader to use texture if material indicates that
- if(mesh->material != 0xffffffff && gltf->GetMaterials()[mesh->material].pbrMetallicRoughness.enabled)
- {
- mModels.emplace_back( CreateModel( *gltf, mesh, VERTEX_SHADER, TEXTURED_FRAGMENT_SHADER ) );
- }
- else
- {
- mModels.emplace_back( CreateModel( *gltf, mesh, VERTEX_SHADER, FRAGMENT_SHADER ) );
- }
- }
- }
-
- void CreateTextureSetsFromGLTF( glTF* gltf, const std::string& basePath )
- {
- const auto& materials = gltf->GetMaterials();
- const auto& textures = gltf->GetTextures();
-
- std::map<std::string, Texture> textureCache{};
-
- for(const auto& material : materials )
- {
- TextureSet textureSet;
- if(material.pbrMetallicRoughness.enabled)
- {
- textureSet = TextureSet::New();
- std::string filename( basePath );
- filename += '/';
- filename += textures[material.pbrMetallicRoughness.baseTextureColor.index].uri;
- Dali::PixelData pixelData = Dali::Toolkit::SyncImageLoader::Load( filename );
-
- auto cacheKey = textures[material.pbrMetallicRoughness.baseTextureColor.index].uri;
- auto iter = textureCache.find(cacheKey);
- Texture texture;
- if(iter == textureCache.end())
- {
- texture = Texture::New(TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(),
- pixelData.GetHeight());
- texture.Upload(pixelData);
- texture.GenerateMipmaps();
- textureCache[cacheKey] = texture;
- }
- else
- {
- texture = iter->second;
- }
- textureSet.SetTexture( 0, texture );
- Dali::Sampler sampler = Dali::Sampler::New();
- sampler.SetWrapMode( Dali::WrapMode::REPEAT, Dali::WrapMode::REPEAT, Dali::WrapMode::REPEAT );
- sampler.SetFilterMode( Dali::FilterMode::LINEAR_MIPMAP_LINEAR, Dali::FilterMode::LINEAR );
- textureSet.SetSampler( 0, sampler );
- }
- mTextureSets.emplace_back( textureSet );
- }
- }
-
void OnPan( Actor actor, const PanGesture& panGesture )
{
auto displacement = panGesture.screenDisplacement;
Layer mLayer3D{};
- std::vector<Actor> mActors {};
- std::vector<CameraActor> mCameras {};
- std::vector<std::unique_ptr<Model>> mModels {};
- std::vector<TextureSet> mTextureSets {};
+ ActorContainer mActors {};
+ CameraContainer mCameras {};
+ ModelContainer mModels {};
+ TextureSetContainer mTextureSets {};
Animation mAnimation {};
float mMockTime { 0.0f };
Property::Index mSunKFactorUniformIndex {};
PanGestureDetector mPanGestureDetector {};
- Vector3 mCameraPos { Vector3::ZERO };
- Vector3 mLightDir { Vector3::ZERO };
Timer mTickTimer {};
CameraActor mCamera3D {};