天天看點

Cesium源碼分析&gltf解析

我這裡的3dtile有一部分資料是由gltf構成的,在建立模型(model)的時候,構造函數裡面,已經将該資料進行了解析。現在我們來看一下源代碼是如何執行的,這裡截取構造函數裡面的一部分代碼。

options = defaultValue(options, defaultValue.EMPTY_OBJECT);

        var cacheKey = options.cacheKey;
        this._cacheKey = cacheKey;
        this._cachedGltf = undefined;
        this._releaseGltfJson = defaultValue(options.releaseGltfJson, false);

        var cachedGltf;
        if (defined(cacheKey) && defined(gltfCache[cacheKey]) && gltfCache[cacheKey].ready) {
            // glTF JSON is in cache and ready
            cachedGltf = gltfCache[cacheKey];
            ++cachedGltf.count;
        } else {
            // glTF was explicitly provided, e.g., when a user uses the Model constructor directly
            var gltf = options.gltf;

            if (defined(gltf)) {
                if (gltf instanceof ArrayBuffer) {
                    gltf = new Uint8Array(gltf);
                }

                if (gltf instanceof Uint8Array) {
                    // Binary glTF
                    var parsedGltf = parseGlb(gltf);

                    cachedGltf = new CachedGltf({
                        gltf : parsedGltf,
                        ready : true
                    });
                } else {
                    // Normal glTF (JSON)
                    cachedGltf = new CachedGltf({
                        gltf : options.gltf,
                        ready : true
                    });
                }

                cachedGltf.count = 1;

                if (defined(cacheKey)) {
                    gltfCache[cacheKey] = cachedGltf;
                }
            }
        }
        setCachedGltf(this, cachedGltf);

        var basePath = defaultValue(options.basePath, '');
        this._resource = Resource.createIfNeeded(basePath);
           

主要是下面的這句代碼,執行了轉換。

var parsedGltf = parseGlb(gltf);
           

現在我們将斷點打入到這個位置,進入到了parseGlb.js裡面。如下所示。

function parseGlb(glb) {
        // Check that the magic string is present
        var magic = getMagic(glb);
        if (magic !== 'glTF') {
            throw new RuntimeError('File is not valid binary glTF');
        }

        var header = readHeader(glb, 0, 5);
        var version = header[1];
        if (version !== 1 && version !== 2) {
            throw new RuntimeError('Binary glTF version is not 1 or 2');
        }

        if (version === 1) {
            return parseGlbVersion1(glb, header);
        }

        return parseGlbVersion2(glb, header);
    }
           

看一下parseGlbVersion2的定義,如下所示。

function parseGlbVersion2(glb, header) {
        var length = header[2];
        var byteOffset = 12;
        var gltf;
        var binaryBuffer;
        while (byteOffset < length) {
            var chunkHeader = readHeader(glb, byteOffset, 2);
            var chunkLength = chunkHeader[0];
            var chunkType = chunkHeader[1];
            byteOffset += 8;
            var chunkBuffer = glb.subarray(byteOffset, byteOffset + chunkLength);
            byteOffset += chunkLength;
            // Load JSON chunk
            if (chunkType === 0x4E4F534A) {
                var jsonString = getStringFromTypedArray(chunkBuffer);
                gltf = JSON.parse(jsonString);
                addPipelineExtras(gltf);
            }
            // Load Binary chunk
            else if (chunkType === 0x004E4942) {
                binaryBuffer = chunkBuffer;
            }
        }
        if (defined(gltf) && defined(binaryBuffer)) {
            var buffers = gltf.buffers;
            if (defined(buffers) && buffers.length > 0) {
                var buffer = buffers[0];
                buffer.extras._pipeline.source = binaryBuffer;
            }
        }
        return gltf;
    }
           

使用如下的語句将資料轉為json格式,做相應的管線渲染。

var jsonString = getStringFromTypedArray(chunkBuffer);
                gltf = JSON.parse(jsonString);
                addPipelineExtras(gltf);
           

最後資料格式如下圖所示。

Cesium源碼分析&amp;gltf解析

繼續閱讀