Pixel-Composer/scripts/obj_reader/obj_reader.gml
2023-08-02 19:11:57 +02:00

179 lines
No EOL
4.2 KiB
Text

function readObj(path, flipUV = false) {
if(!file_exists(path)) return noone;
var _VB = [];
var _VBT = [];
var _VBN = [];
var mats = [];
var matIndex = [];
var mtlPath = "";
var use_normal = true;
var v = [];
var vt = [];
var vn = [];
var f = [];
var ft = [];
var fn = [];
var face = 0;
var file = file_text_open_read(path);
while(!file_text_eof(file)) {
var l = file_text_readln(file);
l = string_replace_all(l, "\n", "");
var sep = string_splice(l, " ");
if(array_length(sep) == 0 || sep[0] == "") continue;
switch(sep[0]) {
case "v" :
array_push(v, [ toNumber(sep[1]), toNumber(sep[2]), toNumber(sep[3]) ]);
break;
case "vt" :
if(flipUV)
array_push(vt, [ toNumber(sep[1]), 1 - toNumber(sep[2]) ]);
else
array_push(vt, [ toNumber(sep[1]), toNumber(sep[2]) ]);
break;
case "vn" :
array_push(vn, [ toNumber(sep[1]), toNumber(sep[2]), toNumber(sep[3]) ]);
break;
case "f" :
var _f = [];
var _ft = [];
var _fn = [];
for( var i = 1; i < array_length(sep); i++ ) {
var _sp = string_splice(sep[i], "/");
if(array_length(_sp) < 2) continue;
_f[i - 1] = toNumber(array_safe_get(_sp, 0));
_ft[i - 1] = toNumber(array_safe_get(_sp, 1));
_fn[i - 1] = toNumber(array_safe_get(_sp, 2));
if(array_length(_sp) < 3) use_normal = false;
}
face++;
array_push(f, _f ); //get position
array_push(ft, _ft); //get texture map
array_push(fn, _fn); //get normal
break;
case "usemtl" :
var mname = "";
for( var i = 1; i < array_length(sep); i++ )
mname += (i == 1? "" : " ") + sep[i];
mname = string_trim(mname);
array_push_unique(mats, mname);
array_push(matIndex, array_find(mats, mname));
if(array_length(f)) {
array_push(_VB, f);
array_push(_VBT, ft);
array_push(_VBN, fn);
f = [];
ft = [];
fn = [];
}
break;
case "mtllib" :
mtlPath = "";
for( var i = 1; i < array_length(sep); i++ )
mtlPath += (i == 1? "" : " ") + sep[i];
mtlPath = string_trim(mtlPath);
break;
case "o" :
//print("Reading vertex group: " + sep[1])
break;
}
}
if(array_length(f)) {
array_push(_VB, f);
array_push(_VBT, ft);
array_push(_VBN, fn);
}
file_text_close(file);
//var txt = "OBJ summary";
//txt += "\n\tVerticies : " + string(array_length(v));
//txt += "\n\tTexture Verticies : " + string(array_length(vt));
//txt += "\n\tNormal Verticies : " + string(array_length(vn));
//txt += "\n\tFaces : " + string(face);
//txt += "\n\tVertex groups : " + string(array_length(_VB));
//print(txt);
#region centralize vertex
var cv = [0, 0, 0];
var vertex = array_length(v);
for( var i = 0; i < vertex; i++ ) {
var _v = v[i];
cv[0] += _v[0];
cv[1] += _v[1];
cv[2] += _v[2];
}
cv[0] /= vertex;
cv[1] /= vertex;
cv[2] /= vertex;
for( var i = 0, n = array_length(v); i < n; i++ ) {
v[i][0] -= cv[0];
v[i][1] -= cv[1];
v[i][2] -= cv[2];
}
#endregion
var VBS = [];
for(var i = 0; i < array_length(_VB); i++) {
var VB = vertex_create_buffer();
vertex_begin(VB, FORMAT_PNT);
var face = _VB[i];
var facet = _VBT[i];
var facen = _VBN[i];
for(var j = 0; j < array_length(face); j++) {
var _f = face[j];
var _ft = facet[j];
var _fn = facen[j];
var _pf = [];
var _pft = [];
var _pfn = [];
for( var k = 0; k < array_length(_f); k++ ) {
var _f1 = v[_f[k] - 1];
var _ft1 = vt[_ft[k] - 1];
var _fn1 = _fn[k]? vn[_fn[k] - 1] : [0, 0, 0];
array_push( _pf, _f1);
array_push(_pft, _ft1);
array_push(_pfn, _fn1);
}
if(array_length(_f) >= 3) {
vertex_add_pnt(VB, _pf[0], _pfn[0], _pft[0]);
vertex_add_pnt(VB, _pf[1], _pfn[1], _pft[1]);
vertex_add_pnt(VB, _pf[2], _pfn[2], _pft[2]);
}
if(array_length(_f) >= 4) {
vertex_add_pnt(VB, _pf[0], _pfn[0], _pft[0]);
vertex_add_pnt(VB, _pf[2], _pfn[2], _pft[2]);
vertex_add_pnt(VB, _pf[3], _pfn[3], _pft[3]);
}
}
vertex_end(VB);
vertex_freeze(VB);
array_push(VBS, VB);
}
return {
vertex_groups: VBS,
materials: mats,
material_index: matIndex,
use_normal: use_normal,
mtl_path: mtlPath,
};
}