2 * Copyright (c) 2021 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-toolkit/public-api/controls/model3d-view/model3d-view.h>
23 #include <dali/devel-api/adaptor-framework/file-loader.h>
24 #include <dali/devel-api/adaptor-framework/image-loading.h>
25 #include <dali/public-api/animation/constraint-source.h>
26 #include <dali/public-api/animation/constraint.h>
27 #include <dali/public-api/animation/constraints.h>
28 #include <dali/public-api/object/type-registry-helper.h>
29 #include <dali/public-api/object/type-registry.h>
32 #include <dali-toolkit/devel-api/controls/control-devel.h>
33 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
34 #include <dali-toolkit/internal/controls/model3d-view/obj-loader.h>
35 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
45 // Texture indices are constants.
48 DIFFUSE_TEXTURE_INDEX,
54 * @brief Loads a texture from a file.
55 * @param[in] imageUrl The URL of the file
56 * @return A texture if loading succeeds, an empty handle otherwise
58 Texture LoadTexture(const char* imageUrl)
61 Devel::PixelBuffer pixelBuffer = LoadImageFromFile(imageUrl);
64 texture = Texture::New(TextureType::TEXTURE_2D, pixelBuffer.GetPixelFormat(), pixelBuffer.GetWidth(), pixelBuffer.GetHeight());
65 PixelData pixelData = Devel::PixelBuffer::Convert(pixelBuffer);
66 texture.Upload(pixelData);
67 texture.GenerateMipmaps();
76 return Toolkit::Model3dView::New();
79 // Setup properties, signals and actions using the type-registry.
80 DALI_TYPE_REGISTRATION_BEGIN(Toolkit::Model3dView, Toolkit::Control, Create);
82 DALI_PROPERTY_REGISTRATION(Toolkit, Model3dView, "geometryUrl", STRING, GEOMETRY_URL)
83 DALI_PROPERTY_REGISTRATION(Toolkit, Model3dView, "materialUrl", STRING, MATERIAL_URL)
84 DALI_PROPERTY_REGISTRATION(Toolkit, Model3dView, "imagesUrl", STRING, IMAGES_URL)
85 DALI_PROPERTY_REGISTRATION(Toolkit, Model3dView, "illuminationType", INTEGER, ILLUMINATION_TYPE)
86 DALI_PROPERTY_REGISTRATION(Toolkit, Model3dView, "texture0Url", STRING, TEXTURE0_URL)
87 DALI_PROPERTY_REGISTRATION(Toolkit, Model3dView, "texture1Url", STRING, TEXTURE1_URL)
88 DALI_PROPERTY_REGISTRATION(Toolkit, Model3dView, "texture2Url", STRING, TEXTURE2_URL)
90 DALI_ANIMATABLE_PROPERTY_REGISTRATION(Toolkit, Model3dView, "lightPosition", VECTOR3, LIGHT_POSITION)
92 DALI_TYPE_REGISTRATION_END()
94 } // anonymous namespace
98 Model3dView::Model3dView()
99 : Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT))
101 mIlluminationType = Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP;
103 mCameraFOV = Math::PI_OVER_180 * 45.f;
105 mControlSize = Vector2(100., 100.);
108 Model3dView::~Model3dView()
112 Toolkit::Model3dView Model3dView::New()
114 Model3dView* impl = new Model3dView();
116 Dali::Toolkit::Model3dView handle = Dali::Toolkit::Model3dView(*impl);
118 // Second-phase init of the implementation
119 // This can only be done after the CustomActor connection has been made...
125 void Model3dView::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
127 Toolkit::Model3dView model3dView = Toolkit::Model3dView::DownCast(Dali::BaseHandle(object));
131 Model3dView& impl(GetImpl(model3dView));
134 case Toolkit::Model3dView::Property::GEOMETRY_URL:
136 if(value.Get(impl.mObjUrl))
139 impl.CreateGeometry();
143 case Toolkit::Model3dView::Property::MATERIAL_URL:
145 if(value.Get(impl.mTextureSetUrl))
148 impl.CreateMaterial();
153 case Toolkit::Model3dView::Property::IMAGES_URL:
155 if(value.Get(impl.mImagesUrl))
161 case Toolkit::Model3dView::Property::ILLUMINATION_TYPE:
163 int illuminationType;
164 if(value.Get(illuminationType))
166 impl.mIlluminationType = Toolkit::Model3dView::IlluminationType(illuminationType);
167 impl.CreateGeometry();
168 impl.CreateMaterial();
173 case Toolkit::Model3dView::Property::TEXTURE0_URL:
175 value.Get(impl.mTexture0Url);
178 case Toolkit::Model3dView::Property::TEXTURE1_URL:
180 value.Get(impl.mTexture1Url);
183 case Toolkit::Model3dView::Property::TEXTURE2_URL:
185 value.Get(impl.mTexture2Url);
192 Property::Value Model3dView::GetProperty(BaseObject* object, Property::Index index)
194 Property::Value value;
196 Toolkit::Model3dView model3dView = Toolkit::Model3dView::DownCast(Dali::BaseHandle(object));
200 Model3dView& impl(GetImpl(model3dView));
203 case Toolkit::Model3dView::Property::GEOMETRY_URL:
205 value = impl.mObjUrl;
208 case Toolkit::Model3dView::Property::MATERIAL_URL:
210 value = impl.mTextureSetUrl;
213 case Toolkit::Model3dView::Property::IMAGES_URL:
215 value = impl.mImagesUrl;
218 case Toolkit::Model3dView::Property::ILLUMINATION_TYPE:
220 value = int(impl.mIlluminationType);
223 case Toolkit::Model3dView::Property::TEXTURE0_URL:
225 value = impl.mTexture0Url;
228 case Toolkit::Model3dView::Property::TEXTURE1_URL:
230 value = impl.mTexture1Url;
233 case Toolkit::Model3dView::Property::TEXTURE2_URL:
235 value = impl.mTexture2Url;
244 /////////////////////////////////////////////////////////////
246 void Model3dView::OnSceneConnection(int depth)
248 CustomActor self = Self();
249 self.AddRenderer(mRenderer);
251 if(mObjLoader.IsSceneLoaded())
253 mMesh = mObjLoader.CreateGeometry(GetShaderProperties(mIlluminationType), true);
258 mRenderer.SetGeometry(mMesh);
260 //create constraint for lightPosition Property with uLightPosition in the shader
261 Vector3 lightPosition(0, 0, 0);
262 Dali::Property::Index lightProperty = mShader.RegisterProperty("uLightPosition", lightPosition);
263 Constraint constraint = Constraint::New<Vector3>(mShader, lightProperty, EqualToConstraint());
264 constraint.AddSource(Source(self, Toolkit::Model3dView::Property::LIGHT_POSITION));
268 Control::OnSceneConnection(depth);
271 ///////////////////////////////////////////////////////////
276 void Model3dView::OnInitialize()
278 //Create empty versions of the geometry and material so we always have a Renderer
279 Geometry mesh = Geometry::New();
280 Shader shader = Shader::New(SHADER_MODEL3D_VIEW_SIMPLE_SHADER_VERT, SHADER_MODEL3D_VIEW_SIMPLE_SHADER_FRAG);
281 mRenderer = Renderer::New(mesh, shader);
283 DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) {
284 return std::unique_ptr<Dali::Accessibility::Accessible>(
285 new DevelControl::AccessibleImpl(actor, Dali::Accessibility::Role::IMAGE));
289 void Model3dView::LoadGeometry()
291 //Load file in adaptor
292 std::streampos fileSize;
293 Dali::Vector<char> fileContent;
295 if(FileLoader::ReadFile(mObjUrl, fileSize, fileContent, FileLoader::TEXT))
297 mObjLoader.ClearArrays();
298 mObjLoader.LoadObject(fileContent.Begin(), fileSize);
300 //Get size information from the obj loaded
301 mSceneCenter = mObjLoader.GetCenter();
302 mSceneSize = mObjLoader.GetSize();
310 void Model3dView::LoadMaterial()
312 //Load file in adaptor
313 std::streampos fileSize;
314 Dali::Vector<char> fileContent;
316 if(FileLoader::ReadFile(mTextureSetUrl, fileSize, fileContent, FileLoader::TEXT))
318 mObjLoader.LoadMaterial(fileContent.Begin(), fileSize, mTexture0Url, mTexture1Url, mTexture2Url);
326 void Model3dView::Load()
332 void Model3dView::OnRelayout(const Vector2& size, RelayoutContainer& container)
337 void Model3dView::UpdateView()
339 if(mObjLoader.IsSceneLoaded())
341 //The object will always be centred
344 scaleMatrix.SetIdentityAndScale(Vector3(1.0, -1.0, 1.0));
346 mShader.RegisterProperty("uObjectMatrix", scaleMatrix);
350 void Model3dView::CreateGeometry()
352 if(mObjLoader.IsSceneLoaded())
354 mMesh = mObjLoader.CreateGeometry(GetShaderProperties(mIlluminationType), true);
358 mRenderer.SetGeometry(mMesh);
359 mRenderer.SetProperty(Renderer::Property::DEPTH_WRITE_MODE, DepthWriteMode::ON);
360 mRenderer.SetProperty(Renderer::Property::DEPTH_TEST_MODE, DepthTestMode::ON);
365 void Model3dView::UpdateShaderUniforms()
369 //Update shader related info, uniforms, etc. for the new shader
372 Vector3 lightPosition(0, 0, 0);
373 Dali::Property::Index lightProperty = mShader.RegisterProperty("uLightPosition", lightPosition);
375 CustomActor self = Self();
377 //create constraint for lightPosition Property with uLightPosition in the shader
380 Constraint constraint = Constraint::New<Vector3>(mShader, lightProperty, EqualToConstraint());
381 constraint.AddSource(Source(self, Toolkit::Model3dView::Property::LIGHT_POSITION));
387 void Model3dView::CreateMaterial()
389 if(mObjLoader.IsMaterialLoaded() && (mTexture0Url != "") && mObjLoader.IsTexturePresent())
391 if((mTexture2Url != "") && (mTexture1Url != "") && (mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP))
393 mShader = Shader::New(SHADER_MODEL3D_VIEW_NRMMAP_SHADER_VERT, SHADER_MODEL3D_VIEW_NRMMAP_SHADER_FRAG);
395 else if(mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_TEXTURE ||
396 mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP)
398 mShader = Shader::New(SHADER_MODEL3D_VIEW_SHADER_VERT, SHADER_MODEL3D_VIEW_SHADER_FRAG);
402 mShader = Shader::New(SHADER_MODEL3D_VIEW_SIMPLE_SHADER_VERT, SHADER_MODEL3D_VIEW_SIMPLE_SHADER_FRAG);
407 mShader = Shader::New(SHADER_MODEL3D_VIEW_SIMPLE_SHADER_VERT, SHADER_MODEL3D_VIEW_SIMPLE_SHADER_FRAG);
410 mTextureSet = TextureSet::New();
414 mRenderer.SetTextures(mTextureSet);
415 mRenderer.SetShader(mShader);
416 mRenderer.SetProperty(Renderer::Property::FACE_CULLING_MODE, FaceCullingMode::BACK);
419 UpdateShaderUniforms();
422 void Model3dView::LoadTextures()
429 Sampler sampler = Sampler::New();
430 sampler.SetFilterMode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR_MIPMAP_LINEAR);
432 // Setup diffuse texture.
433 if(!mTexture0Url.empty() && (mIlluminationType != Toolkit::Model3dView::DIFFUSE))
435 std::string imageUrl = mImagesUrl + mTexture0Url;
438 Texture diffuseTexture = LoadTexture(imageUrl.c_str());
441 mTextureSet.SetTexture(DIFFUSE_TEXTURE_INDEX, diffuseTexture);
442 mTextureSet.SetSampler(DIFFUSE_TEXTURE_INDEX, sampler);
446 if(mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP)
448 // Setup normal map texture.
449 if(!mTexture1Url.empty())
451 std::string imageUrl = mImagesUrl + mTexture1Url;
454 Texture normalTexture = LoadTexture(imageUrl.c_str());
457 mTextureSet.SetTexture(NORMAL_TEXTURE_INDEX, normalTexture);
458 mTextureSet.SetSampler(NORMAL_TEXTURE_INDEX, sampler);
461 if(!mTexture2Url.empty())
463 // Setup gloss map texture.
464 std::string imageUrl = mImagesUrl + mTexture2Url;
467 Texture glossTexture = LoadTexture(imageUrl.c_str());
470 mTextureSet.SetTexture(GLOSS_TEXTURE_INDEX, glossTexture);
471 mTextureSet.SetSampler(GLOSS_TEXTURE_INDEX, sampler);
477 int Model3dView::GetShaderProperties(Toolkit::Model3dView::IlluminationType illuminationType)
479 int objectProperties = 0;
481 if(illuminationType == Toolkit::Model3dView::DIFFUSE_WITH_TEXTURE ||
482 illuminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP)
484 objectProperties |= ObjLoader::TEXTURE_COORDINATES;
487 if(illuminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP)
489 objectProperties |= ObjLoader::TANGENTS | ObjLoader::BINORMALS;
492 return objectProperties;
495 } // namespace Internal
496 } // namespace Toolkit