DJ's WebGL Tutorial 006--模型加载、显示

本节将加载并显示一个3D模型,
从渲染方法上讲,和上一节的立方体没有本质区别,只是顶点数据不一样。
立方体是我们自己定义顶点数据,
而3D模型,是从资源文件读取顶点数据,
所以这一节的重点在于数据读取。


从指定url加载文件二进制数据

DataLoader.LoadAsync = function(url, callback, obj) {
    var req = new XMLHttpRequest();
    req.open("GET", url, true);
    req.responseType = 'arraybuffer';
    req.onreadystatechange = function() {
        if(req.readyState == 4) {
            if(req.status == 200 || req.status == 0) {
                callback(new DataView(req.response), obj);
            } else {
                alert('Could not load ' + url + ' (' + req.status + ')');
            }
        }
    };

    req.send(null);
};

加载mesh文件

Mesh.Load = function(url, onload) {
    var m = new Mesh();
    m.onload = onload;

    DataLoader.LoadAsync(url, on_mesh_data_load, m);

    return m;
};

读取mesh数据

function on_mesh_data_load(data, mesh) {
    var offset = [0];
    read_string(data, offset);

    var mesh_count = DataLoader.ReadInt32(data, offset);

    for(var i=0; i<mesh_count; i++) {
        var name = read_string(data, offset);
        var position = read_vector3(data, offset);
        var rotation = read_quaternion(data, offset);
        var scale = read_vector3(data, offset);

        var vertex_count = DataLoader.ReadInt32(data, offset);
        var vertices = new Float32Array(vertex_count * 3);
        for(var j=0; j<vertex_count; j++) {
            var v = read_vector3(data, offset);
            vertices.set(v, j*3);
        }
        mesh.vertices = vertices;

        var color_count = DataLoader.ReadInt32(data, offset);
        var colors = new Float32Array(color_count * 4);
        for(var j=0; j<color_count; j++) {
            //read color
            var v = read_quaternion(data, offset);
            colors.set(v, j*4);
        }

        var uv_count = DataLoader.ReadInt32(data, offset);
        var uvs = new Float32Array(uv_count * 2);
        for(var j=0; j<uv_count; j++) {
            var x = DataLoader.ReadFloat32(data, offset);
            var y = 1 - DataLoader.ReadFloat32(data, offset);
            uvs.set([x, y], j*2);
        }
        mesh.uv = uvs;

        var uv2_count = DataLoader.ReadInt32(data, offset);
        var uv2s = new Float32Array(uv2_count * 2);
        for(var j=0; j<uv2_count; j++) {
            var x = DataLoader.ReadFloat32(data, offset);
            var y = 1 - DataLoader.ReadFloat32(data, offset);
            uv2s.set([x, y], j*2);
        }

        var normal_count = DataLoader.ReadInt32(data, offset);
        var normals = new Float32Array(normal_count * 3);
        for(var j=0; j<normal_count; j++) {
            var v = read_vector3(data, offset);
            normals.set(v, j*3);
        }

        var tangent_count = DataLoader.ReadInt32(data, offset);
        var tangents = new Float32Array(tangent_count * 4);
        for(var j=0; j<tangent_count; j++) {
            //read vector4
            var v = read_quaternion(data, offset);
            tangents.set(v, j*4);
        }

        var index_count = DataLoader.ReadInt32(data, offset);
        var indices = new Uint16Array(index_count);
        for(var j=0; j<index_count; j++) {
            var v = DataLoader.ReadUint16(data, offset);
            indices[j] = v;
        }
        mesh.indices = indices;

        var submeshs = [];
        var submesh_count = DataLoader.ReadInt32(data, offset);
        for(var j=0; j<submesh_count; j++) {
            var sub_count = DataLoader.ReadInt32(data, offset);
            var sub_indices = new Uint16Array(index_count);
            for(var k=0; k<sub_count; k++) {
                var v = DataLoader.ReadUint16(data, offset);
                sub_indices[k] = v;
            }

            submeshs[j] = sub_indices;
        }

        break;
    }

    mesh.loaded = true;

    mesh.onload(mesh);
};

创建顶点buffer

function create_buffer() {
    mesh = Mesh.Load("ranger.mesh", function(m) {
        vertex_buffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(m.vertices), gl.STATIC_DRAW);

        uv_buffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, uv_buffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(m.uv), gl.STATIC_DRAW);

        index_buffer = gl.createBuffer();
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(m.indices), gl.STATIC_DRAW);
    });
}

初始化:

function init_gl() {
    gl.clearColor(0.0, 0.0, 1.0, 1.0);
    gl.enable(gl.DEPTH_TEST);
    gl.enable(gl.CULL_FACE);
    gl.frontFace(gl.CW);

    create_shader();
    create_buffer();
    create_texture();
}

这里新加了gl.frontFace(gl.CW)修改三角形正面的顶点顺序为CW顺时针。
因为mesh数据是我从Unity3D导出的,Unity3D引擎使用的顶点顺序是CW,
而gl默认是使用CCW逆时针。


渲染的时候,调整一下模型的位置和角度,其它的和上一节立方体渲染完全一样:

var mat_m = Matrix4x4.TRS([0, -1.1, 0], [0, rot, 0], [1, 1, 1]);

运行结果:


代码下载

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值