AR -portaal võõrastest asjadest ülespoole: 10 sammu (piltidega)
AR -portaal võõrastest asjadest ülespoole: 10 sammu (piltidega)

Video: AR -portaal võõrastest asjadest ülespoole: 10 sammu (piltidega)

Video: AR -portaal võõrastest asjadest ülespoole: 10 sammu (piltidega)
Video: 8 Exceli tööriista, mida kõik peaksid saama kasutada 2025, Jaanuar
Anonim
AR -portaal võõrastest asjadest ülespoole
AR -portaal võõrastest asjadest ülespoole
AR -portaal võõrastest asjadest ülespoole
AR -portaal võõrastest asjadest ülespoole

See juhendatav loob iPhone'ile liitreaalsuse mobiilirakenduse, mille portaal viib Stranger Thingsist tagurpidi. Võite minna portaali sisse, jalutada ja tagasi tulla. Kõike portaali sees saab näha ainult portaali kaudu, kuni sisenete sisse. Sisenedes muutub kõik kõikjal, kuni kõnnite tagasi päris maailma. Kasutame Unity 3D videomängumootorit koos Apple ARKiti pistikprogrammiga. Kogu tarkvara, mida kasutame, saab tasuta alla laadida ja kasutada. Selle jälgimiseks ei pea te olema ekspert, me läheme iga sammu läbi!

Samm: alustage uut ühtsuse projekti

Alustage uue Unity projektiga
Alustage uue Unity projektiga

Kõigepealt laadige alla Unity3D ja installige kindlasti IOS -i platvormi koostamisfailid. Samuti peate alla laadima Xcode'i ja registreeruma tasuta Apple'i arendajakontole. Teie iPhone'il peab olema ka operatsioonisüsteem IOS 11 või uuem. Tänase, 5. veebruari 2018 seisuga on IOS 11.3 väljas, kuid xCode 9.2 -l pole selle jaoks veel tugifaile. Seega, kui kasutate IOS -i uusimat versiooni, laadige kindlasti alla uusim Xcode'i beetaversioon saidilt Apple. Developer.com.

Kui teil on kõik vajalikud programmid, avage Unity ja alustage uut projekti, nimetage seda kuidas soovite. Meil on vaja Apple ARKiti pistikprogrammi, et saaksime oma telefoni kaamera abil tuvastada maapinda ja asetada põrandale esemeid. Impordime selle nüüd, minnes vahekaardile Varade pood ja otsides "ARKit". Peate looma tasuta Unity konto, kui teil seda veel pole, ja klõpsake pistikprogrammi hankimiseks nuppu Impordi.

Liikuge ARKiti kausta näidiste kausta ja leidke "UnityARKitScene". Selle avamiseks topeltklõpsake seda. Me kasutame seda stseeni lähtepunktina ja ehitame siit edasi. See stseen võimaldab vaikimisi maapinda tuvastada ja ekraani puudutades paigutatakse sellesse kohta kuup.

Võtame kõigepealt meie ehituse seaded ruuduks, et me ei unustaks seda hiljem teha. Klõpsake faili, looge seaded ja eemaldage loendist kõik stseenid. Meie praeguse stseeni lisamiseks klõpsake nuppu Lisa avatud stseenid. Viimane asi, mille peame siin seadistama, on mängijate seadetes kimpude identifikaator ja selle stringi vorming on com. YourCompanyName. YourAppName, nii et minu puhul teen midagi sellist nagu com. MatthewHallberg. PortalTest.

2. samm: stseeni seadistamine

Stseeni seadistamine
Stseeni seadistamine

Kõigepealt vaadake vasakule ja leidke mänguobjekt nimega "GeneratePlanes". Kui see on esile tõstetud, vaadake kohe paremale ja klõpsake selle keelamiseks märkeruutu. Nii ei tekita me inetuid siniseid ruute, kui ARKit tuvastab maapinna. Seejärel kustutage mänguobjekt "RandomCube", sest me ei taha seda oma stseenis näha.

Nüüd peame esmalt looma oma portaali ukseava. Kustutage kuup, mis on "HitCubeParent" laps. Paremklõpsake ja valige Loo tühi mänguobjekt. Nimeta see ümber portaaliks. Nüüd paremklõpsake sellel objektil ja looge kuup, see teeb sellest portaali alam. Nimetage see ümber "PostLeft" ja see on meie portaali vasak postitus. Skaleerige see nii, et x on 1, y on 28 ja z on üks. Tehke sama asja õige postituse jaoks. Nüüd looge ülemine post ja skaleerige y kuni 14. Pöörake seda külili ja liigutage seda nii, et see ühendaks teised postid. Tehke kogu portaali skaala 1,3 x 1,4 x 1.

Minge google'i ja sisestage puidu või koore tekstuur. Laadige alla üks neist piltidest ja lohistage see Unity varade kausta. Nüüd lohistage see pilt kõigile oma portaalipostitustele.

Klõpsake uuesti objekti "Portaal" ja paremal nuppu Lisa komponent. Lisage sellele skript "UnityARHitTestExample". Seal on tühi pesa "Hit Transform" jaoks, lohistage objekt "HitCubeParent" sellesse pesasse.

3. samm: teeme mõned osakesed

Teeme mõned osakesed
Teeme mõned osakesed

Nüüd kasutame Unity Particle süsteemi, et teha meie portaalis suitsu ja hõljuvate osakeste efekt. Avage ülemises menüüribas Varad, standardvara ja importige osakeste süsteeme.

Looge oma portaali sisse kaks tühja mänguobjekti ja nimetage ühte "SmokeParticles" ja teist "FloatingParticles".

Lisage suitsuosakestele tahkete osakeste süsteemi komponent.

Sellel komponendil on palju võimalusi, kuid me peame ainult paari muutma.

Muutke stardivärv tumesiniseks umbes 50% läbipaistvusega. Tehke emissioonimäär 100. Kuju sees tehke raadius.01. Muuda allosas oleva renderdusosa minimaalseks suuruseks 0,8 ja maksimaalseks suuruseks 5. Materjali komponendil vali lihtsalt loendist suitsumaterjal, kuid me muudame seda hiljem.

Lisage hõljuvate osakeste mänguobjektile kohe osakeste süsteem ja määrake heitkoguseks 500. Seadke algusajaks 2, raadius 10, osakeste minimaalne suurus 0,01 ja maksimaalne osakeste suurus 0,05. Seadke materjal vaikimisi osakesteks.

Lõpuks võtke mõlemad mänguobjektid ja pöörake neid x -i 90 kraadi võrra ning tõstke need õhku, et need kiirguksid portaali ukseavale.

4. samm: osakeste aeglustamine

Osakeste aeglustamine
Osakeste aeglustamine

Kuna me tahame, et need osakesed hõlmaksid suurt ala, kuid liiguksid ka aeglaselt, peame looma oma proovifunktsiooni. Seega paremklõpsake varade kaustas ja looge uus C# skript ning nimetage see osakeste näidiseks. Kopeerige ja kleepige see kood:

kasutades System. Collections;

kasutades System. Collections. Generic; UnityEngine'i kasutamine; public class ParticleSample: MonoBehaviour {private ParticleSystem ps; // Kasutage seda lähtestamiseks void Start () {ps = GetComponent (); StartCoroutine (SampleParticleRoutine ()); } IEnumerator SampleParticleRoutine () {var main = ps.main; main.simulationSpeed = 1000f; ps. Mängi (); tootlus tagastab uue WaitForSeconds (.1f); main.simulationSpeed =.05f; }}

Nüüd lohistage see skript igale oma osakeste süsteemimängu objektile.

5. samm: portaali loomine

Portaali loomine!
Portaali loomine!

Nüüd peame portaali looma, nii et paremklõpsake portaalimängu objekti ja looge quad. Skaleerige nelinurk nii, et see hõlmaks kogu portaali, sellest saab meie portaali aken. Esimese asjana peame sellele lisama portaali varjutaja, see renderdab ainult objekte, millel on teine konkreetne varjutaja. Paremklõpsake varade kausta ja looge uus valgustamata varjutaja. Eemaldage sealt kõik ja kleepige see kood:

Shader "Portaal/portaalaken"

{SubShader {Zwrite off Colormask 0 cull off trafarett {Ref 1 Pass asenda} Pass {}}}

Paremklõpsake hierarhiat ja looge uus materjal, nimetage see PortalWindowMatiks, leidke selle materjali rippmenüüst portaali jaotis ja valige portaali aken. Lohistage see materjal oma portaali neljale.

6. samm: osakeste varjutid

Osakeste varjutajad
Osakeste varjutajad

Paremklõpsake uuesti varade kaustas ja looge uus varjutaja. Peame portaali sisse minevate osakeste jaoks varjendeid valmistama. Asendage kogu kood sellega:

Shader "Portaal/osakesed" {

Atribuudid {_TintColor ("Toonivärv", värv) = (0,5, 0,5, 0,5, 0,5) _MainTex ("Osakeste tekstuur", 2D) = "valge" {} _InvFade ("Pehmete osakeste tegur", vahemik (0,01, 3,0)) = 1.0 _Stencil ("stencil", int) = 6} Kategooria {Tags {"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane"} Sega SrcAlpha OneMinusSrcAlpha ColorMask RGB Cull Off Lighting Off ZWrite Off SubShader {Trafarett {Ref 1 Comp [_Stencil]} Pass {CGPROGRAM #pragma tipex vert #pragma fragment frag #pragma target 2.0 #pragma multi_compile_particles #pragma multi_compile_fog #include "UnityCG.cg fikseeritud4 _TintColor; structure appdata_t {float4 tipp: POSITION; fikseeritud4 värv: COLOR; float2 texcoord: TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID}; structure v2f {float4 tipp: SV_POSITION; fikseeritud4 värv: COLOR; float2 texcoord: TEXCOORD0; UNITY_FOG_COORDS (1) #ifdef SOFTPARTICLES_ON float4 projPos: TEXCOORD2; #endif UNITY_VERTEX_OUTPUT_STEREO}; float4 _MainTex_ST; v2f vert (appdata_t v) {v2f o; UNITY_SETUP_INSTANCE_ID (v); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO (o); o.vertex = UnityObjectToClipPos (v.vertex); #ifdef SOFTPARTICLES_ON o.projPos = ComputeScreenPos (o.vertex); COMPUTE_EYEDEPTH (o.projPos.z); #endif o.color = v.color * _TintColor; o.texcoord = TRANSFORM_TEX (v.texcoord, _MainTex); UNITY_TRANSFER_FOG (o, o.vertex); tagasitulek o; } UNITY_DECLARE_DEPTH_TEXTURE (_CameraDepthTexture); float _InvFade; fix4 frag (v2f i): SV_Target {#ifdef SOFTPARTICLES_ON float sceneZ = LinearEyeDepth (SAMPLE_DEPTH_TEXTURE_PROJ (_CameraDepthTexture, UNITY_PROJ_COORD (i.projPos)))); float partZ = i.projPos.z; float fade = küllastuma (_InvFade * (stseenZ-partZ)); i.color.a *= tuhmumine; #endif fix4 col = 2.0f * i.color * tex2D (_MainTex, i.texcoord); UNITY_APPLY_FOG (i.fogCoord, kollane); return col; } LÕPP}}}}

Looge kaks uut materjali, millest üks on portalSmoke ja teine portaalParticles.

Igaühe jaoks valige see varjutaja rippmenüüst portaalides osakesed. Suitsuosakeste jaoks valige suitsu tekstuur ja osakeste jaoks osakeste tekstuur. Muutke suitsu värv tumedamaks siniseks umbes 50% läbipaistvusega. Minge oma portaali iga osakesesüsteemi renderduskomponendi juurde ja valige nende materjalid, mille me just lõime.

Samm: looge Skybox

Looge Skybox
Looge Skybox

Nüüd, et tõeliselt tagurpidi välimust luua, peame kõik tumesiniseks toonima. Selleks kasutame läbipaistvat taevakasti, nii et tehke uus varjutaja ja kleepige see kood:

Shader "Portal/portalSkybox" {

Atribuudid {_Tint ("Toonivärv", värv) = (.5,.5,.5,.5) [Gamma] _Exposure ("Säritus", vahemik (0, 8)) = 1,0 _Rotation ("Rotation", Range) (0, 360)) = 0 [NoScaleOffset] _Tex ("Cubemap (HDR)", Cube) = "hall" {} _Stencil ("StencilNum", int) = 6} SubShader {Sildid {"Queue" = "Taust" "RenderType" = "Background" "PreviewType" = "Skybox"} Kustuta ZWrite väljalülitatud segu SrcAlpha OneMinusSrcAlpha šabloon {Ref 1 Comp [_Stencil]} Pass {CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 2.0 #include "UnC.cginc "samplerCUBE _Tex; pool4 _Tex_HDR; pool4 _Tint; pool _Säritus; float _Rotation; float3 RotateAroundYInDegrees (float3 tipp, ujukraadid) {float alpha = kraadi * UNITY_PI / 180.0; float sina, cosa; sincos (alfa, sina, cosa); float2x2 m = float2x2 (cosa, -sina, sina, cosa); return float3 (mul (m, tipp.xz), tipp.y).xzy; } structure appdata_t {float4 tipp: POSITION; UNITY_VERTEX_INPUT_INSTANCE_ID}; structure v2f {float4 tipp: SV_POSITION; float3 texcoord: TEXCOORD0; UNITY_VERTEX_OUTPUT_STEREO}; v2f vert (appdata_t v) {v2f o; UNITY_SETUP_INSTANCE_ID (v); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO (o); float3 rotated = RotateAroundYInDegrees (v.vertex, _Rotation); o.vertex = UnityObjectToClipPos (pööratud); o.texcoord = v.vertex.xyz; tagasitulek o; } fikseeritud4 fragment (v2f i): SV_Target {half4 tex = texCUBE (_Tex, i.texcoord); pool3 c = dekodeerib HDR (tex, _Tex_HDR); c = c * _Tint.rgb * unity_ColorSpaceDouble.rgb; c *= _Säritus; tagastus pool4 (c,.5); } ENDCG}} Varuvõimalus välja}

Nüüd looge uus skyboxi materjal, nimetage see "PortalSkybox" ja valige portaali menüüst see portalSkybox shader. Minge ülaosas aknasse Valgustus ja valige see äsja loodud skybox. Minge põhikaamera juurde ja määrake skyboxile selged lipud. Siin olles lubame oma kaamerale lisada mõned komponendid, et saaksime kokkupõrkeid tuvastada. Lisage kaamerale jäik kehaosa ja tühjendage valik gravitatsiooni kasutamine. Lisage kasti põrkur ja kontrollige, kas see käivitab. Tehke kasti põrkurite suurus.5 x 1 x 4. Seadke kaameral olev lõiketasand väärtuseks.01.

8. samm: portaaliloogika

Portaali loogika
Portaali loogika

Viimane asi, mida peame tegema, on luua loogika, mis kontrollib meie portaali. Looge uus C# skript ja nimetage see PortalControlleriks.

kasutades System. Collections;

kasutades System. Collections. Generic; UnityEngine'i kasutamine; nimeruum UnityEngine. XR.iOS {public class PortalController: MonoBehaviour {public Material materjalid; avalik MeshRenderer meshRenderer; avalik UnityARVideo UnityARVideo; private bool isInside = false; private bool isOutside = true; // Kasuta seda initsialiseerimisel void Start () {OutsidePortal (); } void OnTriggerStay (kokkupõrke kol.) {Vector3 playerPos = Camera.main.transform.position + Camera.main.transform.forward * (Camera.main.nearClipPlane * 4); if (transform. InverseTransformPoint (playerPos).z <= 0) {if (isOutside) {isOutside = false; isInside = tõsi; InsidePortal (); }} else {if (isInside) {isInside = false; isOutside = tõsi; OutsidePortal (); }}} void OutsidePortal () {StartCoroutine (DelayChangeMat (3)); } void InsidePortal () {StartCoroutine (DelayChangeMat (6)); } IEnumerator DelayChangeMat (int stencilNum) {UnityARVideo.shouldRender = false; tootlus tagastab uue WaitForEndOfFrame (); meshRenderer.enabled = vale; foreach (Materjalimatt materjalides) {mat. SetInt ("_Stencil", stencilNum); } tootlus tagastab uue WaitForEndOfFrame (); meshRenderer.enabled = true; UnityARVideo.shouldRender = true; }}}

Lohistage see uus skript oma portaali aknale. See viib meid portaali sisse ja sealt välja, kui meie kaamera põrkur põrkab portaali aknaga kokku. Funktsioonis, mis muudab kõiki materjale, käsime ARkiti pistikprogrammil raami mitte renderdada, nii et minge põhikaamera juurde ja avage UnityARVideo skript. Looge ülaosas avalik bool shouldRender ja määrake see väärtuseks true. Funktsiooni OnPreRender () alla mähkige kõik if -lause, kus kõik sees käivitatakse ainult juhul, kui peaks olema tõene. Kogu skript peaks välja nägema selline:

süsteemi kasutamine;

kasutades System. Runtime. InteropServices; UnityEngine'i kasutamine; kasutades UnityEngine. Rendering; nimeruum UnityEngine. XR.iOS {avalik klass UnityARVideo: MonoBehaviour {public Material m_ClearMaterial; [HideInInspector] avalik bool peaksRender = true; privaatne CommandBuffer m_VideoCommandBuffer; privaatne Texture2D _videoTextureY; privaatne Texture2D _videoTextureCbCr; privaatne Matrix4x4 _displayTransform; privaatne bool bCommandBufferInitialized; public void Start () {UnityARSessionNativeInterface. ARFrameUpdatedEvent += UpdateFrame; bCommandBufferInitialized = vale; } tühine UpdateFrame (UnityARCamera nukk) {_displayTransform = uus Matrix4x4 (); _displayTransform. SetColumn (0, cam.displayTransform.column0); _displayTransform. SetColumn (1, cam.displayTransform.column1); _displayTransform. SetColumn (2, cam.displayTransform.column2); _displayTransform. SetColumn (3, cam.displayTransform.column3); } void InitializeCommandBuffer () {m_VideoCommandBuffer = uus CommandBuffer (); m_VideoCommandBuffer. Blit (null, BuiltinRenderTextureType. CurrentActive, m_ClearMaterial); GetComponent (). AddCommandBuffer (CameraEvent. BeforeForwardOpaque, m_VideoCommandBuffer); bCommandBufferInitialized = tõsi; } void OnDestroy () {GetComponent (). RemoveCommandBuffer (CameraEvent. BeforeForwardOpaque, m_VideoCommandBuffer); UnityARSessionNativeInterface. ARFrameUpdatedEvent -= UpdateFrame; bCommandBufferInitialized = vale; } #if! UNITY_EDITOR public void OnPreRender () {if (shouldRender) {ARTextureHandles handles = UnityARSessionNativeInterface. GetARSessionNativeInterface (). GetARVideoTextureHandles (); if (handles.textureY == System. IntPtr. Zero || handles.textureCbCr == System. IntPtr. Zero) {return; } if (! bCommandBufferInitialized) {InitializeCommandBuffer (); } Resolutsioon currentResolution = Screen.currentResolution; // Tekstuur Y, kui (_videoTextureY == null) {_videoTextureY = Texture2D. CreateExternalTexture (currentResolution.width, currentResolution.height, TextureFormat. R8, false, false, (System. IntPtr) käepidemed.tekstuurY); _videoTextureY.filterMode = FilterMode. Bilinear; _videoTextureY.wrapMode = TextureWrapMode. Repeat; m_ClearMaterial. SetTexture ("_ textureY", _videoTextureY); } // Tekstuuri CbCr if (_videoTextureCbCr == null) {_videoTextureCbCr = Texture2D. CreateExternalTexture (currentResolution.width, currentResolution.height, TextureFormat. RG16, false, false, (System. IntPtr) käepidemed.texC; _videoTextureCbCr.filterMode = FilterMode. Bilinear; _videoTextureCbCr.wrapMode = TextureWrapMode. Repeat; m_ClearMaterial. SetTexture ("_ textureCbCr", _videoTextureCbCr); } _videoTextureY. UpdateExternalTexture (käepidemed.tekstuurY); _videoTextureCbCr. UpdateExternalTexture (handles.textureCbCr); m_ClearMaterial. SetMatrix ("_ DisplayTransform", _displayTransform); }} #else public void SetYTexure (Texture2D YTex) {_videoTextureY = YTex; } public void SetUVTexure (Texture2D UVTex) {_videoTextureCbCr = UVTex; } public void OnPreRender () {if (! bCommandBufferInitialized) {InitializeCommandBuffer (); } m_ClearMaterial. SetTexture ("_ textureY", _videoTextureY); m_ClearMaterial. SetTexture ("_ textureCbCr", _videoTextureCbCr); m_ClearMaterial. SetMatrix ("_ DisplayTransform", _displayTransform); } #endif}}

Samm: peaaegu valmis

Peaaegu valmis!
Peaaegu valmis!

Lõpuks, kui klõpsame ekraanil ja asetame portaali, tahame, et see oleks alati meie poole suunatud. Selleks minge portaali skripti "UnityARHitTestExample". Asendage kõik seestpoolt järgmisega:

süsteemi kasutamine;

kasutades System. Collections. Generic; nimeruum UnityEngine. XR.iOS {avalik klass UnityARHitTestExample: MonoBehaviour {public Transform m_HitTransform; avalik ujuk maxRayDistance = 30.0f; public LayerMask collisionLayer = 1 <0) {foreach (var hitResult in hitResults) {Debug. Log ("Sain löögi!"); m_HitTransform.position = UnityARMatrixOps. GetPosition (hitResult.worldTransform); m_HitTransform.rotation = UnityARMatrixOps. GetRotation (hitResult.worldTransform); Debug. Log (string. Format ("x: {0: 0. ######} y: {1: 0. ######} z: {2: 0. ###### } ", m_HitTransform.position.x, m_HitTransform.position.y, m_HitTransform.position.z)); Vector3 currAngle = transform.eulerAngles; transform. LookAt (Camera.main.transform); transform.eulerAngles = uus Vector3 (currAngle.x, transform.eulerAngles.y, currAngle.z); tagastama tõene; }} return false; } // Värskendust kutsutakse üks kord kaadri kohta tühjaks Värskendus () {#if UNITY_EDITOR // me kasutame seda skripti ainult redaktori poolel, kuigi miski ei takista seda seadmes töötamast, kui (Input. GetMouseButtonDown (0)) {Ray ray = Camera.main. ScreenPointToRay (Input.mousePosition); RaycastHit tabas; // proovime tabada ühte pistikprogrammi loodud lennuki kokkupõrke mänguobjekti // mis sarnaneb tegelikult HitTesti helistamisega ARHitTestResultType. ARHitTestResultTypeExistingPlaneUsingExtent if (Physics. Raycast (ray, out hit, maxRayDistance, collisionLayer)) {// saame positsiooni kontaktpunktist m_HitTransform.position = hit.point; Debug. Log (string. Format ("x: {0: 0. ######} y: {1: 0. ######} z: {2: 0. ###### } ", m_HitTransform.position.x, m_HitTransform.position.y, m_HitTransform.position.z)); // ja pöörlemine tasapõrkesti teisendusest m_HitTransform.rotation = hit.transform.rotation; }} #else if (Input.touchCount> 0 && m_HitTransform! = null) {var touch = Input. GetTouch (0); if (touch.phase == TouchPhase. Began || touch.phase == TouchPhase. Moved) {var screenPosition = Camera.main. ScreenToViewportPoint (touch.position); ARPointi punkt = uus ARPoint {x = screenPosition.x, y = screenPosition.y}; // Prioritiseerima reults liiki ARHitTestResultType resultTypes = {ARHitTestResultType. ARHitTestResultTypeExistingPlaneUsingExtent, // kui te soovite kasutada lõpmatu lennukid kasutavad seda: //ARHitTestResultType. ARHitTestResultTypeExistingPlane, ARHitTestResultType. ARHitTestResultTypeHorizontalPlane, ARHitTestResultType. ARHitTestResultTypeFeaturePoint}; foreach (ARHitTestResultType resultType in resultTypes) {if (HitTestWithResultType (point, resultType)) {return; }}}} #endif}}}

Samm: pange rakendus oma telefoni

Pange rakendus oma telefoni!
Pange rakendus oma telefoni!

Lõpuks oleme valmis. Minge faili, looge seaded ja klõpsake ehita. Avage Xcode ja valige kaust, mis ehitise põhjal loodi. Valige oma arendusmeeskond ja pange rakendus oma telefoni! Võib -olla soovite osakeste ja taevakasti värve muuta, et need vastaksid teie vajadustele. Kui teil on küsimusi ja andke teada, andke mulle kommentaarides teada!