2 using System.Runtime.InteropServices;
3 using Tizen.NUI.BaseComponents;
4 using System.Collections.Generic;
6 namespace Tizen.NUI.Samples
8 // Make custom view to ignore Layout features so we can use Depth information
9 public class Custom3DView : CustomView
11 // Default View Enabled SizeNegotiations, and It is Breakdown the depth values.
12 // So we need to create CustomView whitch CustomViewBehavior.DisableSizeNegotiation.
13 public Custom3DView() : base("Custom3DView", CustomViewBehaviour.DisableSizeNegotiation)
15 // Make this object use centered.
16 PositionUsesPivotPoint = true;
17 ParentOrigin = Position.ParentOriginCenter;
18 PivotPoint = Position.PivotPointCenter;
21 public override void OnInitialize()
26 // copied from https://github.com/hinohie/nui-demo/blob/geotest/Mesh/Mesh.cs
27 public class DisposeTest : IExample
33 public Vec2(float xIn, float yIn)
44 public Vec3(float xIn, float yIn, float zIn)
52 struct TexturedQuadVertex
59 static readonly string VERTEX_SHADER =
60 "attribute mediump vec3 aPosition;\n" +
61 "attribute mediump vec3 aNormal;\n" +
62 "attribute mediump vec2 aTexCoord;\n" +
63 "uniform mediump mat4 uMvpMatrix;\n" +
64 "uniform mediump mat3 uNormalMatrix;\n" +
65 "uniform mediump vec3 uSize;\n" +
66 "varying mediump vec3 vNormal;\n" +
67 "varying mediump vec2 vTexCoord;\n" +
68 "varying mediump vec3 vPosition;\n" +
71 " vec4 pos = vec4(aPosition, 1.0)*vec4(uSize,1.0);\n"+
72 " gl_Position = uMvpMatrix*pos;\n" +
73 " vPosition = aPosition;\n" +
74 " vNormal = normalize(uNormalMatrix * aNormal);\n" +
75 " vTexCoord = aTexCoord;\n" +
78 static readonly string FRAGMENT_SHADER =
79 "uniform lowp vec4 uColor;\n" +
80 "uniform sampler2D sTexture;\n" +
81 "varying mediump vec3 vNormal;\n" +
82 "varying mediump vec2 vTexCoord;\n" +
83 "varying mediump vec3 vPosition;\n" +
84 "mediump vec3 uLightDir = vec3(2.0, 0.5, 1.0);\n" + // constant light dir
85 "mediump vec3 uViewDir = vec3(0.0, 0.0, 1.0);\n" + // constant view dir.
86 "mediump vec3 uAmbientColor = vec3(0.2, 0.2, 0.2);\n" +
87 "mediump vec3 uDiffuseColor = vec3(0.8, 0.8, 0.8);\n" +
88 "mediump vec3 uSpecularColor = vec3(0.5, 0.5, 0.5);\n" +
91 " mediump vec3 lightdir = normalize(uLightDir);\n" +
92 " mediump vec3 eyedir = normalize(uViewDir);\n" +
93 " mediump vec4 texColor = texture2D( sTexture, vTexCoord ) * uColor;\n" +
94 " mediump float diffuse = min(max(-dot(vNormal, lightdir) + 0.1, 0.0), 1.0);\n" +
95 " mediump vec3 reflectdir = reflect(-lightdir, vNormal);\n" +
96 " mediump float specular = pow(max(0.0, dot(reflectdir, eyedir)), 50.0);\n" +
97 " mediump vec4 color = texColor * vec4(uAmbientColor + uDiffuseColor * diffuse, 1.0) + vec4(uSpecularColor, 0.0) * specular;\n" +
98 " gl_FragColor = color;\n" +
101 // Copy from dali-toolkit/internal/visuals/primitive/primitive-visual.cpp
102 // NOTE. I add one more slices for texture coordinate
103 private global::System.IntPtr SphereVertexDataPtr()
105 TexturedQuadVertex[] vertices = new TexturedQuadVertex[SPHERE_VERTEX_NUMBER];
107 const int slices = SPHERE_SLICES;
108 const int stacks = SPHERE_STACKS;
111 int vertexIndex = 0; //Track progress through vertices.
117 vertices[vertexIndex].position = new Vec3(0.0f, 0.5f, 0.0f);
118 vertices[vertexIndex].normal = new Vec3(0.0f, 1.0f, 0.0f);
119 vertices[vertexIndex].texcoord = new Vec2(0.5f, 1.0f);
123 for (int i = 1; i < stacks; i++)
125 //Note. This vertex method is not common.
126 //We set one more vertexes for correct texture coordinate. at j == slices
127 //j==0 and j==slices have equal position, normal, but there texcoord.x is different
128 for (int j = 0; j <= slices; j++, vertexIndex++)
130 float cos_j = (float)Math.Cos(2.0f * (float)Math.PI * j / (float)slices);
131 float sin_j = (float)Math.Sin(2.0f * (float)Math.PI * j / (float)slices);
132 float cos_i = (float)Math.Cos((float)Math.PI * i / (float)stacks);
133 float sin_i = (float)Math.Sin((float)Math.PI * i / (float)stacks);
138 vertices[vertexIndex].position = new Vec3(x / 2.0f, y / 2.0f, z / 2.0f);
139 vertices[vertexIndex].normal = new Vec3(x, y, z);
140 vertices[vertexIndex].texcoord = new Vec2((float)j / (float)slices, 1.0f - (float)i / (float)stacks);
145 vertices[vertexIndex].position = new Vec3(0.0f, -0.5f, 0.0f);
146 vertices[vertexIndex].normal = new Vec3(0.0f, -1.0f, 0.0f);
147 vertices[vertexIndex].texcoord = new Vec2(0.5f, 0.0f);
151 int length = Marshal.SizeOf(vertices[0]);
152 global::System.IntPtr pA = Marshal.AllocHGlobal(length * SPHERE_VERTEX_NUMBER);
154 for (int i = 0; i < SPHERE_VERTEX_NUMBER; i++)
156 Marshal.StructureToPtr(vertices[i], pA + i * length, true);
162 private ushort[] SphereIndexData()
164 ushort[] indices = new ushort[SPHERE_INDEX_NUMBER];
165 const int slices = SPHERE_SLICES;
166 const int stacks = SPHERE_STACKS;
170 int indiceIndex = 0; //Used to keep track of progress through indices.
171 int previousCycleBeginning = 1; //Stores the index of the vertex that started the cycle of the previous stack.
172 int currentCycleBeginning = 1 + slices + 1;
174 //Top stack. Loop from index 1 to index slices, as not counting the very first vertex.
175 for (int i = 1; i <= slices; i++, indiceIndex += 3)
177 indices[indiceIndex] = 0;
178 indices[indiceIndex + 1] = (ushort)(i + 1);
179 indices[indiceIndex + 2] = (ushort)i;
182 //Middle Stacks. Want to form triangles between the top and bottom stacks, so loop up to the number of stacks - 2.
183 //Note. This index method is not common.
184 //We increase Beginning indexes slices+1 cause we add one more vertexes for correct texture coordinate.
185 for (int i = 0; i < stacks - 2; i++, previousCycleBeginning += slices + 1, currentCycleBeginning += slices + 1)
187 for (int j = 0; j < slices; j++, indiceIndex += 6)
189 indices[indiceIndex] = (ushort)(previousCycleBeginning + j);
190 indices[indiceIndex + 1] = (ushort)(previousCycleBeginning + 1 + j);
191 indices[indiceIndex + 2] = (ushort)(currentCycleBeginning + j);
192 indices[indiceIndex + 3] = (ushort)(currentCycleBeginning + j);
193 indices[indiceIndex + 4] = (ushort)(previousCycleBeginning + 1 + j);
194 indices[indiceIndex + 5] = (ushort)(currentCycleBeginning + 1 + j);
198 //Bottom stack. Loop around the last stack from the previous loop, and go up to the penultimate vertex.
199 for (int i = 0; i < slices; i++, indiceIndex += 3)
201 indices[indiceIndex] = (ushort)(previousCycleBeginning + slices + 1);
202 indices[indiceIndex + 1] = (ushort)(previousCycleBeginning + i);
203 indices[indiceIndex + 2] = (ushort)(previousCycleBeginning + i + 1);
210 const int SPHERE_SLICES = 30; // >= 3
211 const int SPHERE_STACKS = 20; // >= 1
212 const int SPHERE_VERTEX_NUMBER = (SPHERE_SLICES + 1) * (SPHERE_STACKS - 1) + 2;
213 const int SPHERE_INDEX_NUMBER = 6 * SPHERE_SLICES * (SPHERE_STACKS - 1);
216 private const int AutoDisposedObjectCount = 10;
217 private const int ManualDisposedObjectCount = 10;
218 private const int RecuvelyDisposedObjectCount = 10;
222 private bool toggle = false;
223 private string resource;
224 private List<Custom3DView> views;
225 private List<Custom3DView> depthViews; // List of tree-formed views. 0 indexes view is root.
226 private Animation rotateAnimation;
228 public void Activate()
230 win = NUIApplication.GetDefaultWindow();
231 resource = Tizen.Applications.Application.Current.DirectoryInfo.Resource;
232 // Set layer behavior as Layer3D. without this, Rendering will be broken
233 win.GetDefaultLayer().Behavior = Layer.LayerBehavior.Layer3D;
237 WidthResizePolicy = ResizePolicyType.FillToParent,
238 HeightResizePolicy = ResizePolicyType.FillToParent,
242 views = new List<Custom3DView>();
243 depthViews = new List<Custom3DView>();
244 rotateAnimation = new Animation(1500); //1.5s
249 timer = new Timer(3000); //3s
250 timer.Tick += OnTimerTick;
255 private bool OnTimerTick(object source, Timer.TickEventArgs e)
260 Tizen.Log.Error("NUI", $"View Creation Start\n");
262 Tizen.Log.Error("NUI", $"View Creation Finish\n");
266 Tizen.Log.Error("NUI", $"Manual Dispose Start\n");
268 Tizen.Log.Error("NUI", $"Manual Dispose Finish\n");
274 private Geometry GenerateGeometry()
276 PropertyMap vertexFormat = new PropertyMap();
277 vertexFormat.Add("aPosition", new PropertyValue((int)PropertyType.Vector3));
278 vertexFormat.Add("aNormal", new PropertyValue((int)PropertyType.Vector3));
279 vertexFormat.Add("aTexCoord", new PropertyValue((int)PropertyType.Vector2));
280 PropertyBuffer vertexBuffer = new PropertyBuffer(vertexFormat);
282 vertexBuffer.SetData(SphereVertexDataPtr(), SPHERE_VERTEX_NUMBER);
284 ushort[] indexBuffer = SphereIndexData();
286 Geometry geometry = new Geometry();
287 geometry.AddVertexBuffer(vertexBuffer);
288 geometry.SetIndexBuffer(indexBuffer, SPHERE_INDEX_NUMBER);
289 geometry.SetType(Geometry.Type.TRIANGLES);
293 private void AddManyViews()
295 Random rand = new Random();
297 for (int i = 0; i < AutoDisposedObjectCount; i++)
300 var view = new Custom3DView()
302 Size = new Size(viewSize, viewSize, viewSize),
303 Position = new Position(
304 rand.Next(10, win.WindowSize.Width - 10) - win.WindowSize.Width / 2,
305 rand.Next(10, win.WindowSize.Height - 10) - win.WindowSize.Height / 2,
306 rand.Next(-3 * viewSize, 3 * viewSize)
308 Name = "Auto_" + i.ToString(),
312 PixelData pixelData = PixelBuffer.Convert(ImageLoader.LoadImageFromFile(
313 resource + "/images/PopupTest/circle.jpg",
315 FittingModeType.ScaleToFill
317 Texture texture = new Texture(
318 TextureType.TEXTURE_2D,
319 pixelData.GetPixelFormat(),
320 pixelData.GetWidth(),
321 pixelData.GetHeight()
323 texture.Upload(pixelData);
324 TextureSet textureSet = new TextureSet();
325 textureSet.SetTexture(0u, texture);
326 Renderer renderer = new Renderer(GenerateGeometry(), new Shader(VERTEX_SHADER, FRAGMENT_SHADER));
327 renderer.SetTextures(textureSet);
328 view.AddRenderer(renderer);
330 rotateAnimation.AnimateBy(view, "Orientation", new Rotation(new Radian(new Degree(360.0f)), Vector3.YAxis));
333 for (int i = 0; i < ManualDisposedObjectCount; i++)
336 var view = new Custom3DView()
338 Size = new Size(viewSize, viewSize, viewSize),
339 Position = new Position(
340 rand.Next(10, win.WindowSize.Width - 10) - win.WindowSize.Width / 2,
341 rand.Next(10, win.WindowSize.Height - 10) - win.WindowSize.Height / 2,
342 rand.Next(-3 * viewSize, 3 * viewSize)
344 Name = "Manual_" + i.ToString(),
349 PixelData pixelData = PixelBuffer.Convert(ImageLoader.LoadImageFromFile(
350 resource + "/images/PaletteTest/red2.jpg",
352 FittingModeType.ScaleToFill
354 Texture texture = new Texture(
355 TextureType.TEXTURE_2D,
356 pixelData.GetPixelFormat(),
357 pixelData.GetWidth(),
358 pixelData.GetHeight()
360 texture.Upload(pixelData);
361 TextureSet textureSet = new TextureSet();
362 textureSet.SetTexture(0u, texture);
363 Renderer renderer = new Renderer(GenerateGeometry(), new Shader(VERTEX_SHADER, FRAGMENT_SHADER));
364 renderer.SetTextures(textureSet);
365 view.AddRenderer(renderer);
367 rotateAnimation.AnimateBy(view, "Orientation", new Rotation(new Radian(new Degree(-360.0f)), Vector3.YAxis));
370 for (int i = 0; i < RecuvelyDisposedObjectCount; i++)
373 var view = new Custom3DView()
375 // Note that we need to disconnect inherit to make this view shows well.
376 InheritPosition = false,
377 InheritOrientation = false,
379 Size = new Size(viewSize, viewSize, viewSize),
381 Position = new Position(
382 rand.Next(10, win.WindowSize.Width - 10) - win.WindowSize.Width / 2,
383 rand.Next(10, win.WindowSize.Height - 10) - win.WindowSize.Height / 2,
384 rand.Next(-3 * viewSize, 3 * viewSize)
386 Name = "Recursive_" + i.ToString(),
389 // Add view recursively.
396 int parentIndex = rand.Next(i);
397 var parent = depthViews[parentIndex];
400 depthViews.Add(view);
402 PixelData pixelData = PixelBuffer.Convert(ImageLoader.LoadImageFromFile(
403 resource + "/images/PaletteTest/rock.jpg",
405 FittingModeType.ScaleToFill
407 Texture texture = new Texture(
408 TextureType.TEXTURE_2D,
409 pixelData.GetPixelFormat(),
410 pixelData.GetWidth(),
411 pixelData.GetHeight()
413 texture.Upload(pixelData);
414 TextureSet textureSet = new TextureSet();
415 textureSet.SetTexture(0u, texture);
416 Renderer renderer = new Renderer(GenerateGeometry(), new Shader(VERTEX_SHADER, FRAGMENT_SHADER));
417 renderer.SetTextures(textureSet);
418 view.AddRenderer(renderer);
420 //rotateAnimation.AnimateBy(view, "Orientation", new Rotation(new Radian(new Degree(360.0f)), Vector3.ZAxis));
422 rotateAnimation.Looping = true;
423 rotateAnimation.Play();
425 private void RemoveAllViews()
427 uint cnt = root.ChildCount;
428 for (int i = (int)(cnt - 1); i >= 0; i--)
430 root.Remove(root.GetChildAt((uint)i));
432 foreach(var view in views)
434 var renderer = view.GetRendererAt(0);
438 if(depthViews?.Count > 0)
440 depthViews[0].DisposeRecursively();
445 rotateAnimation.Clear();
448 private void FullGC()
450 global::System.GC.Collect();
451 global::System.GC.WaitForPendingFinalizers();
452 global::System.GC.Collect();
455 public void Deactivate()
459 rotateAnimation?.Dispose();
463 // Revert default layer behavior as LayerUI
464 win.GetDefaultLayer().Behavior = Layer.LayerBehavior.LayerUI;