Glesa voxelträd: skapande och lagring HENNING TEGEN

Storlek: px
Starta visningen från sidan:

Download "Glesa voxelträd: skapande och lagring HENNING TEGEN"

Transkript

1 Glesa voxelträd: skapande och lagring HENNING TEGEN Examensarbete Stockholm, Sverige 2010

2 Glesa voxelträd: skapande och lagring HENNING TEGEN Examensarbete i datalogi om 30 högskolepoäng vid Programmet för datateknik Kungliga Tekniska Högskolan år 2010 Handledare på CSC var Lars Kjelldahl Examinator var Lars Kjelldahl TRITA-CSC-E 2010:054 ISRN-KTH/CSC/E--10/054--SE ISSN Kungliga tekniska högskolan Skolan för datavetenskap och kommunikation KTH CSC Stockholm URL:

3 Sammanfattning Voxlar (volumetric-pixel) har historiskt använts mest för att representera volymetrisk data som rök, vätskor och olika tillämpningar inom medicin. Minneskomplexiteten för detta är dock ofta O(n 3 ) vilket gör voxelgrafik ineffektivt för modeller där vi enbart är intresserade av att spara ytor. Med hjälp av en datastruktur som kallas glesa voxelträd (Sparse Voxel Octree) går det att minska minneskomplexiteten närmare O(n 2 ) förutsatt att man bara är intresserad av att spara ytor i modellen. Detta öppnar möjligheter för voxelgrafiken att på sikt inom vissa områden ersätta triangelgrafik då voxlar har flera fördelar mot trianglar, som t.ex. automatiserad LOD (Level Of Detail) kalkylering. Om voxelgrafik med hjälp av glesa voxelträd ska kunna ersätta triangelgrafik måste det finnas robusta och effektiva sätt att skapa och lagra glesa voxelträd vilket är precis vad jag undersöker i denna rapport. Jag gör en utförlig analys av fördelar och nackdelar med de olika datastrukturerna för att spara noderna i ett glest voxelträd. Vidare undersöker jag några viktiga aspekter för voxelmodellering såsom modeller större än minnesutrymmet samt undo-redo funktionalitet. Under detta arbete har jag även implementerat en prototyp som demonstrerar att ovanstående teknik fungerar i praktiken. I slutet av rapporten går jag igenom gränssnittet för min prototyp.

4 Abstract Sparse Voxel Octrees: creating and storing Historically voxels have mostly been used to represent volymetric data such as smoke, fluids and various applications in medicine where we are interested in the volume of the model. The memory complexity for this is usually O(n 3 ) which make voxel graphics inefficient for models where we only are interested in storing surfaces. With the help from a data structure called Sparse Voxel Octrees it is possible to reduce the memory complexity closer to O(n 2 ) presuming that we are mostly storing surfaces in our model. This opens up the possibilities for voxel graphics to replace triangle graphics in certain areas where voxels have an advantage (e.g. automatic LOD calculation). If voxel graphics, with the help from Sparse Voxel Octrees, should be able to replace triangle graphics there must exist robust and efficient solutions to create and store them, which is precisely what I research in the paper. I have made a comprehensive study on possible data structures for storing node data with there advantages and disadvantages. Furthermore, I research some important aspects of voxel modeling, such as larger models than what can fit inside the main memory and undo-redo functionality. I have also implemented a prototype to demonstrate that the above technology really works in practice. At the end of this paper I describe the interface for my prototype.

5 Förord Denna magisteruppstats i datalogi är utförd på CSC på Kungliga Tekniska Högskolan i Stockholm under våren Jag har skrivit rapporten på svenska, inte engelska, vilket gett mig en del problem då de flesta facktermer kommer från engelskan. Många av de engelska termerna har ingen tidigare svensk översättning, jag har därför tagit mig friheten att själv översätta några av dem till svenska. Detta inkluderar titeln på rapporten: glesa voxelträd. Jag skulle vilja tacka de personer som gett mig tips och råd under projektet samt min familj som bland annat har hjälpt mig med korrekturläsning. Slutligen vill jag tacka min handledare och examinator Lars Kjelldahl. Henning Tegen, Stockholm, 9 juni 2010

6

7 Innehåll 1 Inledning Vad jag förutsätter av läsaren Bakgrund Trianglar och texturer Parallellisering Ray tracing Ett nytt modelleringsparadigm Voxelgrafik Glesa voxelträd Disposition Tekniska termer Målsättning Problemställning Mål Avgränsningar Tidigare arbeten Voxelforskning och 90-talet talet Inläsning Teori Ray tracing Voxel Octree Glesa Voxelträd (GVT) Dataseparation Topologidata Shadingdata Mipmapping Paging

8 4.8 Rendering en GVT-modell Voxalisering Transformation SMP (Parallellisering på CPU:n) Dataåtkomst Analys av datastrukturer Översikt och problemställning Grundläggande datastrukturer för GVT Pekarträd XYZ-Hashtabell Morton-Hashtabell Trädkod Trädkod-offset Sammanfattning av grundläggande datastrukturer Förbättringar till datastrukturerna Leafbits Nodblock Val av datastruktur Tre olika datastrukturer Datastruktur för generering och editering Datastruktur för CUDA rendering Metadata Analys av algoritmer Nodtraversering Bredden-först-sökning (BFS) Djupet-först-sökning (DFS) Djupet-först-sökning med mipmapping DFS och BFS kombination Skapa en nod Förändring av rotnoden Paging Översikt Page LRU (Least Recently Used) Page metadata Page datastruktur Parallelliserad paging Layers Undo-Redo Algoritm Datastruktur Lagring på disk Översikt

9 6.6.2 Komprimering till disk Implementation Programmeringsspråk Operativsystemsmiljö Implementeringsstruktur Front-End Back-End FS (File System) Skal Resultat Prototypen Syfte Implementering Demonstration Datastrukturer Nod Page Layers och History Uppfyllande av målen Mål 1: Editering Mål 2: Ingen rumsgräns Mål 3: Multipla undo-redo samt layers Mål 4: Modeller större än minnesutrymme Mål 5: CUDA Export Mål 6: Minimera hårdiskutrymme Mål 7: Prestanda Diskussion och slutsats Diskussion Jämförelse med triangelgrafik Kommersiell framtid för GVT Min vision Framtidsförbättringar Optimerade GVT modeller Automatisk mipmapping Nätverkseditering GVT-animering Användargränssnitt Progressiv editering CSG modellering Pekarträd med struct-hack Slutsats

10 Referenser 65

11 Kapitel 1 Inledning 1.1 Vad jag förutsätter av läsaren För att kunna tillgodogöra sig innehållet i denna rapport bör läsaren ha en grundläggande förståelse för programmering och datorgrafik. I kapitel 1.4 finns det en ordlista över tekniska termer. Ordlistan är dock mer tänkt som en påminnelse. Om läsaren aldrig hört talas om orden i listan kommer rapporten bli svårbegriplig. 1.2 Bakgrund Trianglar och texturer Sedan 3D-grafikens begynnelse har triangeln stått i fokus för all form av modellering av linjära ytor. De viktigaste anledningarna till detta är att en triangel tar lite plats i minne samt att det finns mycket effektiva algoritmer för att rasterisera dem till skärmen. Det finns även många metoder för att modellera krökta ytor som t.ex. bézier-kurvor och NURBS. Gemensamt för alla krökta ytor är dock att det vanligaste sättet att rendera dem är att först konvertera dem till trianglar [Akenine 2002, p. 512]. Genom ökad efterfrågan på realism och detaljrikedom i datorgrafik har man de sedan länge börjat lägga på texturer på trianglarna. Till en början för att representera färger men på senare tid även för kunna ändra mer avancerade saker som normal och reflexion. När man började använda texturer (framför allt i realtidsgrafik) använde man först så kallade tiles, vilket innebär att man har en liten textur som man sedan repetitivt upprepar gång på gång över trianglarna i syfta att spara minne. Detta minskar dock realismen då varje yta inte kan ha sin egna speciella karaktär. På senare år har företag som id Software börjat med vad de kallar för unik-texturering vilket betyder att varje yta i världen får sin egna unika textur. En konstnär kan sedan gå in och ge varje yta i världen sin egna distinkta karaktär [Carmack 2007b]. När unik-texturering används tar triangelmodellen dock inte längre lite plats i 1

12 KAPITEL 1. INLEDNING minne vilket ju var en av anledningarna att använda dem från början. id Software uppskattar t.ex. att en värld i deras nya spel Rage kan ta över 20 GB i rå form [Carmack 2007a] Parallellisering De senaste åren har hårdvarutillverkare gått mot mer och mer parallellisering i sina chip till skillnad från 80- och 90-talet då majoriteten av prestandaökningen kom från högre klockfrekvens. Den drivande anledningen bakom detta är att hårdvarutillverkare får svårare och svårare att höja klockfrekvensen och det är enklare att ha två beräkningskärnor med halva hastigheten i stället för en med den dubbla. Detta skapar dock nya problem för programmerare som nu måste anpassa sin mjukvara för flera beräkningskärnor. Två intressanta händelser de senaste åren som är relevant för mitt arbete är dels Cell-processorn som sitter i alla Playstation 3 och dels NVIDIA s nya grafikkort som stödjer CUDA. Båda dessa är exempel på att parallellisering är här för att stanna. Speciellt intressant för mitt arbete är CUDA, det har gjorts ett antal demonstrationer som visar att det nu är möjligt att köra ray tracing i realtid på grafikkortet. Se [Raytracey] för en bra sammanfattning av realtids ray tracers Ray tracing Under de senaste åren har vi sett ett ökat intresse för ray tracing. Än så länge är det mest en trend för offline-renderare som RenderMan [Cortes 2006]. Men som framgår ovan går det idag att köra ray tracing i realtid och jag skulle inte bli förvånad om det snart dyker upp datorspel och annan interaktiv mjukvara som utnyttjar detta faktum. Anledningen till att ray tracing blivit mer populärt är en kombination av implementeringens enkelhet, fysikaliska korrekthet samt dess flexibilitet. Problem som reflexion, refraktion, skuggor och global ljussättning som alltid varit svåra problem för en rasteriserare blir triviala för en ray tracer. En ray tracer går även enkelt att skala mellan kvalitet och prestanda genom att bara höja och sänka upplösningen samt antalet samplingar per pixel. Den primära orsak som hållit tillbaka ray tracing är att det än så länge varit betydligt långsammare än triangelrasterisering. Det finns två huvudanledningar bakom detta: 1. Att undersöka om en triangel och en stråle skär varandra är relativt långsamt. 2. En triangel kan vara utformad precis hur som helst vilket medför att man måste testa strålen mot alla trianglar. 3. Ray tracing mot trianglar kan söka i minnet i en ordning som inte lämpar sig bra för cachen. 2

13 1.2. BAKGRUND För att lösa problem 2 har triangel ray tracers använt sig av så kallade space partition scheman [Ericson 2005, kap. 7] vilket är en datastruktur som läggs ovanpå triangelmodellen och gör att strålen inte behöver testas mot alla trianglar. Detta ökar dock komplexiteten i implementeringen samt begränsar möjligheten för animation. Även om ray tracing är långsammare än rasterisering i dag är det på sikt möjligt att ray tracing kan gå om rasterisering i hastighet [Olick 2008] då Amdahl s lag sätter begränsningar för hur mycket prestandaökning en triangelrasteriserare kan uppnå vid parallellisering. Ray tracing har dock ingen sådan begränsning då ray tracing är vad som kallas för ett embarrassingly parallel problem vilket betyder att prestanda för ray tracing växer linjärt med antalet processorkärnor Ett nytt modelleringsparadigm För att få 3D-grafik till nästa nivå av realism hävdar jag och många andra [Laine 2010] [Crassin 2009] [Olick 2008] att ett nytt paradigm för 3D-modeller som bättre möter dagens krav är nödvändigt. Målen för detta nya paradigm, alltså det man vill undvika från dagens triangelrasterisering är följande: 1. Skala prestanda bra då datorer får mer och mer parallell beräkningskapacitet. 2. Möjlighet för realistisk reflektion, refraktion, skuggor och global-ljussättning. 3. Automatiserad, effektiv och korrekt nersampling av 3D-modellen, så kallad LOD. 4. Visualisera världar med unik texturering i storleksordningen 100 GB. 5. En så enkel implementering som möjligt. Det har länge varit känt att ray tracing löser mål 1, 2 och 5 [Suffern 2007] [Driemeyer 2005]. Problemet är alltså att hitta ett modelleringsparadigm som löser mål 3 och 4, samt är effektiv för ray tracing Voxelgrafik Parallellt med triangelns framgång har voxeln alltid varit populär i den akademiska världen samt i vissa specialiserade användningsområden i kommersiellavärlden [Akenine 2002, s. 342]. På senare senare år har det kommit så kallade digitala skulpteringsprogram (t.ex. ZBrush och Mudbox) som ofta använder någon form av voxelgrafik. Dessa skulpteringsprogram lämpar sig väl för ytor med mycket geometriska detaljer men skulle även teoretiskt fungera för att modellera vilka ytor som helst. Voxelgrafik är något som passar mycket bra tillsammans med unik texturering då varje del av modellen ändå måste representeras av en unik voxel. Detta gör voxelgrafik mer intressant för framtiden då unik texturering antagligen är här för att stanna. 3

14 KAPITEL 1. INLEDNING Glesa voxelträd För att rendera voxlar snabbt behöver man en datastruktur som kapslar in voxlarna och lämpar sig för ray tracing. I ett tidigare arbete [Tegen 2009] jag utförde under hösten 2009 visade jag att en teknik kallad glesa voxelträd (Sparse Voxel Octree) är en bra kandidat för detta. Det har även bekräftats av andra aktörer speciellt inom spelindustrin [Laine 2010] [Olick 2008] [Carmack 2008]. Den viktigaste poängen med voxelmodellering med GVT-teknik är att vi inte längre skiljer på geometri och texturer som i dagens triangelgrafik. Det finns bara en byggsten för både texturdata och geometridata: voxeln. GVT-tekniken gör det även möjligt att automatiserat nersampla modeller med en metod som liknar 2D mipmapping. [Laine 2010] har visat att glesa voxelträd är en datastruktur som är effektiv att ray tracea emot och ray tracing löser i sin tur ännu flera av de problem som triangel rasterisering har. Den största nackdelen med GVT-modellering jämfört med triangelgrafik ser i dagsläget ut att vara dynamisk geometri och animation. Det är inte trivialt hur detta kan utföras på en GVT-modell. Vad jag känner till finns det inte någon forskning på området så vi vet väldigt lite om det i dagsläget. Både [Olick 2008] och [Laine 2010] har några intressanta idéer för animering av GVT-modeller men ingen har provat dem i praktiken. Även om inte GVT-modeller lämpar sig för animering finns det stora användningsområden för statiska modeller som t.ex. landskap och städer. På sikt är det även möjligt att någon lyckas hitta en effektiv metod för animering av GVT-modeller vilket skulle öppna möjligheterna ytterligare. 1.3 Disposition I kapitel 2 presenterar jag problemställningen och målen för mitt arbete. I kapitel 3 presenterar jag tidigare arbeten som berör samma ämne. I kapitel 4 går jag igenom den grundläggande teorin som läsaren måste känna till för att kunna tillgodogöra sig resten av rapporten. Jag har delat upp analysen i två kapitel: kapitel 5 för datastrukturer och kapitel 6 för algoirtmer. Efter analysen följer en genomgång av min implementering i kapitel 7. Slutligen presenterar jag resultatet av arbetet i kapitel 8 följt av en diskution och slutsats i kapitel Tekniska termer Amdahls lag: Lag som definierar max teoretiska hastighetsökning vid parallellisering då en viss del av koden förblir seriell. Callback funktion: En funktion som är specificerad av användaren som sedan någon specifik modul använder. 4

15 1.4. TEKNISKA TERMER CPU: Står för Central Processing Unit, alltså datorns processor. CSG: Står för Constructive Solid Geometry, vilket är ett klassiskt sätt att utföra solid modellering. GPU: Står för Graphic Processing Unit, alltså datorns grafikkortsprocessor. GVT: Förkortning för Glesa VoxelTräd, alltså det rapporten handlar om. Då jag inte känner till någon tidigare översättning av Sparse Voxel Octree har jag tagit mig friheten att själv översätta det till glesa voxelträd. CUDA: Ett C liknande programmeringsspråk för nvidias grafikkort. Gränssnitt: Publika funktioner från ett programmeringsbibliotek. Detta är den enda kommunikations länken mellan ett programmeringsbibliotek och övrig kod. Layers: Hämtat från Photoshop termen som betyder att man har flera bilder ( layers ) i samma fil. Octree: En träddatastruktur där varje nod har upp till åtta barn. Page: Ett bit av ett virtuellt minne, som används i syfte att kunna ha mer data än vad det finns minne (se kapitel 6.3 för en mer utförlig förklaring). Programmeringsbibliotek: Kod kompilerat till ett paket som sedan kan användas av andra program. Rastergrafik: Rektangulärt rutnät av pixlar. För att kunna visa något på skärmen måste man först göra om det till rastergrafik. Rasterisera: Processen att gå från vektorgrafik till rastergrafik. Ray tracing: Processen att skjuta ut en stråle per pixel från skärmen och se vilket som är det första objekt i virtuell världen som den träffar. Rendering: Processen att genera en bild från någon slags modell. 5

16 KAPITEL 1. INLEDNING RW-lås: Står för Read-Write lås, alltså ett lås som ser till att flera trådar kan läsa från minnet men bara en kan skriva till det. Scanline conversion: Den klassiska metoden att rasterisera vektorgrafik. Shading: Processen att öka en ytas realism genom att bland annat skugga den enligt någon speciell ljusmodell. SMP: Förkortning för Symmetric MultiProcessing. Det vanligaste sättet att parallellisera arbete på en CPU. SVO: Förkortning för Sparse Voxel Octree, engelska benämningen på GVT. Textur: Tvådimensionell bild som projiceras på en tredimensionell yta i syfte att öka detaljrikedomen av denna yta. Triangelsoppa: Från engelskans triangle soup, vilket betyder en mängd trianglar där den inbördes ordningen inte är viktig. Undo: Att ångra en skrivoperation. Unik texturering: När varje triangel har sin egna texturyta. Voxel: Ordet kommer från en sammanslagning av volumetric och pixel vilket alltså är pixelns motsvarighet i 3D. Geometriskt blir detta en kub i rymden med ett visst antal attributer som t.ex. färg. X86: Vanligaste processorarkitekturen för persondatorer de senaste 25 åren. 6

17 Kapitel 2 Målsättning I detta kapitel går jag igenom problemställningen och målen för arbetet. I kapitel 8.3 går jag sedan igenom målen ytterligare en gång för att se hur bra jag lyckats uppfylla dem. 2.1 Problemställning Syftet med detta arbete är att undersöka de olika aspekterna för att kunna skapa och lagra GVT-modeller (Gelsa VoxelTräd modeller). Arbetet kan ses om en förstudie till ett Photoshop för GVT, alltså en applikation för editering av stora GVTmodeller. För att på sikt kunna bygga en sådan applikation finns det flera tekniska problem som måste lösas. Under arbetet har jag byggt en prototyp för att kunna undersöka de tekniska problemen i praktiken. I kapitel 2.2 listar jag de mål som min prototyp ska uppfylla. 2.2 Mål Följande mål vill jag att min prototyp ska uppfylla: 1. Editering Med editering menar jag att användaren ska kunna gå obegränsat fram och tillbaka mellan skapande och rendering av GVT-modellen. 2. Ingen rumsgräns Det ska inte finnas någon gräns i rumstorlek för GVT-modellen. Användaren ska inte heller behöva bestämma i förväg hur stor modellen slutligen kommer bli. 3. Multipla undo-redo samt layers Användaren ska kunna ångra ändringar han gjort till GVT-modellen samt ha flera GVT-modeller i samma fil. 7

18 KAPITEL 2. MÅLSÄTTNING 4. Stora modeller En 32-bitars process kan max använda 2 GB minne. GVT-modellerna vi hanterar i systemet ska dock kunna vara betydligt större än så. 5. CUDA export Möjlighet att exportera GVT-modellen till CUDA för rendering. 6. Minimera hårdiskutrymme Rå-data för en GVT-modell kan vara flera gigabyte så det är viktigt att komprimera data så mycket som möjligt innan vi skriver ut den på disk. Då min prototyp är tänkt för editering begränsar jag mig till lossless komprimering. 7. Prestanda Det är självklart alltid önskvärt att maximera prestanda. För att ta hjälp av parallellisering på dagens CPU tänker jag ta hjälp av SMP (Symmetric MultiProcessing). Bland ovanstående mål visar det sig att 3 och 4 är betydligt svårare att lösa än övriga och jag har därför valt att spendera mest tid på dem. Det visar sig även att varje mål var för sig är relativt lättlösligt men när man ska ha en implementering som uppfyller alla mål blir det genast mycket svårare. 2.3 Avgränsningar Mitt arbete har handlat primärt om skapande och lagring av GVT-modeller. Rendering är självklart en mycket viktig del av ett komplett system för GVT men då det redan finns effektiva algoritmer, framför allt av [Laine 2010] har jag i stället valt att fokusera på de mer outforskade delarna. Vad jag känner till finns det inget utförligt arbete om hur man effektivt skapar och lagra GVT-modeller. För en utförlig beskrivning och implementering av rendering av GVT-modeller hänvisar jag till [Laine 2010] och [Samet 1989] rapport. Mitt arbete fokuserar på det tekniska i att skapa GVT-modeller. Det finns även många problem för hur man låter en användare jobba med GVT-modeller på en smidigt sätt. Detta är dock något som jag lägger utanför fokus för denna rapport. 8

19 Kapitel 3 Tidigare arbeten I detta kapitel går jag igenom tidigare arbeten som är relevanta för mitt arbete. I kapitel 3.4 listar jag litteratur som inte direkt behandlar GVT-teknik, men som ändå har viss relevans för arbetet. 3.1 Voxelforskning Visualisering av volymer har varit ett aktivt forskningsområde i många år, mycket tack vare ett behov från medicinvärlden att visualisera olika delar av kroppen. En bra sammanfattning över volymvisualisering är [Engel 2006]. Jag är dock primärt intresserad av att använda voxlar för att visualisera ytor och inte volymer. De flesta datastrukturer från volymforskningen använder O(n 3 ) minne där n är bredd-höjdlängden av volymen och det blir därför inte relevanta för mitt arbete och 90-talet Två utförliga arbeten om octree s och voxlar är [Samet 1987] och [Samet 1989]. Dessa två artiklar är över 20 år gamla så deras definition av mycket minne (3 MB) har ändrats en del. Den underliggande teorin är dock densamma även om man i dagsläget har betydligt större möjligheter än de hade. [Samet 1987] är speciellt intressant för mitt arbete då den beskriver olika implementeringsidéer för GVTträd, de som kapitel 5 handlar om. En annan intressant rapport som också har några år på nacken är [Zesheng 1991]. Det mest intressanta i denna rapport är hur han konverterar mellan vektorgrafik och voxelgrafik samt utför olika manipulationer av GVT-modellen. Zesheng s Divide and Conquer teknik är en av de tekniker jag använder för generering av GVTmodeller. [Kaufman 1986] och [Houng 1998] har skrivit två intressanta rapporter om voxalisering, alltså processen att gå från vektormodell till voxelmodell. 9

20 KAPITEL 3. TIDIGARE ARBETEN talet Under sent 90-tal och tidigt 2000-tal verkar intresset för voxelgrafik varit lågt. Det finns inte många artiklar från dessa år och jag skulle gissa att anledningen till detta är triangelns framfart som till stor del berodde på dedikerad hårdvara. På senare år verkar intresset för voxelgrafik vaknat till liv igen. [Knoll 2006] och [Knoll 2009] är två rapporter som fortfarande primärt är inriktade på voxelgrafik för att representera volymer men använder ändå en datastruktur liknande KD-träd, vilket är intressant för mitt arbete då KD-träd och octree s delar flera likheter. [Crassin 2009] presenterar en algoritm som delar upp ray tracing av voxeldata i två delar. I den första kör han ray tracing mot ett octree, där varje löv representerar ett block av voxlar. I steg två av algoritmen använder han sedan en metod liknande [Amanatides 1987]. Crassin s metod är snabb och lämpar sig bra för dagens hårdvara men om man bara är intresserad av att spara ytor tenderar blocken att använda fruktansvärt mycket minne i onödan. [Olick 2008] har en presentation där han går igenom grunderna för GVT. Då det bara är en muntlig presentation saknas detaljer, men Olick beskriver precis det som är intressant för mitt arbete. Det mest relevanta tidigare arbetet för mig är dock [Laine 2010] som publicerades vintern 2010, två månader efter jag redan börjat på mitt arbete. [Laine 2010] presenterar en full algoritm med källkod för snabb rendering av GVT-modeller på CUDA. Deras papper fokuserar mestadels på rendering och fick mig att ändra fokus på mitt egna arbete från rendering till generering och lagring. En bra sammanfattande bok över datastrukturer för att spara geometriska ting är [Samet 2006]. 3.4 Inläsning Utöver den inläsning som är direkt relaterad till voxlar och GVT har jag även funnit följande böcker användbara för mitt arbete. Foundations of Multidimensional and Metric Data Structures [Samet 2006] En mycket utförlig bok som sammanfattar stor del av all forskning av datastrukturer för att spara geometriska ting. Boken har även en mycket imponerande referenslista vilket är användbart om man vill gå till källan för en viss datastruktur. Ray Tracing from the Group Up [Suffern 2007] Bästa boken jag känner till gällande ray tracing. Computer Graphics Principles and Practice [Foley 1996] Har ett intressant kapitel om solidmodellering. Real-Time Massive Model Rendering [Yoon 2008] En bra bok som beskriver olika metoder för att rendera stora modeller. 10

21 3.4. INLÄSNING Real-Time Collision Detection [Ericson 2005] Beskriver Octree s, Morton Keys, KD-träd och mycket annat som har hög relevans för mitt arbete och skriver om det på ett sätt som är lätt att ta till sig. Boken innehåller även källkod till del flesta algoritmerna. Rendering with Mental Ray [Driemeyer 2005] Egentligen en handbok för Mental Ray men beskriver även bra många koncept angående ray tracing från en implementationsmässig synvinkel. GPU Gems 3 [Nguyen 2008] Har några bra kapitel om CUDA programmering. 11

22

23 Kapitel 4 Teori I detta kapitel går jag igenom den bakomliggande teorin som läsaren bör känna till för att kunna tillgodogöra sig resterande delen av rapporten. 4.1 Ray tracing En stråle kan definieras matematiskt med r = r 0 + tv (0 < t < ) Där r 0 är strålens startpunk och v är dess riktning. När vi tracear en stråle är vi intresserad av att få reda på vilket som är det första objekt strålen träffar (lägst t) samt träffpunktens position (kan beräknas från t). Vanligaste användningsområdet för ray tracing är att rendera en bild av en virtuell värld. För att åstadkomma detta skickar man ut en stråle per pixel för att ta reda vilket som är det första objektet strålen träffar. Denna process illustreras i figur 4.1. Även om den vanligaste strålen i ray tracing är den som kommer från kameran finns det flera andra typer av strålar. En av dem är strålen för att beräkna skuggor som vi ser exempel på i figur 4.1. En virtuell värld kan teoretiskt bestå av vilka geometriska objekt som helst förutsatt att vi kan testa om en stråle träffar dem. Det är dock fördelaktigt att ha geometriska objekt där beräkningen om strålen träffar dem kan göras effektivt. En voxel (kub där sidorna är parallella till axlarna) är ett exempel på en sådant geometriskt objekt [Ericson 2005, s. 179]. 4.2 Voxel Ordet voxel kommer från en sammandragning av volumetric och pixel. En voxel är alltså pixelns motsvarighet i 3D vilket blir en kub i rymden med ett antal attribut som t.ex. färg. I figur 4.2 har jag grå-skuggat en av många voxlar. Precis som i 2D-fallet där flera pixlar kan bygga upp en bild kan flera voxlar bygga upp en modell. I 2D fallet använder man nästan alltid en matris för att lagra 13

24 KAPITEL 4. TEORI Figur 4.1. Beskriver grundläggande konceptet av ray tracing. Bilden är tagen från Wikipedia. Figur 4.2. En mängd voxlar varav en är gråskuggad. Bilden är tagen från Wikipedia. pixlarna och minnesutrymmet kommer då att växa med O(n 2 ) där n är matrisen bredd/höjd. Även voxlar kan lagras i 3D-versionen av en matris. Minnesutrymmet kommer dock nu växa med O(n 3 ) där n är matrisens bredd/höjd/djup vilket alltså är en polynomgrad snabbare än för 2D-fallet. En minneskonsumtion på O(n 3 ) kan lätt skapa praktiska problem för lite större voxelmodeller då en modell med enbart en bredd/höjd/djup på 1000 behöver 1 miljard voxlar ( ). I många voxelmodeller är det heller inte nödvändigt att spara alla voxlar om modellen t.ex. innehåller mycket tomrum. Detta är sant i vårt fall som primärt är inriktat på att spara ytor i voxelform. Det finns därför ett behov av en bättre datastruktur som kan utnyttja tomrum i modellen och därmed kan använda mindre minne än O(n 3 ). 4.3 Octree Octree är en datastruktur som är löst relaterat till voxlar. Från en matematisk synvinkel kan man beskriva ett octree som ett tredimensionellt binärt träd [Ericson 2005, 14

25 4.4. GLESA VOXELTRÄD (GVT) s. 308] där varje nod kan ha mellan 0 och 8 barn (childs). Första noden i trädet kallas för rot och om en nod inte har några barn kallar vi noden för löv. Från en geometrisk synvinkel kan man säga att ett octree rekursivt delar in rymden i kubiska block där varje block kan ha upp till 8 underblock. Ett exempel på detta kan ses i figur 4.3. Djupet i octree t kalas för nivå, där roten alltid ligger på nivå 0 och löven ligger i praktiken runt 8 till 18 (beror på hur stor modellen är). Figur 4.3. Varje nod kan delas upp i 8 underblock som i sin tur kan delas upp i 8 underblock. 4.4 Glesa Voxelträd (GVT) Ett glest voxelträd (Sparse Voxel Octree) är ett octree där löven i trädet är voxlar. Denna datastruktur gör att minnesutrymmet växer långsammare än O(n 3 ) förutsatt att det finns tomrum i modellen. Anledningen till detta är att vi slutar att förgrena en specifik nod om det inte finns några flera voxlar inuti denna som vi vill representera i modellen. I figur 4.4 ser vi en 2D motsvarighet av ett GVT (Glest VoxelTräd) där man bara fortsätter förgrena en nod om det finns underliggande geometri (voxlar). När nodernas storlek nått ett visst tröskelvärde slutar man att att förgrena dem och gör noderna till voxlar (ifyllda rutorna till vänster i figur 4.4). Denna rekursiva process skapar ett träd med max fördelningsfaktor 8 per nod som vi ser till höger i figur 4.4 (figuren är 2D fallet med max fördelningsfaktor 4). Processen är svårare att visualisera för 3D fallet (octree) men om man sätter kameran väldigt nära en GVT-modell och gör en rendering kan man se voxlarna (figur 4.5). Notera att i praktiken ska kameran aldrig komma så pass nära GVTmodellen och figur 4.5 är enbart till för att symbolisera GVT-tekniken. Förutsatt att vi bara sparar ytor i modellen och att voxelstorleken är någorlunda liten jämfört med ytorna vi vill spara får vi nu en minneskonsumtion som växer närmare mantelytan (O(n 2 )) av modellen jämfört med volymen (O(n 3 )). Anledningen till att jag säger närmare mantelytan beror på att den exakta minneskomplexiteten varierar från modell till modell. 15

26 KAPITEL 4. TEORI Figur 4.4. I vänstra bilden ser vi den geometriska aspekten av 2D versionen av ett octree (quadtree) och i högra ser vi den matematiska. Figur 4.5. Om kameran kommer för nära modellen ser man enskilda voxlar. Detta kallas för LEGO effekten. I tabell 4.1 har jag listat antal noder per nivå i trädet för en viss GVT-modell. De exakta siffrorna är inte relevanta men vi kan se att antalet noder växer med ca 4 (LAD = 2 motsvarar O(n 2 )) per nivå för de högra nivåerna, vilket bekräftar att antalet noder växer närmare mantelytan av modellen, jämfört med volymen. 4.5 Dataseparation När man sparar en GVT-modell i minnet eller på hårdisken kan man dela upp voxeldata i två delar: Den ena definierar jag som topologidata och den andra som shadingdata. Shadingdata är typiskt data som färg, normal och reflexion, alltså sådan data som behövs för att utföra ljusberäkningar (shading). Topologidata är 16

27 4.5. DATASEPARATION Tabell 4.1. Visar antal noder per nivå för en specifik GVT-modell. LAD värdet är andra logaritmen av skillnaden mellan nuvarande och föregående nivå (LAD = log 2(X n X n 1), där X är antal noder och n är nivå) Nivå Antal noder LAD data som bestämmer GVT-modellens form. Majoriteten av detta arbete behandlar topologidata då det visar sig vara ett mycket svårare problem en shadingdata Topologidata Det finns flera olika varianter hur man kan spara topologidata. Valet av datastruktur är en av de viktigaste delarna av en effektiv implementering av GVTsystemet och jag har därför lagt stora möda på att undersöka de olika datastrukturskandidaterna. Nedan följer en beskrivning av de problem som topologidatan ska lösa. Som vi ser i figur 4.6 har varje nod i en GVT-modell potentiellt upp till åtta barn. För att kunna definiera trädets form (topologi) behöver vi veta två saker för varje nod: 1. Finns det ett barn c? (där c är ett tal mellan 0 och 7) 2. Var i minnet finns barn c? Detta vill man göra så flexibelt, snabbt och minneseffektivt som möjligt. I kapitel 5 undersöker jag de olika datastrukturs-kandidaterna för att lösa ovanstående problem Shadingdata Varje nod i GVT-modellen har utöver topologidata också shadingdata. Denna data används vid rendering för att bestämma utseendet på noden. Den enklaste shadingdata sparar bara en färg per nod men om man vill ha mer avancerade ljussättning kan varje nod även behöva spara data som t.ex. normal och reflexion. 17

28 KAPITEL 4. TEORI Figur 4.6. En nod med dess 8 barn (childs) utritade. En praktisk förenkling av shadingdata är att spara den i en lista av kanaler med 1 byte per kanal. Detta gör att övriga delar av koden inte behöver veta exakt vilken kanal som betyder vad, som i sin tur underlättar för saker som mipmapping (kapitel 4.6) och komprimering. I tabell 4.2 listar jag några av de vanligaste shadingkanalerna. Tabell 4.2. Visar några av de vanligaste kanalerna för en voxel. Typ Antal kanaler Färg 3 Normal 3 Specular 1 Shininess 1 Transparans Mipmapping En viktig egenskap hos GVT-tekniken är så kallad mipmapping vilket är en metod för att nersampla shadingdata upp i trädet. Mipmapping är en metod som har används på texturer i många år för att skapa en miniatyrversion av texturen som sedan kan användas när texturen ses på långt avstånd. Detta görs dels i syfte att minska aliasing och dels för att minska mängden minne som behöver läsas in. I figur 4.7 ser vi ett exempel på 2D mipmapping. 18

29 4.7. PAGING Figur D versionen av mipmapping Mipmapping i en GVT-modell är samma princip men överförd till 3D fallet. Själva mipmap-processen fungerar så att varje nod tar genomsnittsvärdet per kanal i shadingdatan av alla sina barn och sätter till sitt eget värde: n = n 0 + n 1 + n 2 + n 3 + n 4 + n 5 + n 6 + n 7 8 Detta fortsätter sedan rekursivt upp i trädet enda tills man når roten. Varje nod har nu ett genomsnittsvärde av alla noder under sig vilket betyder att varje nod (utom löven) blir en miniatyr av hela trädet under sig. GVT-modellen blir nu vad som kallas för en multiresolution model [Samet 2006, s. 391]. Detta kan användas för att dynamiskt bestämma upplösningen på modellen vid t.ex. rendering. En modell som är långt från kameran behöver inte ha lika hög upplösning som en modell som är nära. Detta är en mycket viktig egenskap hos GVT-tekniken då det dels minskar aliasing och dels minskar mängden data man måste hålla minnet/cachen. För att illustrera mipmapping av en GVT-modell har jag i figur 4.8 två versioner av samma modell där den högra är en mipmappad version (3 mipmap-steg för att framhäva effekten). Om man såg dessa bilder på tillräckligt långt avstånd skulle man inte kunna skilja dem åt vilket är precis vad mipmapping utnyttjar. Notera här att vi både samplat ner geometri- och färg-data. Detta är något som inte går i triangelgrafik då man måste hantera trianglar och texturer separat. 4.7 Paging Ett av målen för min implementering är att inte hela GVT-modellen ska behöva ligga i minnet för att kunna rendera och editera den. Detta är nödvändigt eftersom en GVT-modell kan vara betydligt större än vad som går in i en 32-bitarsprocess virtuella adressrymd (2 GB). Lösningen på problemet ligger i att på något sätt 19

30 KAPITEL 4. TEORI Figur 4.8. Två bilder av samma modell. Den högra är 3 mipmap steg lägre än den vänstra. klumpa ihop noder i block, där vi sedan bara har de block som vi behöver för tillfället i minnet. I operativsystem kallas denna process för paging och jag har valt att använda samma benämning. För att förstå varför paging fungerar så bra i ett GVT-system måste man förstå de tekniska implikationer som mipmapping medför. Datamängden från en GVTmodell som vi max kan behöva för att rendera en bild är enbart relaterat till upplösningen på bilden och inte till modellstorleken. Detta är så viktigt att jag tänkte upprepa det: Max datamängden för att rendera en bild är enbart relaterat till upplösningen på bilden och inte till modellstorleken. Vi kommer nu till frågan över hur dessa pageblock ska konstrueras för att på bästa sätt minimera mängden data som måste läsas och skrivas till disk för att kunna rendera en bild samt göra förändringar i modellen. Jag testade flera olika metoder innan jag bestämde mig för vilken jag tyckte var bäst. Både [Olick 2008] och [Laine 2010] använder sig också av ett paging system där mitt liknar [Laine 2010]. Det finns två varianter för att gruppera noder i pages som jag kallar för horisontal och vertikal paging. I horisontal paging är alla noder i en viss page på samma nivå i trädet medan i vertikal paging behöver så inte vara fallet. Skillnaden beskrivs bäst med en bild. I figur 4.9 ser vi två bilder den vänstra är exempel på horisontalpaging och i högra på vertikalpaging. Oavsett om vi använder horisontal- eller vertikal-paging kommer varje page vara begränsad till en viss del av modellen. Pagingen delar därmed upp modellen i en form av rutnät som vi ser exempel på i figur Detta är önskvärt vid editering av modellen då majoriteten av alla förändringar är lokala. 4.8 Rendering en GVT-modell Även om rendering inte ingår i mitt arbete tänkte jag ge en snabb förklaring hur detta går till. Om läsaren är intresserade av hur rendering av GVT-modeller kan implementeras finns det flera rapporter som behandlar detta: [Samet 1989] 20

31 4.8. RENDERING EN GVT-MODELL Figur 4.9. Till vänster ser vi ett exempel på horisontalpaging. Till höger ser vi ett exempel av vertikalpaging. Figur En GVT-modell där pages är symboliserade med olika färger. [Knoll 2006] [Crassin 2009] [Knoll 2009] [Krishnamachari 2009] och [Laine 2010]. Att rendera en GVT-modell på skärmen görs enklast med ray tracing. Tekniken bygger på algoritmen som [Ericson 2005, p. 179] sammanfattar och avgör om en stråle (ray) och en låda (box) skär varandra. För att ta reda på vilken voxel strålen träffar först börjar man med att se om strålen skär lådan för rotnoden i GVT-trädet. Om den inte skär lådan för rotnoden vet vi att strålen missar GVT-modellen helt. Om däremot strålen träffar lådan fortsätter vi rekursivt att se vilka av rotnodens barn strålen skär. Förutsatt att vi itererar nodernas barn i rätt ordning (framifrån, från kameran sett) vet vi att så fort vi stöter på ett löv (voxel) i trädet är detta den första voxel strålen träffar. En viktig teknik vid rendering som använder det faktum att en GVT-modell är en så kallad multiresolution model (kapitel 4.6) är att sluta traversera trädet när en specifik nod har mindre projektionsarea på skärmen än en pixel [Knoll 2006]. Detta minimerar aliasing, gör renderingen snabbare samt minskar mängden noder vi behöver ha i minnet. 21

32 KAPITEL 4. TEORI 4.9 Voxalisering När man vill skapa en GVT-modell är det viktigt att man kan importera etablerade modellformat. Majoriteten av all 3D-modeller sparas i dagsläget som en triangelsoppa med tillhörande texturer. Det är därför viktigt att kunna göra en så kallad voxalisering av en triangelsoppa till motsvarande GVT-modell. Denna process är en form av 3D rasterisering där vi går från vektorgrafik till voxelgrafik. [Olick 2008] och [Zesheng 1991] nämner flera olika sätt detta kan göras på. Nedan listar jag tre av dem: 1. 3D scanline conversion bygger på klassisk 2D scanline conversion [Foley 1996] överförd till 3D fallet [Houng 1998] [Kaufman 1986]. 2. Divide and Conquer söker rekursivt igenom trädet och testar om en specifik nod skär någon av trianglarna [Zesheng 1991]. 3. Subdivision liknar REYES algoritm [Cortes 2006, kap. 1] där varje triangel subdividas tills det inte finns några hål i den för att sedan konvertera alla vertexes till voxlar. Det har gjorts mycket forskning på 3D scanline conversion -metoden [Kaufman 1986] [Houng 1998] och jag har därför valt att använda denna metod. Jag har även undersökt Divide and Conquer -metoden under arbetet. Metoden har en intressant fördel jämfört med 3D scanline conversion -metoden: Med hjälp av en kombination av bredden-först och djupet-först sökning kan man stoppa voxaliseringen när som helst och få en GVT-modell som går att visa för användaren även om den inte visas i full upplösning. Tyvärr faller dock Divide and Conquer - metoden på grund av prestanda. Jag lyckades som mest få upp metoden till enbart en tiondel av hastigheten mot 3D scanline conversion -metoden vilket är för dåligt för att kunna används i praktiken. [Zesheng 1991] poängterar dock att Divide and Conquer kan vara en bra metod för voxalisering av enklare konvexa objekt som: plan, polyeders, sfärer etc Transformation Att rotera en GVT-modell runt en godtycklig axel är inte trivialt [Zesheng 1991]. För att komma runt detta problem samt för att kunna utföra alla andra former av linjära transformationer använder vi en matris M för varje GVT-modell. Alla former av linjära operationer man vill utföra på GVT-modellen utförs nu enbart på M vilket självklart går i O(1). Innan vi vill utföra ray tracing mot GVT-modellen måste vi överföra den till modellens koordinatsystem: r 0 = M 1 r 0 v = M 1 v (4.1) 22

33 4.11. SMP (PARALLELLISERING PÅ CPU:N) I formel 4.1 förutsätter jag att M är ortogonal. Att sedan transformera tillbaka den potentiella träffpunkten är lätt: x = Mx Problemet med att rotera en specifik del av GVT-modellen kvarstår dock. Detta ingår inte i detta arbete och jag hänvisar i stället till [Zesheng 1991] som presenterar en intressant metod SMP (Parallellisering på CPU:n) Dagens processorer kommer nästan alltid med två eller fler kärnor. För att utnyttja alla prestanda till max hos dagens processorer måste programmen delas upp i flera trådar med hjälp av SMP. Det bästa sättet att parallellisera ett problem är att dela upp problemet i minst lika många delproblem som det finns kärnor. Dessa delproblem kan sedan köras på varsin processortråd Dataåtkomst När vi vill komma åt till topologidata och shadingdata från GVT-modellen har jag definierat tre olika åtkomstlägen: 1. Read Vi får enbart läsa topologidata och shadingdata. Vanligaste användning är för rendering. 2. Touch Vi får både läsa och skriva shadingdata, men enbart läsa topologidata. Vanligast för mipmapping. 3. Forge Vi får skriva och läsa både topologidata och shadingdata. Vanligast för voxalisering av vektorgrafik. Dessa lägen får stor betydelse när vi använder SMP för att parallellisera arbetet. 23

34

35 Kapitel 5 Analys av datastrukturer I detta kapitel går jag igenom de datastrukturer jag undersökt för att spara GVTmodellens topologidata. I kapitel 6 använder jag sedan några av dessa datastrukturer för att uppfylla de mål jag satte upp i kapitel Översikt och problemställning Jag har undersökt följande datastrukturer: Pekarträd, XYZ-hashtabell, Mortonhashtabell, trädkod samt trädkod-offset. Alla ovanstående datastrukturer försöker lösa problemet som jag ställde upp i kapitel 4.5.1: 1. Finns det ett barn c (där c är ett tal mellan 0 och 7)? 2. Var i minnet finns barn c? [Samet 1987] som i sin tur refererar till [Knuth 1975] visar att det går att dela in alla olika implementeringar av träddatastrukturer i tre kategorier. Nedan ger jag en kort beskrivning av dessa tre och vilka kategorier mina datastrukturer tillhör. För en mer utförlig beskrivning hänvisar jag till [Samet 1987]. 1. Pekarträd där varje nod sparar en pekare till sina barn. Min pekarträd-lösning tillhör denna kategori. 2. Förbestämd traversering utnyttjar den inbördes ordningen mellan noderna i minnet för att spara all topologidata. Min trädkod-lösning tillhör denna denna kategori och min trädkod-offset-lösning är en modifikation av den. 3. Dewey-decimal kodning kommer från det populära sättet att organisera ett bibliotek [Dewey 1876] där varje nod i trädet får en distinkt kod som beskriver hur man tar sig till den från roten. Min Morton-Hashtabell-lösning tillhör denna kategori och XYZ-hashtabell-lösningen är en modifikation av den. 25

36 KAPITEL 5. ANALYS AV DATASTRUKTURER 5.2 Grundläggande datastrukturer för GVT Pekarträd Det enklast sättet att skapa en datastruktur som uppfyller målen jag satte upp i kapitel är följande: struct node { struct node *childs[8]; }; struct node *root; Alltså 8 pekare per nod som pekar vidare till de potentiella barnen. Om ett specifikt barn inte finns sparar vi NULL i barnpekaren. Denna datastruktur tar 32 bytes per nod (förutsatt att en pekare tar 4 bytes) vilket är ganska mycket men för det får vi en datastruktur som är blixtsnabb att traversera XYZ-Hashtabell Att använda en hashtabell som datastruktur har varit en populär implementeringsmetod för voxelgrafik [Ericson 2005, s. 288], ett exempel på detta är [Knoll 2006, Knoll 2009] som använder en hashtabell-baserad datastruktur för voxelrendering. Min implementering av XYZ-hashtabell datastrukturen ser ut på följande sätt: struct node { struct node *next; int x, y, z; }; struct node *hash_buckets[max_hash]; int root_x, root_y, root_z; Varje nod sparar sin rumsposition i x, y, z variablerna samt en pekare till nästa nod i samma hash-hink. När vi traverserar denna datastruktur sparar vi alltid nuvarande x, y, z värde och använder sedan en enkel funktion med invärde c (ett tal mellan 0 och 7) för att ta oss till ett specifikt barn. Det finns dock ett allvarligt problem med denna datastruktur: Vi vet inte i förväg om ett visst barn finns eller ej utan vi måste först göra ett uppslag i hashtabellen för att avgöra det. Detta blir en extra kostnad som slöar ner traversen men det finns lyckligtvis ett sätta att undkomma problemet: För varje nod introducerar vi en så kallad childbits variabel, denna variabel är en byte (8 bitar) där varje bit representerar om det finns en nod för ett specifikt för barn c. Den nya noddatastrukturen ser nu ut på följande sätt: 26

37 5.2. GRUNDLÄGGANDE DATASTRUKTURER FÖR GVT struct node { struct node *next; int x, y, z; byte childbits; }; Ovanstående datastruktur tar 17 bytes per nod plus hashtabellens storlek (kompilatorn kan även avrunda den till 20 bytes på grund av aligning ). Om man vill minimera antalet hashkollisioner bör hashtabellen vara i samma storleksordning som antalet noder. Detta ger ytterligare ca 4 bytes per nod som leder till en nodstorlek på ca 21 bytes. 21 bytes är ca två tredjedelar av utrymmet för pekarträd-lösningen vilket är en förbättring men fortfarande ganska mycket. Det skulle gå att minska precisionen på x, y, z variablerna då 32 bitar ofta är onödigt mycket. Tyvärr är antagligen 16 bitar för lite och 24 bitar är krångligt att hantera vilket gör att vi är fast med 32 bitar. En fördel med XYZ-hashtabell-lösningen över pekarträd-lösningen är att det blir trivialt att hitta en specifik nods granne (bara lägg-till/dra-ifrån 1 från x, y eller z variabeln) medan det i pekarträd-lösningen är betydligt mer kostsamt. En annan fördel är att vi undviker direkta minnesreferenser vilket kommer visa sig ha en stor fördel vid undo-redo samt paging. Ett problem med XYZ hashtabell-lösningen datastruktur är att hashtabellens storlek inte kan ändras hur som helst medan man kör programmet utan att iterera igenom alla noder. Att detta är en nackdel beror på att stora modeller vill ha en stor hashtabell medan för små modeller tar en stor hashtabell bara onödig plats. Det finns metoder som linjär och spiral hashning [Samet 2006, s. 729] som kommer runt detta problem, dessa metoder introducerar dock andra problem och ökar komplexiteten på implementering vilket jag vill undvika Morton-Hashtabell Morton key s [Ericson 2005, s. 316] är ett koncept relaterat till childbits som går ut på att varje position i ett octree kan representeras av en serie ettor och nollor grupperade om 3 där varje grupp säger vilken av de 8 barn man ska ta för att komma till den specifika noden i fråga. Enklaste sättet att generera en Morton key för en viss nod är att konkatenera alla c (ett tal mellan 0 och 7, alltså 3 bitar) vi har använt för att komma ner till den specifika noden. Storleken för att identifiera en viss nod blir octree s maxhöjd multiplicerat med 3. En GVT-maxhöjd på 21 skulle räcka för i stort sätt alla modeller vilket skulle ge en Morton key storlek på 63 bitar per nod. Min implementering av en Mortonhashtabell lösning ser ut på följande sätt: struct node { struct node *next; 27

38 KAPITEL 5. ANALYS AV DATASTRUKTURER }; long long byte mortonkey; childbits; struct node *tabel_buckets[max_hash]; int root_mortonkey; Datastrukturen tar upp 13 bytes per nod plus hashtabellens storlek vilket ger ca 17 bytes per nod. Morton-hashtabell-lösningen har samma fördelar som XYZhashtabell-lösningen men vi tjänar 4 bytes per nod samt att det är lite enklare att traversera trädet. Det visar sig dock att Morton-hashtabell-lösningen har en rejäl svaghet om man vill ha möjlighet att lägga till en större rotnod när man redan har en stor GVT-modell. Detta kräver nämligen att alla Morton key s i hela modellen måste omkalkyleras vilket blir enormt kostsamt Trädkod Det går att visa att all topologidata kan komprimeras ner till enbart 1 byte per nod, både [Olick 2008] och [Samet 1987] poängterar detta faktum. Tekniken kallas trädkod (treecode) och introduceras av [Oliver 1983]. Tekniken bygger på att serielarisera hela GVT-modellen med bredden-först sökning där varje nivå i trädet sparas i en egen lista (figur 5.1). Det enda vi då behöver spara ut är per nod är childbits (1 byte). När vi sedan ska traversera det serialiserade GVT-trädet gör man på följande sätt: 1. Att veta om ett specifikt barn finns är trivialt då vi enbart tittar på nodens childbits (det enda vi vet om noden). 2. När vi sedan ska traversera ner till ett specifikt barn hoppar vi tillbaka till listans start och räknar hur många 1:or (barn) som finns innan vårt specifika barn. Vi går sedan till listan för nästa nivå i trädet och hoppar in så många noder som vi räknade 1:or på den tidigare listan. Vi står nu i nodens barn. Fördelarna med denna metod är att varje nod enbart tar 1 byte. Nackdelen är att det blir enormt långsamt att traversera Trädkod-offset Om vi använder samma princip som i trädkod-lösningen, men för varje nod även sparar hur många 1:or det finns före i listan, skulle traverseringen kunna göras mycket snabbare. Vi kan dock gå ett steg längre och bunta in nästa nivås liststart så vi slipper ta reda på den separat. Nod-datastrukturen ser då ut på följande sätt: 28

39 5.2. GRUNDLÄGGANDE DATASTRUKTURER FÖR GVT Figur 5.1. I trädkod datastrukturen sparar vi varje nivå av trädet i en egen lista. struct node { int offset; byte childbits; }; int root_offset; För att traversera till ett specifikt barn c använder vi nuvarande nodpositionen, adderar offset och adderar ytterligare så många 1:or vi hittar i childbits före c (Detta kan göras extremt effektivt med en lookup-tabell). Fördelen med denna implementering är att den enbart tar 5 bytes per nod (4 bytes om man bara behöver 24 bitar för offset) och är snabb att traversera. [Laine 2010] antyder till och med att denna metod kan vara snabbare att traversera än pekarträd lösning på grund av att mängden cachemissar minskar då vi använder betydligt mindre minne. Nackdelen med denna datastruktur är att ändringar av trädet blir kostsamma då stora delar av noderna måste räknas om Sammanfattning av grundläggande datastrukturer I tabell 5.1 har jag gjort en sammanställning över alla grundläggande datastrukturer med deras fördelar respektive nackdelar. 29

40 KAPITEL 5. ANALYS AV DATASTRUKTURER Tabell 5.1. Sammanfattning av alla grundläggande datastrukturer. Datastruktur Nodstorlek Fördelar Nackdelar Pekarträd 32 (100%) Snabb Minnesstorlek XYZ-hashtabell 21 (66%) Snabb, flexibel Minnesstorlek, förbestämd hashtabell Morton-hashtabell 17 (53%) Snabb Minnesstorlek, förbestämd hashtabell, fixed rotnod Trädkod 1 (3%) Liten plats Långsam Trädkod offset 5 (16%) Snabb läsning, liten plats Långsam editering 5.3 Förbättringar till datastrukturerna Leafbits Om vi mestadels sparar ytor i vår GVT-modell kommer varje nod i snitt ha ca 4 barn. En intressant fråga är då: hur stor andel av alla noder är löv? För att svara på denna fråga kan vi räkna baklänges från löven sett. Om vi sätter antalet löv till 1 ser vi att nivån ovan löven blir ca 0.25, ytterligare en nivå upp får vi Om man fortsätter denna beräkning till nivåstorleken blir försumbar ser vi att löven står för ca 70% av all noder. Detta bekräftas av av tabell 5.2. Tabell 5.2. Visar antal noder per nivå för en specifik GVT-modell. Nivå Antal noder Andel % % % % % % % % % % % % Ett löv behöver inte spara lika mycket topologiinformation som en nod då lövet 30

41 5.3. FÖRBÄTTRINGAR TILL DATASTRUKTURERNA omöjligt kan ha barn. Detta har fått [Knoll 2009] att introducera begreppet cap nodes där vi sparar mindre information för löven än för noderna i syfte att spara minne. Notera att jag nu bara pratar om topologidata, shadingdata måste vi fortfarande spara för alla löv. Ett smart tillägg till alla ovanstående datastrukturer är att för varje nod lägga till en så kallad leafbits variabel. Leafbit variabeln har samma upplägg som childbit variabeln men där varje bit i stället avgör om barnet är ett löv eller ej. Detta gör att vi inte behöver spara någon topologidata för löven vilket i sin tur kan spara oss upp till 70% av all topologidata för kostnaden av 1 extra byte per nod. [Laine 2010] använder en liknande lösning Nodblock XYZ-hashtabell datastrukturen är en av de mest attraktiva lösningar men den har två huvudproblem: 1. Tar ganska mycket plats i minne (21 bytes per nod). 2. Hashtabellens storlek skalar inte bra mellan både stora och små modeller. Det går dock att lösa båda ovanstående problem genom att dela in alla noder i block. Varje block är en kub i rummet som max kan innehålla noder. Detta gör att x, y, z variablerna i nodstrukturen kan använda enbart 1 byte per variabel. Den nya noddatastrukturen ser ut på följande sätt: struct node { struct node *next; byte x, y, z; byte childbits; }; Denna noddatastruktur tar enbart 8 bytes (jämfört med 17 bytes) plus hashtabellens storlek, vilket är en klar förbättring. En annan fördel är att vi nu har en hashtabell per block där vi vet blockets normalstorlek vilket gör att vi kan anpassa hashtabellens storlek till detta. Datastrukturen för huvudet av ett nodblock ser ut på följande sätt: struct block { struct node struct block }; *hash_buckets[max_hash]; *childs[8]; Nodblock är även en form av horisontal paging vilket gör nodblock ännu mer attraktivt när vi kommer till att implementera paging. 31

42 KAPITEL 5. ANALYS AV DATASTRUKTURER 5.4 Val av datastruktur Tre olika datastrukturer Val av noddatastruktur är ett av de viktigaste besluten för hela GVT-systemet. När vi hanterar en GVT-modell finns det tre kategorier på saker vi vill kunna göra med den: Generering och editering. CUDA Rendering Lagring på disk Dessa tre kategorier kommer ha sina respektive datastrukturer på tre fysikaliska olika ställen. Generering och editering sker på CPU:n, CUDA rendering på grafikkortet och lagring på disk på en hårdisk, CD, DVD eller Blue-Ray. För maximera vad som är viktigt för varje enskild kategori har jag valt att använda olika datastrukturer för de olika kategorierna. Nedan listar jag i prioriteringsordning vad jag anser viktigast för de olika kategorierna: Generering och editering (CPU) 1. Möjlighet till Layers och Undo 2. Skriv och lägg-till/ta-bort hastighet 3. Undvik fragmentering 4. Läshastighet 5. Minnesutrymme Rendering (GPU) 1. Läshastighet 2. Cachevänligt 3. Minnesutrymme Lagring på disk (Hårdisk/CD/DVD) 1. Horisontalpaging 2. Diskutrymme Den viktigaste kategorin för mitt arbete är generering och editering. Lagring på disk tillhör förvisso fokus för mitt arbete men detta kan behandlas som en specialfall när vi väl vill skriva ner noddata på disk. I kapitel ger jag en kort beskrivning av vilka datastrukturer som är intressant för CUDA rendering samt hur jag konverterar till dessa. 32

43 5.4. VAL AV DATASTRUKTUR Datastruktur för generering och editering Ett av de viktigaste målen för datastrukturen för generering och editering är att vi snabbt kan lägga-till och ta-bort noder. Detta utesluter direkt trädkod och trädkodoffset lösningarna. Vidare kan vi även utesluta Morton-hashtabell-lösningen då ett av målen vi satte upp i kapitel 2.2 kräver att storleken av modellen måste kunna växa vartefter användaren jobbar med modellen, något som inte går att göra med en Morton hashtabell. Nu återstår två datastrukturer: pekarträd och XYZ-hashtabell. Jag har provat att implementera båda och pekarträdet har fördelen att vara snabbare medan XYZhashtabellen tar mindre minne. I slutändan var jag dock tvungen att även utesluta pekarträd-lösningen då denna visade sig vara svår att implementera tillsammans med paging och undo-redo vilket jag återkommer till i kapitel 6.3 och 6.5. Tabell 5.3. Sammanställning av val av datastruktur för generering och editering. Datastruktur Status Kommentar Trädkod Utesluten Långsam att traversera Trädkod-offset Utesluten Långsam att lägga till och ta bort noder Morton hashtabell Utesluten Ineffektivt att ändra rotnoden Pekarträd Utesluten Stor plats, svårt att implementera undo-redo samt paging XYZ-hashblock Uppfyller alla krav För att undkomma XYZ-hashtabellens svagheter (mycket minne och förbestämd tabellstorlek) använder jag nodblock metoden jag beskrev i kapitel Detta visar sig även vara en fenomenal indelning för paging vilket jag återkommer till i kapitel 6.3. I tabell 5.3 har jag gjort en sammanställning av valet av datastruktur för generering och editering Datastruktur för CUDA rendering Det är fördelaktigt att kunna exportera GVT-modellen till ett format som lämpar sig för snabb rendering på CUDA. [Laine 2010] föreslår en trädkod-offset liknande lösning med leafbits för att undvika att behöva spara topologidata för löven. Vidare föreslår de ett vertikalt pagingschema för att kunna rendera större GVT-modeller än vad som får plats i CUDA minnet. Även jag har implementerat en CUDA renderare som fungerar på liknande sätt och kan bekräfta att trädkod-offset-lösningen med vertikal paging är en mycket effektiv datastruktur. För information hur man konstruerar en effektiv GTV rend- 33

44 KAPITEL 5. ANALYS AV DATASTRUKTURER erare för CUDA hänvisar jag till [Laine 2010]. För en mer generell beskrivning av GVT-rendering hänvisar jag till [Samet 1989]. För att exportera en GVT-modell med XYZ-hastabell som datastruktur till en trädkod-offset datastruktur väljer man en startnod i XYZ-hashtabell trädet (välj rotnoden om man vill ha hela trädet). Man traverserar sedan trädet rekursivt tills man kommer till ett löv eller ett fördefinerat stoppdjup. I varje traverseringssteg skriver man ut nuvarande nod till en sidobuffer i trädkod-offset format. Denna sidobuffer kan sedan laddas in i grafikkortet för att renderas av CUDA. När GVT-modellen förändras måste vi uppdatera sidobuffern. Men då de flesta förändringar är lokala behöver vi bara uppdatera den del av sidobuffern som innehåller de förändrade noderna vilket snabbar upp processen. 5.5 Metadata Varje GVT-modell har även lite metadata som jag presenterar nedan: struct layer { vec3 mins; vec3 maxs; int x, y, z; }; Min- och maxvariablerna är lådan för rotnoden. Dessa värden skickas sedan vidare ner till barnen när vi traverserar GVT-trädet som jag visar i kapitel Genom att göra på detta vis kan vi få reda på den aktuella lådan för varje nod utan att behöva spara den på nodnivå. x, y, z variablen är xyz värdet för rotnoden i GVT-modellen. Traverseringar av GVT-modellen börjar alltid i denna nod. 34

45 Kapitel 6 Analys av algoritmer I detta kapitel beskriver jag de algoritmer tillsammans med några av datastrukturerna från kapitel 5 jag använder för att uppfylla målen från kapitel Nodtraversering Det finns flera tillfällen när vi vill traversera igenom GVT-modellen. Det två vanligaste fallet är vid mipmapping och när vi vill skapa en ny nod. [Levitin 2003, p. 162] visar att det går att traversera träd på två olika sätt: bredden-först- (BFS) eller djupet-först-sökning (DFS) Bredden-först-sökning (BFS) Bredden-först-sökning kräver en kö som är minst lika stor som antal löv i trädet. Detta gör att sökningen blir svår att implementera i praktiken då en GVT-modell kan ha fler löv än vad som får plats i minnet. Bredden-först-sökning kan dock användas om man bara är intresserad av att traversera den första biten av trädet, något jag återkommer till i kapitel Djupet-först-sökning (DFS) Djupet-först-sökning behöver enbart en stack av samma storlek som maxdjupet i trädet (några enstaka noder) för att fungera vilket gör att den kan köras på hela trädet. Nedan ger jag exempel på hur en sådan djupet-först-sökning kan se ut. 1 void DepthFirst ( vec3 mins, vec3 maxs, node_ t * node ) { 2 childbits = GetChildBits ( node ); 3 4 //! potenial callback function here! 5 6 if (! childbits ) { 7 return ; 8 } 35

46 KAPITEL 6. ANALYS AV ALGORITMER 9 10 // iterate all potenial childs 11 for ( c = 0; c < 8; c ++ ) { // check if this child exist 14 if (!( childbits & (1<<c) ) ) { 15 continue ; 16 } // create child bounds from parent bounds 19 PushBounds ( childmins, childmaxs, mins, maxs, c ); // get current child 22 childnode = GetChild ( node, c ); // continue recursion 25 DepthFirst ( childmins, childmaxs, childnode ); 26 } 27 } Det finns ett antal saker att notera i ovanstående kod. Det första är användningen av childbits (rad 6 och 14) vilket gör det mycket effektivt att bestämma om ett visst barn finns eller ej. Det andra är att vi skickar med den aktuella nodens min- och max-värden för varje rekursionssteg (rad 1 och 25). Genom att göra på detta vis behöver vi inte spara dem per nod vilket sparar minne. Funktionen PushBounds (rad 19) kan implementeras mycket effektivt med en switch-sats samt några additioner. Det tredje är att det går att stoppa in en callback-funktion i ovanstående kod (rad 4). Callback-funktionen kan användas för att modifiera shadingdata i noden samt att bestämma om vi ska fortsätta rekursionen. Största användingsområdet för ovanstående kod är mipmapping samt voxaliseringsmetoden Divide and Conquer Djupet-först-sökning med mipmapping Vi kan utöka koden i kapitel för mipmapping. De nya raderna i nedanstående kod är 10 12, 32 samt void DepthFirst ( vec3 mins, vec3 maxs, node_ t * node ) { 2 childbits = GetChildBits ( node ); 3 4 //! potenial callback function here! 5 6 if (! childbits ) { 7 return ; 8 } 9 36

47 6.1. NODTRAVERSERING 10 // set mipmap to zero 11 ClearChannels ( mipmap ); 12 mipmapweight = 0; // iterate all potenial childs 15 for ( c = 0; c < 8; c ++ ) { // check if this child exist 18 if (!( childbits & (1<<c) ) ) { 19 continue ; 20 } // create child bounds from parent bounds 23 PushBounds ( childmins, childmaxs, mins, maxs, c ); // get current child 26 childnode = GetChild ( node, c ); // continue recursion 29 DepthFirst ( childmins, childmaxs, childnode ); // get child channels and add to mipmap 32 AddChannels ( mipmap, GetChannels ( childnode ) ); 33 } // normalize channels and update node 36 DivideChannels ( mipmap, mipmapweight ); 37 SetNodeChannels ( node, mipmap ); 38 } DFS och BFS kombination Ett problem med djupet-först-sökning är att det är svårt att parallellisera över SMP. För att lösa detta problem har jag valt att kombinera DFS och BFS sökning på följande sätt: 1. Börja med att köra en bredden-först sökning där vi anger ett stoppdjup. Stoppdjupet är maximala djupet vi får traversera i trädet. Detta körs seriellt och returnerar en lista över alla löv från sökningen. 2. Fortsätt nu genom att iterera igenom alla löv från steg 1 och traversera dessa med djupet-först-sökning, detta kan köras parallellt. Förutsatt att stoppdjupet i steg 1 är lågt, innehåller detta steg majoriteten av allt jobb. 3. Slutligen kör vi sökningen i steg 1 ytterligare en gång så att mipmappingen kan fortplanta sig ända upp till roten av trädet, detta körs seriellt. 37

48 KAPITEL 6. ANALYS AV ALGORITMER Förutsatt att modellen är stor och man väljer ett bra stoppdjup skalar denna algoritm linjärt med antalet processorkärnor Skapa en nod Algoritmen för att sätta en specifik nod är en form av djupet-först-sökning. Nedan är ett exempel på hur det kan se ut: 1 node_ t * SetNode ( vec3 pos, vec3 mids, int depth, node_ t * n ) { 2 3 // check for stop depth 4 if (! depth ) { 5 return ForgeLeafChild ( n, c ); 6 } 7 8 // check what child to traverse 9 c = 0; 10 if ( pos.x > mids.x ) c = (1 < <0); 11 if ( pos.y > mids.y ) c = (1 < <1); 12 if ( pos.z > mids.z ) c = (1 < <2); // get or create child node 15 childnode = ForgeNodeChild ( n, c ); // create child mid values from parent 18 PushMids ( childmids, mids, c ); // continue recursion 21 return SetNode ( pos, childmids, depth - 1, childnode ); 22 } Algoritmen börjar med add traversera trädet från roten. I varje rekursionssteg undersöker vi för vilket av de 8 barnen vi ska fortsätta traversen. När vi slutligen kommit ner till ett visst stoppdjup (när depth är 0) sätter vi noden till ett löv och returnerar. Algoritmen för att hämta en specifik voxel liknar ovanstående men med undantaget att vi aldrig ändrar några noder och om ett visst barn inte finns returneras NULL. 6.2 Förändring av rotnoden När GVT-modellen växer i rumstorlek på grund av att användaren lägger till fler och fler noder kommer vi för eller senare till en punkt där den inte längre får plats i rotnoden. Notera att detta är ett rent geometriskt problem och har inget att göra med mängden noder i modellen. För att lösa problemet måste vi skapa en ny rotnod, som är stor nog att innehålla hela den nya noden. 38

49 6.2. FÖRÄNDRING AV ROTNODEN Jag har löst detta problem genom att före varje förändring av topologidata köra en förberedande funktion som får som invariabler min- och max-värdena för topologiförändringen. Denna funktion undersöker sedan om min- och max-värdena får plats i rotnoden av GVT-modellen. Om så inte är fallet skapar vi en ny större nod och sätter som rotnod, den nya rotnoden får nu den gamla som ett av sina barn. Denna process upprepas rekursivt tills att min- och max-värdena får plats i vår rotnod. Figur 6.1 illustrerar processen. Figur 6.1. När modellen växer sig större än rot noden måste vi skapa en ny rotnod. Eftersom GVT-trädet är ett tredimensionellt binärt träd (octree) måste sidan för den nya rotnoden alltid vara dubbelt så stor som den gamla. Det enda beslut vi har kvar att fatta är åt vilket håll den nya rotnoden ska utvidgas. Det finns 8 möjligheter, då den nya rotnoden har potentiellt upp till 8 barn. Som vi ser i figur 6.1 är det viktigt att utvidga rotnoden åt rätt håll. I praktiken kan detta göras på två olika sätt: Det enklaste sättet är att bara varannan gång utvidga roten i positiv riktning och varannan gång i negativ. Detta har dock nackdelen att GVT-modellen får onödigt många nivåer vilket i sin tur ökar söktiden i trädet då fler noder måste passeras från rot till löv. En bättre lösning är att välja åt vilket håll den nya rotnoden ska expanderas för att bäst passa min- och max-värdena för topologiförändringen. Detta är något som är möjligt för pekarträd, då man där är fri att välja vilket barn man vill för gamla roten. Jag har dock inte lyckats lösa detta för XYZ-hashtabell-lösningen då en viss nods x, y, z variabler avgör vilka förälder den får. Det är möjligt att detta går att komma runt med någon slags permutations-byte eller liknande. I nuvarande implementering har jag dock satt upp x, y, z variablerna i första rotnoden på ett sådant sätt att när vi vill ha en ny rotnod kommer vi att pendla mellan utökning roten i positiv och negativ riktning. 39

50 KAPITEL 6. ANALYS AV ALGORITMER 6.3 Paging Översikt För att dela upp noderna i block använder jag horisontal paging. Fördelen med horisontal paging jämfört med vertikal är att vi minimerar onödiga noder i minnet vid ray tracing genom att bara ladda in så många nivåer av GVT-trädet som vi behöver. När man försöker implementera paging visar det sig att pekarträd-lösningen har en negativ sidoeffekt då den använder direkta minnesreferenser till sina barn. Detta gör att varje gång man läser in eller skriver ut en page på disk måste alla minnesreferenser uppdateras vilket komplicerar implementeringen (problemet blir ännu värre när vi sedan försöker implementera undo-redo). Detta är den primära anledningen till att jag har valt XYZ-hashtabell med nodblock som datastruktur för generering och editering (kapitel 5.4.2). Eftersom XYZ-hashtabell inte använder några direkta minnesreferenser kan vi flytta runt noder och pages hur som helst i minnet vilket underlättar implementeringen. Jag gjorde ett försök att implementera paging med pekarträd som datastruktur men fick ge upp då implementeringen blev så pass krånglig (undo-redo gör den ännu krångligare) att det blev svårt att förutse alla implikationer av den vilket drastiskt ökar risken för buggar. Eftersom jag inte har något fungerande alternativ till XYZhashtabell paging kan jag inte mäta hur denna jämför sig med andra lösningar prestandamässigt Page LRU (Least Recently Used) När GVT-systemet kommer till den punkt där vi behöver flera pages i minnet än vad det finns minne måste systemet prioritera vilka pages som är viktigast. Vi avgör detta genom att titta på vilken page som varit oanvänd längst, och sedan byta ut denna mot den nya pagen som vi behöver. För att ta reda på vilken page som varit oanvänd längst har jag lagt till en variabel per page som sparar den tiden då den senast vart traverserad. Om en viss page var traverserad vid tid t betyder det att dess förälder var traverserad ögonblicken före t. Vi kan utnyttja detta faktum när vi letar efter den page som inte använts på längst tid genom att göra en traversering av alla pages och där vi för varje enskild page fortsätter traversen i det barn med lägst t. När vi har kommit till ett pagelöv vet vi att denna page har lägst t av alla pages i hela GVT-modellen och ska därför skrivas ut på disk så vi kan ladda in den nya pagen. Att hitta LRU (Least Recently Used) pagen går nu i O(log(n)) där n är antal inlästa pages jämfört med O(n) som skulle behövas vid linjär sökning Page metadata I [Laine 2010] implementering ligger page-metadata alltid i minnet då de hävdar att page-metadata tar relativt lite plats samt att det är bekvämt att alltid ha tillgång 40

51 6.3. PAGING till den. Page-metadata i mitt fall är 8 stycken barnpekare (32 bytes) samt ca 18 bytes för övrig information. Även jag började med att alltid lägga page-metadata i minne, men har dock sedan dess kommit fram till att det är bättre att spara de tillsammans med övrig pagedata. Huvudanledningen till detta är att för stora modeller kan även page-metadata ta mycket plats. Som jag skrev ovan tar page-metadata i min implementering ca 50 bytes per page, riktigt stora modeller kan behöva flera miljoner pages vilket kan skapa metadata i storleksordningen 250 MB. Så pass mycket data skapar problem om det alltid måste ligga i minnet dels för att de ockuperar en så pass stor andel av användarens totala minne, dels för att uppstartningstiden för en viss modell blir långsam då 250 MB data måste läsas från disk. Jag har därför valt att lägga page-metadata tillsammans med övrig pagedata och skapar därför inga begränsningar på hur många pages vi kan ha samt att GVTmodeller får näst intill noll i uppstartningstid. Jag har inte hittat något ställe där man skulle behöva tillgång till page metadata utan att övrig pagedata redan är inladdad. Detta gör att [Laine 2010] argument om att det är bekvämt att hålla all page-metadata i minnet faller Page datastruktur Nedan visar jag de viktigaste variablerna i min pagedatastruktur: struct page { int time; // used for paging int refpush; // used for undo-redo // 8 page childs int childs[8]; }; // hashtabel for nodes in this page struct node *tabel[max_hash]; struct page g_pages[max_pages]; struct node g_nodes[max_nodes]; Time-variabeln används för att avgöra vilken page som det var längst tid sedan vi traverserade. Refpush -variabeln förklaras i kapitel 6.5. Childs-variabeln är en pekare till pagens potentiella barn. Detta är inte direkta minnesreferenser utan anger vilket pagenummer pagen har. Detta pagenummer kan både används för att läsa pagen från disk eller hämta en page direkt från minnet. Table-listan är hashtabellen för noderna (vi använder XYZ-hashtabell-lösningen), där noderna sedan sparas i en global lista. 41

52 KAPITEL 6. ANALYS AV ALGORITMER Parallelliserad paging När vi är tvungen att läsa in en page från disk måste vi se till att ingen annan tråd redan håller på att läsa in pagen. Enklaste sättet att implementera detta är med ett RW-lås (Read-Write lås) där skriva (write) betyder läsa in en page i vårat fall. För att en tråd ska få läsa in en page måste den skaffa ett skriv-lås (bara en tråd i taget kan ha detta), och ett skriv-lås kan bara utfärdas om alla andra trådar är i ett säkert läge där de inte läser från den data vi vill skriva till. För att undvika att en tråd kan få vänta på ett skriv-lås i oändlighet har jag använt mig av en så kallad svält-fri låsmekanism [Herlihy 2008, kap. 8.3]. 6.4 Layers Layers visar sig ett vara enkelt problem att lösa: Tekniskt sett är layers-möjligheten att ha flera GVT-modeller i samma fil. Dessa GVT-modeller har ingen data gemensamt och blir därför triviala att implementera. 6.5 Undo-Redo Algoritm En viktig funktion för att kunna editera GVT-modeller är att kunna ångra tidigare förändringar av modellen. Ett trivialt sätt att implementera detta är att före en förändring av modellen duplicerar man hela modellen och utför sedan förändringen på enbart en av dubbletterna. Detta är dock helt ohållbart i praktiken förutom för mycket små modeller av två anledningar: 1. Varje gång vi duplicerar modellen dubblar vi också mängden minne och hårddiskutrymme. 2. Eftersom en modell kan vara på flera GB data kan enorma datamängder behöva dupliceras före varje förändringar av modellen, vilket gör editering extremt långsam. De flesta förändringar användaren förväntas göra är lokala vilket medför att duplicering av hela modellen inte heller är nödvändigt. Jag har löst detta problem med hjälp av en funktion jag kallar Fork. Före varje förändring av trädet som man vill kunna gå tillbaka till med Undo körs funktionen Fork som har följande uppgifter: 1. Duplicera alla metadata om GVT-modellen. Detta inkluderar max- och minvärdena för rotnoden samt ett rotnod-index. 2. Gå till pagen som innehåller rotnoden och öka en variabel som vi kallar för refpush med ett. Detta går i O(1) tid då det inte innehåller någon iteration eller rekursion. Notera också att den enda page vi behöver tillgång till är den som innehåller rotnoden. 42

53 6.6. LAGRING PÅ DISK När Fork är klar kan vi börja förändringen av modellen. Alla funktioner som vill kunna editera GVT-modellen måste använda sig av en intern funktion som jag kallar GetPage. GetPage tar bland annat en flagga, som talar om för GetPage om användaren vill editera modellen. Om GetPage finner denna flagga specificerad utför den följande operationer: 1. Om refpush-variabeln för den page vi vill komma åt är större än 0 måste vi trycka ut refpush värdet till alla pagebarn. Detta betyder att vi laddar in alla pagebarn och adderar original-pagens refpush till deras deras refpushvariabel. 2. Pagen är nu redo att klonas vilket betyder att vi skapar en dubblett av pagen som vi returnerar med GetPage. Även denna operation går i O(1) tid då en page kan ha max 8 barn samt att en page bara kan ha ett begränsat antal noder. Den page GetPage returnerar är nu garanterat att vara unik vilket betyder att enbart denna version av GVT-modellen (den som Fork returnerade) kan komma åt den. Detta betyder i sin tur att vi kan ändra pagen utan att förstöra originalet Datastruktur Alla versioner av metadata om GVT-modellen som uppstår av Fork sparar jag i en lista där man sedan har en pekare till den aktiva versionen av metadatan. Detta gör det väldigt smidigt att utföra Undo och Redo då vi enbart behöver addera eller subtrahera 1 från pekaren: struct history { boolean struct layer } history; used; layers[max_layers]; struct history g_history[max_history]; struct int g_current; Allt detta gör att vi kan utföra undo- och redo-kommandona i realtid samt att en förändring av modellen inte har någon märkbar overhead. 6.6 Lagring på disk Översikt Vi måste självklart kunna spara ner GVT-modellen på disk. Det finns tre tillfällen när GVT-systemet måste använda hårdisken: 43

54 KAPITEL 6. ANALYS AV ALGORITMER 1. En nod som ska renderas eller editeras finns inte i minnet. GVT-systemet måste nu läsa in den page som noden tillhör från hårdisken och göra den tillgänglig i minnet. 2. Det finns inte tillräckligt med minne för att läsa in en page eller allokera en nod. GVT-systemet letar nu efter den page som varit oanvänd längst och skriver ut denna till disk varpå den kan tas bort från minnet. 3. Användaren vill stänga programmet. Innan vi stänger programmet måste GVT-systemet se till att alla noder finns på disk. GVT-systemet läser aldrig in enskilda noder från disk utan behandlar alltid diskoperationer på pagenivå. Den primära fördelen med detta är att vi minskar antalet diskoperationer samt att vi kan utföra komprimering på hela pagen vilket blir mer effektivt. Varje page sparas sedan som en virtuell fil på hårddisken. Användaren ser dock bara en fil på sin hårddisk vilket göra det enkelt för användaren att flytta filen från en plats till en annan. Den filen som användaren ser består dock internt av flera virtuella filer: en per page. Att använda en virtuell fil per page är en bra abstraktion då det blir mycket enklare att uppdatera och ta bort pages Komprimering till disk Eftersom en diskoperation ändå är långsam har vi tid att utföra komprimering av noderna innan vi skriver dem till disk. Det finns många metoder för att göra detta på och jag har inte haft tid att undersöka alla. Komprimering av noderna sker alltid per page. [Olick 2008] visar att det finns olika former av wavelet komprimering [Sayood 2006, kap. 15] som är effektiv för GVT-modeller. Dessa algoritmer är antagligen de mest effektiva, men jag har tyvärr fått lägga dem åt sidan då de inte lämpar sig för modeller som man vill kunna editera. Anledningen till detta är att om alla pages är beroende av sina föräldrar blir alla pages i slutändan beroende av rotpagen. Om rotpagen ändras måste vi nu uppdatera alla pages i hela modellen vilket blir på tok för långsamt. Jag har därför inriktat mig på den typ av komprimering som enbart använder data som finns i den aktuella pagen. Min komprimeringsimplementation kan delas upp i fem steg: 1. Hilbertkurva Första steget är att iterera igenom alla noder i pagen på ett sådant sätt att skillnaden från en specifik nod till nästa är så liten som möjligt. Det finns flera sätt att göra detta på, en av metoderna kallas för en Hilbertkurva [Hilbert 1891]. Poängen med en Hilbertkurva är att vi enbart flyttar oss ett steg i taget i x, y eller z led samtidigt som vi ändå i slutändan itererar igenom alla noder exakt en gång [Samet 2006, s. 200]. Detta kommer leda till bättre komprimering i steg 3, 4, 5. 44

55 6.6. LAGRING PÅ DISK 2. Kolumnordning I stället för att spara noddata grupperat per nod grupperar vi dem i stället på datatyp. De viktigaste datatyperna är childbits samt alla shadingkanaler. Detta steg gör de nästkommande komprimeringsstegen mer effektiva. När detta steg är klart har vi en lista per noddatatyp där listornas längd är antalet noder vi började med. 3. Deltakomprimering Varje element i listorna vi fick ut från steg 2 deltas nu från sitt tidigare värde. Delta betyder att man sparar skillnaden mellan nuvarande och föregående värde i förhoppningen att förändringen ska vara liten. Notera att i detta steg har noddatan fortfarande samma storlek som vi började, men vi har nu arrangerat om noddatan på ett sådan sätt att steg 4 och 5 kommer göra ett så bra jobb som möjligt. 4. Run-Length kodning Efter steg 2 och 3 är det vanligt att flera av listorna innehåller långa sektioner av enbart nollor. Childbit-listan för lövpages är ett exempel på detta. Run- Length kodning komprimerar ner dessa långa sektioner av nollor (och även andra värden) till en nolla och en siffra som säger hur många fler nollor som återstår. 5. Entropikodning Det sista steget komprimerar listorna ytterligare och bygger på Huffman entropikodning [Huffman 1952]. Tekniken bygger på att om vissa tal uppkommer oftare än andra tal i listan (efter deltakomprimering kommer små tal vara mycket vanligare än stora) kan vi spara dessa tal med färre bitar och därmed spara utrymme. När dessa steg är utförda har vi ett antal listor med komprimerad noddata som sedan skrivs till disk. När vi sedan ska läsa in noddata från disk kör vi alla ovanstående steg baklänges. Hela ovanstående process tar självklart en del tid att köra på CPU:n men det visar sig fortfarande bara vara en bråkdel av den tiden det tar för CPU:n att vänta på hårddisken. I vissa fall kan ovanstående process till och med göra paging snabbare, då mindre mängd data behöver skrivas till hårddisken. 45

56

57 Kapitel 7 Implementation I detta kapitel går jag igenom hur jag har implementerat och strukturerat min prototyp samt de viktigaste gränssnitten. Jag berör även valet av programmeringsspråk samt operativsystem 7.1 Programmeringsspråk Jag har valt C som programmeringsspråk. Jag ser framförallt två fördelar med C framför andra språk: Prestanda är alltid mycket viktigt när vi pratar om datorgrafik. C språket har varit med länge och dagens C kompilatorer har genom åren visat sig kunna generera mycket snabb kod, näst intill samma prestanda som väloptimerad assembler. Bra språk för bibliotek. C++ kod kan enkelt använda C kod men inte vice versa. Detta gör att C++ är en nackdel då program skrivna i C får svårare att använda min GVT-prototyp. Vidare har jag inte hittat något ställe i implementeringen där C++ skulle ha en stor fördel över C vilket ytterligare talar för C som språk då det är enklare och snabbare kompilera. 7.2 Operativsystemsmiljö Jag har valt att implementera prototypen på Windows-datorer. Största anledningen till detta är att jag själv använder Windows till vardags. Men Windows är också en välbeprövad plattform med gott stöd för bland annat CUDA. Hjärtat i min implementering använder dock minimialt med operativsystemsfunktionalitet och skulle därför vara mycket enkelt att porta till andra plattformar som t.ex. Linux och MacOS X. 47

58 KAPITEL 7. IMPLEMENTATION 7.3 Implementeringsstruktur Målet för prototypen är att skapa ett programmeringsbibliotek som gömmer alla detaljer som till exempel nod- och page-datastrukturer från användaren (nu pratar jag om användaren av programmeringsbiblioteket vilket inte nödvändigtvis är samma som slutanvändaren). Detta programmeringsbibliotek kan sedan användas av alla typer av program som behöver hantera GVT-modeller genom ett enkel gränssnitt. Programmeringsbiblioteket kallar jag för SVO-modulen (SVO från en engelska benämningen av GVT). För att strukturera implementeringen av SVO-modulen har jag valt att dela upp den i tre delar: Front-end, back-end samt FS som vi ser i figur 7.1. Figur 7.1. De olika modulerna i mitt GVT-system Front-End Front-end-modulens gränssnitt är det enda gränssnitt som användaren av SVOmodulen kommer att se. Jag har lagt stort fokus på att göra detta gränssnitt så enkelt och intuitivt som möjligt för att förenkla för användaren. Front-end-modulen tar sedan dessa enkla funktionsanrop som användaren ger och översätter dem till kommandon för back-end modulen som i sin tur utför jobbet. Nedan listar jag de viktigaste funktionerna i front-end gränssnittet: SetVoxel() Tar en position samt ett antal voxelparametrar som argument. Funktionen traverserar sedan ner GVT-trädet tills den kommer till den position användaren har angivit och ändrar sedan voxelparametrarna för den aktuella voxeln som jag beskriver i kapitel Om en nod i traverseringen inte redan finns kommer back-end modulen lägga till en nod. Detta gör att front-end modulen aldrig behöver bry sig om att allokeringen av nya noder. Det primära användningsområdet för denna funktion är vid voxalisering av vektorgrafik till voxelgrafik. GetVoxel() Tar en position som argument. Funktionen traverserar sedan ned genom GVTträdet tills vi stöter på ett löv och returnerar i så fall detta. Om vi inte finner något löv returnerar funktionen NULL. 48

59 7.3. IMPLEMENTERINGSSTRUKTUR RayTrace() Do() Undo() Tar en start punkt samt en riktning som argument. Funktionen utför sedan en ray trace genom GVT-modellen och returnerar den första voxeln som strålen träffar eller NULL om den inte träffade någon voxel. Denna funktionen kan även ta extra argument om kameran (upplösningen och linstyp) som sedan kan användas för att stoppa traverseringen när en nod i GVT-modellen får mindre projektionsytor på skärmen än en pixel (kapitel 4.8). Det primära användningsområdet för denna funktion är rendering av GVTmodeller. Sparar nuvarande GVT-modellen så att man kan återvända hit med funktionen Undo(). Enklaste sättet av implementera denna funktion skulle vara att ta en kopia av hela GVT-modellen något som i praktiken är helt omöjligt för stora GVT-modeller. I stället använder jag metoden jag beskriver i kapitel 6.5. Återvänder till det läge GVT-modellen befann sig i när vi körde Do(). Notera att denna funktion kan köras flera gånger och vi kommer då hoppa tillbaka ett Do() läge per gång. Touch() Användaren anger en callback funktion som sedan kommer köras rekursivt på hela GVT-modellen så länge callbacken returnerar sant (kapitel 6.1). Callbackfunktionen får som argument den aktuella nodens max- och min-värden samt nuvarande voxelparametrar. Denna funktion kan användas vid mipmapping men även för andra saker som t.ex att förkalkylera ljuset för en GVT-modell Back-End Back-end modulens primära uppgift är att hantera nod- och page-datastrukturerna. Ingen annan del av koden känner till hur dessa datastrukturer är implementerad. Detta gör att vi kan testa flera olika nod-datastrukturer genom att enbart skriva om back-end modulen vilket besparar oss tid jämfört med att behöva skriva om hela SVO-modulen. En annan fördel med att back-end och front-end modulerna inte delar nod/page datastrukturerna är att vi kan ha flera back-end moduler som är optimerade för olika ändamål. Vi kan till exempel ha en back-end för att läsa och skriva till modellen medan en annan back-end enbart är till för att läsa. Detta ger möjligheten för backend modulen att implementeras på de mest optimala sätt vilket kan öka prestanda. 49

60 KAPITEL 7. IMPLEMENTATION Back-end modulens viktigaste uppgifter är allokera och frigöra noder, paging samt komprimerision till hårddisk. Back-end modulen har även en låsmekanism som gör att man kan använda SMP i front-end modulen. Gränssnittet för back-end modulen (kommunikationen mellan front-end och back-end) tar stor användning av dataåtkomstlägena jag definierade i kapitel Back-end modulen använder sedan dessa dataåtkomstlägen för att veta hur den ska behandla nodförfrågan samt att sätta upp korrekta lås för SMP. Nedan listar jag de viktigaste funktionerna i back-end gränssnittet: GetRoot() GetChild() Används för att rekursivt traversera GVT-trädet för läsoperationer som till exempel rendering. GetChild funktionen tar som argument nuvarande nod samt en siffra c mellan 0 och 7 som säger vilket barn vi vill att funktionen ska returnera. Om barnet inte finns returneras NULL. TouchRoot() TouchChild() Samma argument som för GetRoot() och GetChild() men back-end modulen vet nu att front-end modulen tänker ändra på shadingdata i noden. Precis som för GetChild() returnerar vi NULL om noden inte finns. Denna funktion används primärt av front-end funktionen Touch(). ForgeRoot() ForgeNodeChild() ForgeLeafChild() ForgeEmptyChild() Samma argument som tidigare funktioner. Dessa funktioner kommer dock alltid att returnera en nod, om noden inte redan finns skapas en ny. ForgeEmptyChild() är ett undantag till detta då denna funktion friar alla potentiella barn under c och har därför ingen returvariabel. Dessa funktioner är den enda funktionalitet back-end erbjuder för att skapa och ta bort noder. Det är sedan front-end-modulens uppgift att använda dessa funktioner på ett kreativitet sätt för att tillhandahålla de funktioner som vi exporterar ut till front-end gränssnittet. GetMins() GetMaxs() Tar inga argument. Returnerar min- respektive max-värdena för GVT-modellen. Front-end modulen tar kopior på dessa värden när den ska börja en rekursion och uppdaterar sedan värdena under rekursionen så att vi alltid vet den aktuella nodens position (kapitel 6.1.2) FS (File System) FS modulen är en modul som gör att vi lagra flera virtuella filer i en vanlig fil. Detta är praktiskt då jag har valt att ha en fil per page vilket skapar tusentals filer för medelstora modeller och hundratusentals filer för stora modeller. Att användaren ska ha hundratusentals filer på hårdisken för att spara en GVT-modell bör självklart 50

61 7.4. SKAL undvikas, vilket har lätt mig till att implementera denna modul som undkommer problemet. Gränssnittet för FS modulen liknar det som ett operativsystem tillhandahåller men med skillnaden att alla virtuella filer i FS modulen enbart adresseras med en siffra i stället för en textsträng. De interna detaljerna för hur FS modulen fungerar är utanför fokuset för denna rapport. 7.4 Skal För att kunna testa mitt programmeringsbibliotek har jag bäddad in det i ett skal (shell). Skalet består av några enkla kommandon inspirerade från [Cortes 2006] för att operera på GVT-modellen. Nedan listar jag de viktigaste: origin <x> <y> <z> Sätter startpunken för framtida editeringar. spm <num> Står för Subdivisions Per Meter och anger precision för framtida editeringar. vox mesh <path> Voxaliserar en triangelsoppa från en fil. vox sphere <radius> Voxaliserar en sfär med en viss radie. do <text> undo Sparar nuvarande utseende för modellen så vi senare kan återvända hit. Återställer modellen till det utseende den hade vid senaste do-kommandot. render <camera> Renderar en bild av GVT-modellen från en specifik kameravinkel. Bilden kan sedan antingen visas i ett fönster direkt på skärmen eller skrivas till disk. display [-double] Renderar en bild av GVT-modellen från standard kameravinkeln och visar den i ett fönster. -double parametern anger att vi ska dubbla storleken på fönstret. 51

62

63 Kapitel 8 Resultat I detta kapitel visar jag resultatet av arbetet. Jag går även ytterligare en gång igenom de mål jag satte upp i kapitel 2.2 för att se hur bra jag har uppfyllt dem. 8.1 Prototypen Syfte I och med att jag har lyckats bygga en fungerande prototyp har jag visat att de ideer som diskuteras i rapporten är genomförbara i praktiken Implementering Gränssnittet till prototypen för detta arbete är inspirerat av [Cortes 2006] och [Driemeyer 2005]. Min prototyp ligger totalt på ca rader kod (tabell 8.1) varav 7500 ligger i SVO-modulen (Back-end, front-end samt FS). För att minimera buggar har jag även skrivit ett testprogram som kan verifiera korrekt beteende. Det har dock inte varit möjligt att implementera testprogrammet tillräckligt utförligt för att helt kunna garantera buggfri kod inom ramen för detta arbete. Tabell 8.1. Storleken av de olika modulerna i prototypen räknat till antal rader kod. Modul Rader kod Shell 6000 Front-end 2500 Back-end 4000 FS 1000 Total

64 KAPITEL 8. RESULTAT Demonstration Nedan är ett exempel från en körning av min prototyp. Rader som börjar med xade$ är kommandon från användaren. Notera att de specifika tidsangivelserna nedan inte är relevanta. xade$ spm 6 xade$ scale 0.01 xade$ bind texture "data/mesh/house.tga" xade$ do "house" xade$ vox mesh data/mesh/house.obj...loaded house.obj 3225 verts, 1075 faces Voxelized house.obj in seconds xade$ display Rendererd 512x512 pixels in seconds Resultatet av ovanstående körning visar jag i figur 8.1. Figur 8.1. En rendering av en GVT-modell från min prototyp. Låt säga att användaren vill lägga till ytterligare en modell med några tunnor bredvid huset, han fortsätter då på följande sätt: xade$ bind texture "data/mesh/barrel.tga" xade$ do "barrel" xade$ vox mesh data/mesh/barrel.obj 54

4 grundregler. Minneshantering. Problemet. Windows minkrav

4 grundregler. Minneshantering. Problemet. Windows minkrav 4 grundregler 1. Man kan aldrig få för mycket minne 2. Minnet kan aldrig bli för snabbt Minneshantering 3. Minne kan aldrig bli för billigt 4. Programmens storlek ökar fortare än minnet i datorerna (känns

Läs mer

Grafik raytracing. Mattias Axblom.

Grafik raytracing. Mattias Axblom. Grafik raytracing Mattias Axblom mam11003@student.mdh.se 1 SAMMANFATTNING Raytracing, strålföljning eller strålspårning är en metod för att rendera realistiska bilder, film och i framtiden spel. Grundidén

Läs mer

Grafiska pipelinen. Edvin Fischer

Grafiska pipelinen. Edvin Fischer Grafiska pipelinen Edvin Fischer Sammanfattning Rapporten behandlar den grafiska pipelinen och dess steg, vilka stegen är och hur de funkar. Inledning Rapporten har till syfte att beskriva hur den grafiska

Läs mer

HF0010. Introduktionskurs i datateknik 1,5 hp

HF0010. Introduktionskurs i datateknik 1,5 hp HF0010 Introduktionskurs i datateknik 1,5 hp Välkommna - till KTH, Haninge, Datateknik, kursen och till första steget mot att bli programmerare! Er lärare och kursansvarig: Nicklas Brandefelt, bfelt@kth.se

Läs mer

Grafiska pipelinens funktion

Grafiska pipelinens funktion LUNDS TEKNISKA HÖGSKOLA CAMPUS HELSINGBORG Grafiska pipelinens funktion Ludvig von Sydow EDT62, HT17 Datorarkitekturer med Operativsystem Sammanfattning Denna rapport syftar till att beskriva hur en graphics

Läs mer

Vektorkartor för mobila terminaler

Vektorkartor för mobila terminaler Vektorkartor för mobila terminaler Magnus Janlert 3 juni 2004 Introduktion Externt examensarbete, utfört VT2003 Visualiseringscentrum, c:a tio anställda, en del av Lantmäteriet Handledare: Jerry Eriksson

Läs mer

Rastrering och displayalgoritmer. Gustav Taxén

Rastrering och displayalgoritmer. Gustav Taxén Rastrering och displayalgoritmer Gustav Taxén gustavt@csc.kth.se 2D1640 Grafik och Interaktionsprogrammering VT 2007 Klippning Man vill undvika att rastrera de primitiver som hamnar utanför fönstret. Man

Läs mer

Datastrukturer och algoritmer. Föreläsning 15 Inför tentamen

Datastrukturer och algoritmer. Föreläsning 15 Inför tentamen Datastrukturer och algoritmer Föreläsning 15 Inför tentamen 1 Innehåll Kursvärdering Vi behöver granskare! Repetition Genomgång av gammal tenta 2 Första föreläsningen: målsättningar Alla ska höja sig ett

Läs mer

Grafik. För enklare datorsystem

Grafik. För enklare datorsystem Grafik För enklare datorsystem Grafik förr VGA-signalen Direktdriven grafik eller bildminne Bitmap-grafik Tile/teckenbaserad grafik Spritebaserad grafik Kollisionskontroll Rörelse : Hastighet / riktning

Läs mer

Spelutveckling - Scenegrafer. Scenegrafer Optimeringar Culling

Spelutveckling - Scenegrafer. Scenegrafer Optimeringar Culling Spelutveckling - Scenegrafer Scenegrafer Optimeringar Culling Scenegraf vad och varför? En hierkisk representation av en 3d-värld Directed acyclic Graph (DAG) Består av noder med med barn/föräldrar Gör

Läs mer

Shaders. Renderingssystem. Renderingssystem. Renderingssystem. Hårdvara för 3D-rendering. Hårdvara för 3D-rendering

Shaders. Renderingssystem. Renderingssystem. Renderingssystem. Hårdvara för 3D-rendering. Hårdvara för 3D-rendering Shaders Renderingssystem Applikation Geometri Rastrering Martin Fitger d00-mfi@d.kth.se VT 2008, DH2323 / DH2640 / NA8740 Renderingssystem Renderingssystem Applikation Per-vertex operationer Geometri Rastrering

Läs mer

Procedurell renderingsmotor i Javascript och HTML5

Procedurell renderingsmotor i Javascript och HTML5 Procedurell renderingsmotor i Javascript och HTML5 TNM084 Procedurella Metoder för bilder Gustav Strömberg - gusst250@student.liu.se http://gustavstromberg.se/sandbox/html5/shademe/texture_stop_final.html

Läs mer

Datorsystem 2 CPU. Förra gången: Datorns historia Denna gång: Byggstenar i en dators arkitektur. Visning av Akka (för de som är intresserade)

Datorsystem 2 CPU. Förra gången: Datorns historia Denna gång: Byggstenar i en dators arkitektur. Visning av Akka (för de som är intresserade) Datorsystem 2 CPU Förra gången: Datorns historia Denna gång: Byggstenar i en dators arkitektur CPU Visning av Akka (för de som är intresserade) En dators arkitektur På en lägre nivå kan vi ha lite olika

Läs mer

I rastergrafikens barndom...gjorde man grafik genom att skriva i ett videominne. Operationer på buffert och pixlar. Idag... Varför grafikkort?

I rastergrafikens barndom...gjorde man grafik genom att skriva i ett videominne. Operationer på buffert och pixlar. Idag... Varför grafikkort? Operationer på buffert och pixlar I rastergrafikens barndom......gjorde man grafik genom att skriva i ett videominne. Lapped textures Emil Praun et al., SIGGRAPH 2000. Gustav Taxén CID gustavt@nada.kth.se

Läs mer

LUNDS UNIVERSITET. Parallell exekvering av Float32 och INT32 operationer

LUNDS UNIVERSITET. Parallell exekvering av Float32 och INT32 operationer LUNDS UNIVERSITET Parallell exekvering av Float32 och INT32 operationer Samuel Molin Kursansvarig: Erik Larsson Datum 2018-12-05 Referat Grafikkort utför många liknande instruktioner parallellt då typiska

Läs mer

Digitalteknik och Datorarkitektur 5hp

Digitalteknik och Datorarkitektur 5hp Digitalteknik och Datorarkitektur 5hp Minnes-hierarkier och Cache 12 maj 2008 karl.marklund@it.uu.se issa saker använder vi ofta Dessa saker vill vi ha nära till hands Storleken har betydelse Litet är

Läs mer

Parallellism i NVIDIAs Fermi GPU

Parallellism i NVIDIAs Fermi GPU Parallellism i NVIDIAs Fermi GPU Thien Lai Phu IDA2 Abstract This report investigates what kind of computer architecture, based on Flynn s taxonomy, is used on NVIDIAs Fermi-based GPU to achieve parallellism

Läs mer

Teknik för avancerade datorspel!

Teknik för avancerade datorspel! 1(83) Information Coding / Computer Graphics, ISY, LiTH TSBK 03 Teknik för avancerade datorspel Ingemar Ragnemalm, ISY Fysik Datorgrafik Spelmekanismer AI Animation 1(83) Föreläsning 5 GPU computing GPU

Läs mer

Teknik för avancerade datorspel!

Teknik för avancerade datorspel! 1(84) Information Coding / Computer Graphics, ISY, LiTH TSBK 03 Teknik för avancerade datorspel Ingemar Ragnemalm, ISY Fysik Datorgrafik Spelmekanismer AI Animation 1(84) Föreläsning 5 GPU computing GPU

Läs mer

PROGRAMMERING. Ämnets syfte. Kurser i ämnet

PROGRAMMERING. Ämnets syfte. Kurser i ämnet PROGRAMMERING Ämnet programmering behandlar programmeringens roll i informationstekniska sammanhang som datorsimulering, animerad grafik, praktisk datoriserad problemlösning och användaranpassad konfiguration

Läs mer

Cacheminne Intel Core i7

Cacheminne Intel Core i7 EDT621 Datorarkitekturer med operativsystem 7,5 hp 2015-12-07 Cacheminne i Intel Core i7 Författare: Adnan Karahmetovic Handledare: Erik Larsson Innehåll 1. Inledning... 1 1.1 Syfte... 1 1.2 Frågeställning...

Läs mer

Datastrukturer, algoritmer och programkonstruktion (DVA104, HT 2014) Föreläsning 5

Datastrukturer, algoritmer och programkonstruktion (DVA104, HT 2014) Föreläsning 5 Datastrukturer, algoritmer och programkonstruktion (DVA104, HT 2014) Föreläsning 5? FORTSÄTTNING TRÄD RECAP (förra föreläsningen) RECAP (förra föreläsningen) Träd är icke-linjära datastrukturer som ofta

Läs mer

Tentamen TNM061, 3D-grafik och animering för MT2. Onsdag 20/ kl SP71. Inga hjälpmedel

Tentamen TNM061, 3D-grafik och animering för MT2. Onsdag 20/ kl SP71. Inga hjälpmedel Tentamen TNM061, 3D-grafik och animering för MT2 Onsdag 20/8 2014 kl 14-18 SP71 Inga hjälpmedel Tentamen innehåller 7 uppgifter, vilka tillsammans kan ge maximalt 50 poäng. För betyg G (registreras som

Läs mer

PROCEDUELL TERRÄNG. Proceduella metoder för bilder (TNM084) Jimmy Liikala Institutionen för teknik och naturvetenskap

PROCEDUELL TERRÄNG. Proceduella metoder för bilder (TNM084) Jimmy Liikala Institutionen för teknik och naturvetenskap PROCEDUELL TERRÄNG Proceduella metoder för bilder (TNM084) Jimmy Liikala (jimli570@student.liu.se) Institutionen för teknik och naturvetenskap Sammanfattning Rapporten beskriver hur en proceduell terräng

Läs mer

KUNDCASE. Inovia gjorde sin AI-utveckling 10 gånger snabbare med Power-plattformen

KUNDCASE. Inovia gjorde sin AI-utveckling 10 gånger snabbare med Power-plattformen KUNDCASE Inovia gjorde sin AI-utveckling 10 gånger snabbare med Power-plattformen MÖT INOVIA Inovia är ett marknadsledande bolag som är specialiserade på Big Data och AI där lösningarna utvecklas av ett

Läs mer

Spelutveckling 3d-grafik och modellering. Grunder för 3d-grafik Blender Animering

Spelutveckling 3d-grafik och modellering. Grunder för 3d-grafik Blender Animering Spelutveckling 3d-grafik och modellering Grunder för 3d-grafik Blender Animering Grunderna för 3d-grafik Positionering, transformationer Projektion, kameran Objekt i en 3d-värld Ljusmodeller för 3d-grafik

Läs mer

Omtentamen TNM077, 3D datorgrafik och animering (samt även TNM008, 3D datorgrafik och VR)

Omtentamen TNM077, 3D datorgrafik och animering (samt även TNM008, 3D datorgrafik och VR) Omtentamen TNM077, 3D datorgrafik och animering (samt även TNM008, 3D datorgrafik och VR) Grupp: MT2 och NO2MT Datum: Fredagen den 23 april 2004 Tid: 14.00-18.00 Hjälpmedel: inga Ansvarig lärare: Stefan

Läs mer

Grafer, traversering. Koffman & Wolfgang kapitel 10, avsnitt 4

Grafer, traversering. Koffman & Wolfgang kapitel 10, avsnitt 4 Grafer, traversering Koffman & Wolfgang kapitel 1, avsnitt 4 1 Traversering av grafer De flesta grafalgoritmer innebär att besöka varje nod i någon systematisk ordning precis som med träd så finns det

Läs mer

- A Scrum Planning Tool Case Study to Evaluate the The Rich AJAX Platform

- A Scrum Planning Tool Case Study to Evaluate the The Rich AJAX Platform Datavetenskap Opponent(er): Jhonny Carvajal Johan Bjärneryd Respondent(er): Fredrik Häggbom Erik Olsson Haglund Scrumptious - A Scrum Planning Tool Case Study to Evaluate the The Rich AJAX Platform Oppositionsrapport,

Läs mer

Kort introduktion till POV-Ray, del 1

Kort introduktion till POV-Ray, del 1 Kort introduktion till POV-Ray, del 1 Kjell Y Svensson, 2004-02-02,2007-03-13 Denna serie av artiklar ger en grundläggande introduktion och förhoppningsvis en förståelse för hur man skapar realistiska

Läs mer

PARALLELLISERING AV ALGORITMER PROCESSORER FÖR FLERKÄRNIGA

PARALLELLISERING AV ALGORITMER PROCESSORER FÖR FLERKÄRNIGA PARALLELLISERING AV ALGORITMER FÖR FLERKÄRNIGA PROCESSORER 870928 3017 Johan Gustafsson 870303 4952 Gustaf David Hallberg 880525 8210 Per Hallgren 801117 0597 Wuilbert Lopez 1/7 Innehållsförteckning Table

Läs mer

Fö 8: Operativsystem II. Minneshantering. Minneshantering (1) Minneshantering (2) Minneshantering och Virtuelltminne.

Fö 8: Operativsystem II. Minneshantering. Minneshantering (1) Minneshantering (2) Minneshantering och Virtuelltminne. Fö 8: Operativsystem II Minneshantering och Virtuelltminne. Virtuella I/O enheter och Filsystemet. Flerprocessorsystem. Minneshantering Uniprogrammering: Minnet delas mellan operativsystem och användarprogrammet.

Läs mer

Robin Wahlstedt Datavetenskap / Spel Vetenskapsmetodik rwt07001@student.mdh.se. Datorgrafik i spel

Robin Wahlstedt Datavetenskap / Spel Vetenskapsmetodik rwt07001@student.mdh.se. Datorgrafik i spel Robin Wahlstedt Datavetenskap / Spel Vetenskapsmetodik rwt07001@student.mdh.se Datorgrafik i spel 1 Sammanfattning Dator grafik kan delas in i fyra olika områden: information, design, simuleringar och

Läs mer

Schemaläggnings metoderna AMP & SMP i en Multiprocessor

Schemaläggnings metoderna AMP & SMP i en Multiprocessor EDT621 Datorarkitekturer med operativsystem 7,5 HP 2015-12-05 Schemaläggnings metoderna AMP & SMP i en Multiprocessor Författare: Simon Plato Sammanfattning Rapporten beskriver två schemaläggnings metoder.

Läs mer

Fredag 10 juni 2016 kl 8 12

Fredag 10 juni 2016 kl 8 12 KTH CSC, Alexander Baltatzis DD1320/1321 Lösningsförslag Fredag 10 juni 2016 kl 8 12 Hjälpmedel: En algoritmbok (ej pythonkramaren) och ditt eget formelblad. För betyg E krävs att alla E-uppgifter är godkända,

Läs mer

Öppna filer och filsystem i PintOS Hemuppgift TDDI81, 21/

Öppna filer och filsystem i PintOS Hemuppgift TDDI81, 21/ Öppna filer och filsystem i PintOS Hemuppgift TDDI8, /0-03 Almquist Mathias (matal09) Nguyen Johan (johng86) Hamzic Mirza (mirha348) Timliden Erik (eriti930) INLEDNING PintOS är ett operativsystem utvecklat

Läs mer

HAND TRACKING MED DJUPKAMERA

HAND TRACKING MED DJUPKAMERA HAND TRACKING MED DJUPKAMERA ETT PROJEKT I TNM090 - SOFTWARE ENGINEERING Rasmus KARLSSON Per JOHANSSON Erik HAMMARLUND raska293@student.liu.se perjo020@student.liu.se eriha891@student.liu.se 2014-01-14

Läs mer

PROGRAMMERING. Ämnets syfte. Kurser i ämnet

PROGRAMMERING. Ämnets syfte. Kurser i ämnet PROGRAMMERING Ämnet programmering behandlar hur mjukvaror skapas, anpassas och utvecklas samt programmeringens roll i informationstekniska sammanhang som datorsimulering och praktisk datoriserad problemlösning.

Läs mer

Grafik. För enklare datorsystem

Grafik. För enklare datorsystem Grafik För enklare datorsystem Grafik förr VGA-signalen Direktdriven grafik eller bildminne Bitmap-grafik Tile/teckenbaserad grafik Spritebaserad grafik Kollisionskontroll Rörelse : Hastighet / riktning

Läs mer

CDC en jämförelse mellan superskalära processorer. EDT621 Campus Helsingborg av: Marcus Karlsson IDA

CDC en jämförelse mellan superskalära processorer. EDT621 Campus Helsingborg av: Marcus Karlsson IDA CDC6600 - en jämförelse mellan superskalära processorer av: Marcus Karlsson Sammanfattning I denna rapport visas konkret information om hur den första superskalära processorn såg ut och hur den använde

Läs mer

Universe Engine Rapport

Universe Engine Rapport 1 Universe Engine Rapport Alexander Mennborg 2017-05-08 2 Inledning I denna rapport diskuteras utvecklingsprocessen till projektet Universe Engine. Denna diskussion omfattar hela utveckling från starten

Läs mer

Algoritmer, datastrukturer och komplexitet

Algoritmer, datastrukturer och komplexitet Algoritmer, datastrukturer och komplexitet Övning 6 Anton Grensjö grensjo@csc.kth.se 4 oktober 2017 1 Idag Algoritmkonstruktion (lite blandat) Redovisning och inlämning av labbteori 3 2 Uppgifter Uppgift

Läs mer

Lunds Tekniska Högskola Datorarkitektur med operativsystem EITF60. Superscalar vs VLIW. Cornelia Kloth IDA2. Inlämningsdatum:

Lunds Tekniska Högskola Datorarkitektur med operativsystem EITF60. Superscalar vs VLIW. Cornelia Kloth IDA2. Inlämningsdatum: Lunds Tekniska Högskola Datorarkitektur med operativsystem EITF60 Superscalar vs VLIW Cornelia Kloth IDA2 Inlämningsdatum: 2018-12-05 Abstract Rapporten handlar om två tekniker inom multiple issue processorer

Läs mer

After Effects Lathund

After Effects Lathund After Effects After Effects Lathund After Effects En komposition är det samma som ett filmklipp i After Effects. En komposition kan vara hela filmen/ animationen eller så använder man sig av flera kompositioner

Läs mer

SKOLFS. beslutade den -- maj 2015.

SKOLFS. beslutade den -- maj 2015. SKOLFS Föreskrifter om ändring i Skolverkets föreskrifter (SKOLFS 2010:247) om ämnesplan för ämnet programmering i gymnasieskolan och inom kommunal vuxenutbildning på gymnasial nivå; beslutade den -- maj

Läs mer

Algoritmer, datastrukturer och komplexitet

Algoritmer, datastrukturer och komplexitet Algoritmer, datastrukturer och komplexitet Övning 6 Anton Grensjö grensjo@csc.kth.se 9 oktober 2015 Anton Grensjö ADK Övning 6 9 oktober 2015 1 / 23 Översikt Kursplanering Ö5: Grafalgoritmer och undre

Läs mer

Cacheprobe: programbibliotek för extrahering av cacheminnesparametrar

Cacheprobe: programbibliotek för extrahering av cacheminnesparametrar Cacheprobe: programbibliotek för extrahering av cacheminnesparametrar Gabriel Gerhardsson Cacheprobe p.1/38 Abstract Kan analytiskt ta reda på associativitet, line storlek och storlek på processorns cacheminnen

Läs mer

Datorgrafik Ray tracing. Mattias Ekström, Västerås,

Datorgrafik Ray tracing. Mattias Ekström, Västerås, Datorgrafik Ray tracing Mattias Ekström, Västerås, 2010-03-05 1 SAMMANFATTNING Ray tracing är en teknik för att skapa bilder digitalt. Den används komersiellt främst inom film- och spelindustrin. Metoden

Läs mer

SKOLFS. beslutade den XXX 2017.

SKOLFS. beslutade den XXX 2017. 1 (11) Föreskrifter om ändring i Skolverkets föreskrifter (SKOLFS 2010:247) om ämnesplan för ämnet programmering i gymnasieskolan, inom kommunal vuxenutbildning på gymnasial nivå och inom vidareutbildning

Läs mer

Borttagning av skymda ytor Painter s Algorithm och Z-buffering. MICHAEL HJORTHOLT och ANDREAS PAULSSON

Borttagning av skymda ytor Painter s Algorithm och Z-buffering. MICHAEL HJORTHOLT och ANDREAS PAULSSON Borttagning av skymda ytor Painter s Algorithm och Z-buffering MICHAEL HJORTHOLT och ANDREAS PAULSSON Examensarbete Stockholm, Sverige 2010 Borttagning av skymda ytor Painter s Algorithm och Z-buffering

Läs mer

Aktivitetsschemaläggning för flerkärninga processorer

Aktivitetsschemaläggning för flerkärninga processorer Lunds Tekniska Högskola Datorarkitekturer med Operativsystem EDT621 Aktivitetsschemaläggning för flerkärninga processorer Tobias Lilja 5 december 2016 Innehåll 1 Inledning 3 1.1 Syfte................................

Läs mer

Objektorienterad programmering

Objektorienterad programmering Objektorienterad programmering Emil Ahlqvist (c10eat@cs.umu.se) Didrik Püschel (dv11dpl@cs.umu.se) Johan Hammarström (c08jhm@cs.umu.se) Hannes Frimmel Moström (c10hml@cs.umu.se) 1 1. Introduktion 1.1 Objektorienterad

Läs mer

PROGRAMMERING. Ämnets syfte. Kurser i ämnet

PROGRAMMERING. Ämnets syfte. Kurser i ämnet PROGRAMMERING Ämnet programmering behandlar programmeringens roll i informationstekniska sammanhang som datorsimulering, animerad grafik, praktisk datoriserad problemlösning och användaranpassad konfiguration

Läs mer

Tentamen, Algoritmer och datastrukturer

Tentamen, Algoritmer och datastrukturer UNDS TEKNISKA ÖGSKOA (6) Institutionen för datavetenskap Tentamen, Algoritmer och datastrukturer 23 8 29, 8. 3. Anvisningar: Denna tentamen består av fem uppgifter. Totalt är skrivningen på 36 poäng och

Läs mer

Hyper Threading Intels implementation av SMT. Datorarkitekturer med operativsystem - EITF60. Felix Danielsson IDA2

Hyper Threading Intels implementation av SMT. Datorarkitekturer med operativsystem - EITF60. Felix Danielsson IDA2 Hyper Threading Intels implementation av SMT Datorarkitekturer med operativsystem - EITF60 Felix Danielsson IDA2 Sammanfattning Simultaneous multithreading (SMT) är en teknik som används i processorer

Läs mer

Abstrakta datatyper. Primitiva vektorer. Deklarera en vektor

Abstrakta datatyper. Primitiva vektorer. Deklarera en vektor Abstrakta datatyper 1 Primitiva vektorer Vektorer kan skapas av primitiva datatyper, objektreferenser eller andra vektorer. Vektorer indexeras liksom i C från 0. För att referera en vektor används hakparenteser.

Läs mer

Arv. Fundamental objekt-orienterad teknik. arv i Java modifieraren protected Lägga till och modifiera metoder med hjälp av arv Klass hierarkier

Arv. Fundamental objekt-orienterad teknik. arv i Java modifieraren protected Lägga till och modifiera metoder med hjälp av arv Klass hierarkier Arv Fundamental objekt-orienterad teknik arv i Java modifieraren protected Lägga till och modifiera metoder med hjälp av arv Klass hierarkier Programmeringsmetodik -Java 165 Grafisk respresentation: Arv

Läs mer

32 Bitar Blir 64 Sammanfattning

32 Bitar Blir 64 Sammanfattning 32 Bitar Blir 64 Sammanfattning Syftet med rapporten är att ge en insyn i det tillvägagångssätt och problem som uppstod i utvecklingen från 32 bitars CPUs till 64 bitars CPUs samt inblick i skillnaden

Läs mer

Programmering II (ID1019) :00-11:00

Programmering II (ID1019) :00-11:00 ID1019 Johan Montelius Programmering II (ID1019) 2015-06-11 08:00-11:00 Instruktioner Du får inte ha något materiel med dig förutom skrivmateriel. Mobiler etc, skall lämnas till tentamensvakten. Svaren

Läs mer

Optimering av olika slag används inom så vitt skilda områden som produktionsplanering,

Optimering av olika slag används inom så vitt skilda områden som produktionsplanering, Anders Johansson Linjär optimering Exempel på användning av analoga och digitala verktyg i undervisningen Kursavsnittet linjär optimering i Matematik 3b kan introduceras med såväl analoga som digitala

Läs mer

Filsystem. Varför? Hur? För att kunna lagra data mer permanent än i RAM. Vettig organisation Vettiga namn

Filsystem. Varför? Hur? För att kunna lagra data mer permanent än i RAM. Vettig organisation Vettiga namn Varför? För att kunna lagra data mer permanent än i RAM Hur? Vettig organisation Vettiga namn Stora/små bokstäver 8-bitars tecken (teckenkodning) File extensions Längd Struktur på filerna Byte efter byte,

Läs mer

Visualisering med Rhino/Vray/Photoshop av modell som skapats i Revit. AADA15 Revit Workshop 2017 LTH Ludvig Hofsten

Visualisering med Rhino/Vray/Photoshop av modell som skapats i Revit. AADA15 Revit Workshop 2017 LTH Ludvig Hofsten Visualisering med Rhino/Vray/Photoshop av modell som skapats i Revit AADA15 Revit Workshop 2017 LTH Ludvig Hofsten Så här ser min byggnad som exporterats från Revit ut när jag öppnar den i Rhino. Den

Läs mer

Bézierkurvor och parametriska objektrepresentationer

Bézierkurvor och parametriska objektrepresentationer Sidan 1 av 11 Inledning Detta är en kort sammanfattning av teorimaterialet som år 2004 ingår i examinationen i kursen TNM077 3D-grafik och animering som ges vid Linköpings tekniska universitet på Campus

Läs mer

Föreläsning 1: Intro till kursen och programmering

Föreläsning 1: Intro till kursen och programmering Föreläsning 1: Intro till kursen och programmering λ Kursens hemsida http:www.it.uu.se/edu/course/homepage/prog1/mafykht11/ λ Studentportalen http://www.studentportalen.uu.se UNIX-konton (systemansvariga

Läs mer

Tentamen TEN1 HI

Tentamen TEN1 HI Tentamen TEN1 HI1029 2014-03-14 Skrivtid: 8.15-13.00 Hjälpmedel: Referensblad (utdelas), papper (tomma), penna Logga in med tentamenskontot ni får av skrivvakten. Det kommer att ta tid att logga in ha

Läs mer

Självbalanserande träd AVL-träd. Koffman & Wolfgang kapitel 9, avsnitt 1 2

Självbalanserande träd AVL-träd. Koffman & Wolfgang kapitel 9, avsnitt 1 2 Självbalanserande träd AVL-träd Koffman & Wolfgang kapitel 9, avsnitt 1 2 1 Balanserade träd Nodbalanserat träd: skillnaden i antalet noder mellan vänster och höger delträd är högst 1 Höjdbalanserat träd:

Läs mer

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 11 Jonas Lindgren, Institutionen för Datavetenskap, LiU

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 11 Jonas Lindgren, Institutionen för Datavetenskap, LiU TDDC30 Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 11 Jonas Lindgren, Institutionen för Datavetenskap, LiU På denna föreläsning: Designmönster Adapter, Factory, Iterator,

Läs mer

Programmering B med Visual C++ 2008

Programmering B med Visual C++ 2008 Programmering B med Visual C++ 2008 Innehållsförteckning 1 Repetition och lite nytt...5 I detta kapitel... 5 Programexekvering... 5 Loop... 5 Källkod... 6 Verktyg... 6 Säkerhetskopiera... 6 Öppna, kompilera,

Läs mer

BINÄRA TRÄD. (X = pekarvärdet NULL): struct int_bt_node *pivot, *ny; X X X 12 X X 12 X X -3 X X

BINÄRA TRÄD. (X = pekarvärdet NULL): struct int_bt_node *pivot, *ny; X X X 12 X X 12 X X -3 X X Algoritmer och Datastrukturer Kary FRÄMLING/Göran PULKKIS (v23) Kap. 7, Sid 1 BINÄRA TRÄD Träd används för att representera olika slags hierarkier som ordnats på något sätt. Den mest använda trädstrukturen

Läs mer

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 8 Erik Nilsson, Institutionen för Datavetenskap, LiU

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 8 Erik Nilsson, Institutionen för Datavetenskap, LiU TDDC30 Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 8 Erik Nilsson, Institutionen för Datavetenskap, LiU På denna föreläsning: Träd Traversering Insättning, borttagning

Läs mer

Grunder. Grafiktyper. Vektorgrafik

Grunder. Grafiktyper. Vektorgrafik 2 Grunder All vår början bliver svår eller hur det nu brukar heta, och detta är något som gäller även Flash. För den som är ovan vid Flash gäller det säkert extra mycket, då det kan vara knepigt att förstå

Läs mer

C-UPPSATS. Revitalizing classic art using real-time game technology

C-UPPSATS. Revitalizing classic art using real-time game technology C-UPPSATS 2010:125 Revitalizing classic art using real-time game technology - environment modeling and texturing Mathias Berg Luleå tekniska universitet C-uppsats Datorgrafik Institutionen för LTU Skellefteå

Läs mer

Tor Sterner-Johansson Thomas Johansson Daniel Henriksson

Tor Sterner-Johansson Thomas Johansson Daniel Henriksson Lab 4: Anti Tower Defence Oskar Mothander Alan Mendez Larsson dit06omr dit06mln Lärare: Handledare: Johan Eliasson Johan Granberg Tor Sterner-Johansson Thomas Johansson Daniel Henriksson Innehåll 1. Problemspecifikation...

Läs mer

Hyper-Threading i Intelprocessorer

Hyper-Threading i Intelprocessorer Lunds Tekniska Högskola Campus Helsingborg DATORARKITEKTURER MED OPERATIVSYSTEM EITF60 RAPPORT Hyper-Threading i Intelprocessorer 4 december 2017 Rasmus Hanning IDA2 Sammanfattning Det har sedan den första

Läs mer

PROGRAMMERING. Ämnets syfte. Kurser i ämnet

PROGRAMMERING. Ämnets syfte. Kurser i ämnet PROGRAMMERING Ämnet programmering behandlar programmeringens roll i informationstekniska sammanhang som datorsimulering, animerad grafik, praktisk datoriserad problemlösning och användaranpassad konfiguration

Läs mer

Teoretisk del. Facit Tentamen TDDC kl (6) 1. (6p) "Snabba frågor" Alla svar motiveras väl.

Teoretisk del. Facit Tentamen TDDC kl (6) 1. (6p) Snabba frågor Alla svar motiveras väl. Facit Tentamen TDDC30 2015-08-28 kl 08-12 1 (6) Teoretisk del 1. (6p) "Snabba frågor" Alla svar motiveras väl. a) Vad är syftet med ett interface? (1p) Svar:Att ange vilka metoder som ska finnas, utan

Läs mer

Hantering av hazards i pipelines

Hantering av hazards i pipelines Datorarkitektur med operativsystem Hantering av hazards i pipelines Lisa Arvidsson IDA2 Inlämningsdatum: 2018-12-05 Abstract En processor som använder pipelining kan exekvera ett flertal instruktioner

Läs mer

Parallellprogrammering i C++ 17 EDT621 Datorarkitekturer med Operativsystem Viktor Lindgren

Parallellprogrammering i C++ 17 EDT621 Datorarkitekturer med Operativsystem Viktor Lindgren Parallellprogrammering i C++ 17 EDT621 Datorarkitekturer med Operativsystem Viktor Lindgren 2016-12-05 Sammanfattning I följande rapport introduceras de tillägg som planeras genomföras i kommande C++ 17

Läs mer

Titel Mall för Examensarbeten (Arial 28/30 point size, bold)

Titel Mall för Examensarbeten (Arial 28/30 point size, bold) Titel Mall för Examensarbeten (Arial 28/30 point size, bold) SUBTITLE - Arial 16 / 19 pt FÖRFATTARE FÖRNAMN OCH EFTERNAMN - Arial 16 / 19 pt KTH ROYAL INSTITUTE OF TECHNOLOGY ELEKTROTEKNIK OCH DATAVETENSKAP

Läs mer

Classes och Interfaces, Objects och References, Initialization

Classes och Interfaces, Objects och References, Initialization Classes och Interfaces, Objects och References, Initialization Objekt-orienterad programmering och design (DIT953) Niklas Broberg/Johannes Åman Pohjola, 2018 Abstract class En abstract class är en class

Läs mer

Inlämningsuppgift : Finn. 2D1418 Språkteknologi. Christoffer Sabel E-post: csabel@kth.se 1

Inlämningsuppgift : Finn. 2D1418 Språkteknologi. Christoffer Sabel E-post: csabel@kth.se 1 Inlämningsuppgift : Finn 2D1418 Språkteknologi Christoffer Sabel E-post: csabel@kth.se 1 1. Inledning...3 2. Teori...3 2.1 Termdokumentmatrisen...3 2.2 Finn...4 3. Implementation...4 3.1 Databasen...4

Läs mer

Ett generellt träd är. Antingen det tomma trädet, eller en rekursiv struktur: rot /. \ /... \ t1... tn

Ett generellt träd är. Antingen det tomma trädet, eller en rekursiv struktur: rot /. \ /... \ t1... tn Träd allmänt Träd allmänt Ett generellt träd är Antingen det tomma trädet, eller en rekursiv struktur: rot /. \ /... \ t1... tn där t1,..., tn i sin tur är träd och kallas subträd, vars rotnoder kallas

Läs mer

Innehåll. Föreläsning 11. Organisation av Trie. Trie Ytterligare en variant av träd. Vi har tidigare sett: Informell specifikation

Innehåll. Föreläsning 11. Organisation av Trie. Trie Ytterligare en variant av träd. Vi har tidigare sett: Informell specifikation Innehåll Föreläsning 11 Trie Sökträd Trie och Sökträd 356 357 Trie Ytterligare en variant av träd. Vi har tidigare sett: Oordnat träd där barnen till en nod bildar en mängd Ordnat träd där barnen till

Läs mer

Generell säkerhet. Loggning - Hur mycket ska man logga? Inloggningsrutinerna i Unix. Loggning fortsättning

Generell säkerhet. Loggning - Hur mycket ska man logga? Inloggningsrutinerna i Unix. Loggning fortsättning Generell säkerhet Här finns det inga direkta rätt eller fel. Snarare saker man bör tänka på när man implementerar ett program. Kort sagt: Efter att du kommit på hur du tänkt göra, sov på saken och tänk

Läs mer

Introduktion till programmering D0009E. Föreläsning 1: Programmets väg

Introduktion till programmering D0009E. Föreläsning 1: Programmets väg Introduktion till programmering D0009E Föreläsning 1: Programmets väg 1 Vad är en dator? En maskin vars beteende styrs av de innehållet (bitmönster) som finns lagrade i datorns minne (inte helt olikt förra

Läs mer

TDDI16 Datastrukturer och algoritmer. Prioritetsköer, heapar, Union/Find

TDDI16 Datastrukturer och algoritmer. Prioritetsköer, heapar, Union/Find TDDI16 Datastrukturer och algoritmer Prioritetsköer, heapar, Union/Find Prioritetsköer En vanligt förekommande situation: Väntelista (jobbhantering på skrivare, simulering av händelser) Om en resurs blir

Läs mer

Grunderna i C++ T A. Skapad av Matz Johansson BergströmLIMY

Grunderna i C++ T A. Skapad av Matz Johansson BergströmLIMY Grunderna i C++ ARK 385: Virtuella Verktyg i en Materiell värld AT Arkitektur & Teknik Chalmers Tekniska Högskola 2009 - Kursen skapades (3 förel.) 2010-6 förel. + 2 projekt 2011-8 förel. Helt omarbetade

Läs mer

Logging Module into the PRIME Core

Logging Module into the PRIME Core Datavetenskap Opponent: Andreas Lavén Respondenter: Anders Ellvin, Tobias Pulls Implementing a Privacy-Friendly Secure Logging Module into the PRIME Core Oppositionsrapport, E-nivå 2005:xx 1 Sammanfattat

Läs mer

Tentamen TNM061, 3D-grafik och animering för MT2. Tisdag 3/ kl 8-12 TP51, TP52, TP54, TP56, TP41, TP43. Inga hjälpmedel

Tentamen TNM061, 3D-grafik och animering för MT2. Tisdag 3/ kl 8-12 TP51, TP52, TP54, TP56, TP41, TP43. Inga hjälpmedel Tentamen TNM061, 3D-grafik och animering för MT2 Tisdag 3/6 2014 kl 8-12 TP51, TP52, TP54, TP56, TP41, TP43 Inga hjälpmedel Tentamen innehåller 8 uppgifter, vilka tillsammans kan ge maximalt 50 poäng.

Läs mer

Tentamen TEN1 HI

Tentamen TEN1 HI Tentamen TEN1 HI1029 2015-03-17 Skrivtid: 8.15-13.00 Hjälpmedel: Referensblad (utdelas), papper (tomma), penna Logga in med tentamenskontot ni får av skrivvakten. Det kommer att ta tid att logga in ha

Läs mer

Snapdragon 810: Cacheminnet

Snapdragon 810: Cacheminnet Snapdragon 810: Cacheminnet Daniel Eckerström dat14dec@student.lu.se Sammanfattnig Snapdragon 810 innehåller två olika processor arkitekturer, ARM Cortex-A53 samt Cortex-A57. Detta för att kunna på ett

Läs mer

Pipelining i Intel Pentium II

Pipelining i Intel Pentium II Pipelining i Intel Pentium II John Abdulnoor Lund Universitet 04/12/2017 Abstract För att en processor ska fungera måste alla komponenter inuti den samarbeta för att nå en acceptabel nivå av prestanda.

Läs mer

Försättsblad till skriftlig tentamen vid Linköpings Universitet

Försättsblad till skriftlig tentamen vid Linköpings Universitet Försättsblad till skriftlig tentamen vid Linköpings Universitet (fylls i av ansvarig) Datum för tentamen Sal Tid Kurskod Provkod Kursnamn/benämning Institution Antal uppgifter i tentamen Antal sidor på

Läs mer

Designmönster, introduktion. Vad är det? Varför skall man använda mönster?

Designmönster, introduktion. Vad är det? Varför skall man använda mönster? Designmönster, introduktion. Vad är det? Varför skall man använda mönster? Kent Petersson EMW, Mölndal Datavetenskap, Chalmers epost1: kentp@cs.chalmers.se epost2: kent.petersson@emw.ericsson.se URL: http://www.cs.chalmers.se/~kentp

Läs mer

Värmedistribution i plåt

Värmedistribution i plåt Sid 1 (6) Värmedistribution i plåt Introduktion Om vi med konstant temperatur värmer kanterna på en jämntjock plåt så kommer värmen att sprida sig och temperaturen i plåten så småningom stabilisera sig.

Läs mer

Programmering eller Datalogiskt tänkande

Programmering eller Datalogiskt tänkande Programmering eller Datalogiskt tänkande I förskolan handlar programmering om att få en begynnande förståelse vad det kan innebära. Barnen ges ett kreativt utrymme och har möjlighet att forma sin egen

Läs mer

Föreläsning 2. Operativsystem och programmering

Föreläsning 2. Operativsystem och programmering Föreläsning 2 Operativsystem och programmering Behov av operativsystem En dator så som beskriven i förra föreläsningen är nästan oanvändbar. Processorn kan bara ges enkla instruktioner såsom hämta data

Läs mer

Programmering i C++ En manual för kursen Datavetenskaplig introduktionskurs 5p

Programmering i C++ En manual för kursen Datavetenskaplig introduktionskurs 5p Programmering i C++ En manual för kursen Datavetenskaplig introduktionskurs 5p Skriven av Michael Andersson Introduktion Programmering I högnivåspråk fokuserar på själv problemet (algoritmen) istället

Läs mer

Kravspecifikation för hårdvaruprojekt i kursen Datorsystemteknik, HT2005. Temperaturvakt med loggningsfunktion

Kravspecifikation för hårdvaruprojekt i kursen Datorsystemteknik, HT2005. Temperaturvakt med loggningsfunktion Kravspecifikation för hårdvaruprojekt i kursen Datorsystemteknik, HT2005 Temperaturvakt med loggningsfunktion Bakgrund Den här applikationen skall tas fram i syfte att träna studenter på Datorsystemteknikkursen

Läs mer

Beräkning med ord. -hur en dator hanterar perception. Linköpings universitet Artificiell intelligens 2 2010-10-03 Erik Claesson 880816-1692

Beräkning med ord. -hur en dator hanterar perception. Linköpings universitet Artificiell intelligens 2 2010-10-03 Erik Claesson 880816-1692 Beräkning med ord -hur en dator hanterar perception 2010-10-03 Erik Claesson 880816-1692 Innehåll Inledning... 3 Syfte... 3 Kan datorer hantera perception?... 4 Naturligt språk... 4 Fuzzy Granulation...

Läs mer