Objモデルインポート実装
注意:マテリアルファイルの読み取りがまだ終わっていないので、空いているときに更新します.
void function () {
function loadFile(url, syne, type, callback) {
/// <summary>Ajax </summary>
/// <param name="url" type="String"> </param>
/// <param name="syne" type="Boolean"> </param>
/// <param name="type" type="String">Mime </param>
/// <param name="callback" type="Function"> </param>
var xmlHttp = new XMLHttpRequest();
if (syne == null) {
syne = true;
}
if (type == null) {
type = 'text/plain';
}
if (!("withCredentials" in xmlHttp)) {
xmlHttp = new XDomainRequest();
xmlHttp.onload = function () {
callback(this.responseText);
};
xmlHttp.open("GET", url);
} else {
xmlHttp.open('GET', url, syne);
// HTTP
xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
}
// responseType
if (type.indexOf("text") < 0) {
xmlHttp.responseType = type;
}
xmlHttp.onerror = function () {
throw new Error("File \"" + url + "\" failed to load.");
};
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState === 4) {
if (xmlHttp.status == 404) {
this.onerror();
}
if (callback) {
if (type.indexOf("text") < 0) {
callback(xmlHttp.response);
} else {
callback(xmlHttp.responseText);
}
}
this.onreadystatechange = null;
this.onerror = null;
xmlHttp = null;
callback = null;
}
};
xmlHttp.send(null);
};
function hasNaN(o) {
/// <summary> NaN</summary>
/// <param name="o" type="Object"> </param>
for (var k in o) {
if (NaN == o[k])
return true;
}
return false;
}
window.objModelLoader = function (fileName, callback, gl) {
/// <summary> Obj </summary>
/// <param name="fileName" type="String"> </param>
/// <param name="callback" type="Function"> </param>
/// <param name="gl" type="WebGLContext">WebGL </param>
if (!gl) throw new Error("WebGL context not found.");
var _this = this;
// Ajax Obj
loadFile(fileName, true, null, function (obj) {
//obj = obj.toString().trim(); //
//obj = obj.replace(/\r
/g, "
"); //
//obj = obj.replace(/\r/g, "
"); //
//obj = obj.replace(/#+[^
]*
/g, "
"); //
//obj = obj.replace(/\\
/g, ""); //
var objcmds = obj.split(/\s*
+\s*/);
obj = function () {
var model = {
geometricVertices: [],
textureVertices: [],
vertexNormals: [],
parameterSpaceVertices: [],
groups: []
};
var curgroup = null;
for (var i = 0; i < objcmds.length; i++) {
var cmdwords = objcmds[i].split(/\s+/);
var o;
switch (cmdwords[0]) {
case "v":
if (4 > cmdwords.length
|| hasNaN(o = {
x: parseFloat(cmdwords[1]),
y: parseFloat(cmdwords[2]),
z: parseFloat(cmdwords[3])
}))
continue;
model.geometricVertices.push(o);
break;
case "vt":
if (3 > cmdwords.length
|| hasNaN(o = {
u: parseFloat(cmdwords[1]),
v: parseFloat(cmdwords[2])
}))
continue;
model.textureVertices.push(o);
break;
case "vn":
if (4 > cmdwords.length
|| hasNaN(o = {
x: parseFloat(cmdwords[1]),
y: parseFloat(cmdwords[2]),
z: parseFloat(cmdwords[3])
}))
continue;
model.vertexNormals.push(o);
break;
case "vp":
if (4 > cmdwords.length
|| hasNaN(o = {
x: parseFloat(cmdwords[1]),
y: parseFloat(cmdwords[2]),
z: parseFloat(cmdwords[3])
}))
continue;
model.parameterSpaceVertices.push(o);
break;
case "p":
if (2 > cmdwords.length)
continue;
o = [];
for (var j = 1; j < 2; j++) {
o.push(parseInt(cmdwords[j]));
}
if (hasNaN(o))
continue;
if (curgroup)
curgroup.points.push(o);
break;
case "l":
if (3 > cmdwords.length)
continue;
o = [];
for (var j = 1; j < 3; j++) {
o.push(parseInt(cmdwords[j]));
}
if (hasNaN(o))
continue;
if (curgroup)
curgroup.lines.push(o);
break;
case "f":
if (4 > cmdwords.length)
continue;
o = [];
for (var j = 1; j < 4; j++) {
var m = cmdwords[j].match(/^(\d+)\/(\d+)\/(\d+)$/);
if (null != m) {
o.push({ idxVertex: m[1], idxTexture: m[2], idxNormals: m[3] });
continue;
}
o.push(parseInt(cmdwords[j]));
}
if (hasNaN(o))
continue;
if (curgroup)
curgroup.faces.push(o);
break;
case "g":
if (2 > cmdwords.length)
continue;
model.groups.push(curgroup = {
name: cmdwords[1],
points: [],
lines: [],
faces: []
});
break;
}
}
return model;
}();
obj = function (obj) {
var model = {
materials: [],
indices: [],
vertexPositions: [],
vertexNormals: [],
vertexTextureCoords: []
};
var c = 0;
for (var i = 0; i < obj.groups.length; i++) {
var mapping = [];
for (var j = 0; j < obj.groups[i].faces.length; j++) {
for (var k = 0; k < obj.groups[i].faces[j].length; k++) {
var o = obj.groups[i].faces[j][k];
var b = isNaN(o);
var v = b ? o.idxVertex : o;
var t = b ? o.idxTexture : 0.0;
var n = b ? o.idxNormals : 0.0;
var s = v + "/" + t + "/" + n;
if (undefined == mapping[s]) {
mapping[s] = {
index: c++,
vertex: 0 <= v - 1 ? obj.geometricVertices[v - 1] : null,
texture: b && 0 <= t - 1 ? obj.textureVertices[t - 1] : null,
normals: b && 0 <= n - 1 ? obj.vertexNormals[n - 1] : null
};
model.vertexPositions.push(mapping[s].vertex.x);
model.vertexPositions.push(mapping[s].vertex.y);
model.vertexPositions.push(mapping[s].vertex.z);
model.vertexNormals.push(mapping[s].normals.x);
model.vertexNormals.push(mapping[s].normals.y);
model.vertexNormals.push(mapping[s].normals.z);
model.vertexTextureCoords.push(mapping[s].texture.u);
model.vertexTextureCoords.push(mapping[s].texture.v);
}
model.indices.push(mapping[s].index);
}
}
model.materials.push({
numindices: obj.groups[i].faces.length * 3
});
}
model.vertexPositions = new Float32Array(model.vertexPositions);
model.vertexNormals = new Float32Array(model.vertexNormals);
model.indices = new Uint16Array(model.indices);
return model;
}(obj);
//
callback && callback(obj);
});
};
}();