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, "geometry-url", STRING, GEOMETRY_URL)
56 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "material-url", STRING, MATERIAL_URL)
57 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "images-url", STRING, IMAGES_URL)
58 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "illumination-type", INTEGER, ILLUMINATION_TYPE)
59 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "texture0-url", STRING, TEXTURE0_URL)
60 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "texture1-url", STRING, TEXTURE1_URL)
61 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "texture2-url", STRING, TEXTURE2_URL)
63 DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, Model3dView, "light-position", 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 vertPos4 = uModelView * vec4(aPosition.xyz, 1.0);\n
92 vec3 vertPos = vec3(vertPos4) / vertPos4.w;\n
94 vec3 normalInterp = uNormalMatrix * aNormal;\n
96 vec4 lightPos4 = uModelView * vec4(uLightPosition, 1.0);\n
97 vec3 lightPos = vec3(lightPos4) / lightPos4.w;\n
99 vec3 vecToLight = normalize( lightPos.xyz - vertPos.xyz );\n
101 float lightDiffuse = dot( vecToLight, normalInterp );\n
102 lightDiffuse = max(0.0,lightDiffuse);\n
103 vIllumination = vec3(lightDiffuse * 0.5 + 0.5);\n
105 gl_Position = vertexPosition;\n
109 const char* SIMPLE_FRAGMENT_SHADER = MAKE_SHADER(
110 precision mediump float;\n
111 varying mediump vec3 vIllumination;\n
112 uniform lowp vec4 uColor;\n
116 gl_FragColor.rgb = vIllumination.rgb * uColor.rgb;\n
117 gl_FragColor.a = uColor.a;\n
121 // Diffuse and specular illumination shader with albedo texture
123 const char* VERTEX_SHADER = MAKE_SHADER(
124 attribute highp vec3 aPosition;\n
125 attribute highp vec2 aTexCoord;\n
126 attribute highp vec3 aNormal;\n
127 varying mediump vec2 vTexCoord;\n
128 varying mediump vec3 vIllumination;\n
129 varying mediump float vSpecular;\n
130 uniform mediump vec3 uSize;\n
131 uniform mediump mat4 uMvpMatrix;\n
132 uniform mediump mat4 uModelView;
133 uniform mediump mat3 uNormalMatrix;
134 uniform mediump mat4 uObjectMatrix;\n
135 uniform mediump vec3 uLightPosition;\n
139 vec4 vertexPosition = vec4(aPosition*min(uSize.x, uSize.y), 1.0);\n
140 vertexPosition = uObjectMatrix * vertexPosition;\n
141 vertexPosition = uMvpMatrix * vertexPosition;\n
143 //Illumination in Model-View space - Transform attributes and uniforms\n
144 vec4 vertPos4 = uModelView * vec4(aPosition.xyz, 1.0);\n
145 vec3 vertPos = vec3(vertPos4) / vertPos4.w;\n
147 vec4 lightPos4 = uModelView * vec4(uLightPosition, 1.0);\n
148 vec3 lightPos = vec3(lightPos4) / lightPos4.w;\n
150 vec3 normalInterp = normalize(uNormalMatrix * aNormal);\n
152 vec3 vecToLight = normalize( lightPos.xyz - vertPos.xyz );\n
153 vec3 viewDir = normalize(-vertPos);
155 vec3 halfVector = normalize(viewDir + vecToLight);
157 float lightDiffuse = dot( vecToLight, normalInterp );\n
158 lightDiffuse = max(0.0,lightDiffuse);\n
159 vIllumination = vec3(lightDiffuse * 0.5 + 0.5);\n
161 // this is blinn phong
162 //float specAngle = max(dot(halfVector, normalInterp), 0.0);\n
163 //vSpecular = pow(specAngle, 16.0);\n
165 // this is phong (for comparison)
166 vec3 reflectDir = reflect(-vecToLight, normalInterp);
167 float specAngle = max(dot(reflectDir, viewDir), 0.0);
168 // note that the exponent is different here
169 vSpecular = pow(specAngle, 16.0/4.0);
171 vTexCoord = aTexCoord;\n
172 gl_Position = vertexPosition;\n
176 const char* FRAGMENT_SHADER = MAKE_SHADER(
177 precision mediump float;\n
178 varying mediump vec2 vTexCoord;\n
179 varying mediump vec3 vIllumination;\n
180 varying mediump float vSpecular;\n
181 uniform sampler2D sDiffuse;\n
182 uniform lowp vec4 uColor;\n
186 vec4 texture = texture2D( sDiffuse, vTexCoord );\n
187 gl_FragColor.rgb = vIllumination.rgb * texture.rgb * uColor.rgb + vSpecular * 0.3;\n
188 gl_FragColor.a = texture.a * uColor.a;\n
192 // Diffuse and specular illumination shader with albedo texture, normal map and gloss map shader
194 const char* NRMMAP_VERTEX_SHADER = MAKE_SHADER(
195 attribute highp vec3 aPosition;\n
196 attribute highp vec2 aTexCoord;\n
197 attribute highp vec3 aNormal;\n
198 attribute highp vec3 aTangent;\n
199 attribute highp vec3 aBiNormal;\n
200 varying mediump vec2 vTexCoord;\n
201 varying mediump vec3 vLightDirection;\n
202 varying mediump vec3 vHalfVector;\n
203 uniform mediump vec3 uSize;\n
204 uniform mediump mat4 uMvpMatrix;\n
205 uniform mediump mat4 uModelView;
206 uniform mediump mat3 uNormalMatrix;
207 uniform mediump mat4 uObjectMatrix;\n
208 uniform mediump vec3 uLightPosition;\n
212 vec4 vertexPosition = vec4(aPosition*min(uSize.x, uSize.y), 1.0);\n
213 vertexPosition = uObjectMatrix * vertexPosition;\n
214 vertexPosition = uMvpMatrix * vertexPosition;\n
216 vTexCoord = aTexCoord;\n
218 vec3 vNormal = normalize(uNormalMatrix * aNormal);\n
219 vec3 vTangent = normalize(uNormalMatrix * aTangent);\n
220 vec3 vBiNormal = normalize(uNormalMatrix * aBiNormal);\n
222 vec4 vertPos4 = uModelView * vec4(aPosition.xyz, 1.0);\n
223 vec3 vertPos = vec3(vertPos4) / vertPos4.w;\n
225 vec4 lightPos4 = uModelView * vec4(uLightPosition, 1.0);\n
226 vec3 lightPos = vec3(lightPos4) / lightPos4.w;\n
228 vec3 vecToLight = lightPos - vertPos;
229 vLightDirection.x = dot(vecToLight, vTangent);
230 vLightDirection.y = dot(vecToLight, vBiNormal);
231 vLightDirection.z = dot(vecToLight, vNormal);
232 vLightDirection = normalize(vLightDirection);
234 vec3 viewDir = normalize(vertPos);
236 vec3 halfVector = normalize(viewDir + vecToLight);
237 vHalfVector.x = dot (halfVector, vTangent);
238 vHalfVector.y = dot (halfVector, vBiNormal);
239 vHalfVector.z = dot (halfVector, vNormal);
241 gl_Position = vertexPosition;\n
243 //vHalfVector = aTangent;
247 const char* NRMMAP_FRAGMENT_SHADER = MAKE_SHADER(
248 precision mediump float;\n
249 varying mediump vec2 vTexCoord;\n
250 varying mediump vec3 vLightDirection;\n
251 varying mediump vec3 vHalfVector;\n
252 uniform sampler2D sDiffuse;\n
253 uniform sampler2D sNormal;\n
254 uniform sampler2D sGloss;\n
255 uniform lowp vec4 uColor;\n
259 vec4 texture = texture2D( sDiffuse, vTexCoord );\n
260 vec4 nrmMap = texture2D( sNormal, vTexCoord ) * 2.0 - 1.0;\n
261 vec4 glossMap = texture2D( sGloss, vTexCoord );\n
263 vec3 normalizedLightDirection = normalize(vLightDirection);\n
264 float lightDiffuse = max( 0.0, dot( nrmMap.xyz, normalizedLightDirection ) );\n
265 lightDiffuse = lightDiffuse * 0.5 + 0.5;\n
267 float shininess = pow (max (dot (vHalfVector, nrmMap.xyz), 0.0), 16.0) ;
269 gl_FragColor.rgb = texture.rgb * uColor.rgb * lightDiffuse + shininess * glossMap.rgb;\n
270 gl_FragColor.a = texture.a * uColor.a;\n
272 //gl_FragColor.rgb = vHalfVector.rgb;
277 } // anonymous namespace
279 using namespace Dali;
281 void LookAt(Matrix& result, const Vector3& eye, const Vector3& target, const Vector3& up)
283 Vector3 vZ = target - eye;
286 Vector3 vX = up.Cross(vZ);
289 Vector3 vY = vZ.Cross(vX);
292 result.SetInverseTransformComponents(vX, vY, vZ, eye);
296 Model3dView::Model3dView()
297 : Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) )
303 mIlluminationType = Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP;
305 mCameraFOV = Math::PI_OVER_180 * 45.f;
307 mControlSize = Vector2(100.,100.);
310 Model3dView::~Model3dView()
314 Toolkit::Model3dView Model3dView::New()
316 Model3dView* impl = new Model3dView();
318 Dali::Toolkit::Model3dView handle = Dali::Toolkit::Model3dView( *impl );
320 // Second-phase init of the implementation
321 // This can only be done after the CustomActor connection has been made...
327 void Model3dView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
329 Toolkit::Model3dView model3dView = Toolkit::Model3dView::DownCast( Dali::BaseHandle( object ) );
333 Model3dView& impl( GetImpl( model3dView ) );
336 case Toolkit::Model3dView::Property::GEOMETRY_URL:
338 if( value.Get(impl.mObjUrl) )
341 impl.CreateGeometry();
345 case Toolkit::Model3dView::Property::MATERIAL_URL:
347 if( value.Get(impl.mMaterialUrl) )
350 impl.CreateMaterial();
354 case Toolkit::Model3dView::Property::IMAGES_URL:
356 if( value.Get(impl.mImagesUrl) )
362 case Toolkit::Model3dView::Property::ILLUMINATION_TYPE:
364 int illuminationType;
365 if( value.Get(illuminationType) )
367 impl.mIlluminationType = Toolkit::Model3dView::IlluminationType(illuminationType);
368 impl.CreateGeometry();
369 impl.CreateMaterial();
374 case Toolkit::Model3dView::Property::TEXTURE0_URL:
376 value.Get(impl.mTexture0Url);
379 case Toolkit::Model3dView::Property::TEXTURE1_URL:
381 value.Get(impl.mTexture1Url);
384 case Toolkit::Model3dView::Property::TEXTURE2_URL:
386 value.Get(impl.mTexture2Url);
393 Property::Value Model3dView::GetProperty( BaseObject* object, Property::Index index )
395 Property::Value value;
397 Toolkit::Model3dView model3dView = Toolkit::Model3dView::DownCast( Dali::BaseHandle( object ) );
401 Model3dView& impl( GetImpl( model3dView ) );
404 case Toolkit::Model3dView::Property::GEOMETRY_URL:
406 value = impl.mObjUrl;
409 case Toolkit::Model3dView::Property::MATERIAL_URL:
411 value = impl.mMaterialUrl;
414 case Toolkit::Model3dView::Property::IMAGES_URL:
416 value = impl.mImagesUrl;
419 case Toolkit::Model3dView::Property::ILLUMINATION_TYPE:
421 value = int(impl.mIlluminationType);
424 case Toolkit::Model3dView::Property::TEXTURE0_URL:
426 value = impl.mTexture0Url;
429 case Toolkit::Model3dView::Property::TEXTURE1_URL:
431 value = impl.mTexture1Url;
434 case Toolkit::Model3dView::Property::TEXTURE2_URL:
436 value = impl.mTexture2Url;
445 /////////////////////////////////////////////////////////////
448 void Model3dView::OnStageConnection( int depth )
450 CustomActor self = Self();
451 self.AddRenderer( mRenderer );
453 if( mObjLoader.IsSceneLoaded() )
455 mMesh = mObjLoader.CreateGeometry(mIlluminationType);
460 mRenderer.SetGeometry( mMesh );
462 //create constraint for lightPosition Property with uLightPosition in the shader
463 Vector3 lightPosition( 0, 0, 0 );
464 Dali::Property::Index lightProperty = mShader.RegisterProperty( "uLightPosition", lightPosition );
465 Constraint constraint = Constraint::New<Vector3>( mShader, lightProperty, EqualToConstraint() );
466 constraint.AddSource( Source( self, Toolkit::Model3dView::Property::LIGHT_POSITION ) );
471 ///////////////////////////////////////////////////////////
476 void Model3dView::OnInitialize()
478 //Create empty versions of the geometry and material so we always have a Renderer
479 Geometry mesh = Geometry::New();
480 Shader shader = Shader::New( SIMPLE_VERTEX_SHADER, SIMPLE_FRAGMENT_SHADER, (Shader::ShaderHints)(Shader::HINT_REQUIRES_SELF_DEPTH_TEST | Shader::HINT_MODIFIES_GEOMETRY) );
481 Material material = Material::New( shader );
482 mRenderer = Renderer::New( mesh, material );
485 void Model3dView::LoadGeometry()
487 //Load file in adaptor
488 std::streampos fileSize;
489 Dali::Vector<char> fileContent;
491 if (FileLoader::ReadFile(mObjUrl,fileSize,fileContent,FileLoader::TEXT))
493 mObjLoader.ClearArrays();
495 std::string materialUrl;
496 mObjLoader.Load(fileContent.Begin(), fileSize, materialUrl);
498 //Get size information from the obj loaded
499 mSceneCenter = mObjLoader.GetCenter();
500 mSceneSize = mObjLoader.GetSize();
508 void Model3dView::LoadMaterial()
510 //Load file in adaptor
511 std::streampos fileSize;
512 Dali::Vector<char> fileContent;
514 if( FileLoader::ReadFile(mMaterialUrl, fileSize, fileContent, FileLoader::TEXT) )
516 mObjLoader.LoadMaterial(fileContent.Begin(), fileSize, mTexture0Url, mTexture1Url, mTexture2Url);
524 void Model3dView::Load()
530 void Model3dView::OnRelayout( const Vector2& size, RelayoutContainer& container )
535 void Model3dView::UpdateView()
537 if( mObjLoader.IsSceneLoaded() )
539 //The object will always be centred
542 scaleMatrix.SetIdentityAndScale(Vector3(1.0, -1.0, 1.0));
544 mShader.RegisterProperty( "uObjectMatrix", scaleMatrix );
548 void Model3dView::CreateGeometry()
550 if( mObjLoader.IsSceneLoaded() )
552 mMesh = mObjLoader.CreateGeometry(mIlluminationType);
556 mRenderer.SetGeometry( mMesh );
561 void Model3dView::UpdateShaderUniforms()
565 //Update shader related info, uniforms, etc. for the new shader
568 Vector3 lightPosition( 0, 0, 0 );
569 Dali::Property::Index lightProperty = mShader.RegisterProperty( "uLightPosition", lightPosition );
571 CustomActor self = Self();
573 //create constraint for lightPosition Property with uLightPosition in the shader
576 Constraint constraint = Constraint::New<Vector3>( mShader, lightProperty, EqualToConstraint() );
577 constraint.AddSource( Source( self, Toolkit::Model3dView::Property::LIGHT_POSITION ) );
583 void Model3dView::CreateMaterial()
585 if( mObjLoader.IsMaterialLoaded() && (mTexture0Url != ""))
587 if( (mTexture2Url != "") && (mTexture1Url != "") && (mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP))
589 mShader = Shader::New( NRMMAP_VERTEX_SHADER, NRMMAP_FRAGMENT_SHADER, (Shader::ShaderHints)(Shader::HINT_REQUIRES_SELF_DEPTH_TEST | Shader::HINT_MODIFIES_GEOMETRY) );
591 else if(mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_TEXTURE)
593 mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER, (Shader::ShaderHints)(Shader::HINT_REQUIRES_SELF_DEPTH_TEST | Shader::HINT_MODIFIES_GEOMETRY) );
597 mShader = Shader::New( SIMPLE_VERTEX_SHADER, SIMPLE_FRAGMENT_SHADER, (Shader::ShaderHints)(Shader::HINT_REQUIRES_SELF_DEPTH_TEST | Shader::HINT_MODIFIES_GEOMETRY) );
602 mShader = Shader::New( SIMPLE_VERTEX_SHADER, SIMPLE_FRAGMENT_SHADER, (Shader::ShaderHints)(Shader::HINT_REQUIRES_SELF_DEPTH_TEST | Shader::HINT_MODIFIES_GEOMETRY) );
605 mMaterial = Material::New( mShader );
607 mMaterial.SetFaceCullingMode(Material::NONE);
611 mRenderer.SetMaterial( mMaterial );
614 UpdateShaderUniforms();
617 void Model3dView::LoadTextures()
622 if( mTexture0Url != "" )
624 std::string imgUrl = mImagesUrl + mTexture0Url;
627 Image tex0 = ResourceImage::New( imgUrl );
630 size_t index = mMaterial.AddTexture( tex0, "sDiffuse" );
631 mMaterial.SetTextureAffectsTransparency(index, false );
635 if( (mTexture1Url != "") && (mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP) )
637 std::string imgUrl = mImagesUrl + mTexture1Url;
640 Image tex1 = ResourceImage::New( imgUrl );
643 size_t index = mMaterial.AddTexture( tex1, "sNormal" );
644 mMaterial.SetTextureAffectsTransparency(index, false );
648 if( (mTexture2Url != "") && (mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP) )
650 std::string imgUrl = mImagesUrl + mTexture2Url;
653 Image tex2 = ResourceImage::New( imgUrl );
656 size_t index = mMaterial.AddTexture( tex2, "sGloss" );
657 mMaterial.SetTextureAffectsTransparency(index, false );
662 } // namespace Internal
663 } // namespace Toolkit