--- /dev/null
+# cube.obj
+#
+
+g cube
+
+v 0.0 0.0 0.0
+v 0.0 0.0 1.0
+v 0.0 1.0 0.0
+v 0.0 1.0 1.0
+v 1.0 0.0 0.0
+v 1.0 0.0 1.0
+v 1.0 1.0 0.0
+v 1.0 1.0 1.0
+
+vt 0.0 0.0
+vt 0.3 0.3
+vt 0.0 1.0
+vt 0.3 0.7
+vt 1.0 0.0
+vt 0.7 0.3
+vt 1.0 1.0
+vt 0.7 0.7
+
+vn 0.0 0.0 1.0
+vn 0.0 0.0 -1.0
+vn 0.0 1.0 0.0
+vn 0.0 -1.0 0.0
+vn 1.0 0.0 0.0
+vn -1.0 0.0 0.0
+
+f 1/1/2 7/7/2 5/5/2
+f 1/1/2 3/3/2 7/7/2
+f 1/1/6 4/4/6 3/3/6
+f 1/1/6 2/2/6 4/4/6
+f 3/3/3 8/8/3 7/7/3
+f 3/3/3 4/4/3 8/8/3
+f 5/5/5 7/7/5 8/8/5
+f 5/5/5 8/8/5 6/6/5
+f 1/1/4 5/5/4 6/6/4
+f 1/1/4 6/6/4 2/2/4
+f 2/2/1 6/6/1 8/8/1
+f 2/2/1 8/8/1 4/4/1
--- /dev/null
+newmtl lambert3SG
+illum 4
+Kd 0.00 0.00 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+map_Kd tbcol.png
+Ni 1.00
+Ks 0.00 0.00 0.00
+Ns 3.66
--- /dev/null
+newmtl lambert3SG
+illum 4
+Kd 0.00 0.00 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+map_Kd tbcol.png
+bump tb-norm.png -bm 0.05
+Ni 1.00
+Ks 0.00 0.00 0.00
+map_Ks TB-gloss.png
+Ns 3.66
const char* TEST_IMAGE_FILE_NAME = "gallery_image_01.jpg";
const char* TEST_NPATCH_FILE_NAME = "gallery_image_01.9.jpg";
const char* TEST_SVG_FILE_NAME = TEST_RESOURCE_DIR "/svg1.svg";
+const char* TEST_OBJ_FILE_NAME = TEST_RESOURCE_DIR "/Cube.obj";
+const char* TEST_MTL_FILE_NAME = TEST_RESOURCE_DIR "/ToyRobot-Metal.mtl";
+const char* TEST_RESOURCE_LOCATION = TEST_RESOURCE_DIR "/";
}
void dali_control_renderer_startup(void)
END_TEST;
}
+
+//Mesh renderer
+int UtcDaliControlRendererGetPropertyMap8(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcDaliControlRendererGetPropertyMap8: MeshRenderer" );
+
+ //Request MeshRenderer using a property map.
+ RendererFactory factory = RendererFactory::Get();
+ Property::Map propertyMap;
+ propertyMap.Insert( "rendererType", "mesh" );
+ propertyMap.Insert( "objectUrl", TEST_OBJ_FILE_NAME );
+ propertyMap.Insert( "materialUrl", TEST_MTL_FILE_NAME );
+ propertyMap.Insert( "texturesPath", TEST_RESOURCE_LOCATION );
+ propertyMap.Insert( "shaderType", "textureless" );
+ ControlRenderer meshRenderer = factory.GetControlRenderer( propertyMap );
+
+ Property::Map resultMap;
+ meshRenderer.CreatePropertyMap( resultMap );
+
+ //Check values in the result map are identical to the initial map's values.
+ Property::Value* value = resultMap.Find( "rendererType", Property::STRING );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_CHECK( value->Get<std::string>() == "mesh" );
+
+ value = resultMap.Find( "objectUrl", Property::STRING );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_CHECK( value->Get<std::string>() == TEST_OBJ_FILE_NAME );
+
+ value = resultMap.Find( "materialUrl", Property::STRING );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_CHECK( value->Get<std::string>() == TEST_MTL_FILE_NAME );
+
+ value = resultMap.Find( "texturesPath", Property::STRING );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_CHECK( value->Get<std::string>() == TEST_RESOURCE_LOCATION );
+
+ value = resultMap.Find( "shaderType", Property::STRING );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_CHECK( value->Get<std::string>() == "textureless" );
+
+ END_TEST;
+}
const char* TEST_IMAGE_FILE_NAME = "gallery_image_01.jpg";
const char* TEST_NPATCH_FILE_NAME = "gallery_image_01.9.jpg";
-
const char* TEST_SVG_FILE_NAME = TEST_RESOURCE_DIR "/svg1.svg";
+const char* TEST_OBJ_FILE_NAME = TEST_RESOURCE_DIR "/Cube.obj";
+const char* TEST_MTL_FILE_NAME = TEST_RESOURCE_DIR "/ToyRobot-Metal.mtl";
+const char* TEST_SIMPLE_MTL_FILE_NAME = TEST_RESOURCE_DIR "/ToyRobot-Metal-Simple.mtl";
Integration::Bitmap* CreateBitmap( unsigned int imageWidth, unsigned int imageHeight, unsigned int initialColor, Pixel::Format pixelFormat )
{
END_TEST;
}
+//Test if mesh loads correctly when supplied with only the bare minimum requirements, an object file.
+int UtcDaliRendererFactoryGetMeshRenderer1(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcDaliRendererFactoryGetMeshRenderer1: Request mesh renderer with a valid object file only" );
+
+ RendererFactory factory = RendererFactory::Get();
+ DALI_TEST_CHECK( factory );
+
+ //Set up renderer properties.
+ Property::Map propertyMap;
+ propertyMap.Insert( "rendererType", "mesh" );
+ propertyMap.Insert( "objectUrl", TEST_OBJ_FILE_NAME );
+
+ ControlRenderer controlRenderer = factory.GetControlRenderer( propertyMap );
+ DALI_TEST_CHECK( controlRenderer );
+
+ Actor actor = Actor::New();
+ actor.SetSize( 200.f, 200.f );
+ Stage::GetCurrent().Add( actor );
+ controlRenderer.SetSize( Vector2( 200.f, 200.f ) );
+ controlRenderer.SetOnStage( actor );
+
+ application.SendNotification();
+ application.Render( 0 );
+
+ DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
+
+ //Tell the platform abstraction that the required resources have been loaded.
+ TestPlatformAbstraction& platform = application.GetPlatform();
+ platform.SetAllResourceRequestsAsLoaded();
+
+ //Render again to upload the now-loaded textures.
+ application.SendNotification();
+ application.Render( 0 );
+
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+
+ Matrix testScaleMatrix;
+ testScaleMatrix.SetIdentityAndScale( Vector3( 1.0, -1.0, 1.0 ) );
+ Matrix actualScaleMatrix;
+
+ //Test to see if the object has been successfully loaded.
+ DALI_TEST_CHECK( gl.GetUniformValue<Matrix>( "uObjectMatrix", actualScaleMatrix ) );
+ DALI_TEST_EQUALS( actualScaleMatrix, testScaleMatrix, Math::MACHINE_EPSILON_100, TEST_LOCATION );
+
+ controlRenderer.SetOffStage( actor );
+ DALI_TEST_CHECK( actor.GetRendererCount() == 0u );
+
+ END_TEST;
+}
+
+//Test if mesh loads correctly when supplied with an object file as well as a blank material file and images directory.
+int UtcDaliRendererFactoryGetMeshRenderer2(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcDaliRendererFactoryGetMeshRenderer2: Request mesh renderer with blank material file and images directory" );
+
+ RendererFactory factory = RendererFactory::Get();
+ DALI_TEST_CHECK( factory );
+
+ //Set up renderer properties.
+ Property::Map propertyMap;
+ propertyMap.Insert( "rendererType", "mesh" );
+ propertyMap.Insert( "objectUrl", TEST_OBJ_FILE_NAME );
+ propertyMap.Insert( "materialUrl", "" );
+ propertyMap.Insert( "texturesPath", "" );
+
+ ControlRenderer controlRenderer = factory.GetControlRenderer( propertyMap );
+ DALI_TEST_CHECK( controlRenderer );
+
+ //Add renderer to an actor on stage.
+ Actor actor = Actor::New();
+ actor.SetSize( 200.f, 200.f );
+ Stage::GetCurrent().Add( actor );
+ controlRenderer.SetSize( Vector2( 200.f, 200.f ) );
+ controlRenderer.SetOnStage( actor );
+
+ DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
+
+ //Attempt to render to queue resource load requests.
+ application.SendNotification();
+ application.Render( 0 );
+
+ //Tell the platform abstraction that the required resources have been loaded.
+ TestPlatformAbstraction& platform = application.GetPlatform();
+ platform.SetAllResourceRequestsAsLoaded();
+
+ //Render again to upload the now-loaded textures.
+ application.SendNotification();
+ application.Render( 0 );
+
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+
+ Matrix testScaleMatrix;
+ testScaleMatrix.SetIdentityAndScale( Vector3( 1.0, -1.0, 1.0 ) );
+ Matrix actualScaleMatrix;
+
+ //Test to see if the object has been successfully loaded.
+ DALI_TEST_CHECK( gl.GetUniformValue<Matrix>( "uObjectMatrix", actualScaleMatrix ) );
+ DALI_TEST_EQUALS( actualScaleMatrix, testScaleMatrix, Math::MACHINE_EPSILON_100, TEST_LOCATION );
+
+ controlRenderer.SetOffStage( actor );
+ DALI_TEST_CHECK( actor.GetRendererCount() == 0u );
+
+ END_TEST;
+}
+
+//Test if mesh loads correctly when supplied with all parameters, an object file, a material file and a directory location.
+int UtcDaliRendererFactoryGetMeshRenderer3(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcDaliRendererFactoryGetMeshRenderer3: Request mesh renderer with all parameters correct" );
+
+ RendererFactory factory = RendererFactory::Get();
+ DALI_TEST_CHECK( factory );
+
+ //Set up renderer properties.
+ Property::Map propertyMap;
+ propertyMap.Insert( "rendererType", "mesh" );
+ propertyMap.Insert( "objectUrl", TEST_OBJ_FILE_NAME );
+ propertyMap.Insert( "materialUrl", TEST_MTL_FILE_NAME );
+ propertyMap.Insert( "texturesPath", TEST_RESOURCE_DIR "/" );
+
+ ControlRenderer controlRenderer = factory.GetControlRenderer( propertyMap );
+ DALI_TEST_CHECK( controlRenderer );
+
+ //Add renderer to an actor on stage.
+ Actor actor = Actor::New();
+ actor.SetSize( 200.f, 200.f );
+ Stage::GetCurrent().Add( actor );
+ controlRenderer.SetSize( Vector2( 200.f, 200.f ) );
+ controlRenderer.SetOnStage( actor );
+
+ DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
+
+ //Attempt to render to queue resource load requests.
+ application.SendNotification();
+ application.Render( 0 );
+
+ //Tell the platform abstraction that the required resources have been loaded.
+ TestPlatformAbstraction& platform = application.GetPlatform();
+ platform.SetAllResourceRequestsAsLoaded();
+
+ //Render again to upload the now-loaded textures.
+ application.SendNotification();
+ application.Render( 0 );
+
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+
+ Matrix testScaleMatrix;
+ testScaleMatrix.SetIdentityAndScale( Vector3( 1.0, -1.0, 1.0 ) );
+ Matrix actualScaleMatrix;
+
+ //Test to see if the object has been successfully loaded.
+ DALI_TEST_CHECK( gl.GetUniformValue<Matrix>( "uObjectMatrix", actualScaleMatrix ) );
+ DALI_TEST_EQUALS( actualScaleMatrix, testScaleMatrix, Math::MACHINE_EPSILON_100, TEST_LOCATION );
+
+ controlRenderer.SetOffStage( actor );
+ DALI_TEST_CHECK( actor.GetRendererCount() == 0u );
+
+ END_TEST;
+}
+
+//Test if mesh renderer can load a correctly supplied mesh without a normal map or gloss map in the material file.
+int UtcDaliRendererFactoryGetMeshRenderer4(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcDaliRendererFactoryGetMeshRenderer4: Request mesh renderer with diffuse texture but not normal or gloss." );
+
+ RendererFactory factory = RendererFactory::Get();
+ DALI_TEST_CHECK( factory );
+
+ //Set up renderer properties.
+ Property::Map propertyMap;
+ propertyMap.Insert( "rendererType", "mesh" );
+ propertyMap.Insert( "objectUrl", TEST_OBJ_FILE_NAME );
+ propertyMap.Insert( "materialUrl", TEST_SIMPLE_MTL_FILE_NAME );
+ propertyMap.Insert( "texturesPath", TEST_RESOURCE_DIR "/" );
+
+ ControlRenderer controlRenderer = factory.GetControlRenderer( propertyMap );
+ DALI_TEST_CHECK( controlRenderer );
+
+ //Add renderer to an actor on stage.
+ Actor actor = Actor::New();
+ actor.SetSize( 200.f, 200.f );
+ Stage::GetCurrent().Add( actor );
+ controlRenderer.SetSize( Vector2( 200.f, 200.f ) );
+ controlRenderer.SetOnStage( actor );
+
+ DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
+
+ //Attempt to render to queue resource load requests.
+ application.SendNotification();
+ application.Render( 0 );
+
+ //Tell the platform abstraction that the required resources have been loaded.
+ TestPlatformAbstraction& platform = application.GetPlatform();
+ platform.SetAllResourceRequestsAsLoaded();
+
+ //Render again to upload the now-loaded textures.
+ application.SendNotification();
+ application.Render( 0 );
+
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+
+ Matrix testScaleMatrix;
+ testScaleMatrix.SetIdentityAndScale( Vector3( 1.0, -1.0, 1.0 ) );
+ Matrix actualScaleMatrix;
+
+ //Test to see if the object has been successfully loaded.
+ DALI_TEST_CHECK( gl.GetUniformValue<Matrix>( "uObjectMatrix", actualScaleMatrix ) );
+ DALI_TEST_EQUALS( actualScaleMatrix, testScaleMatrix, Math::MACHINE_EPSILON_100, TEST_LOCATION );
+
+ controlRenderer.SetOffStage( actor );
+ DALI_TEST_CHECK( actor.GetRendererCount() == 0u );
+
+ END_TEST;
+}
+
+//Test if mesh renderer handles the case of lacking an object file.
+int UtcDaliRendererFactoryGetMeshRendererN1(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcDaliRendererFactoryGetMeshRendererN1: Request mesh renderer without object file" );
+
+ RendererFactory factory = RendererFactory::Get();
+ DALI_TEST_CHECK( factory );
+
+ //Set up renderer properties.
+ Property::Map propertyMap;
+ propertyMap.Insert( "rendererType", "mesh" );
+ propertyMap.Insert( "materialUrl", TEST_MTL_FILE_NAME );
+ propertyMap.Insert( "texturesPath", TEST_RESOURCE_DIR "/" );
+
+ ControlRenderer controlRenderer = factory.GetControlRenderer( propertyMap );
+ DALI_TEST_CHECK( controlRenderer );
+
+ //Add renderer to an actor on stage.
+ Actor actor = Actor::New();
+ actor.SetSize( 200.f, 200.f );
+ Stage::GetCurrent().Add( actor );
+ controlRenderer.SetSize( Vector2( 200.f, 200.f ) );
+ controlRenderer.SetOnStage( actor );
+
+ DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
+
+ //Attempt to render to queue resource load requests.
+ application.SendNotification();
+ application.Render( 0 );
+
+ //Tell the platform abstraction that the required resources have been loaded.
+ TestPlatformAbstraction& platform = application.GetPlatform();
+ platform.SetAllResourceRequestsAsLoaded();
+
+ //Render again to upload the now-loaded textures.
+ application.SendNotification();
+ application.Render( 0 );
+
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+
+ //Test to see if the object has not been loaded, as expected.
+ Matrix scaleMatrix;
+ DALI_TEST_CHECK( ! gl.GetUniformValue<Matrix>( "uObjectMatrix", scaleMatrix ) );
+
+ controlRenderer.SetOffStage( actor );
+ DALI_TEST_CHECK( actor.GetRendererCount() == 0u );
+
+ END_TEST;
+}
+
+//Test if mesh renderer handles the case of being passed invalid material and images urls.
+int UtcDaliRendererFactoryGetMeshRendererN2(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcDaliRendererFactoryGetMeshRendererN2: Request mesh renderer with invalid material and images urls" );
+
+ RendererFactory factory = RendererFactory::Get();
+ DALI_TEST_CHECK( factory );
+
+ //Set up renderer properties.
+ Property::Map propertyMap;
+ propertyMap.Insert( "rendererType", "mesh" );
+ propertyMap.Insert( "objectUrl", TEST_OBJ_FILE_NAME );
+ propertyMap.Insert( "materialUrl", "invalid" );
+ propertyMap.Insert( "texturesPath", "also invalid" );
+
+ ControlRenderer controlRenderer = factory.GetControlRenderer( propertyMap );
+ DALI_TEST_CHECK( controlRenderer );
+
+ //Add renderer to an actor on stage.
+ Actor actor = Actor::New();
+ actor.SetSize( 200.f, 200.f );
+ Stage::GetCurrent().Add( actor );
+ controlRenderer.SetSize( Vector2( 200.f, 200.f ) );
+ controlRenderer.SetOnStage( actor );
+
+ DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
+
+ //Attempt to render to queue resource load requests.
+ application.SendNotification();
+ application.Render( 0 );
+
+ //Tell the platform abstraction that the required resources have been loaded.
+ TestPlatformAbstraction& platform = application.GetPlatform();
+ platform.SetAllResourceRequestsAsLoaded();
+
+ //Render again to upload the now-loaded textures.
+ application.SendNotification();
+ application.Render( 0 );
+
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+
+ //Test to see if the object has not been loaded, as expected.
+ Matrix scaleMatrix;
+ DALI_TEST_CHECK( ! gl.GetUniformValue<Matrix>( "uObjectMatrix", scaleMatrix ) );
+
+ controlRenderer.SetOffStage( actor );
+ DALI_TEST_CHECK( actor.GetRendererCount() == 0u );
+
+ END_TEST;
+}
+
+//Test if mesh renderer handles the case of being passed an invalid object url
+int UtcDaliRendererFactoryGetMeshRendererN3(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcDaliRendererFactoryGetMeshRendererN3: Request mesh renderer with invalid object url" );
+
+ RendererFactory factory = RendererFactory::Get();
+ DALI_TEST_CHECK( factory );
+
+ //Set up renderer properties.
+ Property::Map propertyMap;
+ propertyMap.Insert( "rendererType", "mesh" );
+ propertyMap.Insert( "objectUrl", "invalid" );
+ propertyMap.Insert( "materialUrl", TEST_MTL_FILE_NAME );
+ propertyMap.Insert( "texturesPath", TEST_RESOURCE_DIR "/" );
+
+ ControlRenderer controlRenderer = factory.GetControlRenderer( propertyMap );
+ DALI_TEST_CHECK( controlRenderer );
+
+ //Add renderer to an actor on stage.
+ Actor actor = Actor::New();
+ actor.SetSize( 200.f, 200.f );
+ Stage::GetCurrent().Add( actor );
+ controlRenderer.SetSize( Vector2( 200.f, 200.f ) );
+ controlRenderer.SetOnStage( actor );
+
+ DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
+
+ //Attempt to render to queue resource load requests.
+ application.SendNotification();
+ application.Render( 0 );
+
+ //Tell the platform abstraction that the required resources have been loaded.
+ TestPlatformAbstraction& platform = application.GetPlatform();
+ platform.SetAllResourceRequestsAsLoaded();
+
+ //Render again to upload the now-loaded textures.
+ application.SendNotification();
+ application.Render( 0 );
+
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+
+ //Test to see if the object has not been loaded, as expected.
+ Matrix scaleMatrix;
+ DALI_TEST_CHECK( ! gl.GetUniformValue<Matrix>( "uObjectMatrix", scaleMatrix ) );
+
+ controlRenderer.SetOffStage( actor );
+ DALI_TEST_CHECK( actor.GetRendererCount() == 0u );
+
+ END_TEST;
+}
+
int UtcDaliRendererFactoryResetRenderer1(void)
{
ToolkitTestApplication application;
END_TEST;
}
+
+//Test resetting mesh and primitive shape renderers
+int UtcDaliRendererFactoryResetRenderer4(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcDaliRendererFactoryResetRenderer4: Mesh and primitive renderers" );
+
+ Actor actor = Actor::New();
+ actor.SetSize( 200.f, 200.f );
+ Stage::GetCurrent().Add( actor );
+ RendererFactory factory = RendererFactory::Get();
+ DALI_TEST_CHECK( factory );
+
+ Property::Map map;
+
+ //******
+
+ //Start with basic color renderer
+ ControlRenderer controlRenderer = factory.GetControlRenderer( Color::RED );
+ DALI_TEST_CHECK( controlRenderer );
+
+ TestControlRendererRender( application, actor, controlRenderer );
+
+ DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
+
+ //Ensure set correctly.
+ Vector4 actualValue( Vector4::ZERO );
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+ DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "mixColor", actualValue ) );
+ DALI_TEST_EQUALS( actualValue, Color::RED, TEST_LOCATION );
+
+ //******
+
+ //Reset to mesh renderer
+ map.Insert( "rendererType", "mesh" );
+ map.Insert( "objectUrl", TEST_OBJ_FILE_NAME );
+ map.Insert( "materialUrl", TEST_MTL_FILE_NAME );
+ map.Insert( "texturesPath", TEST_RESOURCE_DIR "/" );
+ factory.ResetRenderer( controlRenderer, actor, map );
+ application.SendNotification();
+ application.Render( 0 );
+
+ DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
+
+ //Tell the platform abstraction that the required resources have been loaded.
+ TestPlatformAbstraction& platform = application.GetPlatform();
+ platform.SetAllResourceRequestsAsLoaded();
+
+ //Render again to upload the now-loaded textures.
+ application.SendNotification();
+ application.Render( 0 );
+
+ //Ensure set correctly.
+ controlRenderer.CreatePropertyMap( map );
+ DALI_TEST_EQUALS( map.Find( "objectUrl", Property::STRING )->Get<std::string>(), TEST_OBJ_FILE_NAME, TEST_LOCATION );
+
+ Matrix testScaleMatrix;
+ testScaleMatrix.SetIdentityAndScale( Vector3( 1.0, -1.0, 1.0 ) );
+ Matrix actualScaleMatrix;
+
+ //Test to see if the object has been successfully loaded.
+ DALI_TEST_CHECK( gl.GetUniformValue<Matrix>( "uObjectMatrix", actualScaleMatrix ) );
+ DALI_TEST_EQUALS( actualScaleMatrix, testScaleMatrix, Math::MACHINE_EPSILON_100, TEST_LOCATION );
+
+ //******
+
+ //Reset back to color renderer
+ factory.ResetRenderer( controlRenderer, actor, Color::GREEN );
+ application.SendNotification();
+ application.Render( 0 );
+
+ DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
+
+ //Ensure set correctly.
+ DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "mixColor", actualValue ) );
+ DALI_TEST_EQUALS( actualValue, Color::GREEN, TEST_LOCATION );
+
+ //******
+
+ END_TEST;
+}
* else the renderer would be a handle to a newly created internal color renderer.
*
* @param[in] renderer The ControlRenderer to reset
- * @param[in] actor The Actor the renderer is applied to if, empty if the renderer has not been applied to any Actor
+ * @param[in] actor The Actor the renderer is applied to, empty if the renderer has not been applied to any Actor
* @param[in] color The color to be rendered.
*/
void ResetRenderer( ControlRenderer& renderer, Actor& actor, const Vector4& color );
* else the renderer would be a handle to a newly created internal image renderer.
*
* @param[in] renderer The ControlRenderer to reset
- * @param[in] actor The Actor the renderer is applied to if, empty if the renderer has not been applied to any Actor
+ * @param[in] actor The Actor the renderer is applied to, empty if the renderer has not been applied to any Actor
* @param[in] image The Image to be rendered.
*/
void ResetRenderer( ControlRenderer& renderer, Actor& actor, const Image& image );
* else the renderer would be a handle to a newly created internal image renderer.
*
* @param[in] renderer The ControlRenderer to reset
- * @param[in] actor The Actor the renderer is applied to if, empty if the renderer has not been applied to any Actor
+ * @param[in] actor The Actor the renderer is applied to, empty if the renderer has not been applied to any Actor
* @param[in] url The URL to the resource to be rendered.
* @param[in] size The width and height to fit the loaded image to.
*/
void ResetRenderer( ControlRenderer& renderer, Actor& actor, const std::string& url,
ImageDimensions size = ImageDimensions() );
-
/**
* @brief Request the current control renderer from the property map, merging the property map with the renderer
*
* else the renderer would be a handle to a newly created internal renderer.
*
* @param[in] renderer The ControlRenderer to reset
- * @param[in] actor The Actor the renderer is applied to if, empty if the renderer has not been applied to any Actor
+ * @param[in] actor The Actor the renderer is applied to, empty if the renderer has not been applied to any Actor
* @param[in] propertyMap The map contains the properties required by the control renderer
* Depends on the content of the map, different kind of renderer would be returned.
*/
if( mObjLoader.IsSceneLoaded() )
{
- mMesh = mObjLoader.CreateGeometry( mIlluminationType );
+ mMesh = mObjLoader.CreateGeometry( GetShaderProperties( mIlluminationType ) );
CreateMaterial();
LoadTextures();
if (FileLoader::ReadFile(mObjUrl,fileSize,fileContent,FileLoader::TEXT))
{
mObjLoader.ClearArrays();
-
- std::string materialUrl;
- mObjLoader.Load(fileContent.Begin(), fileSize, materialUrl);
+ mObjLoader.LoadObject(fileContent.Begin(), fileSize);
//Get size information from the obj loaded
mSceneCenter = mObjLoader.GetCenter();
{
if( mObjLoader.IsSceneLoaded() )
{
- mMesh = mObjLoader.CreateGeometry( mIlluminationType );
+ mMesh = mObjLoader.CreateGeometry( GetShaderProperties( mIlluminationType ) );
if( mRenderer )
{
}
}
+int Model3dView::GetShaderProperties( Toolkit::Model3dView::IlluminationType illuminationType )
+{
+ int objectProperties = 0;
+
+ if( illuminationType == Toolkit::Model3dView::DIFFUSE_WITH_TEXTURE ||
+ illuminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP )
+ {
+ objectProperties |= ObjLoader::TEXTURE_COORDINATES;
+ }
+
+ if( illuminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP )
+ {
+ objectProperties |= ObjLoader::TANGENTS | ObjLoader::BINOMIALS;
+ }
+
+ return objectProperties;
+}
+
} // namespace Internal
} // namespace Toolkit
} // namespace Dali
void UpdateShaderUniforms();
+ /*
+ * @brief Given a specific shader type, find out which properties are necessary for it.
+ *
+ * @param[in] illuminationType The type of shader we intend to use.
+ * @return A bitmask of the properties we require to be loaded to use the given shader.
+ */
+ int GetShaderProperties( Toolkit::Model3dView::IlluminationType illuminationType );
+
+
ObjLoader mObjLoader;
//Properties
#include "obj-loader.h"
// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
#include <string>
#include <sstream>
#include <string.h>
namespace Internal
{
+namespace
+{
+ const int MAX_POINT_INDICES = 4;
+}
using namespace Dali;
ObjLoader::ObjLoader()
mSceneLoaded = false;
mMaterialLoaded = false;
mHasTexturePoints = false;
- mHasNormalMap = false;
mHasDiffuseMap = false;
+ mHasNormalMap = false;
mHasSpecularMap = false;
mSceneAABB.Init();
}
Dali::Vector<Vector3>& normal,
Dali::Vector<Vector3>& tangent)
{
- normal.Clear();
- normal.Resize(vertex.Size());
-
Dali::Vector<Vector3> tangents;
tangents.Resize( vertex.Size() );
//we need to recalculate the normals too, because we need just one normal,tangent, bitangent per vertex
//In the case of a textureless object, we don't need tangents for our shader and so we skip this step
//TODO: Use a better function to calculate tangents
-
if( mTangents.Size() == 0 && mHasTexturePoints )
{
- mTangents.Resize( mNormals.Size() );
- mBiTangents.Resize( mNormals.Size() );
+ mNormals.Clear();
+
+ mNormals.Resize( mPoints.Size() );
+ mTangents.Resize( mPoints.Size() );
+ mBiTangents.Resize( mPoints.Size() );
+
CalculateTangentArray( mPoints, mTextures, mTriangles, mNormals, mTangents );
+
for ( unsigned int ui = 0 ; ui < mNormals.Size() ; ++ui )
{
mBiTangents[ui] = mNormals[ui].Cross(mTangents[ui]);
}
}
-bool ObjLoader::Load( char* objBuffer, std::streampos fileSize, std::string& materialFile )
+bool ObjLoader::LoadObject( char* objBuffer, std::streampos fileSize )
{
Vector3 point;
Vector2 texture;
- std::string vet[4], name;
- int ptIdx[4];
- int nrmIdx[4];
- int texIdx[4];
+ std::string vet[MAX_POINT_INDICES], name;
+ int ptIdx[MAX_POINT_INDICES];
+ int nrmIdx[MAX_POINT_INDICES];
+ int texIdx[MAX_POINT_INDICES];
TriIndex triangle,triangle2;
int pntAcum = 0, texAcum = 0, nrmAcum = 0;
bool iniObj = false;
}
int numIndices = 0;
- while( isline >> vet[numIndices] )
+ while( isline >> vet[numIndices] && numIndices < MAX_POINT_INDICES )
{
numIndices++;
}
{
isline >> name;
}
- else
- {
- }
}
if ( iniObj )
}
return false;
-
}
-void ObjLoader::LoadMaterial( char* objBuffer, std::streampos fileSize, std::string& texture0Url,
- std::string& texture1Url, std::string& texture2Url )
+void ObjLoader::LoadMaterial( char* objBuffer, std::streampos fileSize, std::string& diffuseTextureUrl,
+ std::string& normalTextureUrl, std::string& glossTextureUrl )
{
float fR,fG,fB;
{
isline >> info;
}
+ else if ( tag == "Ka" ) //ambient color
+ {
+ isline >> fR >> fG >> fB;
+ }
else if ( tag == "Kd" ) //diffuse color
{
isline >> fR >> fG >> fB;
}
- else if ( tag == "Kd" ) //Ambient color
+ else if ( tag == "Ks" ) //specular color
{
isline >> fR >> fG >> fB;
}
else if ( tag == "map_Kd" )
{
isline >> info;
- texture0Url = info;
+ diffuseTextureUrl = info;
mHasDiffuseMap = true;
}
else if ( tag == "bump" )
{
isline >> info;
- texture1Url = info;
+ normalTextureUrl = info;
mHasNormalMap = true;
}
else if ( tag == "map_Ks" )
{
isline >> info;
- texture2Url = info;
+ glossTextureUrl = info;
mHasSpecularMap = true;
}
}
mMaterialLoaded = true;
}
-Geometry ObjLoader::CreateGeometry( Toolkit::Model3dView::IlluminationType illuminationType )
+Geometry ObjLoader::CreateGeometry( int objectProperties )
{
Geometry surface = Geometry::New();
surface.AddVertexBuffer( surfaceVertices );
//Some need texture coordinates
- if( ( (illuminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP ) ||
- (illuminationType == Toolkit::Model3dView::DIFFUSE_WITH_TEXTURE ) ) && mHasTexturePoints && mHasDiffuseMap )
+ if( ( objectProperties & TEXTURE_COORDINATES ) && mHasTexturePoints && mHasDiffuseMap )
{
Property::Map textureFormat;
textureFormat["aTexCoord"] = Property::VECTOR2;
}
//Some need tangent and bitangent
- if( illuminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP && mHasTexturePoints )
+ if( ( objectProperties & TANGENTS ) && ( objectProperties & BINOMIALS ) && mHasTexturePoints )
{
Property::Map vertexExtFormat;
vertexExtFormat["aTangent"] = Property::VECTOR3;
surface.AddVertexBuffer( extraVertices );
}
+ //If indices are required, we set them.
if ( indices.Size() )
{
surface.SetIndexBuffer ( &indices[0], indices.Size() );
}
- vertices.Clear();
- verticesExt.Clear();
- indices.Clear();
-
return surface;
}
// EXTERNAL INCLUDES
#include <dali/devel-api/rendering/renderer.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/public-api/controls/model3d-view/model3d-view.h>
-
+#include <limits>
namespace Dali
{
{}
VertexExt( const Vector3& tangent, const Vector3& binormal )
- : tangent( tangent), bitangent (binormal)
+ : tangent( tangent), bitangent( binormal )
{}
Vector3 tangent;
{
void Init()
{
- pointMin = Vector3(999999.9,999999.9,999999.9);
- pointMax = Vector3(-999999.9,-999999.9,-999999.9);
+ pointMin = Vector3( std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max() );
+ pointMax = Vector3( std::numeric_limits<float>::min(), std::numeric_limits<float>::min(), std::numeric_limits<float>::min() );
}
- void ConsiderNewPointInVolume(const Vector3& position)
+ void ConsiderNewPointInVolume( const Vector3& position )
{
- pointMin.x = std::min(position.x, pointMin.x);
- pointMin.y = std::min(position.y, pointMin.y);
- pointMin.z = std::min(position.z, pointMin.z);
+ pointMin.x = std::min( position.x, pointMin.x );
+ pointMin.y = std::min( position.y, pointMin.y );
+ pointMin.z = std::min( position.z, pointMin.z );
- pointMax.x = std::max(position.x, pointMax.x);
- pointMax.y = std::max(position.y, pointMax.y);
- pointMax.z = std::max(position.z, pointMax.z);
+ pointMax.x = std::max( position.x, pointMax.x );
+ pointMax.y = std::max( position.y, pointMax.y );
+ pointMax.z = std::max( position.z, pointMax.z );
}
Vector3 pointMin;
Vector3 pointMax;
};
+ //Defines bit masks to declare which properties are needed by anyone requesting a geometry.
+ enum ObjectProperties
+ {
+ TEXTURE_COORDINATES = 1 << 0,
+ TANGENTS = 1 << 1,
+ BINOMIALS = 1 << 2
+ };
+
ObjLoader();
virtual ~ObjLoader();
bool IsSceneLoaded();
bool IsMaterialLoaded();
- bool Load(char* objBuffer, std::streampos fileSize, std::string& materialFile);
+ bool LoadObject( char* objBuffer, std::streampos fileSize );
- void LoadMaterial(char* objBuffer, std::streampos fileSize, std::string& texture0Url, std::string& texture1Url, std::string& texture2Url);
+ void LoadMaterial( char* objBuffer, std::streampos fileSize, std::string& diffuseTextureUrl,
+ std::string& normalTextureUrl, std::string& glossTextureUrl );
- Geometry CreateGeometry(Toolkit::Model3dView::IlluminationType illuminationType);
+ Geometry CreateGeometry( int objectProperties );
Vector3 GetCenter();
Vector3 GetSize();
Dali::Vector<Vector3> mBiTangents;
Dali::Vector<TriIndex> mTriangles;
- void CalculateTangentArray(const Dali::Vector<Vector3>& vertex,
- const Dali::Vector<Vector2>& texcoord,
- Dali::Vector<TriIndex>& triangle,
- Dali::Vector<Vector3>& normal,
- Dali::Vector<Vector3>& tangent);
+ void CalculateTangentArray( const Dali::Vector<Vector3>& vertex,
+ const Dali::Vector<Vector2>& texcoord,
+ Dali::Vector<TriIndex>& triangle,
+ Dali::Vector<Vector3>& normal,
+ Dali::Vector<Vector3>& tangent );
- void CenterAndScale(bool center, Dali::Vector<Vector3>& points);
+ void CenterAndScale( bool center, Dali::Vector<Vector3>& points );
- void CreateGeometryArray(Dali::Vector<Vertex> & vertices,
- Dali::Vector<Vector2> & textures,
- Dali::Vector<VertexExt> & verticesExt,
- Dali::Vector<unsigned short> & indices);
+ void CreateGeometryArray( Dali::Vector<Vertex> & vertices,
+ Dali::Vector<Vector2> & textures,
+ Dali::Vector<VertexExt> & verticesExt,
+ Dali::Vector<unsigned short> & indices );
};
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include "mesh-renderer.h"
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/images/resource-image.h>
+#include <dali/public-api/common/stage.h>
+#include <dali/devel-api/adaptor-framework/file-loader.h>
+#include <fstream>
+
+//INTERNAL INCLUDES
+#include <dali-toolkit/internal/controls/renderers/renderer-string-constants.h>
+#include <dali-toolkit/internal/controls/renderers/renderer-factory-impl.h>
+#include <dali-toolkit/internal/controls/renderers/renderer-factory-cache.h>
+#include <dali-toolkit/internal/controls/renderers/control-renderer-data-impl.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+//Defines ordering of textures for shaders.
+//All shaders, if including certain texture types, must include them in the same order.
+//Within the texture set for the renderer, textures are ordered in the same manner.
+enum TextureIndex
+{
+ DIFFUSE_INDEX = 0u,
+ NORMAL_INDEX = 1u,
+ GLOSS_INDEX = 2u
+};
+
+const char * const RENDERER_TYPE_VALUE( "mesh" ); //String label for which type of control renderer this is.
+const char * const LIGHT_POSITION( "uLightPosition" ); //Shader property
+const char * const OBJECT_MATRIX( "uObjectMatrix" ); //Shader property
+
+//Shaders
+//If a shader requires certain textures, they must be listed in order,
+//as detailed in the TextureIndex enum documentation.
+
+//A basic shader that doesn't use textures at all.
+const char* SIMPLE_VERTEX_SHADER = DALI_COMPOSE_SHADER(
+ attribute highp vec3 aPosition;\n
+ attribute highp vec3 aNormal;\n
+ varying mediump vec3 vIllumination;\n
+ uniform mediump vec3 uSize;\n
+ uniform mediump mat4 uMvpMatrix;\n
+ uniform mediump mat4 uModelView;\n
+ uniform mediump mat3 uNormalMatrix;
+ uniform mediump mat4 uObjectMatrix;\n
+ uniform mediump vec3 uLightPosition;\n
+
+ void main()\n
+ {\n
+ vec4 vertexPosition = vec4( aPosition * min( uSize.x, uSize.y ), 1.0 );\n
+ vertexPosition = uObjectMatrix * vertexPosition;\n
+ vertexPosition = uMvpMatrix * vertexPosition;\n
+
+ //Illumination in Model-View space - Transform attributes and uniforms\n
+ vec4 vertPos = uModelView * vec4( aPosition.xyz, 1.0 );\n
+ vec3 normal = uNormalMatrix * mat3( uObjectMatrix ) * aNormal;\n
+ vec4 centre = uModelView * vec4( 0.0, 0.0, 0.0, 1.0 );\n
+ vec4 lightPos = vec4( centre.x, centre.y, uLightPosition.z, 1.0 );\n
+ vec3 vecToLight = normalize( lightPos.xyz - vertPos.xyz );\n
+
+ float lightDiffuse = max( dot( vecToLight, normal ), 0.0 );\n
+ vIllumination = vec3( lightDiffuse * 0.5 + 0.5 );\n
+
+ gl_Position = vertexPosition;\n
+ }\n
+);
+
+//Fragment shader corresponding to the texture-less shader.
+const char* SIMPLE_FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
+ precision mediump float;\n
+ varying mediump vec3 vIllumination;\n
+ uniform lowp vec4 uColor;\n
+
+ void main()\n
+ {\n
+ gl_FragColor = vec4( vIllumination.rgb * uColor.rgb, uColor.a );\n
+ }\n
+);
+
+//Diffuse and specular illumination shader with albedo texture. Texture is index 0.
+const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
+ attribute highp vec3 aPosition;\n
+ attribute highp vec2 aTexCoord;\n
+ attribute highp vec3 aNormal;\n
+ varying mediump vec2 vTexCoord;\n
+ varying mediump vec3 vIllumination;\n
+ varying mediump float vSpecular;\n
+ uniform mediump vec3 uSize;\n
+ uniform mediump mat4 uMvpMatrix;\n
+ uniform mediump mat4 uModelView;
+ uniform mediump mat3 uNormalMatrix;
+ uniform mediump mat4 uObjectMatrix;\n
+ uniform mediump vec3 uLightPosition;\n
+
+ void main()
+ {\n
+ vec4 vertexPosition = vec4( aPosition * min( uSize.x, uSize.y ), 1.0 );\n
+ vertexPosition = uObjectMatrix * vertexPosition;\n
+ vertexPosition = uMvpMatrix * vertexPosition;\n
+
+ //Illumination in Model-View space - Transform attributes and uniforms\n
+ vec4 vertPos = uModelView * vec4( aPosition.xyz, 1.0 );\n
+ vec4 centre = uModelView * vec4( 0.0, 0.0, 0.0, 1.0 );\n
+ vec4 lightPos = vec4( centre.x, centre.y, uLightPosition.z, 1.0 );\n
+ vec3 normal = normalize( uNormalMatrix * mat3( uObjectMatrix ) * aNormal );\n
+
+ vec3 vecToLight = normalize( lightPos.xyz - vertPos.xyz );\n
+ vec3 viewDir = normalize( -vertPos.xyz );
+
+ vec3 halfVector = normalize( viewDir + vecToLight );
+
+ float lightDiffuse = dot( vecToLight, normal );\n
+ lightDiffuse = max( 0.0,lightDiffuse );\n
+ vIllumination = vec3( lightDiffuse * 0.5 + 0.5 );\n
+
+ vec3 reflectDir = reflect( -vecToLight, normal );
+ vSpecular = pow( max( dot( reflectDir, viewDir ), 0.0 ), 4.0 );
+
+ vTexCoord = aTexCoord;\n
+ gl_Position = vertexPosition;\n
+ }\n
+);
+
+//Fragment shader corresponding to the diffuse and specular illumination shader with albedo texture
+const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
+ precision mediump float;\n
+ varying mediump vec2 vTexCoord;\n
+ varying mediump vec3 vIllumination;\n
+ varying mediump float vSpecular;\n
+ uniform sampler2D sDiffuse;\n
+ uniform lowp vec4 uColor;\n
+
+ void main()\n
+ {\n
+ vec4 texture = texture2D( sDiffuse, vTexCoord );\n
+ gl_FragColor = vec4( vIllumination.rgb * texture.rgb * uColor.rgb + vSpecular * 0.3, texture.a * uColor.a );\n
+ }\n
+);
+
+//Diffuse and specular illumination shader with albedo texture, normal map and gloss map shader.
+//Diffuse (albedo) texture is index 0, normal is 1, gloss is 2. They must be declared in this order.
+const char* NORMAL_MAP_VERTEX_SHADER = DALI_COMPOSE_SHADER(
+ attribute highp vec3 aPosition;\n
+ attribute highp vec2 aTexCoord;\n
+ attribute highp vec3 aNormal;\n
+ attribute highp vec3 aTangent;\n
+ attribute highp vec3 aBiNormal;\n
+ varying mediump vec2 vTexCoord;\n
+ varying mediump vec3 vLightDirection;\n
+ varying mediump vec3 vHalfVector;\n
+ uniform mediump vec3 uSize;\n
+ uniform mediump mat4 uMvpMatrix;\n
+ uniform mediump mat4 uModelView;
+ uniform mediump mat3 uNormalMatrix;
+ uniform mediump mat4 uObjectMatrix;\n
+ uniform mediump vec3 uLightPosition;\n
+
+ void main()
+ {\n
+ vec4 vertexPosition = vec4( aPosition * min( uSize.x, uSize.y ), 1.0 );\n
+ vertexPosition = uObjectMatrix * vertexPosition;\n
+ vertexPosition = uMvpMatrix * vertexPosition;\n
+
+ vec4 vertPos = uModelView * vec4( aPosition.xyz, 1.0 );\n
+ vec4 centre = uModelView * vec4( 0.0, 0.0, 0.0, 1.0 );\n
+ vec4 lightPos = vec4( centre.x, centre.y, uLightPosition.z, 1.0 );\n
+
+ vec3 tangent = normalize( uNormalMatrix * aTangent );
+ vec3 binormal = normalize( uNormalMatrix * aBiNormal );
+ vec3 normal = normalize( uNormalMatrix * mat3( uObjectMatrix ) * aNormal );
+
+ vec3 vecToLight = normalize( lightPos.xyz - vertPos.xyz );\n
+ vLightDirection.x = dot( vecToLight, tangent );
+ vLightDirection.y = dot( vecToLight, binormal );
+ vLightDirection.z = dot( vecToLight, normal );
+
+ vec3 viewDir = normalize( -vertPos.xyz );
+ vec3 halfVector = normalize( viewDir + vecToLight );
+ vHalfVector.x = dot( halfVector, tangent );
+ vHalfVector.y = dot( halfVector, binormal );
+ vHalfVector.z = dot( halfVector, normal );
+
+ vTexCoord = aTexCoord;\n
+ gl_Position = vertexPosition;\n
+ }\n
+);
+
+//Fragment shader corresponding to the shader that uses all textures (diffuse, normal and gloss maps)
+const char* NORMAL_MAP_FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
+ precision mediump float;\n
+ varying mediump vec2 vTexCoord;\n
+ varying mediump vec3 vLightDirection;\n
+ varying mediump vec3 vHalfVector;\n
+ uniform sampler2D sDiffuse;\n
+ uniform sampler2D sNormal;\n
+ uniform sampler2D sGloss;\n
+ uniform lowp vec4 uColor;\n
+
+ void main()\n
+ {\n
+ vec4 texture = texture2D( sDiffuse, vTexCoord );\n
+ vec3 normal = normalize( texture2D( sNormal, vTexCoord ).xyz * 2.0 - 1.0 );\n
+ vec4 glossMap = texture2D( sGloss, vTexCoord );\n
+
+ float lightDiffuse = max( 0.0, dot( normal, normalize( vLightDirection ) ) );\n
+ lightDiffuse = lightDiffuse * 0.5 + 0.5;\n
+
+ float shininess = pow ( max ( dot ( normalize( vHalfVector ), normal ), 0.0 ), 16.0 ) ;
+
+ gl_FragColor = vec4( texture.rgb * uColor.rgb * lightDiffuse + shininess * glossMap.rgb, texture.a * uColor.a );\n
+ }\n
+);
+
+} // namespace
+
+MeshRenderer::MeshRenderer( RendererFactoryCache& factoryCache )
+: ControlRenderer( factoryCache ),
+ mShaderType( ALL_TEXTURES ),
+ mUseTexture( true )
+{
+}
+
+MeshRenderer::~MeshRenderer()
+{
+}
+
+void MeshRenderer::DoInitialize( Actor& actor, const Property::Map& propertyMap )
+{
+ Property::Value* objectUrl = propertyMap.Find( OBJECT_URL );
+ if( !objectUrl || !objectUrl->Get( mObjectUrl ) )
+ {
+ DALI_LOG_ERROR( "Fail to provide object URL to the MeshRenderer object.\n" );
+ }
+
+ Property::Value* materialUrl = propertyMap.Find( MATERIAL_URL );
+
+ if( !materialUrl || !materialUrl->Get( mMaterialUrl ) || mMaterialUrl.empty() )
+ {
+ mUseTexture = false;
+ }
+
+ Property::Value* imagesUrl = propertyMap.Find( TEXTURES_PATH );
+ if( !imagesUrl || !imagesUrl->Get( mTexturesPath ) )
+ {
+ //Default behaviour is to assume files are in the same directory,
+ // or have their locations detailed in full when supplied.
+ mTexturesPath.clear();
+ }
+
+ Property::Value* shaderType = propertyMap.Find( SHADER_TYPE );
+ if( shaderType && shaderType->Get( mShaderTypeString ) )
+ {
+ if( mShaderTypeString == "textureless" )
+ {
+ mShaderType = TEXTURELESS;
+ }
+ else if( mShaderTypeString == "diffuseTexture" )
+ {
+ mShaderType = DIFFUSE_TEXTURE;
+ }
+ else if( mShaderTypeString == "allTextures" )
+ {
+ mShaderType = ALL_TEXTURES;
+ }
+ else
+ {
+ DALI_LOG_ERROR( "Unknown shader type provided to the MeshRenderer object.\n");
+ }
+ }
+}
+
+void MeshRenderer::SetSize( const Vector2& size )
+{
+ ControlRenderer::SetSize( size );
+
+ // ToDo: renderer responds to the size change
+}
+
+void MeshRenderer::SetClipRect( const Rect<int>& clipRect )
+{
+ ControlRenderer::SetClipRect( clipRect );
+
+ //ToDo: renderer responds to the clipRect change
+}
+
+void MeshRenderer::SetOffset( const Vector2& offset )
+{
+ //ToDo: renderer applies the offset
+}
+
+void MeshRenderer::DoSetOnStage( Actor& actor )
+{
+ InitializeRenderer();
+}
+
+void MeshRenderer::DoCreatePropertyMap( Property::Map& map ) const
+{
+ map.Clear();
+ map.Insert( RENDERER_TYPE, RENDERER_TYPE_VALUE );
+ map.Insert( OBJECT_URL, mObjectUrl );
+ map.Insert( MATERIAL_URL, mMaterialUrl );
+ map.Insert( TEXTURES_PATH, mTexturesPath );
+ map.Insert( SHADER_TYPE, mShaderTypeString );
+}
+
+void MeshRenderer::InitializeRenderer()
+{
+ //Try to load the geometry from the file.
+ if( !LoadGeometry() )
+ {
+ SupplyEmptyGeometry();
+ return;
+ }
+
+ //If a texture is used by the obj file, load the supplied material file.
+ if( mObjLoader.IsTexturePresent() && !mMaterialUrl.empty() )
+ {
+ if( !LoadMaterial() )
+ {
+ SupplyEmptyGeometry();
+ return;
+ }
+ }
+
+ //Now that the required parts are loaded, create the geometry for the object.
+ if( !CreateGeometry() )
+ {
+ SupplyEmptyGeometry();
+ return;
+ }
+
+ CreateShader();
+
+ //Load the various texture files supplied by the material file.
+ if( !LoadTextures() )
+ {
+ SupplyEmptyGeometry();
+ return;
+ }
+
+ mImpl->mRenderer = Renderer::New( mGeometry, mShader );
+ mImpl->mRenderer.SetTextures( mTextureSet );
+ mImpl->mRenderer.SetProperty( Renderer::Property::DEPTH_WRITE_MODE, DepthWriteMode::ON );
+}
+
+void MeshRenderer::SupplyEmptyGeometry()
+{
+ mGeometry = Geometry::New();
+ mShader = Shader::New( SIMPLE_VERTEX_SHADER, SIMPLE_FRAGMENT_SHADER );
+ mImpl->mRenderer = Renderer::New( mGeometry, mShader );
+
+ DALI_LOG_ERROR( "Initialisation error in mesh renderer.\n" );
+}
+
+void MeshRenderer::UpdateShaderUniforms()
+{
+ Stage stage = Stage::GetCurrent();
+
+ Vector3 lightPosition( 0, 0, stage.GetSize().width );
+ mShader.RegisterProperty( LIGHT_POSITION, lightPosition );
+
+ Matrix scaleMatrix;
+ scaleMatrix.SetIdentityAndScale( Vector3( 1.0, -1.0, 1.0 ) );
+ mShader.RegisterProperty( OBJECT_MATRIX, scaleMatrix );
+}
+
+void MeshRenderer::CreateShader()
+{
+ if( mShaderType == ALL_TEXTURES )
+ {
+ mShader = Shader::New( NORMAL_MAP_VERTEX_SHADER, NORMAL_MAP_FRAGMENT_SHADER );
+ }
+ else if( mShaderType == DIFFUSE_TEXTURE )
+ {
+ mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
+ }
+ else //Textureless
+ {
+ mShader = Shader::New( SIMPLE_VERTEX_SHADER, SIMPLE_FRAGMENT_SHADER );
+ }
+
+ UpdateShaderUniforms();
+}
+
+bool MeshRenderer::CreateGeometry()
+{
+ //Determine if we need to use a simpler shader to handle the provided data
+ if( mShaderType == ALL_TEXTURES )
+ {
+ if( !mObjLoader.IsNormalMapPresent() || !mObjLoader.IsSpecularMapPresent() )
+ {
+ mShaderType = DIFFUSE_TEXTURE;
+ }
+ }
+ if( !mObjLoader.IsTexturePresent() || !mObjLoader.IsDiffuseMapPresent() || !mUseTexture )
+ {
+ mShaderType = TEXTURELESS;
+ }
+
+ int objectProperties = 0;
+
+ if( mShaderType == DIFFUSE_TEXTURE ||
+ mShaderType == ALL_TEXTURES )
+ {
+ objectProperties |= ObjLoader::TEXTURE_COORDINATES;
+ }
+
+ if( mShaderType == ALL_TEXTURES )
+ {
+ objectProperties |= ObjLoader::TANGENTS | ObjLoader::BINOMIALS;
+ }
+
+ //Create geometry with attributes required by shader.
+ mGeometry = mObjLoader.CreateGeometry( objectProperties );
+
+ if( mGeometry )
+ {
+ return true;
+ }
+
+ DALI_LOG_ERROR( "Failed to load geometry in mesh renderer.\n" );
+ return false;
+}
+
+bool MeshRenderer::LoadGeometry()
+{
+ std::streampos fileSize;
+ Dali::Vector<char> fileContent;
+
+ if( FileLoader::ReadFile( mObjectUrl, fileSize, fileContent, FileLoader::TEXT ) )
+ {
+ mObjLoader.ClearArrays();
+ mObjLoader.LoadObject( fileContent.Begin(), fileSize );
+
+ //Get size information from the obj loaded
+ mSceneCenter = mObjLoader.GetCenter();
+ mSceneSize = mObjLoader.GetSize();
+
+ return true;
+ }
+
+ DALI_LOG_ERROR( "Failed to find object to load in mesh renderer.\n" );
+ return false;
+}
+
+bool MeshRenderer::LoadMaterial()
+{
+ std::streampos fileSize;
+ Dali::Vector<char> fileContent;
+
+ if( FileLoader::ReadFile( mMaterialUrl, fileSize, fileContent, FileLoader::TEXT ) )
+ {
+ //Load data into obj (usable) form
+ mObjLoader.LoadMaterial( fileContent.Begin(), fileSize, mDiffuseTextureUrl, mNormalTextureUrl, mGlossTextureUrl );
+ return true;
+ }
+
+ DALI_LOG_ERROR( "Failed to find texture set to load in mesh renderer.\n" );
+ mUseTexture = false;
+ return false;
+}
+
+bool MeshRenderer::LoadTextures()
+{
+ mTextureSet = TextureSet::New();
+
+ if( !mDiffuseTextureUrl.empty() )
+ {
+ std::string imageUrl = mTexturesPath + mDiffuseTextureUrl;
+
+ //Load textures
+ Image diffuseTexture = ResourceImage::New( imageUrl );
+ if( diffuseTexture )
+ {
+ mTextureSet.SetImage( DIFFUSE_INDEX, diffuseTexture );
+ }
+ else
+ {
+ DALI_LOG_ERROR( "Failed to load diffuse map texture in mesh renderer.\n");
+ return false;
+ }
+ }
+
+ if( !mNormalTextureUrl.empty() && ( mShaderType == ALL_TEXTURES ) )
+ {
+ std::string imageUrl = mTexturesPath + mNormalTextureUrl;
+
+ //Load textures
+ Image normalTexture = ResourceImage::New( imageUrl );
+ if( normalTexture )
+ {
+ mTextureSet.SetImage( NORMAL_INDEX, normalTexture );
+ }
+ else
+ {
+ DALI_LOG_ERROR( "Failed to load normal map texture in mesh renderer.\n");
+ return false;
+ }
+ }
+
+ if( !mGlossTextureUrl.empty() && ( mShaderType == ALL_TEXTURES ) )
+ {
+ std::string imageUrl = mTexturesPath + mGlossTextureUrl;
+
+ //Load textures
+ Image glossTexture = ResourceImage::New( imageUrl );
+ if( glossTexture )
+ {
+ mTextureSet.SetImage( GLOSS_INDEX, glossTexture );
+ }
+ else
+ {
+ DALI_LOG_ERROR( "Failed to load gloss map texture in mesh renderer.\n");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_TOOLKIT_INTERNAL_MESH_RENDERER_H__
+#define __DALI_TOOLKIT_INTERNAL_MESH_RENDERER_H__
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <fstream>
+#include <string.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/controls/renderers/control-renderer-impl.h>
+#include <dali-toolkit/internal/controls/model3d-view/obj-loader.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+/**
+ * The renderer which renders a 3D object to the control's quad
+ *
+ * The following Property::Map keys are required to create a MeshRender
+ *
+ * | %Property Name | Type | Representing |
+ * |-----------------|-------------|-----------------------------------------|
+ * | objectUrl | STRING | A URL to the .obj file |
+ * | materialUrl | STRING | A URL to the .mtl file |
+ * | texturesPath | STRING | A URL of the path to the texture images |
+ * | shaderType | STRING | An enum of shader types |
+ */
+class MeshRenderer: public ControlRenderer
+{
+public:
+
+ /**
+ * @brief Constructor.
+ *
+ * @param[in] factoryCache A pointer pointing to the RendererFactoryCache object
+ */
+ MeshRenderer( RendererFactoryCache& factoryCache );
+
+ /**
+ * @brief A reference counted object may only be deleted by calling Unreference().
+ */
+ virtual ~MeshRenderer();
+
+public: // from ControlRenderer
+
+ /**
+ * @copydoc ControlRenderer::SetSize
+ */
+ virtual void SetSize( const Vector2& size );
+
+ /**
+ * @copydoc ControlRenderer::SetClipRect
+ */
+ virtual void SetClipRect( const Rect<int>& clipRect );
+
+ /**
+ * @copydoc ControlRenderer::SetOffset
+ */
+ virtual void SetOffset( const Vector2& offset );
+
+ /**
+ * @copydoc ControlRenderer::CreatePropertyMap
+ */
+ virtual void DoCreatePropertyMap( Property::Map& map ) const;
+
+protected:
+
+ /**
+ * @copydoc ControlRenderer::DoInitialize
+ */
+ virtual void DoInitialize( Actor& actor, const Property::Map& propertyMap );
+
+ /**
+ * @copydoc ControlRenderer::DoSetOnStage
+ */
+ virtual void DoSetOnStage( Actor& actor );
+
+public:
+
+ /**
+ * Declare whether a texture map should be used for the object, if it's present. Defaults to true.
+ * @param[in] useTexture boolean declaration.
+ */
+ void SetUseTexture( bool useTexture );
+
+ /**
+ * Declare whether a normal map should be used for the object, if it's present. Defaults to true.
+ * @param[in] useNormalMap boolean declaration.
+ */
+ void SetUseNormalMap( bool useNormalMap );
+
+private:
+
+ //Corresponds to the shader that will be used by the mesh renderer.
+ enum ShaderType
+ {
+ TEXTURELESS,
+ DIFFUSE_TEXTURE,
+ ALL_TEXTURES
+ };
+
+ /**
+ * @brief Provide an empty geometry for the renderer to use.
+ * @details For use in error cases where the initialisation has failed for varying reasons.
+ */
+ void SupplyEmptyGeometry();
+
+ /**
+ * @brief Initialize the renderer with the geometry and shader from the cache, if not available, create and save to the cache for sharing.
+ */
+ void InitializeRenderer();
+
+ /**
+ * @brief Create a shader for the object to use.
+ */
+ void CreateShader();
+
+ /**
+ * @brief Update shader related info, uniforms, etc. for the new shader.
+ */
+ void UpdateShaderUniforms();
+
+ /**
+ * @brief Use the object URL stored in the renderer to load and create the geometry of the object.
+ * @return Boolean of success of operation.
+ */
+ bool CreateGeometry();
+
+ /**
+ * @brief Use the object URL stored in the renderer to load the geometry of the object.
+ * @return Boolean of success of operation.
+ */
+ bool LoadGeometry();
+
+ /**
+ * @brief Use the material URL stored in the renderer to load the material of the object.
+ * @return Boolean of success of operation.
+ */
+ bool LoadMaterial();
+
+ /**
+ * @brief Use the image and texture URL components to load the different types of texture.
+ * @return Boolean of success of operation. Returns false if any texture fails to load from a url.
+ */
+ bool LoadTextures();
+
+private:
+
+ // Undefined
+ MeshRenderer( const MeshRenderer& meshRenderer );
+
+ // Undefined
+ MeshRenderer& operator=( const MeshRenderer& meshRenderer );
+
+private:
+
+ std::string mObjectUrl;
+ std::string mMaterialUrl;
+
+ std::string mDiffuseTextureUrl;
+ std::string mNormalTextureUrl;
+ std::string mGlossTextureUrl;
+ std::string mTexturesPath;
+
+ std::string mShaderTypeString;
+
+ Shader mShader;
+ Geometry mGeometry;
+ TextureSet mTextureSet;
+
+ ObjLoader mObjLoader;
+ Vector3 mSceneCenter;
+ Vector3 mSceneSize;
+ ShaderType mShaderType;
+
+ bool mUseTexture;
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif /* __DALI_TOOLKIT_INTERNAL_MESH_RENDERER_H__ */
#include <dali-toolkit/internal/controls/renderers/npatch/npatch-renderer.h>
#include <dali-toolkit/internal/controls/renderers/image/image-renderer.h>
#include <dali-toolkit/internal/controls/renderers/svg/svg-renderer.h>
+#include <dali-toolkit/internal/controls/renderers/mesh/mesh-renderer.h>
#include <dali-toolkit/internal/controls/renderers/renderer-factory-cache.h>
#include <dali-toolkit/internal/controls/renderers/renderer-string-constants.h>
#include <dali-toolkit/internal/controls/renderers/image-atlas-manager.h>
std::string typeValue ;
if( type && type->Get( typeValue ))
{
- if( typeValue == COLOR_RENDERER )
+ if( typeValue == COLOR_RENDERER )
{
rendererType = COLOR;
}
{
rendererType = BORDER;
}
- else if( typeValue == GRADIENT_RENDERER )
+ else if( typeValue == GRADIENT_RENDERER )
{
rendererType = GRADIENT;
}
- else if( typeValue == IMAGE_RENDERER )
+ else if( typeValue == IMAGE_RENDERER )
{
rendererType = IMAGE;
}
+ else if( typeValue == MESH_RENDERER )
+ {
+ rendererType = MESH;
+ }
}
// check the url if exist, to decide the renderer type
rendererPtr = new SvgRenderer( *( mFactoryCache.Get() ), *( mAtlasManager.Get() ) );
break;
}
+ case MESH:
+ {
+ rendererPtr = new MeshRenderer( *( mFactoryCache.Get() ) );
+ break;
+ }
case UNDEFINED:
default:
{
//If there's no renderer type specified or if there hasn't been a renderer type change then we can reuse the renderer
if( type == UNDEFINED ||
- ( type == IMAGE && typeid( controlRenderer ) == typeid( ImageRenderer ) ) ||
- ( type == N_PATCH && typeid( controlRenderer ) == typeid( NPatchRenderer ) ) ||
- ( type == COLOR && typeid( controlRenderer ) == typeid( ColorRenderer ) )||
- ( type == GRADIENT && typeid( controlRenderer ) == typeid( GradientRenderer ) ) ||
- ( type == BORDER && typeid( controlRenderer ) == typeid( BorderRenderer ) ) ||
- ( type == SVG && typeid( controlRenderer ) == typeid( SvgRenderer ) ) )
+ ( type == IMAGE && typeid( controlRenderer ) == typeid( ImageRenderer ) ) ||
+ ( type == N_PATCH && typeid( controlRenderer ) == typeid( NPatchRenderer ) ) ||
+ ( type == COLOR && typeid( controlRenderer ) == typeid( ColorRenderer ) ) ||
+ ( type == GRADIENT && typeid( controlRenderer ) == typeid( GradientRenderer ) ) ||
+ ( type == BORDER && typeid( controlRenderer ) == typeid( BorderRenderer ) ) ||
+ ( type == SVG && typeid( controlRenderer ) == typeid( SvgRenderer ) ) ||
+ ( type == MESH && typeid( controlRenderer ) == typeid( MeshRenderer ) ) )
{
controlRenderer.Initialize( actor, propertyMap );
return;
} // namespace Toolkit
} // namespace Dali
-
IMAGE,
N_PATCH,
SVG,
+ MESH,
UNDEFINED
};
const char * const BORDER_RENDERER("border");
const char * const GRADIENT_RENDERER("gradient");
const char * const IMAGE_RENDERER("image");
+const char * const MESH_RENDERER("mesh");
const char * const IMAGE_URL_NAME("url");
const char * const ATLAS_RECT_UNIFORM_NAME ( "uAtlasRect" );
+const char * const COLOR( "color" );
+
+//Mesh properties
+const char * const OBJECT_URL( "objectUrl" );
+const char * const MATERIAL_URL( "materialUrl" );
+const char * const TEXTURES_PATH( "texturesPath" );
+const char * const SHADER_TYPE( "shaderType" );
} // namespace Internal
extern const char * const BORDER_RENDERER;
extern const char * const GRADIENT_RENDERER;
extern const char * const IMAGE_RENDERER;
+extern const char * const MESH_RENDERER;
extern const char * const IMAGE_URL_NAME;
extern const char * const ATLAS_RECT_UNIFORM_NAME;
+extern const char * const COLOR;
+
+//Mesh properties
+extern const char * const OBJECT_URL;
+extern const char * const MATERIAL_URL;
+extern const char * const TEXTURES_PATH;
+extern const char * const SHADER_TYPE;
} // namespace Internal
$(toolkit_src_dir)/controls/renderers/gradient/gradient-renderer.cpp \
$(toolkit_src_dir)/controls/renderers/svg/svg-rasterize-thread.cpp \
$(toolkit_src_dir)/controls/renderers/svg/svg-renderer.cpp \
+ $(toolkit_src_dir)/controls/renderers/mesh/mesh-renderer.cpp \
$(toolkit_src_dir)/controls/alignment/alignment-impl.cpp \
$(toolkit_src_dir)/controls/bloom-view/bloom-view-impl.cpp \
$(toolkit_src_dir)/controls/bubble-effect/bubble-emitter-impl.cpp \
DIFFUSE_WITH_NORMAL_MAP
};
-
/**
* @brief Create a new instance of a Model3dView control.
*
+ [Gradient](@ref gradient-renderer)
+ [Image](@ref image-renderers)
+ [Border](@ref border-renderer)
+ + [Mesh](@ref mesh-renderer)
Controls can provide properties that allow users to specify the renderer type.
Setting renderer properties are done via a property map.
};
~~~
+___________________________________________________________________________________________________
+
+## Mesh Renderer {#mesh-renderer}
+
+Renders a mesh using a .obj file, optionally with textures provided by a mtl file. Scaled to fit the control.
+
+![ ](../assets/img/renderers/mesh-renderer.png)
+![ ](renderers/mesh-renderer.png)
+
+### Properties Supported
+
+**RendererType** "mesh"
+
+| Property Name | Type | Required | Description |
+|---------------|:-------:|:------------------:|----------------------------------------------------------------------|
+| objectUrl | STRING | Yes | The location of the .obj file. |
+| materialUrl | STRING | No | The location of the .mtl file. Leave blank for a textureless object. |
+| texturesPath | STRING | If using material | Path to the directory textures (including gloss and normal) are stored in. |
+| shaderType | STRING | No | Sets the type of shader to be used with the mesh. Note that if anything the shader requires is missing, it will use a simpler one that it can handle with what has been supplied.\n Possible values: "textureless", "diffuseTexture", "allTextures". |
+
+### Usage
+
+~~~{.cpp}
+// C++
+Dali::Toolkit::Control control = Dali::Toolkit::Control::New();
+
+Dali::Property::Map map;
+
+map[ "rendererType" ] = "mesh";
+map[ "objectUrl" ] = "home/models/Dino.obj";
+map[ "materialUrl" ] = "home/models/Dino.mtl";
+map[ "texturesPath" ] = "home/images/";
+
+control.SetProperty( Dali::Toolkit::Control::Property::BACKGROUND, map );
+~~~
+
@class _Guide_Control_Renderers
*/