2 * Copyright(c) 2023 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 using System.Runtime.InteropServices;
20 using System.ComponentModel;
22 using Tizen.NUI.Binding;
23 using Tizen.NUI.BaseComponents;
25 namespace Tizen.NUI.Scene3D
28 /// Model is a Class to show 3D mesh objects.
29 /// Model supports glTF 2.0 and DLI model formats.
30 /// Physically Based Rendering with Image Based Lighting is also supported.
34 /// Since NUI uses a left-handed coordinate system, loaded models are transformed into a left-handed coordinate system with Y pointing down.
35 /// The Animations defined in the glTF or DLI are also loaded and can be retrieved by using <see cref="GetAnimation(uint)"/> and <see cref="GetAnimation(string)"/> methods.
36 /// The number of animation is also retrieved by GetAnimationCount() method.
38 /// Model also supports Physically Based Rendering(PBR) with Image Based Lighting(IBL).
39 /// For the IBL, two cube map textures(diffuse and specular) are required.
40 /// Model supports 4 types layout for Cube Map: Vertical/Horizontal Cross layouts, and Vertical/Horizontal Array layouts.
41 /// And also, ktx format with cube map is supported.
43 /// The model and IBL textures start to be loaded asynchronously when the Model object is on Window.
44 /// ResourcesLoaded signal notifies that the loading of the model and IBL resources have been completed.
45 /// If Model or IBL is requested to be loaded before the other loading is completed, the ResourcesLoaded signal is called after all resources are loaded.
46 /// <see cref="GetAnimation(uint)"/> and <see cref="GetAnimation(string)"/> methods can be used after the model loading is finished.
48 /// By default, the loaded mesh has its own size and <see cref="PivotPoint"/> inferred from position of vertices.
49 /// The <see cref="PivotPoint"/> can be modified after model loading is finished.
50 /// If user set size property, the mesh will be scaled to the input size.
51 /// Default value of <see cref="ParentOrigin"/> of the Model is Center.
56 /// Model model = new Model(modelUrl)
58 /// Size = new Size(width, height),
60 /// model.ResourcesLoaded += (s, e) =>
62 /// model.PivotPoint = new Vector3(0.5f, 0.5f, 0.5f); // Use center as a Pivot.
64 /// int animationCount = model.GetAnimationCount();
65 /// if(animationCount > 0)
67 /// // Play an Animation of index 0.
68 /// model.GetAnimation(0).Play();
71 /// model.SetImageBasedLightSource(diffuseUrl, specularUrl, scaleFactor);
72 /// window.Add(model);
76 /// <since_tizen> 10 </since_tizen>
77 public partial class Model : View
79 internal Model(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
84 /// Create an initialized Model.
86 /// <param name="modelUrl">model file url.(e.g. glTF, and DLI).</param>
87 /// <param name="resourceDirectoryUrl"> The url to derectory containing resources: binary, image etc.</param>
89 /// If resourceDirectoryUrl is empty, the parent directory url of modelUrl is used for resource url.
91 /// http://tizen.org/privilege/mediastorage for local files in media storage.
92 /// http://tizen.org/privilege/externalstorage for local files in external storage.
94 /// <since_tizen> 10 </since_tizen>
95 public Model(string modelUrl, string resourceDirectoryUrl = "") : this(Interop.Model.ModelNew(modelUrl, resourceDirectoryUrl), true)
97 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
98 this.PositionUsesAnchorPoint = true;
102 /// Create an initialized Model.
104 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
105 [EditorBrowsable(EditorBrowsableState.Never)]
106 public Model() : this(Interop.Model.ModelNew(), true)
108 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
109 this.PositionUsesAnchorPoint = true;
113 /// Copy constructor.
115 /// <param name="model">Source object to copy.</param>
116 /// <since_tizen> 10 </since_tizen>
117 public Model(Model model) : this(Interop.Model.NewModel(Model.getCPtr(model)), true)
119 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
123 /// Assignment operator.
125 /// <param name="model">Source object to be assigned.</param>
126 /// <returns>Reference to this.</returns>
127 internal Model Assign(Model model)
129 Model ret = new Model(Interop.Model.ModelAssign(SwigCPtr, Model.getCPtr(model)), false);
130 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
135 /// Set/Get the ImageBasedLight ScaleFactor.
136 /// Scale factor controls light source intensity in [0.0f, 1.0f]
138 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
139 [EditorBrowsable(EditorBrowsableState.Never)]
140 public float ImageBasedLightScaleFactor
144 SetImageBasedLightScaleFactor(value);
148 return GetImageBasedLightScaleFactor();
153 /// Adds modelNode to this Model.
155 /// <param name="modelRoot">Root of a ModelNode tree</param>
156 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
157 [EditorBrowsable(EditorBrowsableState.Never)]
158 public void AddModelNode(ModelNode modelRoot)
160 Interop.Model.AddModelNode(SwigCPtr, ModelNode.getCPtr(modelRoot));
161 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
165 /// Removes modelNode from this Model.
167 /// <param name="modelRoot">Root of a ModelNode tree to be removed</param>
168 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
169 [EditorBrowsable(EditorBrowsableState.Never)]
170 public void RemoveModelNode(ModelNode modelRoot)
172 Interop.Model.RemoveModelNode(SwigCPtr, ModelNode.getCPtr(modelRoot));
173 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
177 /// Removes Returns a child ModelNode object with a name that matches nodeName.
179 /// <param name="nodeName">The name of the child ModelNode object you want to find.</param>
180 /// <returns>Child ModelNode that has nodeName as name.</returns>
181 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
182 [EditorBrowsable(EditorBrowsableState.Never)]
183 public ModelNode FindChildModelNodeByName(string nodeName)
185 global::System.IntPtr cPtr = Interop.Model.FindChildModelNodeByName(SwigCPtr, nodeName);
186 ModelNode ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as ModelNode;
189 // Register new animatable into Registry.
190 ret = new ModelNode(cPtr, true);
194 // We found matched NUI animatable. Reduce cPtr reference count.
195 HandleRef handle = new HandleRef(this, cPtr);
196 Tizen.NUI.Interop.BaseHandle.DeleteBaseHandle(handle);
197 handle = new HandleRef(null, IntPtr.Zero);
199 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
204 /// Changes Image Based Light according to the given input textures.
206 /// <param name="diffuseUrl">The path of Cube map image that will be used as a diffuse IBL source.</param>
207 /// <param name="specularUrl">The path of Cube map image that will be used as a specular IBL source.</param>
208 /// <param name="scaleFactor">Scale factor that controls light source intensity in [0.0f, 1.0f]. Default value is 1.0f.</param>
210 /// http://tizen.org/privilege/mediastorage for local files in media storage.
211 /// http://tizen.org/privilege/externalstorage for local files in external storage.
213 /// <since_tizen> 10 </since_tizen>
214 public void SetImageBasedLightSource(string diffuseUrl, string specularUrl, float scaleFactor = 1.0f)
216 Interop.Model.SetImageBasedLightSource(SwigCPtr, diffuseUrl, specularUrl, scaleFactor);
217 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
221 /// Gets number of animations that has been loaded from model file.
224 /// This method should be called after Model load has been finished.
226 /// <returns>The number of loaded animations.</returns>
227 /// <since_tizen> 10 </since_tizen>
228 public uint GetAnimationCount()
230 uint ret = Interop.Model.GetAnimationCount(SwigCPtr);
231 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
236 /// Gets animation at the index.
239 /// This method should be called after Model load has been finished.
241 /// <param name="index">Index of animation to be retrieved.</param>
242 /// <returns>Animation at the index.</returns>
243 /// <since_tizen> 10 </since_tizen>
244 public Animation GetAnimation(uint index)
246 global::System.IntPtr cPtr = Interop.Model.GetAnimation(SwigCPtr, index);
247 Animation ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as Animation;
250 // Register new animation into Registry.
251 ret = new Animation(cPtr, true);
255 // We found matched NUI animation. Reduce cPtr reference count.
256 HandleRef handle = new HandleRef(this, cPtr);
257 Tizen.NUI.Interop.Animation.DeleteAnimation(handle);
258 handle = new HandleRef(null, IntPtr.Zero);
260 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
265 /// Retrieves animation with the given name.
266 /// Note: This method should be called after Model load finished.
268 /// <param name="name">String name of animation to be retrieved.</param>
269 /// <returns>Animation that has the given name.</returns>
270 /// <since_tizen> 10 </since_tizen>
271 public Animation GetAnimation(string name)
273 global::System.IntPtr cPtr = Interop.Model.GetAnimation(SwigCPtr, name);
274 Animation ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as Animation;
277 // Register new animation into Registry.
278 ret = new Animation(cPtr, true);
282 // We found matched NUI animation. Reduce cPtr reference count.
283 HandleRef handle = new HandleRef(this, cPtr);
284 Tizen.NUI.Interop.Animation.DeleteAnimation(handle);
285 handle = new HandleRef(null, IntPtr.Zero);
287 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
292 /// Gets number of camera parameters that has been loaded from model file.
295 /// This method should be called after Model load has been finished.
297 /// <returns>The number of loaded camera parameters.</returns>
298 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
299 [EditorBrowsable(EditorBrowsableState.Never)]
300 public uint GetCameraCount()
302 uint ret = Interop.Model.GetCameraCount(SwigCPtr);
303 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
308 /// Generate Camera using camera parameters at the index.
309 /// If camera parameter is valid, create new Camera.
310 /// Else, return empty Handle.
313 /// This method should be called after Model load has been finished.
315 /// <returns>Generated Camera by the index, or empty Handle if generation failed.</returns>
316 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
317 [EditorBrowsable(EditorBrowsableState.Never)]
318 public Camera GenerateCamera(uint index)
320 global::System.IntPtr cPtr = Interop.Model.GenerateCamera(SwigCPtr, index);
321 Camera ret = new Camera(cPtr, true); // Always create new camera.
322 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
327 /// Apply camera parameters at the index to inputed Camera.
328 /// If camera parameter is valid and camera is not empty, apply parameters.
329 /// It will change camera's transform and near / far / fov or orthographic size / aspect ratio (if defined)
332 /// This method should be called after Model load has been finished.
334 /// <param name="index">Index of camera to be retrieved.</param>
335 /// <param name="camera">Camera to be applied parameter.</param>
336 /// <returns>True if Apply successed. False otherwise.</returns>
337 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
338 [EditorBrowsable(EditorBrowsableState.Never)]
339 public bool ApplyCamera(uint index, Camera camera)
342 if(camera?.HasBody() == true)
344 ret = Interop.Model.ApplyCamera(SwigCPtr, index, Camera.getCPtr(camera));
345 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
351 /// Load bvh animation and assign to model.
352 /// Scale is additional scale factor of bvh animation. It is possible that
353 /// Model's scale may not matched with bvh animation scale.
354 /// If scale is null, default use as Vector3.ONE
356 /// <param name="bvhFilename">Name of bvh format file.</param>
357 /// <param name="scale">Scale value of bvh animation match with model.</param>
358 /// <param name="translateRootFromModelNode">Whether we should translate the bvh root from it's ModelNode position or not.</param>
359 /// <returns>Animaion of bvh</returns>
360 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
361 [EditorBrowsable(EditorBrowsableState.Never)]
362 public Animation LoadBvhAnimation(string bvhFilename, Vector3 scale = null, bool translateRootFromModelNode = true)
364 global::System.IntPtr cPtr = Interop.Model.LoadBvhAnimation(SwigCPtr, bvhFilename, Vector3.getCPtr(scale), translateRootFromModelNode);
365 Animation ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as Animation;
368 // Register new animation into Registry.
369 ret = new Animation(cPtr, true);
373 // We found matched NUI animation. Reduce cPtr reference count.
374 HandleRef handle = new HandleRef(this, cPtr);
375 Tizen.NUI.Interop.Animation.DeleteAnimation(handle);
376 handle = new HandleRef(null, IntPtr.Zero);
378 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
383 /// Load bvh animation and assign to model.
384 /// Scale is additional scale factor of bvh animation. It is possible that
385 /// Model's scale may not matched with bvh animation scale.
386 /// If scale is null, default use as Vector3.ONE
388 /// <param name="bvhBuffer">Contents of bvh format file.</param>
389 /// <param name="scale">Scale value of bvh animation match with model.</param>
390 /// <param name="translateRootFromModelNode">Whether we should translate the bvh root from it's ModelNode position or not.</param>
391 /// <returns>Animaion of bvh</returns>
392 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
393 [EditorBrowsable(EditorBrowsableState.Never)]
394 public Animation LoadBvhAnimationFromBuffer(string bvhBuffer, Vector3 scale = null, bool translateRootFromModelNode = true)
396 global::System.IntPtr cPtr = Interop.Model.LoadBvhAnimationFromBuffer(SwigCPtr, bvhBuffer, bvhBuffer.Length, Vector3.getCPtr(scale), translateRootFromModelNode);
397 Animation ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as Animation;
400 // Register new animation into Registry.
401 ret = new Animation(cPtr, true);
405 // We found matched NUI animation. Reduce cPtr reference count.
406 HandleRef handle = new HandleRef(this, cPtr);
407 Tizen.NUI.Interop.Animation.DeleteAnimation(handle);
408 handle = new HandleRef(null, IntPtr.Zero);
410 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
415 /// Load facial animation and assign to model.
417 /// <param name="facialFilename">Name of json format file what we predefined.</param>
418 /// <returns>Animaion of facial</returns>
419 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
420 [EditorBrowsable(EditorBrowsableState.Never)]
421 [Obsolete("Do not use this LoadFacialAnimation. Use LoadBlendShapeAnimation instead.")]
422 public Animation LoadFacialAnimation(string facialFilename)
424 return LoadBlendShapeAnimation(facialFilename);
428 /// Load facial animation and assign to model.
430 /// <param name="facialBuffer">Contents of json format file what we predefined.</param>
431 /// <returns>Animaion of facial</returns>
432 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
433 [EditorBrowsable(EditorBrowsableState.Never)]
434 [Obsolete("Do not use this LoadFacialAnimation. Use LoadBlendShapeAnimation instead.")]
435 public Animation LoadFacialAnimationFromBuffer(string facialBuffer)
437 return LoadBlendShapeAnimationFromBuffer(facialBuffer);
441 /// Load blendshape animation and assign to model from json file.
443 /// <param name="jsonFilename">Name of json format file what we predefined.</param>
444 /// <returns>Animaion of facial</returns>
445 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
446 [EditorBrowsable(EditorBrowsableState.Never)]
447 public Animation LoadBlendShapeAnimation(string jsonFilename)
449 global::System.IntPtr cPtr = Interop.Model.LoadBlendShapeAnimation(SwigCPtr, jsonFilename);
450 Animation ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as Animation;
453 // Register new animation into Registry.
454 ret = new Animation(cPtr, true);
458 // We found matched NUI animation. Reduce cPtr reference count.
459 HandleRef handle = new HandleRef(this, cPtr);
460 Tizen.NUI.Interop.Animation.DeleteAnimation(handle);
461 handle = new HandleRef(null, IntPtr.Zero);
463 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
468 /// Load morphing animation and assign to model from json string.
470 /// <param name="jsonBuffer">Contents of json format file what we predefined.</param>
471 /// <returns>Animaion of facial</returns>
472 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
473 [EditorBrowsable(EditorBrowsableState.Never)]
474 public Animation LoadBlendShapeAnimationFromBuffer(string jsonBuffer)
476 global::System.IntPtr cPtr = Interop.Model.LoadBlendShapeAnimationFromBuffer(SwigCPtr, jsonBuffer, jsonBuffer.Length);
477 Animation ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as Animation;
480 // Register new animation into Registry.
481 ret = new Animation(cPtr, true);
485 // We found matched NUI animation. Reduce cPtr reference count.
486 HandleRef handle = new HandleRef(this, cPtr);
487 Tizen.NUI.Interop.Animation.DeleteAnimation(handle);
488 handle = new HandleRef(null, IntPtr.Zero);
490 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
495 /// Prototype of animation generate by MotionData
497 /// <param name="motionData">Inputed list of pair of MotionIndex and MotionValue.</param>
498 /// <param name="durationMilliSeconds">The duration in milliseconds.</param>
499 /// <returns>Generated animation by input motion data</returns>
500 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
501 [EditorBrowsable(EditorBrowsableState.Never)]
502 public Animation GenerateMotionDataAnimation(MotionData motionData, int durationMilliSeconds)
504 return InternalGenerateMotionDataAnimation(motionData, durationMilliSeconds);
508 /// Prototype of MotionData setter.
509 /// Note that this API didn't apply KeyFrames animation.
510 /// If you want to apply the animation, please use <see cref="GenerateMotionDataAnimation(MotionData, int)"/> and play the result.
512 /// <param name="motionData">Inputed list of pair of MotionIndex and MotionValue.</param>
513 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
514 [EditorBrowsable(EditorBrowsableState.Never)]
515 public void SetMotionData(MotionData motionData)
517 InternalSetMotionData(motionData);
521 /// Retrieves model root Actor.
523 /// <returns>Root View of the model.</returns>
524 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
525 [EditorBrowsable(EditorBrowsableState.Never)]
526 private ModelNode GetModelRoot()
528 global::System.IntPtr cPtr = Interop.Model.GetModelRoot(SwigCPtr);
529 ModelNode ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as ModelNode;
532 // Register new animatable into Registry.
533 ret = new ModelNode(cPtr, true);
537 // We found matched NUI animatable. Reduce cPtr reference count.
538 HandleRef handle = new HandleRef(this, cPtr);
539 Tizen.NUI.Interop.BaseHandle.DeleteBaseHandle(handle);
540 handle = new HandleRef(null, IntPtr.Zero);
542 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
547 /// Set the ImageBasedLight ScaleFactor.
549 /// <param name="scaleFactor">Scale factor that controls light source intensity in [0.0f, 1.0f].</param>
550 private void SetImageBasedLightScaleFactor(float scaleFactor)
552 Interop.Model.SetImageBasedLightScaleFactor(SwigCPtr, scaleFactor);
553 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
557 /// Get the ImageBasedLight ScaleFactor.
559 /// <returns>ImageBasedLightScaleFactor that controls light source intensity.</returns>
560 private float GetImageBasedLightScaleFactor()
562 float scaleFactor = Interop.Model.GetImageBasedLightScaleFactor(SwigCPtr);
563 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
568 /// Release swigCPtr.
570 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
571 [EditorBrowsable(EditorBrowsableState.Never)]
572 protected override void ReleaseSwigCPtr(global::System.Runtime.InteropServices.HandleRef swigCPtr)
574 Interop.Model.DeleteModel(swigCPtr);