Qml 中模型数据加载的ThreeLoader.js

重实现了three.js中的 JSON parser

function GLModel() {
this.vertices = [];
this.normals = [];
this.texCoords = [];
this.indices = [];
}

function Geometry() {
this.vertices = [];
this.faceVertexUvs = [];
this.faces = [];
}

function Face3( a, b, c, normal, color, materialIndex ) {

this.a = a;
this.b = b;
this.c = c;

this.normal = normal instanceof Vector3 ? normal : new Vector3();
this.vertexNormals = normal instanceof Array ? normal : [ ];

this.color = color instanceof Array ? color :  [ ];
this.vertexColors = color instanceof Array ? color : [];

this.vertexTangents = [];

this.materialIndex = materialIndex !== undefined ? materialIndex : 0;

this.centroid = new Vector3()

};

function Vector2( x, y ) {
this.x = x || 0;
this.y = y || 0;
};

function Vector3( x, y, z ) {
this.x = x || 0;
this.y = y || 0;
this.z = z || 0;
};

Vector3.prototype = {

constructor: Vector3,

set: function ( x, y, z ) {

    this.x = x;
    this.y = y;
    this.z = z;

    return this;
},

copy: function ( v ) {

    this.x = v.x;
    this.y = v.y;
    this.z = v.z;

    return this;

}

};

Face3.prototype = {

constructor: Face3,

clone: function () {

    var face = new Face3( this.a, this.b, this.c );

    face.normal.copy( this.normal );
    face.color.copy( this.color );
    face.centroid.copy( this.centroid );

    face.materialIndex = this.materialIndex;

    var i, il;
    for ( i = 0, il = this.vertexNormals.length; i < il; i ++ ) face.vertexNormals[ i ] = this.vertexNormals[ i ].clone();
    for ( i = 0, il = this.vertexColors.length; i < il; i ++ ) face.vertexColors[ i ] = this.vertexColors[ i ].clone();
    for ( i = 0, il = this.vertexTangents.length; i < il; i ++ ) face.vertexTangents[ i ] = this.vertexTangents[ i ].clone();

    return face;
}

};

function parseJSON3DModel( json, texturePath )
{
var formatVersion = json.metadata.formatVersion;

if (formatVersion < 4.0 ) {
    var i, j;
    var geometry = new Geometry();
    var scale = ( json.scale !== undefined ) ? 1.0 / json.scale : 1.0;
    parseModel( json, geometry, scale );

    // Translate to model we can use from GL
    var glModel = new GLModel();


    glModel.texCoords[0] = [];
    for (var faceIdx = 0; faceIdx < geometry.faces.length; faceIdx++) {
        var face = geometry.faces[faceIdx];
        // Array indices
        var fidx = faceIdx * 3;
        glModel.indices.push(fidx);
        glModel.indices.push(fidx + 1);
        glModel.indices.push(fidx + 2);

        var v1 = geometry.vertices[face.a];
        var v2 = geometry.vertices[face.b];
        var v3 = geometry.vertices[face.c];

        glModel.vertices.push(v1.x);
        glModel.vertices.push(v1.y);
        glModel.vertices.push(v1.z);
        glModel.vertices.push(v2.x);
        glModel.vertices.push(v2.y);
        glModel.vertices.push(v2.z);
        glModel.vertices.push(v3.x);
        glModel.vertices.push(v3.y);
        glModel.vertices.push(v3.z);

        // Materials
        // face.materialIndex

        // Only parse first layer of UVs for this face
        for(var uvLayer = 0; uvLayer < geometry.faceVertexUvs.length; uvLayer++) {
            var faceUVs = geometry.faceVertexUvs[uvLayer][faceIdx];

            glModel.texCoords[uvLayer].push(faceUVs[0].x);
            glModel.texCoords[uvLayer].push(faceUVs[0].y);
            glModel.texCoords[uvLayer].push(faceUVs[1].x);
            glModel.texCoords[uvLayer].push(faceUVs[1].y);
            glModel.texCoords[uvLayer].push(faceUVs[2].x);
            glModel.texCoords[uvLayer].push(faceUVs[2].y);
        }

        // Normal
        if (face.vertexNormals !== undefined) {
            // Per vertex normals
            var vrtNormals = face.vertexNormals;

            var v1 = vrtNormals[0];
            var v2 = vrtNormals[1];
            var v3 = vrtNormals[2];

            glModel.normals.push(v1.x);
            glModel.normals.push(v1.y);
            glModel.normals.push(v1.z);
            glModel.normals.push(v2.x);
            glModel.normals.push(v2.y);
            glModel.normals.push(v2.z);
            glModel.normals.push(v3.x);
            glModel.normals.push(v3.y);
            glModel.normals.push(v3.z);
        } else if (face.normal !== undefined) {
            // Per face normal
            glModel.normals.push(face.normal.x);
            glModel.normals.push(face.normal.y);
            glModel.normals.push(face.normal.z);
            glModel.normals.push(face.normal.x);
            glModel.normals.push(face.normal.y);
            glModel.normals.push(face.normal.z);
            glModel.normals.push(face.normal.x);
            glModel.normals.push(face.normal.y);
            glModel.normals.push(face.normal.z);
        }
    }
}

return glModel;

};

function parseModel( json, geometry, scale ) {

function isBitSet( value, position )
{
    return value & ( 1 << position );
}

var i, j, fi,

        offset, zLength,

        colorIndex, normalIndex, uvIndex, materialIndex,

        type,
        isQuad,
        hasMaterial,
        hasFaceVertexUv,
        hasFaceNormal, hasFaceVertexNormal,
        hasFaceColor, hasFaceVertexColor,

        vertex, face, faceA, faceB, color, hex, normal,

        uvLayer, uv, u, v,

        faces = json.faces,
        vertices = json.vertices,
        normals = json.normals,
        colors = json.colors,

        nUvLayers = 0;

if ( json.uvs !== undefined ) {
    // disregard empty arrays
    for ( i = 0; i < json.uvs.length; i++ ) {
        if ( json.uvs[ i ].length > 0 ) nUvLayers ++;
    }

    for ( i = 0; i < nUvLayers; i++ ) {
        geometry.faceVertexUvs[ i ] = [];
    }
}

offset = 0;
zLength = vertices.length;

while ( offset < zLength ) {
    vertex = new Vector3();

    vertex.x = vertices[ offset ++ ] * scale;
    vertex.y = vertices[ offset ++ ] * scale;
    vertex.z = vertices[ offset ++ ] * scale;

    geometry.vertices.push( vertex );
}

offset = 0;
zLength = faces.length;

while ( offset < zLength ) {
    type = faces[ offset ++ ];

    isQuad              = isBitSet( type, 0 );
    hasMaterial         = isBitSet( type, 1 );
    hasFaceVertexUv     = isBitSet( type, 3 );
    hasFaceNormal       = isBitSet( type, 4 );
    hasFaceVertexNormal = isBitSet( type, 5 );
    hasFaceColor        = isBitSet( type, 6 );
    hasFaceVertexColor  = isBitSet( type, 7 );

    // console.log("type", type, "bits", isQuad, hasMaterial, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor);

    if ( isQuad ) {
        faceA = new Face3();
        faceA.a = faces[ offset ];
        faceA.b = faces[ offset + 1 ];
        faceA.c = faces[ offset + 3 ];

        faceB = new Face3();
        faceB.a = faces[ offset + 1 ];
        faceB.b = faces[ offset + 2 ];
        faceB.c = faces[ offset + 3 ];

        offset += 4;

        if ( hasMaterial ) {
            materialIndex = faces[ offset ++ ];
            faceA.materialIndex = materialIndex;
            faceB.materialIndex = materialIndex;
        }

        // to get face <=> uv index correspondence
        fi = geometry.faces.length;

        if ( hasFaceVertexUv ) {
            for ( i = 0; i < nUvLayers; i++ ) {
                uvLayer = json.uvs[ i ];
                geometry.faceVertexUvs[ i ][ fi ] = [];
                geometry.faceVertexUvs[ i ][ fi + 1 ] = []

                for ( j = 0; j < 4; j ++ ) {
                    uvIndex = faces[ offset ++ ];

                    u = uvLayer[ uvIndex * 2 ];
                    v = uvLayer[ uvIndex * 2 + 1 ];

                    uv = new Vector2( u, v );

                    if ( j !== 2 ) geometry.faceVertexUvs[ i ][ fi ].push( uv );
                    if ( j !== 0 ) geometry.faceVertexUvs[ i ][ fi + 1 ].push( uv );
                }
            }
        }

        if ( hasFaceNormal ) {
            normalIndex = faces[ offset ++ ] * 3;
            faceA.normal.set(
                        normals[ normalIndex ++ ],
                        normals[ normalIndex ++ ],
                        normals[ normalIndex ]
                        );
            faceB.normal.copy( faceA.normal );
        }

        if ( hasFaceVertexNormal ) {
            for ( i = 0; i < 4; i++ ) {
                normalIndex = faces[ offset ++ ] * 3;
                normal = new Vector3(
                            normals[ normalIndex ++ ],
                            normals[ normalIndex ++ ],
                            normals[ normalIndex ]
                            );

                if ( i !== 2 ) faceA.vertexNormals.push( normal );
                if ( i !== 0 ) faceB.vertexNormals.push( normal );
            }
        }

        if ( hasFaceColor ) {
            colorIndex = faces[ offset ++ ];
            hex = colors[ colorIndex ];
            //                    faceA.color.setHex( hex );
            //                    faceB.color.setHex( hex );
        }

        if ( hasFaceVertexColor ) {
            for ( i = 0; i < 4; i++ ) {
                colorIndex = faces[ offset ++ ];
                hex = colors[ colorIndex ];

                //                        if ( i !== 2 ) faceA.vertexColors.push( new THREE.Color( hex ) );
                //                        if ( i !== 0 ) faceB.vertexColors.push( new THREE.Color( hex ) );
            }
        }

        geometry.faces.push( faceA );
        geometry.faces.push( faceB );

    } else {
        face = new Face3();
        face.a = faces[ offset ++ ];
        face.b = faces[ offset ++ ];
        face.c = faces[ offset ++ ];

        if ( hasMaterial ) {
            materialIndex = faces[ offset ++ ];
            face.materialIndex = materialIndex;
        }

        // to get face <=> uv index correspondence

        fi = geometry.faces.length;

        if ( hasFaceVertexUv ) {

            for ( i = 0; i < nUvLayers; i++ ) {

                uvLayer = json.uvs[ i ];

                geometry.faceVertexUvs[ i ][ fi ] = [];

                for ( j = 0; j < 3; j ++ ) {

                    uvIndex = faces[ offset ++ ];

                    u = uvLayer[ uvIndex * 2 ];
                    v = uvLayer[ uvIndex * 2 + 1 ];

                    uv = new Vector2( u, v );

                    geometry.faceVertexUvs[ i ][ fi ].push( uv );

                }

            }

        }

        if ( hasFaceNormal ) {

            normalIndex = faces[ offset ++ ] * 3;

            face.normal.set(
                        normals[ normalIndex ++ ],
                        normals[ normalIndex ++ ],
                        normals[ normalIndex ]
                        );

        }

        if ( hasFaceVertexNormal ) {

            for ( i = 0; i < 3; i++ ) {

                normalIndex = faces[ offset ++ ] * 3;

                normal = new Vector3(
                            normals[ normalIndex ++ ],
                            normals[ normalIndex ++ ],
                            normals[ normalIndex ]
                            );

                face.vertexNormals.push( normal );

            }

        }


        if ( hasFaceColor ) {
            //                    colorIndex = faces[ offset ];
            offset++;
            //                    face.color.setHex( colors[ colorIndex ] );
        }


        if ( hasFaceVertexColor ) {

            for ( i = 0; i < 3; i++ ) {

                //                        colorIndex = faces[offset];
                offset++;
                //                        face.vertexColors.push( new THREE.Color( colors[ colorIndex ] ) );

            }

        }

        geometry.faces.push( face );

    }

}

};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值