src/viewer/scene/libs/k3d.js
/**
* @private
*/
var K3D = {};
K3D.load = function(path, resp)
{
var request = new XMLHttpRequest();
request.open("GET", path, true);
request.responseType = "arraybuffer";
request.onload = function(e){resp(e.target.response);};
request.send();
}
K3D.save = function(buff, path)
{
var dataURI = "data:application/octet-stream;base64," + btoa(K3D.parse._buffToStr(buff));
window.location.href = dataURI;
}
K3D.clone = function(o)
{
return JSON.parse(JSON.stringify(o));
}
K3D.bin = {};
K3D.bin.f = new Float32Array(1);
K3D.bin.fb = new Uint8Array(K3D.bin.f.buffer);
K3D.bin.rf = function(buff, off) { var f = K3D.bin.f, fb = K3D.bin.fb; for(var i=0; i<4; i++) fb[i] = buff[off+i]; return f[0]; }
K3D.bin.rsl = function(buff, off) { return buff[off] | buff[off+1]<<8; }
K3D.bin.ril = function(buff, off) { return buff[off] | buff[off+1]<<8 | buff[off+2]<<16 | buff[off+3]<<24; }
K3D.bin.rASCII0 = function(buff, off) { var s = ""; while(buff[off]!=0) s += String.fromCharCode(buff[off++]); return s; }
K3D.bin.wf = function(buff, off, v) { var f=new Float32Array(buff.buffer, off, 1); f[0]=v; }
K3D.bin.wsl = function(buff, off, v) { buff[off]=v; buff[off+1]=v>>8; }
K3D.bin.wil = function(buff, off, v) { buff[off]=v; buff[off+1]=v>>8; buff[off+2]=v>>16; buff[off+3]>>24; }
K3D.parse = {};
K3D.parse._buffToStr = function(buff)
{
var a = new Uint8Array(buff);
var s = "";
for(var i=0; i<a.length; i++) s = s.concat(String.fromCharCode(a[i]));
return s;
}
K3D.parse._strToBuff = function(str)
{
var buf = new ArrayBuffer(str.length);
var bufView = new Uint8Array(buf);
for (var i=0; i<str.length; i++) bufView[i] = str.charCodeAt(i);
return buf;
}
K3D.parse._readLine = function(a, off) // Uint8Array, offset
{
var s = "";
while(a[off] != 10) s += String.fromCharCode(a[off++]);
return s;
}
K3D.parse.fromJSON = function(buff)
{
var json = JSON.parse(K3D.parse._buffToStr(buff));
return json;
}
K3D.parse.toJSON = function(object)
{
var str = JSON.stringify(object);
return K3D.parse._strToBuff(str);
}
K3D.parse.fromOBJ = function(buff)
{
var res = {};
res.groups = {};
res.c_verts = [];
res.c_uvt = [];
res.c_norms = [];
res.i_verts = [];
res.i_uvt = [];
res.i_norms = [];
var cg = {from: 0, to:0}; // current group
var off = 0;
var a = new Uint8Array(buff);
while(off < a.length)
{
var line = K3D.parse._readLine(a, off);
off += line.length + 1;
line = line.replace(/ +(?= )/g,'');
line = line.replace(/(^\s+|\s+$)/g, '');
var cds = line.split(" ");
if(cds[0] == "g")
{
cg.to = res.i_verts.length;
if(res.groups[cds[1]] == null) res.groups[cds[1]] = {from:res.i_verts.length, to:0};
cg = res.groups[cds[1]];
}
if(cds[0] == "v")
{
var x = parseFloat(cds[1]);
var y = parseFloat(cds[2]);
var z = parseFloat(cds[3]);
res.c_verts.push(x,y,z);
}
if(cds[0] == "vt")
{
var x = parseFloat(cds[1]);
var y = 1-parseFloat(cds[2]);
res.c_uvt.push(x,y);
}
if(cds[0] == "vn")
{
var x = parseFloat(cds[1]);
var y = parseFloat(cds[2]);
var z = parseFloat(cds[3]);
res.c_norms.push(x,y,z);
}
if(cds[0] == "f")
{
var v0a = cds[1].split("/"), v1a = cds[2].split("/"), v2a = cds[3].split("/");
var vi0 = parseInt(v0a[0])-1, vi1 = parseInt(v1a[0])-1, vi2 = parseInt(v2a[0])-1;
var ui0 = parseInt(v0a[1])-1, ui1 = parseInt(v1a[1])-1, ui2 = parseInt(v2a[1])-1;
var ni0 = parseInt(v0a[2])-1, ni1 = parseInt(v1a[2])-1, ni2 = parseInt(v2a[2])-1;
var vlen = res.c_verts.length/3, ulen = res.c_uvt.length/2, nlen = res.c_norms.length/3;
if(vi0<0) vi0 = vlen + vi0+1; if(vi1<0) vi1 = vlen + vi1+1; if(vi2<0) vi2 = vlen + vi2+1;
if(ui0<0) ui0 = ulen + ui0+1; if(ui1<0) ui1 = ulen + ui1+1; if(ui2<0) ui2 = ulen + ui2+1;
if(ni0<0) ni0 = nlen + ni0+1; if(ni1<0) ni1 = nlen + ni1+1; if(ni2<0) ni2 = nlen + ni2+1;
res.i_verts.push(vi0, vi1, vi2); //cg.i_verts.push(vi0, vi1, vi2)
res.i_uvt .push(ui0, ui1, ui2); //cg.i_uvt .push(ui0, ui1, ui2);
res.i_norms.push(ni0, ni1, ni2); //cg.i_norms.push(ni0, ni1, ni2);
if(cds.length == 5)
{
var v3a = cds[4].split("/");
var vi3 = parseInt(v3a[0])-1, ui3 = parseInt(v3a[1])-1, ni3 = parseInt(v3a[2])-1;
if(vi3<0) vi3 = vlen + vi3+1;
if(ui3<0) ui3 = ulen + ui3+1;
if(ni3<0) ni3 = nlen + ni3+1;
res.i_verts.push(vi0, vi2, vi3); //cg.i_verts.push(vi0, vi2, vi3);
res.i_uvt .push(ui0, ui2, ui3); //cg.i_uvt .push(ui0, ui2, ui3);
res.i_norms.push(ni0, ni2, ni3); //cg.i_norms.push(ni0, ni2, ni3);
}
}
}
cg.to = res.i_verts.length;
return res;
}
K3D.parse.fromMD2 = function(buff)
{
buff = new Uint8Array(buff);
var res = {};
var head = {};
//res.head = head;
head.ident = K3D.bin.ril(buff, 0); /* magic number: "IDP2" */
head.version = K3D.bin.ril(buff, 4); /* version: must be 8 */
head.skinwidth = K3D.bin.ril(buff, 8); /* texture width */
head.skinheight = K3D.bin.ril(buff, 12); /* texture height */
head.framesize = K3D.bin.ril(buff, 16); /* size in bytes of a frame */
head.num_skins = K3D.bin.ril(buff, 20); /* number of skins */
head.num_vertices = K3D.bin.ril(buff, 24); /* number of vertices per frame */
head.num_st = K3D.bin.ril(buff, 28); /* number of texture coordinates */
head.num_tris = K3D.bin.ril(buff, 32); /* number of triangles */
head.num_glcmds = K3D.bin.ril(buff, 36); /* number of opengl commands */
head.num_frames = K3D.bin.ril(buff, 40); /* number of frames */
head.offset_skins = K3D.bin.ril(buff, 44); /* offset skin data */
head.offset_st = K3D.bin.ril(buff, 48); /* offset texture coordinate data */
head.offset_tris = K3D.bin.ril(buff, 52); /* offset triangle data */
head.offset_frames = K3D.bin.ril(buff, 56); /* offset frame data */
head.offset_glcmds = K3D.bin.ril(buff, 60); /* offset OpenGL command data */
head.offset_end = K3D.bin.ril(buff, 64); /* offset end of file */
var off = head.offset_st;
res.c_uvt = [];
for(var i=0; i<head.num_st; i++)
{
var x = K3D.bin.rsl(buff, off )/head.skinwidth;
var y = K3D.bin.rsl(buff, off+2)/head.skinheight;
res.c_uvt.push(x,y); off += 4;
}
var off = head.offset_tris;
var vi = [], ti = [];
res.i_verts = vi;
res.i_uvt = ti;
//res.tris = {i_verts : vi, i_uvt : ti};
for(var i=0; i<head.num_tris; i++)
{
vi.push(K3D.bin.rsl(buff, off ), K3D.bin.rsl(buff, off+2), K3D.bin.rsl(buff, off+4 ));
ti.push(K3D.bin.rsl(buff, off+6), K3D.bin.rsl(buff, off+8), K3D.bin.rsl(buff, off+10));
off += 12;
}
var off = head.offset_skins;
res.skins = [];
for(var i=0; i<head.num_skins; i++)
{
res.skins.push(K3D.bin.rASCII0(buff, off));
off += 64;
}
var off = head.offset_frames;
res.frames = [];
var nms = K3D.parse.fromMD2._normals;
for(var i=0; i<head.num_frames; i++)
{
var fr = {};
var sx = K3D.bin.rf(buff, off), sy = K3D.bin.rf(buff, off+4), sz = K3D.bin.rf(buff, off+8); off += 12;
var tx = K3D.bin.rf(buff, off), ty = K3D.bin.rf(buff, off+4), tz = K3D.bin.rf(buff, off+8); off += 12;
fr.name = K3D.bin.rASCII0(buff, off); off += 16;
fr.verts = [];
fr.norms = [];
for(var j=0; j<head.num_vertices; j++)
{
fr.verts.push(buff[off]*sx+tx, buff[off+1]*sy+ty, buff[off+2]*sz+tz);
fr.norms.push(nms[3*buff[off+3]], nms[3*buff[off+3]+1], nms[3*buff[off+3]+2]);
off += 4;
}
res.frames.push(fr);
}
return res;
}
/*
static MD2 normals
*/
K3D.parse.fromMD2._normals =
[
-0.525731, 0.000000, 0.850651,
-0.442863, 0.238856, 0.864188,
-0.295242, 0.000000, 0.955423,
-0.309017, 0.500000, 0.809017,
-0.162460, 0.262866, 0.951056,
0.000000, 0.000000, 1.000000,
0.000000, 0.850651, 0.525731,
-0.147621, 0.716567, 0.681718,
0.147621, 0.716567, 0.681718,
0.000000, 0.525731, 0.850651,
0.309017, 0.500000, 0.809017,
0.525731, 0.000000, 0.850651,
0.295242, 0.000000, 0.955423,
0.442863, 0.238856, 0.864188,
0.162460, 0.262866, 0.951056,
-0.681718, 0.147621, 0.716567,
-0.809017, 0.309017, 0.500000,
-0.587785, 0.425325, 0.688191,
-0.850651, 0.525731, 0.000000,
-0.864188, 0.442863, 0.238856,
-0.716567, 0.681718, 0.147621,
-0.688191, 0.587785, 0.425325,
-0.500000, 0.809017, 0.309017,
-0.238856, 0.864188, 0.442863,
-0.425325, 0.688191, 0.587785,
-0.716567, 0.681718, -0.147621,
-0.500000, 0.809017, -0.309017,
-0.525731, 0.850651, 0.000000,
0.000000, 0.850651, -0.525731,
-0.238856, 0.864188, -0.442863,
0.000000, 0.955423, -0.295242,
-0.262866, 0.951056, -0.162460,
0.000000, 1.000000, 0.000000,
0.000000, 0.955423, 0.295242,
-0.262866, 0.951056, 0.162460,
0.238856, 0.864188, 0.442863,
0.262866, 0.951056, 0.162460,
0.500000, 0.809017, 0.309017,
0.238856, 0.864188, -0.442863,
0.262866, 0.951056, -0.162460,
0.500000, 0.809017, -0.309017,
0.850651, 0.525731, 0.000000,
0.716567, 0.681718, 0.147621,
0.716567, 0.681718, -0.147621,
0.525731, 0.850651, 0.000000,
0.425325, 0.688191, 0.587785,
0.864188, 0.442863, 0.238856,
0.688191, 0.587785, 0.425325,
0.809017, 0.309017, 0.500000,
0.681718, 0.147621, 0.716567,
0.587785, 0.425325, 0.688191,
0.955423, 0.295242, 0.000000,
1.000000, 0.000000, 0.000000,
0.951056, 0.162460, 0.262866,
0.850651, -0.525731, 0.000000,
0.955423, -0.295242, 0.000000,
0.864188, -0.442863, 0.238856,
0.951056, -0.162460, 0.262866,
0.809017, -0.309017, 0.500000,
0.681718, -0.147621, 0.716567,
0.850651, 0.000000, 0.525731,
0.864188, 0.442863, -0.238856,
0.809017, 0.309017, -0.500000,
0.951056, 0.162460, -0.262866,
0.525731, 0.000000, -0.850651,
0.681718, 0.147621, -0.716567,
0.681718, -0.147621, -0.716567,
0.850651, 0.000000, -0.525731,
0.809017, -0.309017, -0.500000,
0.864188, -0.442863, -0.238856,
0.951056, -0.162460, -0.262866,
0.147621, 0.716567, -0.681718,
0.309017, 0.500000, -0.809017,
0.425325, 0.688191, -0.587785,
0.442863, 0.238856, -0.864188,
0.587785, 0.425325, -0.688191,
0.688191, 0.587785, -0.425325,
-0.147621, 0.716567, -0.681718,
-0.309017, 0.500000, -0.809017,
0.000000, 0.525731, -0.850651,
-0.525731, 0.000000, -0.850651,
-0.442863, 0.238856, -0.864188,
-0.295242, 0.000000, -0.955423,
-0.162460, 0.262866, -0.951056,
0.000000, 0.000000, -1.000000,
0.295242, 0.000000, -0.955423,
0.162460, 0.262866, -0.951056,
-0.442863, -0.238856, -0.864188,
-0.309017, -0.500000, -0.809017,
-0.162460, -0.262866, -0.951056,
0.000000, -0.850651, -0.525731,
-0.147621, -0.716567, -0.681718,
0.147621, -0.716567, -0.681718,
0.000000, -0.525731, -0.850651,
0.309017, -0.500000, -0.809017,
0.442863, -0.238856, -0.864188,
0.162460, -0.262866, -0.951056,
0.238856, -0.864188, -0.442863,
0.500000, -0.809017, -0.309017,
0.425325, -0.688191, -0.587785,
0.716567, -0.681718, -0.147621,
0.688191, -0.587785, -0.425325,
0.587785, -0.425325, -0.688191,
0.000000, -0.955423, -0.295242,
0.000000, -1.000000, 0.000000,
0.262866, -0.951056, -0.162460,
0.000000, -0.850651, 0.525731,
0.000000, -0.955423, 0.295242,
0.238856, -0.864188, 0.442863,
0.262866, -0.951056, 0.162460,
0.500000, -0.809017, 0.309017,
0.716567, -0.681718, 0.147621,
0.525731, -0.850651, 0.000000,
-0.238856, -0.864188, -0.442863,
-0.500000, -0.809017, -0.309017,
-0.262866, -0.951056, -0.162460,
-0.850651, -0.525731, 0.000000,
-0.716567, -0.681718, -0.147621,
-0.716567, -0.681718, 0.147621,
-0.525731, -0.850651, 0.000000,
-0.500000, -0.809017, 0.309017,
-0.238856, -0.864188, 0.442863,
-0.262866, -0.951056, 0.162460,
-0.864188, -0.442863, 0.238856,
-0.809017, -0.309017, 0.500000,
-0.688191, -0.587785, 0.425325,
-0.681718, -0.147621, 0.716567,
-0.442863, -0.238856, 0.864188,
-0.587785, -0.425325, 0.688191,
-0.309017, -0.500000, 0.809017,
-0.147621, -0.716567, 0.681718,
-0.425325, -0.688191, 0.587785,
-0.162460, -0.262866, 0.951056,
0.442863, -0.238856, 0.864188,
0.162460, -0.262866, 0.951056,
0.309017, -0.500000, 0.809017,
0.147621, -0.716567, 0.681718,
0.000000, -0.525731, 0.850651,
0.425325, -0.688191, 0.587785,
0.587785, -0.425325, 0.688191,
0.688191, -0.587785, 0.425325,
-0.955423, 0.295242, 0.000000,
-0.951056, 0.162460, 0.262866,
-1.000000, 0.000000, 0.000000,
-0.850651, 0.000000, 0.525731,
-0.955423, -0.295242, 0.000000,
-0.951056, -0.162460, 0.262866,
-0.864188, 0.442863, -0.238856,
-0.951056, 0.162460, -0.262866,
-0.809017, 0.309017, -0.500000,
-0.864188, -0.442863, -0.238856,
-0.951056, -0.162460, -0.262866,
-0.809017, -0.309017, -0.500000,
-0.681718, 0.147621, -0.716567,
-0.681718, -0.147621, -0.716567,
-0.850651, 0.000000, -0.525731,
-0.688191, 0.587785, -0.425325,
-0.587785, 0.425325, -0.688191,
-0.425325, 0.688191, -0.587785,
-0.425325, -0.688191, -0.587785,
-0.587785, -0.425325, -0.688191,
-0.688191, -0.587785, -0.425325
];
K3D.parse.fromCollada = function(buff)
{
var str = K3D.parse._buffToStr(buff);
var xml = new DOMParser().parseFromString(str,"text/xml");
xml = xml.childNodes[0];
var resp = {};
//console.log(xml);
var ass = xml.getElementsByTagName("asset" )[0];
var geo = xml.getElementsByTagName("library_geometries")[0];
var ima = xml.getElementsByTagName("library_images" )[0];
var mat = xml.getElementsByTagName("library_materials" )[0];
var eff = xml.getElementsByTagName("library_effects" )[0];
//console.log(xml);
if(ass) resp.asset = K3D.parse.fromCollada._asset (ass);
if(geo) resp.geometries = K3D.parse.fromCollada._libGeometries(geo);
if(ima) resp.images = K3D.parse.fromCollada._libImages (ima);
if(mat) resp.materials = K3D.parse.fromCollada._libMaterials (mat);
if(eff) resp.effects = K3D.parse.fromCollada._libEffects (eff);
return resp;
}
K3D.parse.fromCollada._asset = function(xml)
{
//console.log(xml);
return {
created : xml.getElementsByTagName("created" )[0].textContent,
modified: xml.getElementsByTagName("modified")[0].textContent,
up_axis : xml.getElementsByTagName("up_axis" )[0].textContent
};
}
K3D.parse.fromCollada._libGeometries = function(xml)
{
xml = xml.getElementsByTagName("geometry");
var res = [];
for(var i=0; i<xml.length; i++)
{
var g = xml[i];
var o = K3D.parse.fromCollada._getMesh(g.getElementsByTagName("mesh")[0]);
res.push(o);
}
return res;
}
K3D.parse.fromCollada._getMesh = function(mesh)
{
//console.log(mesh);
var res = {};
var ss = mesh.getElementsByTagName("source");
var sources = res.sources = {};
for(var i=0; i<ss.length; i++)
{
var farr = ss[i].getElementsByTagName("float_array")[0].textContent.split(" ");
var fl = farr.length - (farr[farr.length-1] == "" ? 1 : 0);
var arr = new Array(fl);
for(var j=0; j<fl; j++) arr[j] = parseFloat(farr[j]);
sources[ss[i].getAttribute("id")] = arr;
}
res.triangles = [];
var tgs = mesh.getElementsByTagName("triangles");
if(tgs == null) return res;
for(var i=0; i<tgs.length; i++)
{
var t = {};
var tnode = tgs[i];
t.material = tnode.getAttribute("material");
var inputs = tnode.getElementsByTagName("input");
var inds = [];
for(var j=0; j<inputs.length; j++)
{
var inp = inputs[j], arr = [];
inds[parseInt(inp.getAttribute("offset"))] = arr;
var par = inp.getAttribute("semantic");
t["s_"+par] = (par == "VERTEX") ?
mesh.getElementsByTagName("vertices")[0].getElementsByTagName("input")[0].getAttribute("source").substring(1)
: inp.getAttribute("source").substring(1);
t["i_"+par] = arr;
var psrc = sources[t["s_"+par]];
}
var indices = tnode.getElementsByTagName("p")[0].textContent.split(" ");
var inum = 3*Math.floor(indices.length/3);
for(var j=0; j<inum; j++) inds[j%inputs.length].push(parseInt(indices[j]));
/*
if(t.s_VERTEX ) t.u_VERTEX = K3D.edit.unwrap(t.i_VERTEX , sources[t.s_VERTEX ], 3);
if(t.s_TEXCOORD) t.u_TEXCOORD = K3D.edit.unwrap(t.i_TEXCOORD, sources[t.s_TEXCOORD], 2);
if(t.s_NORMAL ) t.u_NORMAL = K3D.edit.unwrap(t.i_NORMAL , sources[t.s_NORMAL ], 3);
//*/
//if(t.s_TEXCOORD) for(var j=1; j<t.u_TEXCOORD.length; j+=2) t.u_TEXCOORD[j] = 1 - t.u_TEXCOORD[j];
/*
t.u_INDEX = new Array(t.i_VERTEX.length);
for(var j=0; j<t.i_VERTEX.length; j++) t.u_INDEX[j] = j;
*/
res.triangles.push(t);
}
return res;
}
K3D.parse.fromCollada._libImages = function(xml)
{
xml = xml.getElementsByTagName("image");
var res = {};
for(var i=0; i<xml.length; i++)
{
res[xml[i].getAttribute("id")] = xml[i].getElementsByTagName("init_from")[0].textContent;
}
return res;
}
K3D.parse.fromCollada._libMaterials = function(xml)
{
xml = xml.getElementsByTagName("material");
var res = {};
for(var i=0; i<xml.length; i++)
{
res[xml[i].getAttribute("name")] = xml[i].getElementsByTagName("instance_effect")[0].getAttribute("url").substring(1);
}
return res;
}
K3D.parse.fromCollada._libEffects = function(xml)
{
xml = xml.getElementsByTagName("effect");
var res = {};
for(var i=0; i<xml.length; i++)
{
var eff = {};
var params = xml[i].getElementsByTagName("newparam");
for(var j=0; j<params.length; j++)
{
var srf = params[j].getElementsByTagName("surface")[0];
if(srf) eff.surface = srf.getElementsByTagName("init_from")[0].textContent;
}
res[xml[i].getAttribute("id")] = eff;
}
return res;
}
K3D.parse.from3DS = function(buff)
{
buff = new Uint8Array(buff);
var res = {};
if(K3D.bin.rsl(buff, 0) != 0x4d4d) return null;
var lim = K3D.bin.ril(buff, 2);
var off = 6;
while(off < lim)
{
var cid = K3D.bin.rsl(buff, off);
var lng = K3D.bin.ril(buff, off+2);
//console.log(cid.toString(16), lng);
if(cid == 0x3d3d) res.edit = K3D.parse.from3DS._edit3ds(buff, off, lng);
if(cid == 0xb000) res.keyf = K3D.parse.from3DS._keyf3ds(buff, off, lng);
off += lng;
}
return res;
}
K3D.parse.from3DS._edit3ds = function(buff, coff, clng) // buffer, chunk offset, length
{
var res = {};
var off = coff+6;
while(off < coff+clng)
{
var cid = K3D.bin.rsl(buff, off);
var lng = K3D.bin.ril(buff, off+2);
//console.log("\t", cid.toString(16), lng);
if(cid == 0x4000) { if(res.objects==null) res.objects = []; res.objects.push(K3D.parse.from3DS._edit_object(buff, off, lng)); }
//if(cid == 0xb000) res.KEYF3DS = K3D.parse.from3DS._keyf3ds(buff, off, lng);
off += lng;
}
return res;
}
K3D.parse.from3DS._keyf3ds = function(buff, coff, clng)
{
var res = {};
var off = coff+6;
while(off < coff+clng)
{
var cid = K3D.bin.rsl(buff, off);
var lng = K3D.bin.ril(buff, off+2);
//console.log("\t\t", cid.toString(16), lng);
//if(cid == 0x4000) { res.objects.push(K3D.parse.from3DS._edit_object(buff, off, lng)); }
if(cid == 0xb002) { if(res.desc==null) res.desc = []; res.desc.push(K3D.parse.from3DS._keyf_objdes(buff, off, lng)); }
off += lng;
}
return res;
}
K3D.parse.from3DS._keyf_objdes = function(buff, coff, clng)
{
var res = {};
var off = coff+6;
while(off < coff+clng)
{
var cid = K3D.bin.rsl(buff, off);
var lng = K3D.bin.ril(buff, off+2);
//console.log("\t\t\t", cid.toString(16), lng);
if(cid == 0xb010) res.hierarchy = K3D.parse.from3DS._keyf_objhierarch(buff, off, lng);
if(cid == 0xb011) res.dummy_name = K3D.bin.rASCII0(buff, off+6);
off += lng;
}
return res;
}
K3D.parse.from3DS._keyf_objhierarch = function(buff, coff, clng)
{
var res = {};
var off = coff+6;
res.name = K3D.bin.rASCII0(buff, off); off += res.name.length+1;
res.hierarchy = K3D.bin.rsl(buff, off+4);
return res;
}
K3D.parse.from3DS._edit_object = function(buff, coff, clng) // buffer, chunk offset, length
{
var res = {};
var off = coff+6;
res.name = K3D.bin.rASCII0(buff, off); off += res.name.length+1;
//console.log(res.name);
while(off < coff+clng)
{
var cid = K3D.bin.rsl(buff, off);
var lng = K3D.bin.ril(buff, off+2);
//console.log("\t\t", cid.toString(16), lng);
if(cid == 0x4100) res.mesh = K3D.parse.from3DS._obj_trimesh(buff, off, lng);
//if(cid == 0xb000) res.KEYF3DS = K3D.parse.from3DS._keyf3ds(buff, off, lng);
off += lng;
}
return res;
}
K3D.parse.from3DS._obj_trimesh = function(buff, coff, clng) // buffer, chunk offset, length
{
var res = {};
var off = coff+6;
while(off < coff+clng)
{
var cid = K3D.bin.rsl(buff, off);
var lng = K3D.bin.ril(buff, off+2);
//console.log("\t\t\t", cid.toString(16), lng);
if(cid == 0x4110) res.vertices = K3D.parse.from3DS._tri_vertexl (buff, off, lng);
if(cid == 0x4120) res.indices = K3D.parse.from3DS._tri_facel1 (buff, off, lng);
if(cid == 0x4140) res.uvt = K3D.parse.from3DS._tri_mappingcoors(buff, off, lng);
if(cid == 0x4160) res.local = K3D.parse.from3DS._tri_local (buff, off, lng);
off += lng;
}
return res;
}
K3D.parse.from3DS._tri_vertexl = function(buff, coff, clng) // buffer, chunk offset, length
{
var res = [];
var off = coff+6;
var n = K3D.bin.rsl(buff, off); off += 2;
for(var i=0; i<n; i++)
{
res.push(K3D.bin.rf(buff, off )); res.push(K3D.bin.rf(buff, off+4)); res.push(K3D.bin.rf(buff, off+8));
off += 12;
}
return res;
}
K3D.parse.from3DS._tri_facel1 = function(buff, coff, clng) // buffer, chunk offset, length
{
var res = [];
var off = coff+6;
var n = K3D.bin.rsl(buff, off); off += 2;
for(var i=0; i<n; i++)
{
res.push(K3D.bin.rsl(buff, off ));
res.push(K3D.bin.rsl(buff, off+2));
res.push(K3D.bin.rsl(buff, off+4));
off += 8;
}
return res;
}
K3D.parse.from3DS._tri_mappingcoors = function(buff, coff, clng) // buffer, chunk offset, length
{
var res = [];
var off = coff+6;
var n = K3D.bin.rsl(buff, off); off += 2;
for(var i=0; i<n; i++)
{
res.push( K3D.bin.rf(buff, off ));
res.push(1-K3D.bin.rf(buff, off+4));
off += 8;
}
return res;
}
K3D.parse.from3DS._tri_local = function(buff, coff, clng) // buffer, chunk offset, length
{
var res = {};
var off = coff+6;
res.X = [K3D.bin.rf(buff, off), K3D.bin.rf(buff, off+4), K3D.bin.rf(buff, off+8)]; off += 12;
res.Y = [K3D.bin.rf(buff, off), K3D.bin.rf(buff, off+4), K3D.bin.rf(buff, off+8)]; off += 12;
res.Z = [K3D.bin.rf(buff, off), K3D.bin.rf(buff, off+4), K3D.bin.rf(buff, off+8)]; off += 12;
res.C = [K3D.bin.rf(buff, off), K3D.bin.rf(buff, off+4), K3D.bin.rf(buff, off+8)]; off += 12;
return res;
}
K3D.parse.fromBIV = function(buff)
{
buff = new Uint8Array(buff);
var res = {};
var head = {};
head.id = K3D.bin.ril(buff, 0);
head.verS = K3D.bin.ril(buff, 4);
head.texS = K3D.bin.ril(buff, 8);
head.indS = K3D.bin.ril(buff, 12);
head.verO = K3D.bin.ril(buff, 16);
head.verL = K3D.bin.ril(buff, 20);
head.texO = K3D.bin.ril(buff, 24);
head.texL = K3D.bin.ril(buff, 28);
head.indO = K3D.bin.ril(buff, 32);
head.indL = K3D.bin.ril(buff, 36);
if(head.verO != 0) res.vertices = K3D.parse.fromBIV._readFloats(buff, head.verO, head.verL);
if(head.texO != 0) res.uvt = K3D.parse.fromBIV._readFloats(buff, head.texO, head.texL);
if(head.indO != 0) res.indices = K3D.parse.fromBIV._readInts (buff, head.indO, head.indL, head.indS);
return res;
}
K3D.parse.toBIV = function(obj)
{
var maxi = 0;
for(var i=0; i<obj.indices.length; i++) maxi = Math.max(maxi, obj.indices[i]);
var indS = 32;
if(maxi<=0xffff) indS = 16;
var len = 40;
if(obj.vertices) len+=obj.vertices.length*4;
if(obj.uvt ) len+=obj.uvt .length*4;
if(obj.indices ) len+=obj.indices .length*indS/8;
var buff = new Uint8Array(len);
K3D.bin.wil(buff, 0, 0x6976616e);
K3D.bin.wil(buff, 4, 32);
K3D.bin.wil(buff, 8, 32);
K3D.bin.wil(buff, 12, indS);
var off = 40;
if(obj.vertices)
{
K3D.bin.wil(buff, 16, off);
K3D.bin.wil(buff, 20, 4*obj.vertices.length);
K3D.parse.fromBIV._writeFloats(buff, off, obj.vertices);
off += 4*obj.vertices.length;
}
if(obj.uvt)
{
K3D.bin.wil(buff, 24, off);
K3D.bin.wil(buff, 28, 4*obj.uvt.length);
K3D.parse.fromBIV._writeFloats(buff, off, obj.uvt);
off += 4*obj.uvt.length;
}
if(obj.indices)
{
K3D.bin.wil(buff, 32, off);
K3D.bin.wil(buff, 36, 4*obj.indices.length);
K3D.parse.fromBIV._writeInts (buff, off, obj.indices, indS);
}
return buff.buffer;
}
K3D.parse.fromBIV._readFloats = function(buff, off, len)
{
var arr = [];
for(var i=0; i<len/4; i++) arr.push( K3D.bin.rf(buff, off+4*i));
return arr;
}
K3D.parse.fromBIV._writeFloats = function(buff, off, arr)
{
for(var i=0; i<arr.length; i++) K3D.bin.wf(buff, off+4*i, arr[i]);
}
K3D.parse.fromBIV._readInts = function(buff, off, len, cs)
{
var arr = [];
for(var i=0; i<len/4; i++)
{
if(cs==16) arr.push( K3D.bin.rsl(buff, off+2*i));
if(cs==32) arr.push( K3D.bin.ril(buff, off+4*i));
}
return arr;
}
K3D.parse.fromBIV._writeInts = function(buff, off, arr, cs)
{
for(var i=0; i<arr.length; i++)
{
if(cs==16) K3D.bin.wsl(buff, off+2*i, arr[i]);
if(cs==32) K3D.bin.wil(buff, off+4*i, arr[i]);
}
}
K3D.gen = {};
K3D.gen.Plane = function(sw, sh, tsw, tsh)
{
if(!tsw) tsw = 1;
if(!tsh) tsh = 1;
var r = {verts:[], inds:[], uvt:[]};
var ssw = sw+1, ssh = sh+1
for(var i=0; i<ssh; i++)
{
for(var j=0; j<ssw; j++)
{
var x = -1 + j*(2/sw);
var y = -1 + i*(2/sh);
r.verts.push(x, y, 0);
r.uvt.push(tsw*j/sw, tsh*i/sh);
if(i<sh && j<sw)
r.inds.push(i*ssw+j, i*ssw+j+1, (i+1)*ssw+j, i*ssw+j+1, (i+1)*ssw+j, (i+1)*ssw+j+1);
}
}
return r;
}
K3D.gen.Cube = function()
{
var r = {
verts:[ -1, 1,-1, 1, 1,-1, -1,-1,-1, 1,-1,-1, // front
-1, 1, 1, 1, 1, 1, -1,-1, 1, 1,-1, 1, // back
-1, 1, 1, -1, 1,-1, -1,-1, 1, -1,-1,-1, // left
1, 1, 1, 1, 1,-1, 1,-1, 1, 1,-1,-1, // right
-1, 1,-1, 1, 1,-1, -1, 1, 1, 1, 1, 1, // top
-1,-1,-1, 1,-1,-1, -1,-1, 1, 1,-1, 1 // bottom
],
inds:[ 0,1,2, 1,2,3, 4,5,6, 5,6,7,
8,9,10, 9,10,11, 12,13,14, 13,14,15,
16,17,18, 17,18,19, 20,21,22, 21,22,23
],
uvt:[
1/4,1/4, 2/4,1/4, 1/4,2/4, 2/4,2/4, // front
4/4,1/4, 3/4,1/4, 4/4,2/4, 3/4,2/4, // back
0/4,1/4, 1/4,1/4, 0/4,2/4, 1/4,2/4, // left
3/4,1/4, 2/4,1/4, 3/4,2/4, 2/4,2/4, // right
1/4,1/4, 2/4,1/4, 1/4,0/4, 2/4,0/4, // top
1/4,2/4, 2/4,2/4, 1/4,3/4, 2/4,3/4, // bottom
]
};
return r;
};
K3D.gen.Sphere = function(sx, sy){
var r = {verts:[], inds:[], uvt:[]};
var dx = 2*Math.PI/sx;
var dy = Math.PI/sy;
var nx = sx+1, ny = sy+1;
for(var i=0; i<ny; i++) // rows
{
for(var j=0; j<nx; j++) // cols
{
var lat = -Math.PI/2 + i*Math.PI/sy;
var lon = j*2*Math.PI/sx;
var x = Math.cos(lat) * Math.cos(lon);
var y = Math.sin(lat);
var z = Math.cos(lat) * Math.sin(lon);
r.verts.push(x,y,z);
r.uvt.push(j/sx, i/sy);
if(i<sy && j<sx) // 6 indices for 2 triangles
r.inds.push(nx*i+j, nx*i+j+1, nx*(i+1)+j, nx*i+j+1, nx*(i+1)+j, nx*(i+1)+j+1);
}
}
return r;
};
K3D.mat = {};
K3D.mat.scale = function(x,y,z){
return [
x,0,0,0,
0,y,0,0,
0,0,z,0,
0,0,0,1
];
};
K3D.mat.translate = function(x,y,z){
return [
1,0,0,0,
0,1,0,0,
0,0,1,0,
x,y,z,1
];
};
K3D.mat.rotateDeg = function(x,y,z){
var r = Math.PI/180;
return K3D.mat.rotate(x*r, y*r, z*r);
};
K3D.mat.rotate = function(x,y,z){
var m = [
1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1
];
var a = x; // alpha
var b = y; // beta
var g = z; // gama
var ca = Math.cos(a), cb = Math.cos(b), cg = Math.cos(g);
var sa = Math.sin(a), sb = Math.sin(b), sg = Math.sin(g);
m[0] = cb*cg; m[1] = -cb*sg; m[2 ] = sb;
m[4] = (ca*sg+sa*sb*cg); m[5] = (ca*cg-sa*sb*sg); m[6 ] = -sa*cb;
m[8] = (sa*sg-ca*sb*cg); m[9] = (sa*cg+ca*sb*sg); m[10] = ca*cb;
return m;
};
K3D.edit = {};
K3D.edit.interpolate = function(a, b, d, t){
for(var i=0; i<a.length; i++) d[i] = a[i] + t*(b[i] - a[i]);
};
K3D.edit.transform = function(a, m){
for(var i=0; i<a.length; i+=3) {
var x = a[i], y = a[i+1], z = a[i+2];
a[i+0] = m[0]*x + m[4]*y + m[8 ]*z + m[12];
a[i+1] = m[1]*x + m[5]*y + m[9 ]*z + m[13];
a[i+2] = m[2]*x + m[6]*y + m[10]*z + m[14];
}
};
// starting indices, starting coordinates, coordinates per index
K3D.edit.unwrap = function(ind, crd, cpi){
var ncrd = new Array(Math.floor(ind.length/3)*cpi);
for(var i=0; i<ind.length; i++)
{
for(var j=0; j<cpi; j++)
{
ncrd[i*cpi+j] = crd[ind[i]*cpi+j];
}
}
return ncrd;
};
// current indices, new indices, current array, coordinates per vertex
K3D.edit.remap = function(ind, nind, arr, cpi){
var ncrd = new Array(arr.length);
for(var i=0; i<ind.length; i++)
{
for(var j=0; j<cpi; j++)
{
ncrd[nind[i]*cpi+j] = arr[ind[i]*cpi+j];
}
}
return ncrd;
};
K3D.utils = {};
K3D.utils.getAABB = function(vts)
{
var minx, miny, minz, maxx, maxy, maxz;
minx = miny = minz = 999999999;
maxx = maxy = maxz = -minx;
for(var i=0; i<vts.length; i+=3)
{
var vx = vts[i+0];
var vy = vts[i+1];
var vz = vts[i+2];
if(vx<minx) minx = vx; if(vx>maxx) maxx = vx;
if(vy<miny) miny = vy; if(vy>maxy) maxy = vy;
if(vz<minz) minz = vz; if(vy>maxz) maxz = vz;
}
return {min:{x:minx, y:miny, z:minz}, max:{x:maxx, y:maxy, z:maxz}};
};
export {K3D};