2 * Copyright (c) 2020 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/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>
32 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
33 #include <dali-toolkit/internal/controls/model3d-view/obj-loader.h>
34 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
48 // Texture indices are constants.
51 DIFFUSE_TEXTURE_INDEX,
57 * @brief Loads a texture from a file.
58 * @param[in] imageUrl The URL of the file
59 * @return A texture if loading succeeds, an empty handle otherwise
61 Texture LoadTexture( const char* imageUrl )
64 Devel::PixelBuffer pixelBuffer = LoadImageFromFile( imageUrl );
67 texture = Texture::New( TextureType::TEXTURE_2D, pixelBuffer.GetPixelFormat(), pixelBuffer.GetWidth(), pixelBuffer.GetHeight() );
68 PixelData pixelData = Devel::PixelBuffer::Convert( pixelBuffer );
69 texture.Upload( pixelData );
70 texture.GenerateMipmaps();
79 return Toolkit::Model3dView::New();
82 // Setup properties, signals and actions using the type-registry.
83 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Model3dView, Toolkit::Control, Create );
85 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "geometryUrl", STRING, GEOMETRY_URL)
86 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "materialUrl", STRING, MATERIAL_URL)
87 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "imagesUrl", STRING, IMAGES_URL)
88 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "illuminationType", INTEGER, ILLUMINATION_TYPE)
89 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "texture0Url", STRING, TEXTURE0_URL)
90 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "texture1Url", STRING, TEXTURE1_URL)
91 DALI_PROPERTY_REGISTRATION( Toolkit, Model3dView, "texture2Url", STRING, TEXTURE2_URL)
93 DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, Model3dView, "lightPosition", VECTOR3, LIGHT_POSITION)
95 DALI_TYPE_REGISTRATION_END()
97 } // anonymous namespace
101 Model3dView::Model3dView()
102 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) )
104 mIlluminationType = Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP;
106 mCameraFOV = Math::PI_OVER_180 * 45.f;
108 mControlSize = Vector2(100.,100.);
111 Model3dView::~Model3dView()
115 Toolkit::Model3dView Model3dView::New()
117 Model3dView* impl = new Model3dView();
119 Dali::Toolkit::Model3dView handle = Dali::Toolkit::Model3dView( *impl );
121 // Second-phase init of the implementation
122 // This can only be done after the CustomActor connection has been made...
128 void Model3dView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
130 Toolkit::Model3dView model3dView = Toolkit::Model3dView::DownCast( Dali::BaseHandle( object ) );
134 Model3dView& impl( GetImpl( model3dView ) );
137 case Toolkit::Model3dView::Property::GEOMETRY_URL:
139 if( value.Get(impl.mObjUrl) )
142 impl.CreateGeometry();
146 case Toolkit::Model3dView::Property::MATERIAL_URL:
148 if( value.Get(impl.mTextureSetUrl) )
151 impl.CreateMaterial();
156 case Toolkit::Model3dView::Property::IMAGES_URL:
158 if( value.Get(impl.mImagesUrl) )
164 case Toolkit::Model3dView::Property::ILLUMINATION_TYPE:
166 int illuminationType;
167 if( value.Get(illuminationType) )
169 impl.mIlluminationType = Toolkit::Model3dView::IlluminationType(illuminationType);
170 impl.CreateGeometry();
171 impl.CreateMaterial();
176 case Toolkit::Model3dView::Property::TEXTURE0_URL:
178 value.Get(impl.mTexture0Url);
181 case Toolkit::Model3dView::Property::TEXTURE1_URL:
183 value.Get(impl.mTexture1Url);
186 case Toolkit::Model3dView::Property::TEXTURE2_URL:
188 value.Get(impl.mTexture2Url);
195 Property::Value Model3dView::GetProperty( BaseObject* object, Property::Index index )
197 Property::Value value;
199 Toolkit::Model3dView model3dView = Toolkit::Model3dView::DownCast( Dali::BaseHandle( object ) );
203 Model3dView& impl( GetImpl( model3dView ) );
206 case Toolkit::Model3dView::Property::GEOMETRY_URL:
208 value = impl.mObjUrl;
211 case Toolkit::Model3dView::Property::MATERIAL_URL:
213 value = impl.mTextureSetUrl;
216 case Toolkit::Model3dView::Property::IMAGES_URL:
218 value = impl.mImagesUrl;
221 case Toolkit::Model3dView::Property::ILLUMINATION_TYPE:
223 value = int(impl.mIlluminationType);
226 case Toolkit::Model3dView::Property::TEXTURE0_URL:
228 value = impl.mTexture0Url;
231 case Toolkit::Model3dView::Property::TEXTURE1_URL:
233 value = impl.mTexture1Url;
236 case Toolkit::Model3dView::Property::TEXTURE2_URL:
238 value = impl.mTexture2Url;
247 /////////////////////////////////////////////////////////////
250 void Model3dView::OnSceneConnection( int depth )
252 CustomActor self = Self();
253 self.AddRenderer( mRenderer );
255 if( mObjLoader.IsSceneLoaded() )
257 mMesh = mObjLoader.CreateGeometry( GetShaderProperties( mIlluminationType ), true );
262 mRenderer.SetGeometry( mMesh );
264 //create constraint for lightPosition Property with uLightPosition in the shader
265 Vector3 lightPosition( 0, 0, 0 );
266 Dali::Property::Index lightProperty = mShader.RegisterProperty( "uLightPosition", lightPosition );
267 Constraint constraint = Constraint::New<Vector3>( mShader, lightProperty, EqualToConstraint() );
268 constraint.AddSource( Source( self, Toolkit::Model3dView::Property::LIGHT_POSITION ) );
272 Control::OnSceneConnection( depth );
275 ///////////////////////////////////////////////////////////
280 void Model3dView::OnInitialize()
282 //Create empty versions of the geometry and material so we always have a Renderer
283 Geometry mesh = Geometry::New();
284 Shader shader = Shader::New( SHADER_MODEL3D_VIEW_SIMPLE_SHADER_VERT, SHADER_MODEL3D_VIEW_SIMPLE_SHADER_FRAG );
285 mRenderer = Renderer::New( mesh, shader );
287 DevelControl::SetAccessibilityConstructor( Self(), []( Dali::Actor actor ) {
288 return std::unique_ptr< Dali::Accessibility::Accessible >(
289 new Control::Impl::AccessibleImpl( actor, Dali::Accessibility::Role::IMAGE ) );
293 void Model3dView::LoadGeometry()
295 //Load file in adaptor
296 std::streampos fileSize;
297 Dali::Vector<char> fileContent;
299 if (FileLoader::ReadFile(mObjUrl,fileSize,fileContent,FileLoader::TEXT))
301 mObjLoader.ClearArrays();
302 mObjLoader.LoadObject(fileContent.Begin(), fileSize);
304 //Get size information from the obj loaded
305 mSceneCenter = mObjLoader.GetCenter();
306 mSceneSize = mObjLoader.GetSize();
314 void Model3dView::LoadMaterial()
316 //Load file in adaptor
317 std::streampos fileSize;
318 Dali::Vector<char> fileContent;
320 if( FileLoader::ReadFile(mTextureSetUrl, fileSize, fileContent, FileLoader::TEXT) )
322 mObjLoader.LoadMaterial(fileContent.Begin(), fileSize, mTexture0Url, mTexture1Url, mTexture2Url);
330 void Model3dView::Load()
336 void Model3dView::OnRelayout( const Vector2& size, RelayoutContainer& container )
341 void Model3dView::UpdateView()
343 if( mObjLoader.IsSceneLoaded() )
345 //The object will always be centred
348 scaleMatrix.SetIdentityAndScale(Vector3(1.0, -1.0, 1.0));
350 mShader.RegisterProperty( "uObjectMatrix", scaleMatrix );
354 void Model3dView::CreateGeometry()
356 if( mObjLoader.IsSceneLoaded() )
358 mMesh = mObjLoader.CreateGeometry( GetShaderProperties( mIlluminationType ), true );
362 mRenderer.SetGeometry( mMesh );
363 mRenderer.SetProperty( Renderer::Property::DEPTH_WRITE_MODE, DepthWriteMode::ON );
364 mRenderer.SetProperty( Renderer::Property::DEPTH_TEST_MODE, DepthTestMode::ON );
369 void Model3dView::UpdateShaderUniforms()
373 //Update shader related info, uniforms, etc. for the new shader
376 Vector3 lightPosition( 0, 0, 0 );
377 Dali::Property::Index lightProperty = mShader.RegisterProperty( "uLightPosition", lightPosition );
379 CustomActor self = Self();
381 //create constraint for lightPosition Property with uLightPosition in the shader
384 Constraint constraint = Constraint::New<Vector3>( mShader, lightProperty, EqualToConstraint() );
385 constraint.AddSource( Source( self, Toolkit::Model3dView::Property::LIGHT_POSITION ) );
391 void Model3dView::CreateMaterial()
393 if( mObjLoader.IsMaterialLoaded() && (mTexture0Url != "") && mObjLoader.IsTexturePresent() )
395 if( (mTexture2Url != "") && (mTexture1Url != "") && (mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP) )
397 mShader = Shader::New( SHADER_MODEL3D_VIEW_NRMMAP_SHADER_VERT, SHADER_MODEL3D_VIEW_NRMMAP_SHADER_FRAG );
399 else if( mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_TEXTURE ||
400 mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP )
402 mShader = Shader::New( SHADER_MODEL3D_VIEW_SHADER_VERT, SHADER_MODEL3D_VIEW_SHADER_FRAG );
406 mShader = Shader::New( SHADER_MODEL3D_VIEW_SIMPLE_SHADER_VERT, SHADER_MODEL3D_VIEW_SIMPLE_SHADER_FRAG );
411 mShader = Shader::New( SHADER_MODEL3D_VIEW_SIMPLE_SHADER_VERT, SHADER_MODEL3D_VIEW_SIMPLE_SHADER_FRAG );
414 mTextureSet = TextureSet::New();
418 mRenderer.SetTextures( mTextureSet );
419 mRenderer.SetShader( mShader );
420 mRenderer.SetProperty( Renderer::Property::FACE_CULLING_MODE, FaceCullingMode::BACK );
423 UpdateShaderUniforms();
426 void Model3dView::LoadTextures()
433 Sampler sampler = Sampler::New();
434 sampler.SetFilterMode( FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR_MIPMAP_LINEAR );
436 // Setup diffuse texture.
437 if( !mTexture0Url.empty() && ( mIlluminationType != Toolkit::Model3dView::DIFFUSE ) )
439 std::string imageUrl = mImagesUrl + mTexture0Url;
442 Texture diffuseTexture = LoadTexture( imageUrl.c_str() );
445 mTextureSet.SetTexture( DIFFUSE_TEXTURE_INDEX, diffuseTexture );
446 mTextureSet.SetSampler( DIFFUSE_TEXTURE_INDEX, sampler );
450 if( mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP )
452 // Setup normal map texture.
453 if( !mTexture1Url.empty() )
455 std::string imageUrl = mImagesUrl + mTexture1Url;
458 Texture normalTexture = LoadTexture( imageUrl.c_str() );
461 mTextureSet.SetTexture( NORMAL_TEXTURE_INDEX, normalTexture );
462 mTextureSet.SetSampler( NORMAL_TEXTURE_INDEX, sampler );
465 if( !mTexture2Url.empty() )
467 // Setup gloss map texture.
468 std::string imageUrl = mImagesUrl + mTexture2Url;
471 Texture glossTexture = LoadTexture( imageUrl.c_str() );
474 mTextureSet.SetTexture( GLOSS_TEXTURE_INDEX, glossTexture );
475 mTextureSet.SetSampler( GLOSS_TEXTURE_INDEX, sampler );
481 int Model3dView::GetShaderProperties( Toolkit::Model3dView::IlluminationType illuminationType )
483 int objectProperties = 0;
485 if( illuminationType == Toolkit::Model3dView::DIFFUSE_WITH_TEXTURE ||
486 illuminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP )
488 objectProperties |= ObjLoader::TEXTURE_COORDINATES;
491 if( illuminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP )
493 objectProperties |= ObjLoader::TANGENTS | ObjLoader::BINORMALS;
496 return objectProperties;
499 } // namespace Internal
500 } // namespace Toolkit