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\n/g, "\n");        // 将整篇文档中的回车换行符替换成换行符
            //obj = obj.replace(/\r/g, "\n");          // 将整篇文档中的回车符替换成换行符
            //obj = obj.replace(/#+[^\n]*\n/g, "\n");  // 将整篇文档中的注释部分替换成换行符
            //obj = obj.replace(/\\\n/g, "");          // 将整篇文档中每行最后的斜线和换行符与下一行连接

            var objcmds = obj.split(/\s*\n+\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);
        });
    };
}();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值