three.js源码注解-WebGLGeometries-基于r142

106 阅读2分钟

WebGLGeometries

函数作用

维护线框绘制数据,以及维护和更新以及在内存管理对象中注册geometry

入口函数

/**
*@gl webgl上下文环境
*@attributes 创建一系列的缓冲区对象,并管理缓冲区顶点数据,利用weakMap做attribute与由attribute创建的buffer的映射
*@info 具有一系列关于显卡内存和渲染过程的统计信息的对象。用于调试
*@bindingStates 创建顶点缓冲区状态与几何以及几何与Program的映射,将attribute缓存,并采用一些webgl缓存措施实现性能优化,通过对比新旧attribute去决定是否更新缓冲以及缓存的绑定。同时控制顶点缓冲区对象与WebGL中attribute变量间的数据传输以及更新
**/
function WebGLGeometries(gl, attributes, info, bindingStates) {
    const geometries = {};//用来记录geometry是否被注册
    const wireframeAttributes = new WeakMap();//映射线框数据
	// bindingStates->用到了bindingStates.releaseStatesOfGeometry(geometry);
}

核心逻辑

/**
* 在内存管理对象中注册geometry,并绑定销毁事件
*/
function get(object, geometry) {
    if (geometries[geometry.id] === true) return geometry;
    geometry.addEventListener('dispose', onGeometryDispose);
    geometries[geometry.id] = true;
    info.memory.geometries++;
    return geometry;
}
function update(geometry) {//顶点数据更新
    const geometryAttributes = geometry.attributes;
    // Updating index buffer in VAO now. See WebGLBindingStates.
    for (const name in geometryAttributes) {
        attributes.update(geometryAttributes[name], 34962);
    }
    // morph targets
    const morphAttributes = geometry.morphAttributes;
    for (const name in morphAttributes) {
        const array = morphAttributes[name];
        for (let i = 0, l = array.length; i < l; i++) {
            attributes.update(array[i], 34962);
        }
    }
}
function updateWireframeAttribute(geometry) {
    const indices = [];
    const geometryIndex = geometry.index;
    const geometryPosition = geometry.attributes.position;
    let version = 0;
    if (geometryIndex !== null) {
        const array = geometryIndex.array;
        version = geometryIndex.version;
        for (let i = 0, l = array.length; i < l; i += 3) {
            const a = array[i + 0];
            const b = array[i + 1];
            const c = array[i + 2];
            indices.push(a, b, b, c, c, a);//整合绘制线的所需数据
        }
    } else {
        const array = geometryPosition.array;
        version = geometryPosition.version;
        for (let i = 0, l = (array.length / 3) - 1; i < l; i += 3) {
            const a = i + 0;
            const b = i + 1;
            const c = i + 2;
            indices.push(a, b, b, c, c, a);
        }
    }
    const attribute = new (arrayNeedsUint32(indices) ? Uint32BufferAttribute : Uint16BufferAttribute)(indices, 1);
    attribute.version = version;
    // Updating index buffer in VAO now. See WebGLBindingStates
    const previousAttribute = wireframeAttributes.get(geometry);
    if (previousAttribute) attributes.remove(previousAttribute);
    wireframeAttributes.set(geometry, attribute);
}
function getWireframeAttribute(geometry) {
    const currentAttribute = wireframeAttributes.get(geometry);
    if (currentAttribute) {
        const geometryIndex = geometry.index;
        if (geometryIndex !== null) {
            // if the attribute is obsolete, create a new one
            if (currentAttribute.version < geometryIndex.version) {
                updateWireframeAttribute(geometry);
            }
        }
    } else {
        updateWireframeAttribute(geometry);
    }
    return wireframeAttributes.get(geometry);
}

销毁

function onGeometryDispose(event) {
    const geometry = event.target;
    if (geometry.index !== null) {//如果存在顶点索引,清除顶点索引
        attributes.remove(geometry.index);
    }
    for (const name in geometry.attributes) {
        attributes.remove(geometry.attributes[name]);
    }
    geometry.removeEventListener('dispose', onGeometryDispose);
    delete geometries[geometry.id];
    const attribute = wireframeAttributes.get(geometry);//获取线框数据
    if (attribute) {
        //清除线框数据
        attributes.remove(attribute);
        wireframeAttributes.delete(geometry);
    }
    bindingStates.releaseStatesOfGeometry(geometry);
    if (geometry.isInstancedBufferGeometry === true) {
        delete geometry._maxInstanceCount;
    }
    info.memory.geometries--;
}

返回值

return {
    get: get,
    update: update,
    getWireframeAttribute: getWireframeAttribute

};