db42cbe9ce6cc1a93221b5f04c626cedfea482b0
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / model3d-view / model3d-view-impl.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include "model3d-view-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/object/type-registry.h>
23 #include <dali/public-api/animation/constraint.h>
24 #include <dali/public-api/animation/constraint-source.h>
25 #include <dali/public-api/animation/constraints.h>
26 #include <dali/public-api/object/type-registry-helper.h>
27 #include <dali-toolkit/public-api/controls/model3d-view/model3d-view.h>
28 #include <dali/devel-api/adaptor-framework/file-loader.h>
29 #include <dali/devel-api/adaptor-framework/image-loading.h>
30
31 // INTERNAL INCLUDES
32 #include <dali-toolkit/internal/controls/model3d-view/obj-loader.h>
33 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
34
35 namespace Dali
36 {
37
38 namespace Toolkit
39 {
40
41 namespace Internal
42 {
43
44 namespace
45 {
46
47 // Texture indices are constants.
48 enum TextureIndex
49 {
50   DIFFUSE_TEXTURE_INDEX,
51   NORMAL_TEXTURE_INDEX,
52   GLOSS_TEXTURE_INDEX
53 };
54
55 /**
56  * @brief Loads a texture from a file.
57  * @param[in] imageUrl The URL of the file
58  * @return A texture if loading succeeds, an empty handle otherwise
59  */
60 Texture LoadTexture( const char* imageUrl )
61 {
62   Texture texture;
63   Devel::PixelBuffer pixelBuffer = LoadImageFromFile( imageUrl );
64   if( pixelBuffer )
65   {
66     texture = Texture::New( TextureType::TEXTURE_2D, pixelBuffer.GetPixelFormat(), pixelBuffer.GetWidth(), pixelBuffer.GetHeight() );
67     PixelData pixelData = Devel::PixelBuffer::Convert( pixelBuffer );
68     texture.Upload( pixelData );
69     texture.GenerateMipmaps();
70   }
71
72   return texture;
73 }
74
75 // Type registration
76 BaseHandle Create()
77 {
78   return Toolkit::Model3dView::New();
79 }
80
81 // Setup properties, signals and actions using the type-registry.
82 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Model3dView, Toolkit::Control, Create );
83
84 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "geometryUrl",  STRING, GEOMETRY_URL)
85 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "materialUrl",  STRING, MATERIAL_URL)
86 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "imagesUrl",  STRING, IMAGES_URL)
87 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "illuminationType",  INTEGER, ILLUMINATION_TYPE)
88 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "texture0Url",  STRING, TEXTURE0_URL)
89 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "texture1Url",  STRING, TEXTURE1_URL)
90 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "texture2Url",  STRING, TEXTURE2_URL)
91
92 DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, Model3dView, "lightPosition",  VECTOR3, LIGHT_POSITION)
93
94 DALI_TYPE_REGISTRATION_END()
95
96
97 #define MAKE_SHADER(A)#A
98
99 //  Diffuse illumination shader
100
101 const char* SIMPLE_VERTEX_SHADER = MAKE_SHADER(
102   attribute highp vec3 aPosition;\n
103   attribute highp vec2 aTexCoord;\n
104   attribute highp vec3 aNormal;\n
105   varying mediump vec3 vIllumination;\n
106   uniform mediump vec3 uSize;\n
107   uniform mediump mat4 uMvpMatrix;\n
108   uniform mediump mat4 uModelView;\n
109   uniform mediump mat3 uNormalMatrix;
110   uniform mediump mat4 uObjectMatrix;\n
111   uniform mediump vec3 uLightPosition;\n
112
113   void main()\n
114   {\n
115     vec4 vertexPosition = vec4(aPosition*min(uSize.x, uSize.y), 1.0);\n
116     vertexPosition = uObjectMatrix * vertexPosition;\n
117     vertexPosition = uMvpMatrix * vertexPosition;\n
118
119     //Illumination in Model-View space - Transform attributes and uniforms\n
120     vec4 vertPos = uModelView * vec4(aPosition.xyz, 1.0);\n
121     vec3 normal = uNormalMatrix * aNormal;\n
122     vec4 lightPos = uModelView * vec4(uLightPosition, 1.0);\n
123     vec3 vecToLight = normalize( lightPos.xyz - vertPos.xyz );\n
124
125     float lightDiffuse = max( dot( vecToLight, normal ), 0.0 );\n
126     vIllumination = vec3(lightDiffuse * 0.5 + 0.5);\n
127
128     gl_Position = vertexPosition;\n
129   }\n
130 );
131
132 const char* SIMPLE_FRAGMENT_SHADER = MAKE_SHADER(
133   precision mediump float;\n
134   varying mediump vec3 vIllumination;\n
135   uniform lowp vec4 uColor;\n
136
137   void main()\n
138   {\n
139     gl_FragColor = vec4( vIllumination.rgb * uColor.rgb, uColor.a);\n
140   }\n
141 );
142
143 //  Diffuse and specular illumination shader with albedo texture
144
145 const char* VERTEX_SHADER = MAKE_SHADER(
146   attribute highp vec3 aPosition;\n
147   attribute highp vec2 aTexCoord;\n
148   attribute highp vec3 aNormal;\n
149   varying mediump vec2 vTexCoord;\n
150   varying mediump vec3 vIllumination;\n
151   varying mediump float vSpecular;\n
152   uniform mediump vec3 uSize;\n
153   uniform mediump mat4 uMvpMatrix;\n
154   uniform mediump mat4 uModelView;
155   uniform mediump mat3 uNormalMatrix;
156   uniform mediump mat4 uObjectMatrix;\n
157   uniform mediump vec3 uLightPosition;\n
158
159   void main()
160   {\n
161     vec4 vertexPosition = vec4(aPosition*min(uSize.x, uSize.y), 1.0);\n
162     vertexPosition = uObjectMatrix * vertexPosition;\n
163     vertexPosition = uMvpMatrix * vertexPosition;\n
164
165     //Illumination in Model-View space - Transform attributes and uniforms\n
166     vec4 vertPos = uModelView * vec4(aPosition.xyz, 1.0);\n
167     vec4 lightPos = uModelView * vec4(uLightPosition, 1.0);\n
168     vec3 normal = normalize(uNormalMatrix * aNormal);\n
169
170     vec3 vecToLight = normalize( lightPos.xyz - vertPos.xyz );\n
171     vec3 viewDir = normalize(-vertPos.xyz);
172
173     vec3 halfVector = normalize(viewDir + vecToLight);
174
175     float lightDiffuse = dot( vecToLight, normal );\n
176     lightDiffuse = max(0.0,lightDiffuse);\n
177     vIllumination = vec3(lightDiffuse * 0.5 + 0.5);\n
178
179     vec3 reflectDir = reflect(-vecToLight, normal);
180     vSpecular = pow( max(dot(reflectDir, viewDir), 0.0), 4.0 );
181
182     vTexCoord = aTexCoord;\n
183     gl_Position = vertexPosition;\n
184   }\n
185 );
186
187 const char* FRAGMENT_SHADER = MAKE_SHADER(
188   precision mediump float;\n
189   varying mediump vec2 vTexCoord;\n
190   varying mediump vec3 vIllumination;\n
191   varying mediump float vSpecular;\n
192   uniform sampler2D sDiffuse;\n
193   uniform lowp vec4 uColor;\n
194
195   void main()\n
196   {\n
197     vec4 texture = texture2D( sDiffuse, vTexCoord );\n
198     gl_FragColor = vec4( vIllumination.rgb * texture.rgb * uColor.rgb + vSpecular * 0.3, texture.a * uColor.a);\n
199   }\n
200 );
201
202 //  Diffuse and specular illumination shader with albedo texture, normal map and gloss map shader
203
204 const char* NRMMAP_VERTEX_SHADER = MAKE_SHADER(
205   attribute highp vec3 aPosition;\n
206   attribute highp vec2 aTexCoord;\n
207   attribute highp vec3 aNormal;\n
208   attribute highp vec3 aTangent;\n
209   attribute highp vec3 aBiNormal;\n
210   varying mediump vec2 vTexCoord;\n
211   varying mediump vec3 vLightDirection;\n
212   varying mediump vec3 vHalfVector;\n
213   uniform mediump vec3 uSize;\n
214   uniform mediump mat4 uMvpMatrix;\n
215   uniform mediump mat4 uModelView;
216   uniform mediump mat3 uNormalMatrix;
217   uniform mediump mat4 uObjectMatrix;\n
218   uniform mediump vec3 uLightPosition;\n
219
220   void main()
221   {\n
222     vec4 vertexPosition = vec4(aPosition*min(uSize.x, uSize.y), 1.0);\n
223     vertexPosition = uObjectMatrix * vertexPosition;\n
224     vertexPosition = uMvpMatrix * vertexPosition;\n
225
226     vec4 vertPos = uModelView * vec4(aPosition.xyz, 1.0);\n
227     vec4 lightPos = uModelView * vec4(uLightPosition, 1.0);\n
228
229     vec3 tangent = normalize(uNormalMatrix * aTangent);
230     vec3 binormal = normalize(uNormalMatrix * aBiNormal);
231     vec3 normal = normalize(uNormalMatrix * aNormal);
232
233     vec3 vecToLight = normalize( lightPos.xyz - vertPos.xyz );\n
234     vLightDirection.x = dot(vecToLight, tangent);
235     vLightDirection.y = dot(vecToLight, binormal);
236     vLightDirection.z = dot(vecToLight, normal);
237
238     vec3 viewDir = normalize(-vertPos.xyz);
239     vec3 halfVector = normalize(viewDir + vecToLight);
240     vHalfVector.x = dot(halfVector, tangent);
241     vHalfVector.y = dot(halfVector, binormal);
242     vHalfVector.z = dot(halfVector, normal);
243
244     vTexCoord = aTexCoord;\n
245     gl_Position = vertexPosition;\n
246   }\n
247 );
248
249 const char* NRMMAP_FRAGMENT_SHADER = MAKE_SHADER(
250   precision mediump float;\n
251   varying mediump vec2 vTexCoord;\n
252   varying mediump vec3 vLightDirection;\n
253   varying mediump vec3 vHalfVector;\n
254   uniform sampler2D sDiffuse;\n
255   uniform sampler2D sNormal;\n
256   uniform sampler2D sGloss;\n
257   uniform lowp vec4 uColor;\n
258
259   void main()\n
260   {\n
261     vec4 texture = texture2D( sDiffuse, vTexCoord );\n
262     vec3 normal = normalize( texture2D( sNormal, vTexCoord ).xyz * 2.0 - 1.0 );\n
263     vec4 glossMap = texture2D( sGloss, vTexCoord );\n
264
265     float lightDiffuse = max( 0.0, dot( normal, normalize(vLightDirection) ) );\n
266     lightDiffuse = lightDiffuse * 0.5 + 0.5;\n
267
268     float shininess = pow (max (dot (normalize( vHalfVector ), normal), 0.0), 16.0)  ;
269
270     gl_FragColor = vec4( texture.rgb * uColor.rgb * lightDiffuse + shininess * glossMap.rgb, texture.a * uColor.a);\n
271   }\n
272 );
273
274
275 } // anonymous namespace
276
277 using namespace Dali;
278
279 Model3dView::Model3dView()
280 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) )
281 {
282   mIlluminationType = Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP;
283
284   mCameraFOV = Math::PI_OVER_180 * 45.f;
285
286   mControlSize = Vector2(100.,100.);
287
288   DevelControl::SetAccessibilityConstructor( Self(), []( Dali::Actor actor ) {
289     return std::unique_ptr< Dali::Accessibility::Accessible >(
290       new Control::Impl::AccessibleImpl( actor, Dali::Accessibility::Role::IMAGE ) );
291   } );
292 }
293
294 Model3dView::~Model3dView()
295 {
296 }
297
298 Toolkit::Model3dView Model3dView::New()
299 {
300   Model3dView* impl = new Model3dView();
301
302   Dali::Toolkit::Model3dView handle = Dali::Toolkit::Model3dView( *impl );
303
304   // Second-phase init of the implementation
305   // This can only be done after the CustomActor connection has been made...
306   impl->Initialize();
307
308   return handle;
309 }
310
311 void Model3dView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
312 {
313   Toolkit::Model3dView model3dView = Toolkit::Model3dView::DownCast( Dali::BaseHandle( object ) );
314
315   if( model3dView )
316   {
317     Model3dView& impl( GetImpl( model3dView ) );
318     switch( index )
319     {
320       case Toolkit::Model3dView::Property::GEOMETRY_URL:
321       {
322         if( value.Get(impl.mObjUrl) )
323         {
324           impl.LoadGeometry();
325           impl.CreateGeometry();
326         }
327         break;
328       }
329       case Toolkit::Model3dView::Property::MATERIAL_URL:
330       {
331         if( value.Get(impl.mTextureSetUrl) )
332         {
333           impl.LoadMaterial();
334           impl.CreateMaterial();
335           impl.LoadTextures();
336         }
337         break;
338       }
339       case Toolkit::Model3dView::Property::IMAGES_URL:
340       {
341         if( value.Get(impl.mImagesUrl) )
342         {
343           impl.LoadTextures();
344         }
345         break;
346       }
347       case Toolkit::Model3dView::Property::ILLUMINATION_TYPE:
348       {
349         int illuminationType;
350         if( value.Get(illuminationType) )
351         {
352           impl.mIlluminationType = Toolkit::Model3dView::IlluminationType(illuminationType);
353           impl.CreateGeometry();
354           impl.CreateMaterial();
355           impl.LoadTextures();
356         }
357         break;
358       }
359       case Toolkit::Model3dView::Property::TEXTURE0_URL:
360       {
361         value.Get(impl.mTexture0Url);
362         break;
363       }
364       case Toolkit::Model3dView::Property::TEXTURE1_URL:
365       {
366         value.Get(impl.mTexture1Url);
367         break;
368       }
369       case Toolkit::Model3dView::Property::TEXTURE2_URL:
370       {
371         value.Get(impl.mTexture2Url);
372         break;
373       }
374     }
375   }
376 }
377
378 Property::Value Model3dView::GetProperty( BaseObject* object, Property::Index index )
379 {
380   Property::Value value;
381
382   Toolkit::Model3dView model3dView = Toolkit::Model3dView::DownCast( Dali::BaseHandle( object ) );
383
384   if( model3dView )
385   {
386     Model3dView& impl( GetImpl( model3dView ) );
387     switch( index )
388     {
389       case Toolkit::Model3dView::Property::GEOMETRY_URL:
390       {
391         value = impl.mObjUrl;
392         break;
393       }
394       case Toolkit::Model3dView::Property::MATERIAL_URL:
395       {
396         value = impl.mTextureSetUrl;
397         break;
398       }
399       case Toolkit::Model3dView::Property::IMAGES_URL:
400       {
401         value = impl.mImagesUrl;
402         break;
403       }
404       case Toolkit::Model3dView::Property::ILLUMINATION_TYPE:
405       {
406         value = int(impl.mIlluminationType);
407         break;
408       }
409       case Toolkit::Model3dView::Property::TEXTURE0_URL:
410       {
411         value = impl.mTexture0Url;
412         break;
413       }
414       case Toolkit::Model3dView::Property::TEXTURE1_URL:
415       {
416         value = impl.mTexture1Url;
417         break;
418       }
419       case Toolkit::Model3dView::Property::TEXTURE2_URL:
420       {
421         value = impl.mTexture2Url;
422         break;
423       }
424     }
425   }
426
427   return value;
428 }
429
430 /////////////////////////////////////////////////////////////
431
432
433 void Model3dView::OnSceneConnection( int depth )
434 {
435   CustomActor self = Self();
436   self.AddRenderer( mRenderer );
437
438   if( mObjLoader.IsSceneLoaded() )
439   {
440     mMesh = mObjLoader.CreateGeometry( GetShaderProperties( mIlluminationType ), true );
441
442     CreateMaterial();
443     LoadTextures();
444
445     mRenderer.SetGeometry( mMesh );
446
447     //create constraint for lightPosition Property with uLightPosition in the shader
448     Vector3 lightPosition( 0, 0, 0 );
449     Dali::Property::Index lightProperty = mShader.RegisterProperty( "uLightPosition", lightPosition );
450     Constraint constraint = Constraint::New<Vector3>( mShader, lightProperty, EqualToConstraint() );
451     constraint.AddSource( Source( self, Toolkit::Model3dView::Property::LIGHT_POSITION ) );
452     constraint.Apply();
453   }
454
455   Control::OnSceneConnection( depth );
456 }
457
458 ///////////////////////////////////////////////////////////
459 //
460 // Private methods
461 //
462
463 void Model3dView::OnInitialize()
464 {
465   //Create empty versions of the geometry and material so we always have a Renderer
466   Geometry mesh = Geometry::New();
467   Shader shader = Shader::New( SIMPLE_VERTEX_SHADER, SIMPLE_FRAGMENT_SHADER );
468   mRenderer = Renderer::New( mesh, shader );
469
470 }
471
472 void Model3dView::LoadGeometry()
473 {
474   //Load file in adaptor
475   std::streampos fileSize;
476   Dali::Vector<char> fileContent;
477
478   if (FileLoader::ReadFile(mObjUrl,fileSize,fileContent,FileLoader::TEXT))
479   {
480     mObjLoader.ClearArrays();
481     mObjLoader.LoadObject(fileContent.Begin(), fileSize);
482
483     //Get size information from the obj loaded
484     mSceneCenter = mObjLoader.GetCenter();
485     mSceneSize = mObjLoader.GetSize();
486   }
487   else
488   {
489     //Error
490   }
491 }
492
493 void Model3dView::LoadMaterial()
494 {
495   //Load file in adaptor
496   std::streampos fileSize;
497   Dali::Vector<char> fileContent;
498
499   if( FileLoader::ReadFile(mTextureSetUrl, fileSize, fileContent, FileLoader::TEXT) )
500   {
501     mObjLoader.LoadMaterial(fileContent.Begin(), fileSize, mTexture0Url, mTexture1Url, mTexture2Url);
502   }
503   else
504   {
505     //Error
506   }
507 }
508
509 void Model3dView::Load()
510 {
511   LoadGeometry();
512   LoadMaterial();
513 }
514
515 void Model3dView::OnRelayout( const Vector2& size, RelayoutContainer& container )
516 {
517   UpdateView();
518 }
519
520 void Model3dView::UpdateView()
521 {
522   if( mObjLoader.IsSceneLoaded() )
523   {
524     //The object will always be centred
525
526     Matrix scaleMatrix;
527     scaleMatrix.SetIdentityAndScale(Vector3(1.0, -1.0, 1.0));
528
529     mShader.RegisterProperty( "uObjectMatrix", scaleMatrix );
530   }
531 }
532
533 void Model3dView::CreateGeometry()
534 {
535   if( mObjLoader.IsSceneLoaded() )
536   {
537     mMesh = mObjLoader.CreateGeometry( GetShaderProperties( mIlluminationType ), true );
538
539     if( mRenderer )
540     {
541       mRenderer.SetGeometry( mMesh );
542       mRenderer.SetProperty( Renderer::Property::DEPTH_WRITE_MODE, DepthWriteMode::ON );
543       mRenderer.SetProperty( Renderer::Property::DEPTH_TEST_MODE, DepthTestMode::ON );
544     }
545   }
546 }
547
548 void Model3dView::UpdateShaderUniforms()
549 {
550   if( mShader )
551   {
552     //Update shader related info, uniforms, etc. for the new shader
553     UpdateView();
554
555     Vector3 lightPosition( 0, 0, 0 );
556     Dali::Property::Index lightProperty = mShader.RegisterProperty( "uLightPosition", lightPosition );
557
558     CustomActor self = Self();
559
560     //create constraint for lightPosition Property with uLightPosition in the shader
561     if( lightProperty )
562     {
563       Constraint constraint = Constraint::New<Vector3>( mShader, lightProperty, EqualToConstraint() );
564       constraint.AddSource( Source( self, Toolkit::Model3dView::Property::LIGHT_POSITION ) );
565       constraint.Apply();
566     }
567   }
568 }
569
570 void Model3dView::CreateMaterial()
571 {
572   if( mObjLoader.IsMaterialLoaded() && (mTexture0Url != "") && mObjLoader.IsTexturePresent() )
573   {
574     if( (mTexture2Url != "") && (mTexture1Url != "") && (mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP) )
575     {
576       mShader = Shader::New( NRMMAP_VERTEX_SHADER, NRMMAP_FRAGMENT_SHADER );
577     }
578     else if( mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_TEXTURE ||
579              mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP )
580     {
581       mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
582     }
583     else
584     {
585       mShader = Shader::New( SIMPLE_VERTEX_SHADER, SIMPLE_FRAGMENT_SHADER );
586     }
587   }
588   else
589   {
590     mShader = Shader::New( SIMPLE_VERTEX_SHADER, SIMPLE_FRAGMENT_SHADER );
591   }
592
593   mTextureSet = TextureSet::New();
594
595   if( mRenderer )
596   {
597     mRenderer.SetTextures( mTextureSet );
598     mRenderer.SetShader( mShader );
599     mRenderer.SetProperty( Renderer::Property::FACE_CULLING_MODE, FaceCullingMode::BACK );
600   }
601
602   UpdateShaderUniforms();
603 }
604
605 void Model3dView::LoadTextures()
606 {
607   if( !mTextureSet )
608   {
609     return;
610   }
611
612   Sampler sampler = Sampler::New();
613   sampler.SetFilterMode( FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR_MIPMAP_LINEAR );
614
615   // Setup diffuse texture.
616   if( !mTexture0Url.empty() && ( mIlluminationType != Toolkit::Model3dView::DIFFUSE ) )
617   {
618     std::string imageUrl = mImagesUrl + mTexture0Url;
619
620     //Load textures
621     Texture diffuseTexture = LoadTexture( imageUrl.c_str() );
622     if( diffuseTexture )
623     {
624       mTextureSet.SetTexture( DIFFUSE_TEXTURE_INDEX, diffuseTexture );
625       mTextureSet.SetSampler( DIFFUSE_TEXTURE_INDEX, sampler );
626     }
627   }
628
629   if( mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP )
630   {
631     // Setup normal map texture.
632     if( !mTexture1Url.empty() )
633     {
634       std::string imageUrl = mImagesUrl + mTexture1Url;
635
636       //Load textures
637       Texture normalTexture = LoadTexture( imageUrl.c_str() );
638       if( normalTexture )
639       {
640         mTextureSet.SetTexture( NORMAL_TEXTURE_INDEX, normalTexture );
641         mTextureSet.SetSampler( NORMAL_TEXTURE_INDEX, sampler );
642       }
643     }
644     if( !mTexture2Url.empty() )
645     {
646       // Setup gloss map texture.
647       std::string imageUrl = mImagesUrl + mTexture2Url;
648
649       //Load textures
650       Texture glossTexture = LoadTexture( imageUrl.c_str() );
651       if( glossTexture )
652       {
653         mTextureSet.SetTexture( GLOSS_TEXTURE_INDEX, glossTexture );
654         mTextureSet.SetSampler( GLOSS_TEXTURE_INDEX, sampler );
655       }
656     }
657   }
658 }
659
660 int Model3dView::GetShaderProperties( Toolkit::Model3dView::IlluminationType illuminationType )
661 {
662   int objectProperties = 0;
663
664   if( illuminationType == Toolkit::Model3dView::DIFFUSE_WITH_TEXTURE ||
665       illuminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP )
666   {
667     objectProperties |= ObjLoader::TEXTURE_COORDINATES;
668   }
669
670   if( illuminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP )
671   {
672     objectProperties |= ObjLoader::TANGENTS | ObjLoader::BINORMALS;
673   }
674
675   return objectProperties;
676 }
677
678 } // namespace Internal
679 } // namespace Toolkit
680 } // namespace Dali