INHOUDSOPGAWE:

AR -portaal onderstebo van vreemde dinge: 10 stappe (met foto's)
AR -portaal onderstebo van vreemde dinge: 10 stappe (met foto's)

Video: AR -portaal onderstebo van vreemde dinge: 10 stappe (met foto's)

Video: AR -portaal onderstebo van vreemde dinge: 10 stappe (met foto's)
Video: 10 gewoontes om gelukkig te worden 2024, November
Anonim
AR -portaal onderstebo van vreemde dinge
AR -portaal onderstebo van vreemde dinge
AR -portaal onderstebo van vreemde dinge
AR -portaal onderstebo van vreemde dinge

Hierdie Instructable gaan deur die skep van 'n augmented reality -mobiele app vir die iPhone met 'n portaal wat na die onderkant van die Stranger Things lei. U kan binne -in die portaal gaan, rondloop en terugkom. Alles binne die portaal kan slegs deur die portaal gesien word totdat u binne stap. As dit eers binne is, sal alles oral weergegee word, totdat jy weer deur die werklike wêreld loop. Ons gebruik die Unity 3D -videospeletjie -enjin met die Apple ARKit -inprop. Al die sagteware wat ons gebruik, kan gratis afgelaai en gebruik word. U hoef nie 'n deskundige te wees om saam te volg nie; ons sal elke stap ondergaan!

Stap 1: Begin 'n nuwe eenheidsprojek

Begin 'n nuwe eenheidsprojek
Begin 'n nuwe eenheidsprojek

Laai eers Unity3D af en maak seker dat u die boulêers vir die IOS -platform installeer. U moet ook Xcode aflaai en aanmeld vir 'n gratis app -ontwikkelaarrekening. U iPhone moet ook IOS 11 of hoër hê. Vanaf 5 Februarie 2018 is IOS 11.3 uit, maar xCode 9.2 het nog nie ondersteuningslêers daarvoor nie. As u dus die nuutste IOS -weergawe gebruik, moet u die nuutste Xcode -beta -weergawe van Apple. Developer.com aflaai.

Sodra u al die nodige programme het, maak Unity oop en begin 'n nuwe projek, noem dit wat u wil. Ons gaan die Apple ARKit -inprop nodig hê sodat ons die kamera van ons telefoon kan gebruik om die grond op te spoor en 'n voorwerp op die vloer te vind. Laat ons dit nou invoer deur na die tabblad Asset Store te gaan en "ARKit" te soek. U moet 'n gratis Unity -rekening skep as u nog nie een het nie, en klik dan op invoer om die inprop te kry.

Gaan na die gids voorbeelde in die ARKit -lêergids en vind die 'UnityARKitScene'. Dubbelklik daarop om dit oop te maak. Ons gaan hierdie toneel as vertrekpunt gebruik en van hieruit bou. Met hierdie toneel kan u standaard die grond opspoor, en as u op die skerm tik, word 'n kubus in die posisie geplaas.

Laat ons eers ons bou -instellings kwadraat, sodat ons nie vergeet om dit later te doen nie. Klik op lêer, bou instellings en verwyder alle tonele uit die lys. Klik op Voeg oop tonele by om ons huidige een by te voeg. Die laaste ding wat ons hier moet opstel, is in die spelerinstellings na die bundel -identifiseerder en die formaat vir hierdie string is com. YourCompanyName. YourAppName, so in my geval doen ek iets soos com. MatthewHallberg. PortalTest.

Stap 2: Stel die toneel op

Stel die toneel op
Stel die toneel op

Kyk eers na links en vind die spelvoorwerp genaamd "GeneratePlanes". As dit gemerk is, kyk nou regs en klik op die boks om dit uit te skakel. Op hierdie manier word die lelike blou vierkante nie gegenereer wanneer ARKit 'n grondvlak opspoor nie. Skrap dan die "RandomCube" spelvoorwerp omdat ons dit nie in ons toneel wil sien nie.

Nou moet ons eers ons portaalopening skep. Verwyder die kubus wat 'n kind van die "HitCubeParent" is. Regskliek en kies om 'n leë spelvoorwerp te skep. Hernoem dit "Portal". Klik nou met die rechtermuisknop op die voorwerp en skep 'n kubus, dit maak dit 'n kind van die portaal. Hernoem dit "PostLeft" en dit sal die linkerpos van ons portaal wees. Skaal dit sodat die x 1 is y die 28 en die z een is. Doen dieselfde vir die regte pos. Skep nou die boonste paal en skaal die y tot 14. Draai dit sywaarts en skuif dit sodat dit die ander poste verbind. Maak die hele portaalskaal 1,3 x 1,4 x 1.

Gaan na Google en tik hout- of bastekstuur in. Laai een van die beelde af en sleep dit na u batesmap in Unity. Sleep die prentjie nou na al u portaalposte.

Klik weer op die "Portal" -voorwerp en klik op voeg komponent aan die regterkant. Voeg die script "UnityARHitTestExample" daarby. Daar is 'n leë gleuf vir "Hit Transform", sleep die "HitCubeParent" -voorwerp na die gleuf.

Stap 3: Kom ons maak 'n paar deeltjies

Kom ons maak 'n paar deeltjies
Kom ons maak 'n paar deeltjies

Nou gaan ons die Unity Particle -stelsel gebruik om 'n rook- en drywende deeltjie -effek vir ons portaal te maak. Gaan na bates in die boonste menubalk, standaardbates en invoerdeeltjiesisteme.

Skep twee leë spelvoorwerpe in u portaal en noem die een 'SmokeParticles' en die ander 'FloatingParticles'.

Voeg 'n deeltjiesisteemkomponent by die rookdeeltjies.

Hierdie komponent het baie opsies, maar ons hoef slegs 'n paar te verander.

Verander die beginkleur na iets donkerblou met ongeveer 50% deursigtigheid. Maak die emissiesnelheid 100. Binne -vorm, maak die radius.01. In die weergawegedeelte onderaan verander die grootte na 0,8 en die maksimum grootte na 5. Kies die rookmateriaal uit die lys op die materiaalkomponent, maar ons gaan dit later verander.

Voeg nou 'n deeltjiesisteem by die drywende deeltjie -wildvoorwerp en stel die emissie op 500. Stel die beginleeftyd op 2, radius op 10, min deeltjiegrootte tot 0,01 en die maksimum deeltjiegrootte op 0,015. Stel die materiaal vir eers op standaarddeeltjie.

Uiteindelik neem albei wildvoorwerpe en draai hulle met 90 grade op die x en lig hulle in die lug sodat hulle na die portaalopening uitstraal.

Stap 4: Vertraag die deeltjies

Vertraag die deeltjies
Vertraag die deeltjies

Aangesien ons wil hê dat hierdie deeltjies 'n groot gebied moet bedek, maar ook stadig beweeg, moet ons ons eie monsterfunksie skep. Klik met die rechtermuisknop in die map bates en skep 'n nuwe C# -skrip en noem dit 'ParticleSample'. Kopieer en plak hierdie kode in:

met behulp van System. Collections;

met behulp van System. Collections. Generic; gebruik UnityEngine; openbare klas ParticleSample: MonoBehaviour {private ParticleSystem ps; // Gebruik dit vir inisialisering leemte Start () {ps = GetComponent (); StartCoroutine (SampleParticleRoutine ()); } IEnumerator SampleParticleRoutine () {var main = ps.main; main.simulationSpeed = 1000f; ps. Play (); opbrengs opbrengs nuwe WaitForSeconds (.1f); main.simulationSpeed =.05f; }}

Sleep hierdie skrip nou na elk van u deeltjiestelselspelvoorwerpe.

Stap 5: Skep die portaal

Skep die portaal!
Skep die portaal!

Nou moet ons die portaal skep, met die rechtermuisknop op die portaalspel -voorwerp en 'n vierhoek skep. Skaal die vierkant sodat dit die hele portaal dek; dit word ons portaalvenster. Die eerste ding wat ons moet byvoeg, is die portaalskaker, dit gee slegs voorwerpe weer met 'n ander spesifieke skakering. Klik met die rechtermuisknop in die batesmap en skep 'n nuwe onbelaaide skadu. Verwyder alles daar en plak hierdie kode in:

Shader "Portal/portalWindow"

{SubShader {Zwrite off Colormask 0 cull off Stencil {Ref 1 Pass vervang} Pas {}}}

Klik met die rechtermuisknop in die hiërargie en skep 'n nuwe materiaal, noem dit PortalWindowMat, vind in die keuselys vir hierdie materiaal die portaalafdeling en kies portaalvenster. Sleep hierdie materiaal na u portaal -quad.

Stap 6: Particle Shaders

Particle Shaders
Particle Shaders

Regskliek weer in die batesmap en skep 'n nuwe shader. Ons moet die shaders maak vir die deeltjies wat binne -in die portaal gaan. Vervang al die kode hiermee:

Shader "portaal/deeltjies" {

Eienskappe {_TintColor ("Tint Color", Color) = (0.5, 0.5, 0.5, 0.5) _MainTex ("Particle Textuur", 2D) = "white" {} _InvFade ("Soft Particles Factor", Range (0.01, 3.0)) = 1.0 _Stencil ("stencil", int) = 6} Kategorie {Tags {"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane"} Blend SrcAlpha OneMinusSrcAlpha ColorMask RGB Uitskakel Beligting Uit ZWrite Off SubShader {Stencil {Ref 1 Comp [_Stencil]} Slaag {CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 2.0 #pragma multi_compile_particles #pragma multi_compile_fog #include "UnityCG.cginc" fixed4 _TintColor; struct appdata_t {float4 hoekpunt: POSISIE; fixed4 kleur: KLEUR; float2 texcoord: TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID}; struct v2f {float4 hoekpunt: SV_POSITION; fixed4 kleur: KLEUR; 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.kleur = v.kleur * _TintColor; o.texcoord = TRANSFORM_TEX (v.texcoord, _MainTex); UNITY_TRANSFER_FOG (o, o.vertex); terugkeer o; } UNITY_DECLARE_DEPTH_TEXTURE (_CameraDepthTexture); float _InvFade; fixed4 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 = saturate (_InvFade * (sceneZ-partZ)); i.color.a *= vervaag; #endif fixed4 col = 2.0f * i.color * tex2D (_MainTex, i.texcoord); UNITY_APPLY_FOG (i.fogCoord, kol); terugkeer kol; } ENDCG}}}}}

Skep twee nuwe materiale, een genaamd portalSmoke en een met die naam portalParticles.

Kies vir elkeen hierdie skakerings, in die keuselys, in portale, deeltjies. Kies vir die rookdeeltjies 'n rooktekstuur en vir die deeltjies die deeltjietekstuur. Verander die kleur van die rook na 'n donkerder blou met ongeveer 50% deursigtigheid. Gaan na die renderer -komponent van elke deeltjiesisteem in u portaal en kies hul onderskeie materiale wat ons pas geskep het.

Stap 7: Skep die Skybox

Skep die Skybox
Skep die Skybox

Om die onderstebo voorkoms regtig te skep, moet ons alles donkerblou kleur. Hiervoor gebruik ons 'n deursigtige skybox, maak 'n nuwe shader en plak hierdie kode in:

Skaduwee "Portal/portalSkybox" {

Eienskappe {_Tint ("Tint Color", Color) = (.5,.5,.5,.5) [Gamma] _Exposure ("Exposure", Range (0, 8)) = 1.0 _Rotation ("Rotation", Range (0, 360)) = 0 [NoScaleOffset] _Tex ("Cubemap (HDR)", Cube) = "grys" {} _Stencil ("StencilNum", int) = 6} SubShader {Tags {"Queue" = "Agtergrond" "RenderType" = "Agtergrond" "PreviewType" = "Skybox"} Skrap ZWrite Off Blend SrcAlpha OneMinusSrcAlpha Stencil {Ref 1 Comp [_Stencil]} Slaag {CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 2.0 #include "UnityCG.cginc "samplerCUBE _Tex; half4 _Tex_HDR; half4 _Tint; half _Beligting; float _Rotasie; float3 RotateAroundYInDegrees (float3 hoekpunt, float grade) {float alfa = grade * UNITY_PI / 180.0; float sina, cosa; sincos (alfa, sina, cosa); float2x2 m = float2x2 (cosa, -sina, sina, cosa); return float3 (mul (m, vertex.xz), vertex.y).xzy; } struct appdata_t {float4 hoekpunt: POSISIE; UNITY_VERTEX_INPUT_INSTANCE_ID}; struct v2f {float4 hoekpunt: 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 gedraai = RotateAroundYInDegrees (v.vertex, _Rotation); o.vertex = UnityObjectToClipPos (geroteer); o.texcoord = v.vertex.xyz; terugkeer o; } fixed4 frag (v2f i): SV_Target {half4 tex = texCUBE (_Tex, i.texcoord); half3 c = DecodeHDR (tex, _Tex_HDR); c = c * _Tint.rgb * unity_ColorSpaceDouble.rgb; c *= _ Blootstelling; gee half4 terug (c,.5); } ENDCG}} Terugval af}

Skep nou 'n nuwe skybox -materiaal, noem dit 'PortalSkybox' en kies hierdie portalSkybox -skakering uit die portaalkieslys. Gaan na Venster, Beligting bo -aan en kies hierdie skybox wat ons pas geskep het. Gaan na die hoofkamera en stel duidelike vlae op die skybox. Terwyl ons hier is, kan ons 'n paar komponente by ons kamera voeg sodat ons botsings kan opspoor. Voeg 'n stewige liggaamskomponent by die kamera en verwyder die gebruik van swaartekrag. Voeg 'n boksbotser by en kyk of die sneller is. Maak die boksbotsers grootte, 5 x 1 x 4. Stel die knipvlak op die kamera op.01.

Stap 8: Portaallogika

Portaallogika
Portaallogika

Die laaste ding wat ons moet doen, is om die logika te skep wat ons portaal beheer. Skep 'n nuwe C# -skrip en noem dit PortalController.

met behulp van System. Collections;

met behulp van System. Collections. Generic; gebruik UnityEngine; naamruimte UnityEngine. XR.iOS {public class PortalController: MonoBehaviour {public Material materials; openbare MeshRenderer meshRenderer; openbare UnityARVideo UnityARVideo; private bool isInside = false; private bool isOutside = waar; // Gebruik dit vir inisialisering leemte Start () {OutsidePortal (); } ongeldig OnTriggerStay (Collider col) {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 = waar; InsidePortal (); }} anders {if (isInside) {isInside = false; isOutside = waar; OutsidePortal (); }}} ongeldig OutsidePortal () {StartCoroutine (DelayChangeMat (3)); } maak InsidePortal () {StartCoroutine (DelayChangeMat (6)) ongeldig; } IEnumerator DelayChangeMat (int stencilNum) {UnityARVideo.shouldRender = false; opbrengs opbrengs nuwe WaitForEndOfFrame (); meshRenderer.enabled = false; foreach (Materiaalmat in materiale) {mat. SetInt ("_Stencil", stencilNum); } opbrengs opbrengs nuwe WaitForEndOfFrame (); meshRenderer.enabled = true; UnityARVideo.shouldRender = waar; }}}

Sleep hierdie nuwe skrif na u portaalvenster. Dit sal ons in en uit die portaal oorgaan wanneer die botsing op ons kamera met die portaalvenster bots. In die funksie wat al die materiaal verander, sê ons dat die ARkit -inprop nie die raam moet weergee nie, dus gaan na die hoofkamera en maak die UnityARVideo -script oop. Skep 'n openbare bool as dit aan die bokant gelewer word en stel dit gelyk aan waar. Onder in die OnPreRender () -funksie, draai alles in 'n if -verklaring, waar alles binne -in slegs loop as shouldRender waar is. Die hele skrif moet so lyk:

met behulp van System;

met behulp van System. Runtime. InteropServices; gebruik UnityEngine; gebruik UnityEngine. Rendering; naamruimte UnityEngine. XR.iOS {openbare klas UnityARVideo: MonoBehaviour {publieke materiaal m_ClearMaterial; [HideInInspector] openbare bool shouldRender = true; private CommandBuffer m_VideoCommandBuffer; private Texture2D _videoTextureY; private Texture2D _videoTextureCbCr; private Matrix4x4 _displayTransform; private bool bCommandBufferInitialized; openbare leemte Begin () {UnityARSessionNativeInterface. ARFrameUpdatedEvent += UpdateFrame; bCommandBufferInitialized = vals; } ongeldige UpdateFrame (UnityARCamera -kamera) {_displayTransform = nuwe 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); } ongeldig InitializeCommandBuffer () {m_VideoCommandBuffer = nuwe CommandBuffer (); m_VideoCommandBuffer. Blit (null, BuiltinRenderTextureType. CurrentActive, m_ClearMaterial); GetComponent (). AddCommandBuffer (CameraEvent. BeforeForwardOpaque, m_VideoCommandBuffer); bCommandBufferInitialized = waar; } ongeldig OnDestroy () {GetComponent (). RemoveCommandBuffer (CameraEvent. BeforeForwardOpaque, m_VideoCommandBuffer); UnityARSessionNativeInterface. ARFrameUpdatedEvent -= UpdateFrame; bCommandBufferInitialized = vals; } #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; } as (! bCommandBufferInitialized) {InitializeCommandBuffer (); } Resolution currentResolution = Screen.currentResolution; // Tekstuur Y as (_videoTextureY == null) {_videoTextureY = Texture2D. CreateExternalTexture (currentResolution.width, currentResolution.height, TextureFormat. R8, false, false, (System. IntPtr) handles.textureY); _videoTextureY.filterMode = FilterMode. Bilinear; _videoTextureY.wrapMode = TextureWrapMode. Repeat; m_ClearMaterial. SetTexture ("_ textureY", _videoTextureY); } // Texture CbCr if (_videoTextureCbCr == null) {_videoTextureCbCr = Texture2D. CreateExternalTexture (currentResolution.width, currentResolution.height, TextureFormat. RG16, false, false, (System. IntPtr) handles.textureCbCr); _videoTextureCbCr.filterMode = FilterMode. Bilinear; _videoTextureCbCr.wrapMode = TextureWrapMode. Repeat; m_ClearMaterial. SetTexture ("_ textureCbCr", _videoTextureCbCr); } _videoTextureY. UpdateExternalTexture (handles.textureY); _videoTextureCbCr. UpdateExternalTexture (handles.textureCbCr); m_ClearMaterial. SetMatrix ("_ DisplayTransform", _displayTransform); }} #else public void SetYTexure (Texture2D YTex) {_videoTextureY = YTex; } openbare leemte SetUVTexure (Texture2D UVTex) {_videoTextureCbCr = UVTex; } openbare leegte OnPreRender () {if (! bCommandBufferInitialized) {InitializeCommandBuffer (); } m_ClearMaterial. SetTexture ("_ textureY", _videoTextureY); m_ClearMaterial. SetTexture ("_ textureCbCr", _videoTextureCbCr); m_ClearMaterial. SetMatrix ("_ DisplayTransform", _displayTransform); } #endif}}

Stap 9: Byna klaar

Amper klaar!
Amper klaar!

As ons uiteindelik op die skerm klik en die portaal plaas, wil ons hê dat dit altyd na ons toe kyk. Gaan na die script "UnityARHitTestExample" op die portaal. Vervang alles binne deur:

met behulp van System;

met behulp van System. Collections. Generic; naamruimte UnityEngine. XR.iOS {openbare klas UnityARHitTestExample: MonoBehaviour {public Transform m_HitTransform; openbare vlot maxRayDistance = 30.0f; public LayerMask collisionLayer = 1 <0) {foreach (var hitResult in hitResults) {Debug. Log ("Got hit!"); m_HitTransform.position = UnityARMatrixOps. GetPosition (hitResult.worldTransform); m_HitTransform.rotation = UnityARMatrixOps. GetRotation (hitResult.worldTransform); Ontfout.log (string. Format ("x: {0: 0. #######} j: {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 = nuwe Vector3 (currAngle.x, transform.eulerAngles.y, currAngle.z); terugkeer waar; }} vals teruggee; } // Opdatering word een keer per raam leeggemaak Update () {#if UNITY_EDITOR // ons sal hierdie script slegs aan die redakteurskant gebruik, alhoewel daar niks is wat dit verhinder om op die toestel te werk as (Input. GetMouseButtonDown (0)) {Ray ray = Camera.main. ScreenPointToRay (Input.mousePosition); RaycastHit tref; // ons sal probeer om een van die vliegtuigbotsers -objekte wat deur die inprop gegenereer is, te raak // effektief soortgelyk aan die oproep van HitTest met ARHitTestResultType. ARHitTestResultTypeExistingPlaneUsingExtent if (Physics. Raycast (ray, out hit, maxRayDistance, collisionLayer)) {// ons gaan die posisie kry van die kontakpunt m_HitTransform.position = hit.point; Ontfout.log (string. Format ("x: {0: 0. #######} j: {1: 0. #######} z: {2: 0. ####### } ", m_HitTransform.position.x, m_HitTransform.position.y, m_HitTransform.position.z)); // en die rotasie vanaf die transformasie van die vliegtuigbotser m_HitTransform.rotation = hit.transform.rotation; }} #else if (Input.touchCount> 0 && m_HitTransform! = null) {var touch = Input. GetTouch (0); as (touch.phase == TouchPhase. Began || touch.phase == TouchPhase. Moved) {var screenPosition = Camera.main. ScreenToViewportPoint (touch.position); ARPoint -punt = nuwe ARPoint {x = screenPosition.x, y = screenPosition.y}; // Prioritiseer reults tipes ARHitTestResultType resultTypes = {ARHitTestResultType. ARHitTestResultTypeExistingPlaneUsingExtent, // as wat jy wil gebruik oneindige vliegtuie gebruik hierdie: //ARHitTestResultType. ARHitTestResultTypeExistingPlane, ARHitTestResultType. ARHitTestResultTypeHorizontalPlane, ARHitTestResultType. ARHitTestResultTypeFeaturePoint}; foreach (ARHitTestResultType resultType in resultTypes) {if (HitTestWithResultType (punt, resultType)) {return; }}}} #endif}}}

Stap 10: Sit die app op u telefoon

Sit die app op u telefoon!
Sit die app op u telefoon!

Uiteindelik is ons klaar. Gaan na lêer, bou instellings en klik op bou. Maak Xcode oop en kies die gids wat uit die build gemaak is. Kies u ontwikkelingspan en plaas die app op u telefoon! U kan die kleure van deeltjies en skybox verander om aan u behoeftes te voldoen. Laat weet my in die kommentaar as u vrae het en dankie dat u kyk!

Aanbeveel: