ThreeJS WebGLGeometries

227 阅读1分钟
  • dispose中,删除方法种,要删除index和attributes和 wireframeAttributes
    • geometry.addEventListener("dispose", onGeometryDispose);
  • attributes只是个键值对对象
  • 网格状态下,网格对象的棱角直接使用线段进行绘制(平常模式下是三角形)
    • 索引进行变换了
    • 会判断数据量是否超过16位
    • attribute存放在 wireframeAttributes
function WebGLGeometries(gl, attributes, info, bindingStates) { //threejs中管理网格对象的方法
	const geometries = {};
	const wireframeAttributes = new WeakMap();

	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--;
	}

	function get(object, geometry) {
		if (geometries[geometry.id] === true) return geometry; //得到当前的buffergeometry对象

		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); //array
			}
		}

		const attribute = new(arrayMax(indices) > 65535 ?
			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);
	}

	return {
		get: get,
		update: update,

		getWireframeAttribute: getWireframeAttribute,
	};
}
function Uint32BufferAttribute(array, itemSize, normalized) {
	BufferAttribute.call(this, new Uint32Array(array), itemSize, normalized);
}