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::make_unique<DevelControl::ControlAccessible>(actor, Dali::Accessibility::Role::IMAGE);
288 void Model3dView::LoadGeometry()
290 //Load file in adaptor
291 std::streampos fileSize;
292 Dali::Vector<char> fileContent;
294 if(FileLoader::ReadFile(mObjUrl, fileSize, fileContent, FileLoader::TEXT))
296 mObjLoader.ClearArrays();
297 mObjLoader.LoadObject(fileContent.Begin(), fileSize);
299 //Get size information from the obj loaded
300 mSceneCenter = mObjLoader.GetCenter();
301 mSceneSize = mObjLoader.GetSize();
309 void Model3dView::LoadMaterial()
311 //Load file in adaptor
312 std::streampos fileSize;
313 Dali::Vector<char> fileContent;
315 if(FileLoader::ReadFile(mTextureSetUrl, fileSize, fileContent, FileLoader::TEXT))
317 mObjLoader.LoadMaterial(fileContent.Begin(), fileSize, mTexture0Url, mTexture1Url, mTexture2Url);
325 void Model3dView::Load()
331 void Model3dView::OnRelayout(const Vector2& size, RelayoutContainer& container)
336 void Model3dView::UpdateView()
338 if(mObjLoader.IsSceneLoaded())
340 //The object will always be centred
343 scaleMatrix.SetIdentityAndScale(Vector3(1.0, -1.0, 1.0));
345 mShader.RegisterProperty("uObjectMatrix", scaleMatrix);
349 void Model3dView::CreateGeometry()
351 if(mObjLoader.IsSceneLoaded())
353 mMesh = mObjLoader.CreateGeometry(GetShaderProperties(mIlluminationType), true);
357 mRenderer.SetGeometry(mMesh);
358 mRenderer.SetProperty(Renderer::Property::DEPTH_WRITE_MODE, DepthWriteMode::ON);
359 mRenderer.SetProperty(Renderer::Property::DEPTH_TEST_MODE, DepthTestMode::ON);
364 void Model3dView::UpdateShaderUniforms()
368 //Update shader related info, uniforms, etc. for the new shader
371 Vector3 lightPosition(0, 0, 0);
372 Dali::Property::Index lightProperty = mShader.RegisterProperty("uLightPosition", lightPosition);
374 CustomActor self = Self();
376 //create constraint for lightPosition Property with uLightPosition in the shader
379 Constraint constraint = Constraint::New<Vector3>(mShader, lightProperty, EqualToConstraint());
380 constraint.AddSource(Source(self, Toolkit::Model3dView::Property::LIGHT_POSITION));
386 void Model3dView::CreateMaterial()
388 if(mObjLoader.IsMaterialLoaded() && (mTexture0Url != "") && mObjLoader.IsTexturePresent())
390 if((mTexture2Url != "") && (mTexture1Url != "") && (mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP))
392 mShader = Shader::New(SHADER_MODEL3D_VIEW_NRMMAP_SHADER_VERT, SHADER_MODEL3D_VIEW_NRMMAP_SHADER_FRAG);
394 else if(mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_TEXTURE ||
395 mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP)
397 mShader = Shader::New(SHADER_MODEL3D_VIEW_SHADER_VERT, SHADER_MODEL3D_VIEW_SHADER_FRAG);
401 mShader = Shader::New(SHADER_MODEL3D_VIEW_SIMPLE_SHADER_VERT, SHADER_MODEL3D_VIEW_SIMPLE_SHADER_FRAG);
406 mShader = Shader::New(SHADER_MODEL3D_VIEW_SIMPLE_SHADER_VERT, SHADER_MODEL3D_VIEW_SIMPLE_SHADER_FRAG);
409 mTextureSet = TextureSet::New();
413 mRenderer.SetTextures(mTextureSet);
414 mRenderer.SetShader(mShader);
415 mRenderer.SetProperty(Renderer::Property::FACE_CULLING_MODE, FaceCullingMode::BACK);
418 UpdateShaderUniforms();
421 void Model3dView::LoadTextures()
428 Sampler sampler = Sampler::New();
429 sampler.SetFilterMode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR_MIPMAP_LINEAR);
431 // Setup diffuse texture.
432 if(!mTexture0Url.empty() && (mIlluminationType != Toolkit::Model3dView::DIFFUSE))
434 std::string imageUrl = mImagesUrl + mTexture0Url;
437 Texture diffuseTexture = LoadTexture(imageUrl.c_str());
440 mTextureSet.SetTexture(DIFFUSE_TEXTURE_INDEX, diffuseTexture);
441 mTextureSet.SetSampler(DIFFUSE_TEXTURE_INDEX, sampler);
445 if(mIlluminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP)
447 // Setup normal map texture.
448 if(!mTexture1Url.empty())
450 std::string imageUrl = mImagesUrl + mTexture1Url;
453 Texture normalTexture = LoadTexture(imageUrl.c_str());
456 mTextureSet.SetTexture(NORMAL_TEXTURE_INDEX, normalTexture);
457 mTextureSet.SetSampler(NORMAL_TEXTURE_INDEX, sampler);
460 if(!mTexture2Url.empty())
462 // Setup gloss map texture.
463 std::string imageUrl = mImagesUrl + mTexture2Url;
466 Texture glossTexture = LoadTexture(imageUrl.c_str());
469 mTextureSet.SetTexture(GLOSS_TEXTURE_INDEX, glossTexture);
470 mTextureSet.SetSampler(GLOSS_TEXTURE_INDEX, sampler);
476 int Model3dView::GetShaderProperties(Toolkit::Model3dView::IlluminationType illuminationType)
478 int objectProperties = 0;
480 if(illuminationType == Toolkit::Model3dView::DIFFUSE_WITH_TEXTURE ||
481 illuminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP)
483 objectProperties |= ObjLoader::TEXTURE_COORDINATES;
486 if(illuminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP)
488 objectProperties |= ObjLoader::TANGENTS | ObjLoader::BINORMALS;
491 return objectProperties;
494 } // namespace Internal
495 } // namespace Toolkit