3D software rendering med Delphi

Tags:    delphi
Skrevet af Bruger #1474 @ 11.08.2008

TGA Klasse

Vores lille program vil blive en simpel konsol. Konsol programmer har ingen grafisk brugerflade og kan derfor kun vise tekst. Det gør heldigvis ikke noget, for vi vil gemme de renderede pixels i et billedformat og til sidst gemme billedet til harddisken. Billedet kan derefter vises i et billedbehandligsprogram. Det er ganske almindelig at bruge konsol programmer når man skriver renderings software, da det giver den mulighed at man kan forstørre billedet for at studere nærmere detaljer. Vi vil derfor skrive en klasse der kan både gemme og indlæse et kendt billedformat. Indlæsningen vil blive brugt til senere brug, når vi vil lægge tekstur (texture) oven på vores 3D objekter. Der findes mange forskellige billedformater som sagtens kan anvendes til dette formål. Jeg har valgt at bruge TGA formatet, fordi dette er en ukomprimeret format der kan behandles på alle platforme.

TGA klassen minder meget om mange andre klasser af samme art. Den kan som sagt indlæse en TGA fil fra harddisken og skrive til en TGA fil. Der er dog et par små funktioner der er tilføjet. Alle pixels i et digitalt billede bliver normalt gemt i bytes. Det vil sige, at farve skalaen for et billede vil ligge fraogmed 0 tilogmed 255. Når vi beregner farver i forbindelse med en rendering, vil vi gerne bruge en større og mere nøjagtig skala. Vi vil også gerne havde muligheden for at gå ud over den almindelige farve skala. Det færdige resultat vil dog tilsidst blive gemt i bytes. Da komponenterne X, Y, Z og W i vores vektor klasse er af float typen: double, hvorfor så ikke bruge samme type for vores farver! Vi vil derfor gerne kunne tilskrive og aflæse pixels i TGA klassen, som om de var af float typen: double. Vi kunne sagtens gøre dette udenfor klassen, men for at undgå at havde samme kode skrevet mange forskellige steder, skriver vi det ind i vores klasse.

Der er en anden funktion i TGA klassen der er forskellig fra en almindelig billede klasse. Vi har muligheden for at aflæse en pixel ved hjælp af UVW eller tekstur (texture) koordinater. Normalt vil man aflæse en pixel ved at angive indekset for den ønskede pixel eller ved at angine X og Y koordinaterne. Vi vil få brug for denne funktion når vi vil skal til at rendere tekstur (texture) på vores geometri. Funktionen hedder GetPixel og er en overload til de mere almindelige funktioner af samme navn. TGA Klassen vil komme til at se således ud:

Fold kodeboks ind/udKode 


Som du sikkert har bemærket bruger TGA klassen en anden klasse ved navn: TRGBA. Denne klasse er en simpel klasse med komponenterne: R, G, B og A. De er alle af float typen: double. Denne klasse vil repræsentere vores farver. Der er en lille funktion i klassen der hedder: Clamp. Den har to parameterer: Min og Max. Med denne funktion kan farve komponenterne afskæres til et minimum og maksimum værdi. I de fleste tilfælde vil vi bruge en skala mellem 0 og 1. Her er klassen:

Fold kodeboks ind/udKode 


Geometri Klasse

Denne klasse vil holde alt data for vores geometri eller 3D objekter. Som nævnt tidligere er 3D objekter som regel bygget op af trekanter. Det vil vores 3D objekter derfor også være. Men der er forskellige måder at definere trekanter på. Det kommer helt an på, hvordan man ønsker at komprimere dataerne. Denne artkel vil ikke bruge komprimeringsmodeller. For at gøre denne artikel så simpel som muligt vil vi kun anvende ukomprimeret data. Klassen indeholder en array af vertex'er, hvoraf tre vertex'er vil definere en trekant.

En vertex indeholder følgende data:
1) Geometrisk koordinater
2) En farve
3) Tekstur (texture) koordinater
4) En normal

Den geometriske koordinat bliver repræsenteret af en vektor.
Farven er repræsenteret af en TRGBA klasse.
Tekstur (texture) koordinaterne vil blive repræsenteret af en ny klasse som indeholder komponenterne U,V og W. Tidligere nævnte jeg at vi ikke vil komme til at bruge W komponenten men for en ordens skyld bør vi nok tilføje den. Denne klasse har ikke nogle nævneværdige funktioner og vil derfor komme til at se således ud:

Fold kodeboks ind/udKode 


Nomalen for vores vertex vil vi komme til at bruge når vi skal beregne lysfaldet for vores trekanter. Den bruger kun tre komponenter X, Yog Z. Af nemheds skyld vil vi derfor definer den som en almindelig vektor trods vi aldrig kommer til at bruge W komponenten. Det vil være nemmest at lave en lille vertex klasse der indeholder disse klasser:

Fold kodeboks ind/udKode 


Geometri klassen har et par nævneværdige funktioner: InterpolateVertexColors, InterpolateTextureCoordinates og InterpolateNormals. De alle har fire ens parametere. Den første parameter forventer en skæringsvektor og de sidste forventer tre vertex'er. Funktionen: InterpolateVertexColor, vil finde den farve som ligger tættest på skæreringspunktet ved at blande de tre vertex farver afhængigt af vektorens barycentriske koordinater. Resultatet vil blive returneret i en farve klasse. De to andre funktioner gør nøjagtig det samme dog bare med trekantens henholdsvis tekstur (texture) koordinater og normaler. Sidst i klassen er der en stribe funktioner der hver kan lave en geometrisk objekt så som en kasse og en cylinder. Af hensyn til denne artikels længde vil vi ikke komme nærmere indpå, hvordan algoritmerne i disse funktioner virker. Geometri klassen ser således ud:

Fold kodeboks ind/udKode 



Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.

Del også gerne artiklen med dine Facebook venner:  

Kommentarer (2)

User
Bruger #14855 @ 17.06.09 15:33
Hmm, god artikel, men ringe du har lavet PRÆCIS den samme artikel, bare med C++!
User
Bruger #1474 @ 29.06.09 19:03
Koden er jo ikke den samme!
Du skal være logget ind for at skrive en kommentar.
t