2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include "model3d-view-impl.h"
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/devel-api/object/type-registry-helper.h>
27 #include <dali-toolkit/public-api/controls/model3d-view/model3d-view.h>
28 #include <dali/public-api/images/resource-image.h>
29 #include <dali/devel-api/adaptor-framework/file-loader.h>
32 #include <dali-toolkit/internal/controls/model3d-view/obj-loader.h>
49 return Toolkit::Model3dView::New();
52 // Setup properties, signals and actions using the type-registry.
53 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Model3dView, Toolkit::Control, Create );
55 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "geometryUrl", STRING, GEOMETRY_URL)
56 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "materialUrl", STRING, MATERIAL_URL)
57 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "imagesUrl", STRING, IMAGES_URL)
58 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "illuminationType", INTEGER, ILLUMINATION_TYPE)
59 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "texture0Url", STRING, TEXTURE0_URL)
60 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "texture1Url", STRING, TEXTURE1_URL)
61 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "texture2Url", STRING, TEXTURE2_URL)
63 DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, Model3dView, "lightPosition", VECTOR3, LIGHT_POSITION)
65 DALI_TYPE_REGISTRATION_END()
68 #define MAKE_SHADER(A)#A
70 // Diffuse illumination shader
72 const char* SIMPLE_VERTEX_SHADER = MAKE_SHADER(
73 attribute highp vec3 aPosition;\n
74 attribute highp vec2 aTexCoord;\n
75 attribute highp vec3 aNormal;\n
76 varying mediump vec3 vIllumination;\n
77 uniform mediump vec3 uSize;\n
78 uniform mediump mat4 uMvpMatrix;\n
79 uniform mediump mat4 uModelView;\n
80 uniform mediump mat3 uNormalMatrix;
81 uniform mediump mat4 uObjectMatrix;\n
82 uniform mediump vec3 uLightPosition;\n
86 vec4 vertexPosition = vec4(aPosition*min(uSize.x, uSize.y), 1.0);\n
87 vertexPosition = uObjectMatrix * vertexPosition;\n
88 vertexPosition = uMvpMatrix * vertexPosition;\n
90 //Illumination in Model-View space - Transform attributes and uniforms\n
91 vec4 vertPos = uModelView * vec4(aPosition.xyz, 1.0);\n
92 vec3 normal = uNormalMatrix * aNormal;\n
93 vec4 lightPos = uModelView * vec4(uLightPosition, 1.0);\n
94 vec3 vecToLight = normalize( lightPos.xyz - vertPos.xyz );\n
96 float lightDiffuse = max( dot( vecToLight, normal ), 0.0 );\n
97 vIllumination = vec3(lightDiffuse * 0.5 + 0.5);\n
99 gl_Position = vertexPosition;\n
103 const char* SIMPLE_FRAGMENT_SHADER = MAKE_SHADER(
104 precision mediump float;\n
105 varying mediump vec3 vIllumination;\n
106 uniform lowp vec4 uColor;\n
110 gl_FragColor = vec4( vIllumination.rgb * uColor.rgb, uColor.a);\n
114 // Diffuse and specular illumination shader with albedo texture
116 const char* VERTEX_SHADER = MAKE_SHADER(
117 attribute highp vec3 aPosition;\n
118 attribute highp vec2 aTexCoord;\n
119 attribute highp vec3 aNormal;\n
120 varying mediump vec2 vTexCoord;\n
121 varying mediump vec3 vIllumination;\n
122 varying mediump float vSpecular;\n
123 uniform mediump vec3 uSize;\n
124 uniform mediump mat4 uMvpMatrix;\n
125 uniform mediump mat4 uModelView;
126 uniform mediump mat3 uNormalMatrix;
127 uniform mediump mat4 uObjectMatrix;\n
128 uniform mediump vec3 uLightPosition;\n
132 vec4 vertexPosition = vec4(aPosition*min(uSize.x, uSize.y), 1.0);\n
133 vertexPosition = uObjectMatrix * vertexPosition;\n
134 vertexPosition = uMvpMatrix * vertexPosition;\n
136 //Illumination in Model-View space - Transform attributes and uniforms\n
137 vec4 vertPos = uModelView * vec4(aPosition.xyz, 1.0);\n
138 vec4 lightPos = uModelView * vec4(uLightPosition, 1.0);\n
139 vec3 normal = normalize(uNormalMatrix * aNormal);\n
141 vec3 vecToLight = normalize( lightPos.xyz - vertPos.xyz );\n
142 vec3 viewDir = normalize(-vertPos.xyz);
144 vec3 halfVector = normalize(viewDir + vecToLight);
146 float lightDiffuse = dot( vecToLight, normal );\n
147 lightDiffuse = max(0.0,lightDiffuse);\n
148 vIllumination = vec3(lightDiffuse * 0.5 + 0.5);\n
150 vec3 reflectDir = reflect(-vecToLight, normal);
151 vSpecular = pow( max(dot(reflectDir, viewDir), 0.0), 4.0 );
153 vTexCoord = aTexCoord;\n
154 gl_Position = vertexPosition;\n
158 const char* FRAGMENT_SHADER = MAKE_SHADER(
159 precision mediump float;\n
160 varying mediump vec2 vTexCoord;\n
161 varying mediump vec3 vIllumination;\n
162 varying mediump float vSpecular;\n
163 uniform sampler2D sDiffuse;\n
164 uniform lowp vec4 uColor;\n
168 vec4 texture = texture2D( sDiffuse, vTexCoord );\n
169 gl_FragColor = vec4( vIllumination.rgb * texture.rgb * uColor.rgb + vSpecular * 0.3, texture.a * uColor.a);\n
173 // Diffuse and specular illumination shader with albedo texture, normal map and gloss map shader
175 const char* NRMMAP_VERTEX_SHADER = MAKE_SHADER(
176 attribute highp vec3 aPosition;\n
177 attribute highp vec2 aTexCoord;\n
178 attribute highp vec3 aNormal;\n
179 attribute highp vec3 aTangent;\n
180 attribute highp vec3 aBiNormal;\n
181 varying mediump vec2 vTexCoord;\n
182 varying mediump vec3 vLightDirection;\n
183 varying mediump vec3 vHalfVector;\n
184 uniform mediump vec3 uSize;\n
185 uniform mediump mat4 uMvpMatrix;\n
186 uniform mediump mat4 uModelView;
187 uniform mediump mat3 uNormalMatrix;
188 uniform mediump mat4 uObjectMatrix;\n
189 uniform mediump vec3 uLightPosition;\n
193 vec4 vertexPosition = vec4(aPosition*min(uSize.x, uSize.y), 1.0);\n
194 vertexPosition = uObjectMatrix * vertexPosition;\n
195 vertexPosition = uMvpMatrix * vertexPosition;\n
197 vec4 vertPos = uModelView * vec4(aPosition.xyz, 1.0);\n
198 vec4 lightPos = uModelView * vec4(uLightPosition, 1.0);\n
200 vec3 tangent = normalize(uNormalMatrix * aTangent);
201 vec3 binormal = normalize(uNormalMatrix * aBiNormal);
202 vec3 normal = normalize(uNormalMatrix * aNormal);
204 vec3 vecToLight = normalize( lightPos.xyz - vertPos.xyz );\n
205 vLightDirection.x = dot(vecToLight, tangent);
206 vLightDirection.y = dot(vecToLight, binormal);
207 vLightDirection.z = dot(vecToLight, normal);
209 vec3 viewDir = normalize(-vertPos.xyz);
210 vec3 halfVector = normalize(viewDir + vecToLight);
211 vHalfVector.x = dot(halfVector, tangent);
212 vHalfVector.y = dot(halfVector, binormal);
213 vHalfVector.z = dot(halfVector, normal);
215 vTexCoord = aTexCoord;\n
216 gl_Position = vertexPosition;\n
220 const char* NRMMAP_FRAGMENT_SHADER = MAKE_SHADER(
221 precision mediump float;\n
222 varying mediump vec2 vTexCoord;\n
223 varying mediump vec3 vLightDirection;\n
224 varying mediump vec3 vHalfVector;\n
225 uniform sampler2D sDiffuse;\n
226 uniform sampler2D sNormal;\n
227 uniform sampler2D sGloss;\n
228 uniform lowp vec4 uColor;\n
232 vec4 texture = texture2D( sDiffuse, vTexCoord );\n
233 vec3 normal = normalize( texture2D( sNormal, vTexCoord ).xyz * 2.0 - 1.0 );\n
234 vec4 glossMap = texture2D( sGloss, vTexCoord );\n
236 float lightDiffuse = max( 0.0, dot( normal, normalize(vLightDirection) ) );\n
237 lightDiffuse = lightDiffuse * 0.5 + 0.5;\n
239 float shininess = pow (max (dot (normalize( vHalfVector ), normal), 0.0), 16.0) ;
241 gl_FragColor = vec4( texture.rgb * uColor.rgb * lightDiffuse + shininess * glossMap.rgb, texture.a * uColor.a);\n
246 } // anonymous namespace
248 using namespace Dali;
250 void LookAt(Matrix& result, const Vector3& eye, const Vector3& target, const Vector3& up)
252 Vector3 vZ = target - eye;
255 Vector3 vX = up.Cross(vZ);
258 Vector3 vY = vZ.Cross(vX);
261 result.SetInverseTransformComponents(vX, vY, vZ, eye);
265 Model3dView::Model3dView()
266 : Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) )
272 mIlluminationType = Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP;
274 mCameraFOV = Math::PI_OVER_180 * 45.f;
276 mControlSize = Vector2(100.,100.);
279 Model3dView::~Model3dView()
283 Toolkit::Model3dView Model3dView::New()
285 Model3dView* impl = new Model3dView();
287 Dali::Toolkit::Model3dView handle = Dali::Toolkit::Model3dView( *impl );
289 // Second-phase init of the implementation
290 // This can only be done after the CustomActor connection has been made...
296 void Model3dView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
298 Toolkit::Model3dView model3dView = Toolkit::Model3dView::DownCast( Dali::BaseHandle( object ) );
302 Model3dView& impl( GetImpl( model3dView ) );
305 case Toolkit::Model3dView::Property::GEOMETRY_URL:
307 if( value.Get(impl.mObjUrl) )
310 impl.CreateGeometry();
314 case Toolkit::Model3dView::Property::MATERIAL_URL:
316 if( value.Get(impl.mTextureSetUrl) )
319 impl.CreateMaterial();
323 case Toolkit::Model3dView::Property::IMAGES_URL:
325 if( value.Get(impl.mImagesUrl) )
331 case Toolkit::Model3dView::Property::ILLUMINATION_TYPE:
333 int illuminationType;
334 if( value.Get(illuminationType) )
336 impl.mIlluminationType = Toolkit::Model3dView::IlluminationType(illuminationType);
337 impl.CreateGeometry();
338 impl.CreateMaterial();
343 case Toolkit::Model3dView::Property::TEXTURE0_URL:
345 value.Get(impl.mTexture0Url);
348 case Toolkit::Model3dView::Property::TEXTURE1_URL:
350 value.Get(impl.mTexture1Url);
353 case Toolkit::Model3dView::Property::TEXTURE2_URL:
355 value.Get(impl.mTexture2Url);
362 Property::Value Model3dView::GetProperty( BaseObject* object, Property::Index index )
364 Property::Value value;
366 Toolkit::Model3dView model3dView = Toolkit::Model3dView::DownCast( Dali::BaseHandle( object ) );
370 Model3dView& impl( GetImpl( model3dView ) );
373 case Toolkit::Model3dView::Property::GEOMETRY_URL:
375 value = impl.mObjUrl;
378 case Toolkit::Model3dView::Property::MATERIAL_URL:
380 value = impl.mTextureSetUrl;
383 case Toolkit::Model3dView::Property::IMAGES_URL:
385 value = impl.mImagesUrl;
388 case Toolkit::Model3dView::Property::ILLUMINATION_TYPE:
390 value = int(impl.mIlluminationType);
393 case Toolkit::Model3dView::Property::TEXTURE0_URL:
395 value = impl.mTexture0Url;
398 case Toolkit::Model3dView::Property::TEXTURE1_URL:
400 value = impl.mTexture1Url;
403 case Toolkit::Model3dView::Property::TEXTURE2_URL:
405 value = impl.mTexture2Url;
414 /////////////////////////////////////////////////////////////
417 void Model3dView::OnStageConnection( int depth )
419 Control::OnStageConnection( depth );
421 CustomActor self = Self();
422 self.AddRenderer( mRenderer );
424 if( mObjLoader.IsSceneLoaded() )
426 mMesh = mObjLoader.CreateGeometry(mIlluminationType);
431 mRenderer.SetGeometry( mMesh );
433 //create constraint for lightPosition Property with uLightPosition in the shader
434 Vector3 lightPosition( 0, 0, 0 );
435 Dali::Property::Index lightProperty = mShader.RegisterProperty( "uLightPosition", lightPosition );
436 Constraint constraint = Constraint::New<Vector3>( mShader, lightProperty, EqualToConstraint() );
437 constraint.AddSource( Source( self, Toolkit::Model3dView::Property::LIGHT_POSITION ) );
442 ///////////////////////////////////////////////////////////
447 void Model3dView::OnInitialize()
449 //Create empty versions of the geometry and material so we always have a Renderer
450 Geometry mesh = Geometry::New();
451 Shader shader = Shader::New( SIMPLE_VERTEX_SHADER, SIMPLE_FRAGMENT_SHADER );
452 mRenderer = Renderer::New( mesh, shader );
456 void Model3dView::LoadGeometry()
458 //Load file in adaptor
459 std::streampos fileSize;
460 Dali::Vector<char> fileContent;
462 if (FileLoader::ReadFile(mObjUrl,fileSize,fileContent,FileLoader::TEXT))
464 mObjLoader.ClearArrays();
466 std::string materialUrl;
467 mObjLoader.Load(fileContent.Begin(), fileSize, materialUrl);
469 //Get size information from the obj loaded
470 mSceneCenter = mObjLoader.GetCenter();
471 mSceneSize = mObjLoader.GetSize();
479 void Model3dView::LoadMaterial()
481 //Load file in adaptor
482 std::streampos fileSize;
483 Dali::Vector<char> fileContent;
485 if( FileLoader::ReadFile(mTextureSetUrl, fileSize, fileContent, FileLoader::TEXT) )
487 mObjLoader.LoadMaterial(fileContent.Begin(), fileSize, mTexture0Url, mTexture1Url, mTexture2Url);
495 void Model3dView::Load()
501 void Model3dView::OnRelayout( const Vector2& size, RelayoutContainer& container )
506 void Model3dView::UpdateView()
508 if( mObjLoader.IsSceneLoaded() )
510 //The object will always be centred
513 scaleMatrix.SetIdentityAndScale(Vector3(1.0, -1.0, 1.0));
515 mShader.RegisterProperty( "uObjectMatrix", scaleMatrix );
519 void Model3dView::CreateGeometry()
521 if( mObjLoader.IsSceneLoaded() )
523 mMesh = mObjLoader.CreateGeometry(mIlluminationType);
527 mRenderer.SetGeometry( mMesh );
528 mRenderer.SetProperty( Renderer::Property::DEPTH_WRITE_MODE, Renderer::DEPTH_WRITE_ON );
533 void Model3dView::UpdateShaderUniforms()
537 //Update shader related info, uniforms, etc. for the new shader
540 Vector3 lightPosition( 0, 0, 0 );
541 Dali::Property::Index lightProperty = mShader.RegisterProperty( "uLightPosition", lightPosition );
543 CustomActor self = Self();
545 //create constraint for lightPosition Property with uLightPosition in the shader
548 Constraint constraint = Constraint::New<Vector3>( mShader, lightProperty, EqualToConstraint() );
549 constraint.AddSource( Source( self, Toolkit::Model3dView::Property::LIGHT_POSITION ) );
555 void Model3dView::CreateMaterial()
557 if( mObjLoader.IsMaterialLoaded() && (mTexture0Url != "") && mObjLoader.IsTexturePresent() )
559 if( (mTexture2Url != "") && (mTexture1Url != "") && (mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP) && mObjLoader.IsNormalMapPresent() )
561 mShader = Shader::New( NRMMAP_VERTEX_SHADER, NRMMAP_FRAGMENT_SHADER );
563 else if( mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_TEXTURE )
565 mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
569 mShader = Shader::New( SIMPLE_VERTEX_SHADER, SIMPLE_FRAGMENT_SHADER );
574 mShader = Shader::New( SIMPLE_VERTEX_SHADER, SIMPLE_FRAGMENT_SHADER );
577 mTextureSet = TextureSet::New();
581 mRenderer.SetTextures( mTextureSet );
582 mRenderer.SetShader( mShader );
583 mRenderer.SetProperty( Renderer::Property::FACE_CULLING_MODE, Renderer::CULL_NONE);
586 UpdateShaderUniforms();
589 void Model3dView::LoadTextures()
594 if( mTexture0Url != "" )
596 std::string imgUrl = mImagesUrl + mTexture0Url;
599 Image tex0 = ResourceImage::New( imgUrl );
602 mTextureSet.SetImage( 0u, tex0 );
606 if( (mTexture1Url != "") && (mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP) )
608 std::string imgUrl = mImagesUrl + mTexture1Url;
611 Image tex1 = ResourceImage::New( imgUrl );
614 mTextureSet.SetImage( 1u, tex1 );
618 if( (mTexture2Url != "") && (mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP) )
620 std::string imgUrl = mImagesUrl + mTexture2Url;
623 Image tex2 = ResourceImage::New( imgUrl );
626 mTextureSet.SetImage( 2u, tex2 );
631 } // namespace Internal
632 } // namespace Toolkit