Introduksjon
3D modeller kan enkelt «håndkodes» ved å angi vertekser som utgjør et antall trekanter som til sammen utgjør modellen. Etter hvert som modellene blir større og mer komplekse vil denne metoden bli uoverkommelig. I stedet for å håndkode 3D-modeller bruker man normalt verktøy som er spesiallaget for slike oppgaver, dvs. modellering og/eller animasjoner. Eksempler på slike er:
Modellformatet .obj
Filformatet .obj ble opprinnelig utviklet av Wavefront Technologies (Wikipedia). Dette er et åpent filformat som støttes av mange 3D-verktøy. Filformatet er relativt enkelt og lagrer data relatert til modellens geometri. Mer spesifikt lagres det for hver verteks posisjonsdata (x,y,z), farge, normalvektor og teksturkoordinater. Verteksene er organisert som «faces» som tilsvarer polygoner, f.eks. trekanter. En .obj fil, tilsvarende en kube, eksportert fra Blender kan f.eks. se slik ut:
cube1.obj
# Blender v2.69 (sub 0) OBJ File: 'cube.blend' # www.blender.org mtllib cube1.mtl o Cube_Cube.001 v 1.000000 -1.000000 -1.000000 v 1.000000 -1.000000 1.000000 v -1.000000 -1.000000 1.000000 v -1.000000 -1.000000 -1.000000 v 1.000000 1.000000 -0.999999 v 0.999999 1.000000 1.000001 v -1.000000 1.000000 1.000000 v -1.000000 1.000000 -1.000000 vt 0.126874 0.998126 vt 0.126874 0.749375 vt 0.375625 0.998126 vt 0.375625 0.749375 vt 0.375624 0.500625 vt 0.375625 0.251875 vt 0.624375 0.500624 vt 0.624374 0.251874 vt 0.624375 0.749375 vt 0.624375 0.998126 vt 0.375624 0.003126 vt 0.624373 0.003126 vt 0.873126 0.749375 vt 0.873126 0.998126 vn 0.000000 0.000000 -1.000000 vn 1.000000 -0.000000 0.000000 vn 1.000000 0.000000 0.000001 vn -1.000000 -0.000000 -0.000000 vn 0.000000 1.000000 0.000000 vn 0.000000 -0.000000 1.000000 vn 0.000000 -1.000000 0.000000 usemtl MaterialDiffuseR s off f 5/1/1 1/2/1 8/3/1 f 1/2/1 4/4/1 8/3/1 usemtl MaterialDiffuseM f 1/5/2 5/6/2 2/7/2 f 5/6/3 6/8/3 2/7/3 usemtl MaterialSpecularG f 3/9/4 7/10/4 4/4/4 f 7/10/4 8/3/4 4/4/4 usemtl MaterialSpecularY f 5/6/5 8/11/5 6/8/5 f 8/11/5 7/12/5 6/8/5 usemtl MaterialPhongB f 2/13/6 6/14/6 3/9/6 f 6/14/6 7/10/6 3/9/6 usemtl MaterialPhongC f 1/5/7 2/7/7 4/4/7 f 2/7/7 3/9/7 4/4/7
Første linje etter kommentarlinjene spesifiserer navnet på en «materialfil». Når man eksporterer til .obj får man normalt to filer: en .obj (som vist) og en .mtl fil der informasjon om «materiale» dvs. lys og tekstur ligger lagret. I dette tilfellet ser .mtl fila slik ut (viser kun et utsnitt, komplett fil ligger i vedlegg 1):
cube1.mtl
# Blender MTL File: 'cube.blend' # Material Count: 6 newmtl MaterialDiffuseM Ns 96.078431 Ka 0.000000 0.000000 0.000000 Kd 1.000000 0.000000 1.000000 Ks 0.000000 0.000000 0.000000 Ni 1.000000 d 1.000000 illum 0 newmtl MaterialDiffuseR Ns 96.078431 Ka 0.000000 0.000000 0.000000 Kd 1.000000 0.000000 0.000000 Ks 0.000000 0.000000 0.000000 Ni 1.000000 d 1.000000 illum 0 . . .
Videre i .obj fila brukes ‘o’ til å skille på grupper av polygoner (trekanter). En modell kan bestå av mange slike grupper (her kun en). De neste 8 linjene definerer kubens vertekser. Deretter følger et antall ‘vt’ linjer som definerer teksturkoordinater og et antall ‘vn’ linjer som definerer normalvektorene til verteksene.
På neste linje står det «usemtl MaterialDiffuseR» som indikerer at materialdefinisjonen MaterialDiffuseR, definert i .mtl-fila, skal benyttes på etterfølgende «face»-definisjoner. Etter dette følger to ‘f’ definisjoner, før en ny «usemtl …».
Hver ‘f’ definerer en «face», som i dette tilfellet tilsvarer en trekant. Ved eksport fra 3D-verktøy (her Blender) er det som regel mulig å angi «Triangulate model» e.l. slik at hver «face» tilsvarer en trekant (en face kan alternativt være en 4-kant, en 5-kant osv.). I Blender kan en modell som ikke består av trekanter «trianguleres» før eksport. Se vedlegg 3.
Bak ‘f’ er det tre tallgrupper. Hver tallgruppe består igjen av tre verdier, eller indekser. Første verdi i en tallgruppe tilsvarer en verteksposisjonsindeks. Indekseringa starter på 1 og tilsvarer rekkefølgen verteksene, ‘v’, er definert i fila. Første verteks har indeks 1, andre indeks 2 osv.
Den andre verdien er en indeksverdi for teksturkoordinatene, ‘vt’, mens den siste er en indeksverdi for normalvektorene, ‘vn’.
Dersom det står:
f 5/1/1 1/2/1 8/3/1
tilsvarer dette en trekant bestående av verteksene nr: 5,1 og 8, dvs. i dette tilfellet:
v 1.000000 1.000000 -0.999999 v 1.000000 -1.000000 -1.000000 v -1.000000 1.000000 -1.000000
teksturkoordinatene 1,2 og 3, dvs.:
vt 0.126874 0.998126 vt 0.126874 0.749375 vt 0.375625 0.998126
og verteksnormalene 1,1,1 (altså samme normalvektor på de tre verteksene som utgjør trekanten, noes om er naturlig siden en normalvektor star vinkelrett på flaten), dvs.:
vn 0.000000 0.000000 -1.000000 vn 0.000000 0.000000 -1.000000 vn 0.000000 0.000000 -1.000000
Dette er ment som en kort introduksjon til grunnleggende struktur til .obj formatet. Formatet omfatter en del andre elementer som ikke er omtalt her. Se f.eks. her (Wikipedia) for mer informasjon om formatet.
Når man kjenner strukturen på en slik fil kan man lage en import-funksjon i WebGL/Javascript som leser gjennom fila og bygger opp nødvendige buffer (verteksposisjon, farge osv.) som igjen brukes til å tegne modellen.
Dette kan imidlertid være en krevende øvelse og man bør derfor bruke eksisterende biblioteker til dette. Three.js, som vi etter hvert skal se på, støtter flere formater og gjør det svært enkelt å importere eksterne modeller inn i våre WebGL/Three-programmer.Vedlegg 1: Wavefront .mat fil for en kube
# Blender MTL File: 'cube.blend' # Material Count: 6 newmtl MaterialDiffuseM Ns 96.078431 Ka 0.000000 0.000000 0.000000 Kd 1.000000 0.000000 1.000000 Ks 0.000000 0.000000 0.000000 Ni 1.000000 d 1.000000 illum 0 newmtl MaterialDiffuseR Ns 96.078431 Ka 0.000000 0.000000 0.000000 Kd 1.000000 0.000000 0.000000 Ks 0.000000 0.000000 0.000000 Ni 1.000000 d 1.000000 illum 0 newmtl MaterialPhongB Ns 96.078431 Ka 0.000000 0.000000 0.000000 Kd 0.000000 0.000000 0.500000 Ks 1.000000 1.000000 1.000000 Ni 1.000000 d 1.000000 illum 0 newmtl MaterialPhongC Ns 96.078431 Ka 0.000000 0.000000 0.000000 Kd 0.000000 0.500000 0.500000 Ks 1.000000 1.000000 1.000000 Ni 1.000000 d 1.000000 illum 0 newmtl MaterialSpecularG Ns 96.078431 Ka 0.000000 0.000000 0.000000 Kd 0.000000 0.000000 0.000000 Ks 0.000000 1.000000 0.000000 Ni 1.000000 d 1.000000 illum 0 newmtl MaterialSpecularY Ns 96.078431 Ka 0.000000 0.000000 0.000000 Kd 0.000000 0.000000 0.000000 Ks 1.000000 1.000000 0.000000 Ni 1.000000 d 1.000000 illum 0
Vedlegg 2: En kube eksportert fra Blender vha. Three-eksporter.
{
"metadata" :
{
"formatVersion" : 3.1,
"generatedBy" : "Blender 2.65 Exporter",
"vertices" : 8,
"faces" : 6,
"normals" : 8,
"colors" : 0,
"uvs" : [14],
"materials" : 8,
"morphTargets" : 0,
"bones" : 0
},
"scale" : 1.000000,
"materials" : [ {
"DbgColor" : 15658734,
"DbgIndex" : 0,
"DbgName" : "undefined_dummy_0",
"vertexColors" : false
},
{
"DbgColor" : 15597568,
"DbgIndex" : 1,
"DbgName" : "MaterialDiffuseR",
"blending" : "AdditiveBlending",
"colorAmbient" : [1.0, 0.0, 0.0],
"colorDiffuse" : [1.0, 0.0, 0.0],
"colorSpecular" : [0.0, 0.0, 0.0],
"depthTest" : true,
"depthWrite" : true,
"shading" : "Lambert",
"specularCoef" : 50,
"transparency" : 1.0,
"transparent" : false,
"vertexColors" : false
},
{
"DbgColor" : 60928,
"DbgIndex" : 2,
"DbgName" : "MaterialDiffuseM",
"blending" : "AdditiveBlending",
"colorAmbient" : [1.0, 0.0, 1.0],
"colorDiffuse" : [1.0, 0.0, 1.0],
"colorSpecular" : [0.0, 0.0, 0.0],
"depthTest" : true,
"depthWrite" : true,
"shading" : "Lambert",
"specularCoef" : 50,
"transparency" : 1.0,
"transparent" : false,
"vertexColors" : false
},
{
"DbgColor" : 238,
"DbgIndex" : 3,
"DbgName" : "MaterialSpecularG",
"blending" : "AdditiveBlending",
"colorAmbient" : [0.0, 0.0, 0.0],
"colorDiffuse" : [0.0, 0.0, 0.0],
"colorSpecular" : [0.0, 1.0, 0.0],
"depthTest" : true,
"depthWrite" : true,
"shading" : "Lambert",
"specularCoef" : 50,
"transparency" : 1.0,
"transparent" : false,
"vertexColors" : false
},
{
"DbgColor" : 15658496,
"DbgIndex" : 4,
"DbgName" : "MaterialSpecularY",
"blending" : "AdditiveBlending",
"colorAmbient" : [0.0, 0.0, 0.0],
"colorDiffuse" : [0.0, 0.0, 0.0],
"colorSpecular" : [1.0, 1.0, 0.0],
"depthTest" : true,
"depthWrite" : true,
"shading" : "Lambert",
"specularCoef" : 50,
"transparency" : 1.0,
"transparent" : false,
"vertexColors" : false
},
{
"DbgColor" : 61166,
"DbgIndex" : 5,
"DbgName" : "MaterialPhongB",
"blending" : "AdditiveBlending",
"colorAmbient" : [0.0, 0.0, 0.5],
"colorDiffuse" : [0.0, 0.0, 0.5],
"colorSpecular" : [1.0, 1.0, 1.0],
"depthTest" : true,
"depthWrite" : true,
"shading" : "Lambert",
"specularCoef" : 50,
"transparency" : 1.0,
"transparent" : false,
"vertexColors" : false
},
{
"DbgColor" : 15597806,
"DbgIndex" : 6,
"DbgName" : "MaterialPhongC",
"blending" : "AdditiveBlending",
"colorAmbient" : [0.0, 0.5, 0.5],
"colorDiffuse" : [0.0, 0.5, 0.5],
"colorSpecular" : [1.0, 1.0, 1.0],
"depthTest" : true,
"depthWrite" : true,
"shading" : "Lambert",
"specularCoef" : 50,
"transparency" : 1.0,
"transparent" : false,
"vertexColors" : false
},
{
"DbgColor" : 419610,
"DbgIndex" : 7,
"DbgName" : "Material",
"blending" : "AdditiveBlending",
"colorAmbient" : [0.6400000190734865, 0.6400000190734865, 0.6400000190734865],
"colorDiffuse" : [0.6400000190734865, 0.6400000190734865, 0.6400000190734865],
"colorSpecular" : [0.5, 0.5, 0.5],
"depthTest" : true,
"depthWrite" : true,
"shading" : "Lambert",
"specularCoef" : 50,
"transparency" : 1.0,
"transparent" : false,
"vertexColors" : false
}],
"vertices" : [1,-1,-1,1,-1,1,-1,-1,1,-1,-1,-1,1,1,-1,0.999999,1,1,-1,1,1,-1,1,-1],
"morphTargets" : [],
"normals" : [0.577349,-0.577349,-0.577349,0.577349,-0.577349,0.577349,-0.577349,-0.577349,0.577349,-0.577349,-0.577349,-0.577349,0.577349,0.577349,-0.577349,-0.577349,0.577349,-0.577349,-0.577349,0.577349,0.577349,0.577349,0.577349,0.577349],
"colors" : [],
"uvs" : [[0.375624,0.500625,0.624375,0.500624,0.624375,0.749375,0.375625,0.749375,0.375625,0.251875,0.375624,0.003126,0.624373,0.003126,0.624374,0.251874,0.873126,0.749375,0.873126,0.998126,0.624375,0.998126,0.375625,0.998126,0.126874,0.998126,0.126874,0.749375]],
"faces" : [43,0,1,2,3,6,0,1,2,3,0,1,2,3,43,4,7,6,5,4,4,5,6,7,4,5,6,7,43,0,4,5,1,2,0,4,7,1,0,4,7,1,43,1,5,6,2,5,8,9,10,2,1,7,6,2,43,2,6,7,3,3,2,10,11,3,2,6,5,3,43,4,0,3,7,1,12,13,3,11,4,0,3,5],
"bones" : [],
"skinIndices" : [],
"skinWeights" : [],
"animations" : []
}
Vedlegg 3: Triangulere en modell i Blender
I Blender kan en modell som ikke består av trekanter «trianguleres» før eksport. Dette gjøres enklest ved å velge hele modellen i «Object mode» og deretter gå til «Edit mode» og trykk Ctrl+T. Se figur under.
Ingen kommentarer:
Legg inn en kommentar