# Richtlijn voor het maken van 3D modellen voor Ultimate Stunts

### Inleiding

Ultimate Stunts is een 3D-spel, en het gebruikt 3D-modellen om de baan uit op te bouwen en voor de auto's. Deze 3D-modellen kunnen in externe 3D modelleer-software gemaakt worden, geïmporteerd worden met het stunts3dedit programma, getransformeerd en gekleurd worden, en opgeslagen worden in Ultimate Stunts' interne .glb formaat. Dit document beschrijft niet hoe u dit kunt doen. In plaats daarvan beschrijft het wat voor soort 3D-modellen passen bij de doelstellingen van Ultimate Stunts.

### Doelstellingen voor goede 3D-modellen

Een 3D-model is goed als het aan twee eisen voldoet: het moet er goed uit zien, en het moet snel weergegeven kunnen worden. Deze twee eisen hebben natuurlijk vaak een tegengesteld effect op het 3D-model: een model dat er goed uit ziet wordt vaak traag weergegeven, en een snel weergegeven model ziet er vaak slecht uit. In dit document worden enkele trucs vermeld om 3D-modellen zowel snel als mooi te laten zijn.

### Snelheids-eisen, en doel-platforms

Het juiste evenwicht tussen snelheid en detail hangt natuurlijk af van de hardware. Ultimate Stunts gebruikt OpenGL, en dat kan vele malen sneller zijn als het hardware-versnelling gebruikt. Het Ultimate Stunts project probeert erg flexibel te zijn in de hardware-eisen: mensen met slechte hardware moeten in staat zijn om een acceptabele frame rate te krijgen (met slechte graphics), en mensen met goede hardware moeten hoge kwaliteit graphics kunnen krijgen. De gebruiker kan verschillende grafische instellingen wijzigen in Ultimate Stunts, zoals de texture-Level-Of-Detail, aan/uitschakelen van blenden van doorschijnende oppervlakken, en zelfs aan/uitschakelen van de Z-buffer.

### Level Of Detail (LOD)

Voor de 3D-geometrie ontwerper is het belangrijk om te weten dat Ultimate Stunts verschillende Levels Of Detail (LOD) gebruikt in verschillende situaties. De 3D-geometrie van elke LOD moet gedefinieerd worden in het .glb-bestand (natuurlijk kunt u een enkel model gebruiken in elke LOD, maar dat is niet de optimale situatie). Op dit moment zijn er zes LODs: 1 (meeste detail) tot 4 (minste detail), c (voor botsings-detectie) en s (voor rij-oppervlaktes).

### Polygon count

Zelfs op goede hardware kan het aantal polygonen in een model het te traag maken. Elke polygon heeft een aantal vertices, en voor elke vertex moet er een aantal transformaties en tests gedaan worden om het te projecteren op het scherm-oppervlak. In feite is de vertex count belangrijker dan de polygon count; er kan een verschil zijn als vertices gedeeld worden tussen polygonen.

Een model met minder polygonen is altijd minder gedetailleerd dan een model met meer polygonen. Vooral gekromde oppervlaktes kunnen er slecht uit zien als ze zijn opgebouwd uit te weinig polygonen. Er zijn een aantal trucs die toegepast kunnen worden om te verhullen dat een model maar een paar polygonen heeft:

- Gekromde oppervlaktes kunne gemaakt worden met gladde schaduwen, of "Gouraud shading". Normaal gesproken kan het oog alleen de grens tussen de vlakken zien doordat de vlakken verschillende kleur-intensiteiten hebben, wat veroorzaakt wordt door de verschillende oriëntaties van de vlakken ten opzichte van de lichtbron. Met "flat shading" heeft elke polygon een uniforme kleur, waardoor de gebruiker een intensiteitsverschil kan zien op de grens tussen polygonen. Met "smooth shading" wordt de schaduw-intensiteit niet berekend per vlak, maar per vertex. Binnen een polygon wordt de intensiteit geïnterpoleerd tussen vertices. Als nu twee polygonen van een gekromd oppervlak die naast elkaar liggen vertices gemeenschappelijk hebben, dan wordt hun kleurintensiteit op de grens ook het zelfde. Het resultaat is dat de gebruiker de grens tussen de polygonen niet kan zien.

  Om dit te laten werken moet er een "normaalvector" gedefinieerd worden voor elke vertex. De normaalvector definieert de richting van het oppervlak op de positie van de vertex, die gebruikt wordt om de schaduw-intensiteit te berekenen. Veel 3D-modelleerprogramma's kunnen deze normaalvectoren automatisch genereren, als "smooth shading" wordt aangeschakeld voor een groep polygonen.

  Het effect van smooth shading kan echt spectaculair zijn. Een cylinder kan gemaakt worden uit 10 polygonen, terwijl het aantal polygonen alleen zichtbaar is aan de platte kanten van de cylinder. Meestal is het een goed idee om meer polygonen te gebruiken voor grote en belangrijke objecten, zoals loopings en wielen, en minder polygonen voor kleine onbelangrijke objecten, zoals in scenery. U zou het ook verschillend kunnen maken in verschillende LODs.

- Veel details kunnen gedaan worden met textures in plaats van polygonen. Bijvoorbeeld, een deur van een gebouw kan een enkele polygon zijn met een deur-texture erop. Een hek kan opgebouwd worden uit een groot aantal cylinders, elk bestaande uit een groot aantal polygonen, maar het kan ook gemaakt worden met een enkele polygon met een hek-texture erop. Textures worden op polygonen geplakt door "texture coördinaten" te definiëren voor elke vertex. Voor elke pixel in de polygon worden de texture-coördinaten geïnterpoleerd, en de kleur die overeen komt met die coördinaten wordt gevonden in de texture-afbeelding. Deze operaties hangen niet zo sterk af van de texture-afmetingen, dus ze kunnen veel sneller gedaan worden dan 3D vertex-transformaties voor een net zo gedetailleerd model dat uit polygonen is opgebouwd in plaats van textures. Dus, als u zowel snelheid als kwaliteit wilt: gebruik textures.

### Textures

Textures kunnen dus gebruikt worden om gedetailleerde modellen te maken met een klein aantal polygonen. Het nadeel is het extra aantal per-pixel berekeningen dat nodig is om de kleur van de pixel te bepalen. Op hardware-versnelde systemen worden deze operaties gedaan door de videokaart-processor in plaats van de centrale processor. De videokaart-processor is geoptimaliseerd om de zelfde taak vele malen tegelijkertijd uit te voeren, en daardoor kan het de per-pixel berekeningen veel sneller uitvoeren dan de centrale processor. Het probleem is dat de video-processor toegang moet hebben tot de texture-data. Met moderne AGP/PCIe-poorten is de communicatie tussen videokaart en CPU / werkgeheugen erg snel, maar alle textures op een 25 fps snelheid versturen zou nog steeds te veel bandbreedte nodig hebben. Dat is waarom textures in het geheugen van de videokaart geplaatst moeten worden, en dat is waarom het belangrijk is om genoeg videokaart-geheugen te hebben.

Voor de 3D-modeller is het belangrijk om zich te realiseren dat de prestaties zullen dalen als niet alle textures in het videogeheugen passen. Het geheugengebruik kan natuurlijk beperkt worden door kleinere textures te gebruiken (zelfs de gebruiker kan dit doen in Ultimate Stunts' instellingen: Ultimate Stunts schaalt de textures voordat het ze aan OpenGL doorgeeft). Dit herschalen is zo eenvoudig dat het niet echt belangrijk is voor de modeller. Een andere manier om texture-geheugen te verminderen is belangrijk om te weten: het delen van textures tussen modellen. Een texture die door veel modellen gebruikt wordt, wordt maar één keer geladen, dus het gebruikt het geheugen maar één keer. Dus in plaats van op elke tile een andere gras-texture te gebruiken, is het beter om overal de zelfde gras-texture te gebruiken.

Textures voor Ultimate Stunts kunnen ook een alpha-kanaal hebben, dat gebruikt kan worden voor doorzichtigheids-effecten. Bijvoorbeeld, de bladeren van een boom kunnen getekend worden in een texture met een alpha-kanaal, waarbij het deel van de texture buiten de bladeren doorzichtig is. Een boom kan dan gemaakt worden met maar een paar polygonen, terwijl het nog steeds erg gedetailleerd kan zijn. Een nadeel van textures met grote doorzichtige gebieden is dat er voor veel pixels een hoop berekeningen gedaan worden om tot de conclusie te komen dat er niets getekend hoeft te worden. Voor grote objecten (die er groot uitzien op het scherm, zodat ze veel pixels bevatten) zou het beter kunnen zijn om een meer gedetailleerd polygon-model te maken om het aantal onnodige piexl-operaties te verminderen. Een ander nadeel is dat voor mensen die de doorzichtigheids-blending uitschakelen, de doorzichtige gebieden er ondoorzichtig uit zien. Voor deze gebruikers zou een meer gedetailleerd polygon-model een betere oplossing kunnen zijn.

### De z-buffer

In een correct gerenderd 3D-beeld bedekken objecten die voor andere objecten staan deze andere objecten, zodat ze niet zichtbaar zijn. Er zijn een aantal manieren om dit doel te bereiken. Één manier is om de objecten te sorteren en ze van achter naar voren te tekenen. Zodra een object bovenop een ander object getekend wordt, vervangt het de pixels, en het resultaat is correct. Een andere manier om het te doen is door de diepte van elke getekende pixel te onthouden (de z-coördinaat) te onthouden in een buffer, de z-buffer. Als een pixel getekend wordt, wordt de diepte vergeleken met de bestaande pixel, en de nieuwe pixel wordt alleen getekend als deze zich voor de oude bevindt. Deze methode is nauwkeuriger dan de andere, doordat het per-pixel vergelijkt in plaats van per-object. In theorie zou het altijd het juiste resultaat moeten geven, maar in werkelijkheid zijn er wat problemen.

Één van deze problemen is dat de z-buffer een beperkte nauwkeurigheid heeft. Polygonen die vlak achter elkaar staan, zoals een raam bovenop een muur, worden soms op een lelijke manier samengevoegd, doordat de z-buffer niet kan bepalen welke van de twee dichter bij de camera staat.

Een ander probleem doet zich voor bij doorschijnende oppervlaktes. Als deze oppervlaktes getekend worden voordat de objecten achter de oppervlaktes getekend zijn, dan worden de objecten achter de oppervlaktes niet getekend, omdat de z-buffer waarden ingesteld zijn op de diepte van het doorschijnende oppervlak. Ultimate Stunts lost dit op door te proberen om objecten zo veel mogelijk van achter naar voren te tekenen, maar binnen een object verandert het de teken-volgorde niet. De tekenvolgorde zou op zo'n manier ingesteld moeten worden dat het een correct resultaat geeft vanuit de meeste standpunten. De tekenvolgorde is ook belangrijk als er geen doorschijnende oppervlaktes zijn in een object, omdat de z-buffer om performance-redenen uitgeschakeld kan worden. In zulke situaties is de tekenvolgorde het enige dat de dingen nog een beetje goed houdt.

### Ontwerpbeslissingen

Dus, ter conclusie, de volgende beslissingen moeten gemaakt worden:

- Het aantal vlakken voor ronde vormen. U kunt dit variëren voor verschillende LODs. In het algemeen is een klein aantal voldoende als u gebruik maakt van smooth shading.
- Details die in de textures zitten versus details die in de geometrie zitten. Textures zijn meestal beter als de speler geen diepte-verschil hoeft te zien.
- Recycling van textures: gebruik textures die al vaker gebruikt zijn in Ultimate Stunts, of gebruik textures die in de toekomst hergebruikt kunnen worden.

### Botsingsdetectie

Ik ben vergeten om over de botsingsdetectie te vertellen. Tot nu toe gebben we het alleen gehad over de graphics, maar de geometrie van objecten is ook van invloed op hun fysieke interactie via botsingen. Er zijn aparte LODs ("c" en "s") voor het botsingsmodel.

De botsingsmodellen voor tiles, auto-vormen en auto-wielen zijn op verschillende manieren gedefinieerd. Tile-botsingsmodellen zijn een set polygonen, net zoals het graphics-model, dus voor veel tiles kan het graphics-model ook gebruikt worden voor botsingsdetectie.

Het enige bijzondere aan tiles is dat "oppervlakte"-polygonen in de "s" LOD geplaatst moeten worden, en niet in de normale "c" LOD. Dit is omdat Ultimate Stunts berijdbare oppervlaktes anders behandelt dan botsings-oppervlaktes. Water-oppervlaktes moeten onderdeel zijn van zowel "s" als "c".

Het botsingsmodel van een auto is een "bounding volume", dat de vorm van de auto benadert met een aantal vlakken. Elk vlak deelt de hele ruimte op in twee delen, en zegt "de auto is aan deze kant van het vlak". Met genoeg vlakken (met slim gekozen oriëntaties) blijft er maar een klein volume over, en dit volume zou een benadering moeten zijn voor de vorm van de auto. De vlakken zijn gedefinieerd met polygonen in de "c" LOD. In de bestaande auto's kunt u voorbeelden van botsingsmodellen zien, waarbij de botsingsvlakken meestal doorschijnend blauw zijn.

De wielen hebben cylindrische botsingsmodellen. De cylinder wordt gedefinieerd met twee polygonen op de posities van de "eindvlakken" van de cylinder. (de symmetrie-as van een wiel is de x-as, dus de polygonen moeten loodrecht op de x-as staan.) Ook hier kunt u voorbeelden vinden in bestaande auto's.

Een erg gedetailleerd botsingsmodel kan de botsingsdetectie erg tijdrovend maken, en gelukkig is een gedetailleerd botsingsmodel niet zo hard nodig als een gedetailleerd graphics-model. Sommige complexe vormen met veel polygonen kunnen benaderd worden met een eenvoudiger botsingsmodel, en sommige objecten hebben geen botsingsmodel nodig omdat auto's er nooit mee zullen botsen. In sommige situaties is het zelfs ongewenst dat een object botsingseffecten genereert, bijv. met struiken of bloemen.