• No results found

5.3 Implementation

5.3.4 Visualisering med X3DOM

För att utveckla en X3DOM applikation krävs en HTML fil1 4 och i de flesta fall är det tillräckligt med en referens till X3DOM biblioteket. Men för denna applikation då objekt måste skapas mer dynamiskt används även en extern JavaScript fil, HTML och JavaScript filen presenteras komplett i appendix C och appendix D. Figur 24 visar ett första stadie av HTML filen för att komma igång med X3DOM utveckling.

Figur 24 Början på en X3DOM applikation

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<script src="../lib/x3dom-1.8.1/x3dom-full.js"></script>

<link rel="stylesheet" href="../lib/x3dom-1.8.1/x3dom.css">

<title>X3DOM ARTEFAKT</title>

</head>

<body>

<x3d>

<scene width="100%" height ="100%">

</scene>

</x3d>

<script src="../lib/chance.min.js"></script>

<script src="x3dom.js"></script>

</body>

</html>

Större delen av applikationen utgår ifrån HTML filen men med hjälp av JavaScript går det att skapa dynamik. I X3DOM är det enklare och mindre steg för att skapa en kamera och scen för att visa 3D objekt. Taggarna <x3d> och <scene> är allt som krävs för att skapa en färdig scen med en kamera. Inom <scene> taggen går det nu att lägga till 3D objekt med <shapes>

taggen och till en början skapas ett 2D plan vilket karttexturen skall appliceras på. <shapes>

taggen tar en under tagg, i detta fall <plane>, men kan även vara <cylinder> som kommer användas senare. Se Figur 25 för exempel kod på att skapa ett 2D plan i X3DOM.

Figur 25 Exempel på hur ett 2D plan kan skapas i X3DOM

När ett 3D objekt existerar går det att fritt lägga till texturer på objektet vilket kräver taggen

<appearance> och undertaggen <ImageTexture>. <appearance> applicerar

<ImageTexture> på ett objekt och det enda som krävs är att applicera en bild som textur är att sätta en referens till bilden som skall användas1 5, se Figur 26.

Figur 26 Exempel på applicering av en bild som textur på skapade

2D planet i Figur 25

<shape>

<plane solid="true" size="32 32"></plane>

</shape>

<shape>

<appearance>

<ImageTexture

url="../img/3_no_ice_clouds_16k_modified.jpg"><ImageTexture/>

</appearance>

<plane solid="true" size="32 32"></plane>

</shape>

En kamera behöver inte programmeras in likt ThreeJS men med <Viewpoint> taggen går det att bestämma en start vy applikationen ska placera kameran på som standard1 6. <Viewpoint>

taggen tar ett antal egenskaper vilket avgöra hur stort synfältet ska vara, orientering, hur långt respektive hur nära objekt relativt från kamerans placering ska renderas samt

mittpunkten kameran skall rotera runt. Alla dessa egenskaper behöver sättas om en standard punkt för kameran skall användas men denna tagg behöver inte skrivas manuellt då X3DOM har ett inbyggt debugging verktyg. När applikationen exekveras i webbläsaren går det att med tangenten D öppna detta verktyg och sedan trycka på V för att hämta alla inställningar till

<Viewpoint> taggen beroende på hur kameran är ställd när V tangenten trycks ner. Detta sparade mycket tid då istället för att ändra värden tills rätt värden hittades kunde hela taggen kopieras från debugging verktyget när kameran vinklats på önskat sätt. Se Figur 27 för exempel på hur <Viewpoint> taggen kan se ut.

Figur 27 Exempel på en standard Viewpoint.

<Viewpoint position="8.71025 -9.76534 9.28174"

orientation="0.78101 0.32915 0.53075 1.14474"

zNear="3.34706" zFar="32.17348" centerOfRotation="0.00000 0.00000 0.00000"

fieldOfView="45.00000" description="defaultX3DViewpointNode">

</Viewpoint>

X3DOM är ett DOM baserat bibliotek så för att dynamiskt lägga till objekt går det alltså att använda sig utav JavaScript funktionerna .createElement och .appendChild. Med

.createElement går det att programmatiskt skapa en tagg vilket med .appendChild

funktionen lägger till taggen under en existerande tagg i DOM;en. Den här applikationens tagg vilket cylinder objekten kommer skapas under är en <transform> tagg. <transform>

taggen fungerar likadant som i CSS i vilket den har möjlighet att rotera och placera grafik.

Denna tagg är viktig för att vända cylindrarna till ett horisontellt läge och tar x,y,z

koordinater som egenskaper. Till sist sätts även ett ID på <transform> taggen vilket behövs för att enkelt kunna programmatiskt bestämma att nya taggar skall placeras under denna

<transform> tagg1 7, se Figur 28.

Figur 28 Exempel på en transform tagg med ID för att kunna lägga

till undertaggar.

Likt ThreeJS artefakten skapades även i X3DOM en FOR-loop vilket styr hur många cylindrar som kommer ritas ut till scenen. Beroende på datavärdet färgläggs cylindrarna efter detta vid varje iteration av loopen. Färger kan appliceras med cylinder attributet diffusecolor.

Först måste taggarna <material> och <appearance> inom en cylinder <shape> skapas med .createElement, därefter kan funktionen .setAttribute användas för att lägga till attribut till tidigare skapade material och appearance taggar1 8, i detta fall är det färgen, se Figur 29.

Figur 29 Exempel kod för färgsättning av cylinder objekt för varje

ny cylinder skapad vid en iteration av FOR-loopen.

for (var i = 0; i < 1000; i++) {

var mat = document.createElement('Material');

var app = document.createElement('Appearance');

if (heightARR[i] > 700) {

<transform id="root" rotation="1 0 0 -1.57">

</transform>

Med redan nämnda funktioner går det att skapa cylindrarna1 9, en till <transform> tagg används för att slumpmässigt ge cylindrar en position på kartan och sedan lägga till cylindrarna i DOM;en. Här används ChanceJS funktionerna till att slumpmässigt generera X och Y koordinater vilket är punkten cylindern ska placeras på i scenen. Koordinaterna sätts som attribut till den nya <transform> taggen vilket kommer hålla cylindern. Under den nya

<transform> taggen skapas en <shape> tagg med en cylinder där beroende på värdet i datasettet påverkar höjden hos cylindern. Funktionen Math.round används här för att hantera de värden från det existerande datasettet vilket innehåller decimaler och avrundar till närmaste heltal, se Figur 30 samt Figur 31 för resultatet av koden.

Figur 30 Exempel kod för att sätta höjd på cylindrar och en seedad

slump position.

1 7 https://github.com/redines/A17PONGO-EXJOBB2020/commit/3edb588

1 8 https://github.com/redines/A17PONGO-EXJOBB2020/commit/d21f0de var t = document.createElement('Transform');

t.setAttribute(

'translation',

seed.floating({ min: -5.8, max: -1.8 }) +

' -0.5 ' + seed.floating({ min: -10.5, max: -3.5 }) );

var s = document.createElement('Shape');

s.appendChild(app);

t.appendChild(s);

var b = document.createElement('Cylinder');

b.setAttribute('radius', 0.01);

b.setAttribute('height', "0." + Math.round(heightARR[i]));

s.appendChild(b);

var ot = document.getElementById('root');

ot.appendChild(t);

Figur 31 Slutresultat av koden för X3DOM artefakten

Related documents