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:
Vha. 3D Studio max eller Blender utvikles 3D modeller som deretter kan eksporteres til et format som kan importeres og tolkes i WebGL/Javascript-programmet. Importerte modeller kan deretter f.eks. transformeres og animeres på samme måte som håndkodede modeller.
Som nevnt finnes det i dag mange verktøy for utvikling av 3D modeller. Disse opererer med ulike filformater som har ulike egenskaper. De ulike verktøyene har som regel mulighet til å både eksportere og importere filer fra andre formater enn det de selv opererer med. 3D Studio max opererer med .fbx men kan også lagre modeller i andre formater som .obj, .3ds m.fl. Her finnes det mange «standarder» med høyst ulike egenskaper, muligheter, tilgang og kvalitet på dokumentasjon m.m.
Siden enkelte av de nevnte verktøyer lar oss lage animasjoner hadde det vært fint å få dette med når man eksporterer og importerer til WebGL. Fbx-formatet støtter f.eks. også animasjoner mens .obj ikke gjør det.
Khronos group har utviklet et modell & animasjonsformat for WebGL som heter glTF (graphics library transmission format). Se https://www.khronos.org/gltf for mer informasjon.
Obj formatet er mye brukt og et relativt enkelt å forholde seg til. Som en introduksjon til hvordan et 3D modellformat kan se ut gis det her en kort introduksjon til .obj formatet.
Deretter skal vi se på .json formatet som benyttes av THREE-biblioteket. Det er dette vi vil bruke i våre WebGL-programmer.
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.
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