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