UNPKG

@babylonjs/core

Version:

Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.

197 lines (196 loc) 8.42 kB
import { VertexBuffer, Buffer } from "../../Buffers/buffer.js"; import { BindBonesParameters, BindMorphTargetParameters, PrepareAttributesForBakedVertexAnimation, PrepareDefinesAndAttributesForMorphTargets, } from "../../Materials/materialHelper.functions.js"; import { extractMinAndMax } from "../../Maths/math.functions.js"; import { Vector3 } from "../../Maths/math.vector.js"; import "../../Shaders/gpuTransform.vertex.js"; import "../../Shaders/gpuTransform.fragment.js"; /** @internal */ export class TransformFeedbackBoundingHelper { /** * Creates a new TransformFeedbackBoundingHelper * @param engine defines the engine to use */ constructor(engine) { this._buffers = {}; this._effects = {}; this._meshListCounter = 0; this._engine = engine; } /** @internal */ // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax processAsync(meshes) { if (!Array.isArray(meshes)) { meshes = [meshes]; } this._meshListCounter = 0; this._processMeshList(meshes); return Promise.resolve(); } _processMeshList(meshes) { const parallelShaderCompile = this._engine.getCaps().parallelShaderCompile; this._engine.getCaps().parallelShaderCompile = undefined; for (let i = 0; i < meshes.length; ++i) { const mesh = meshes[i]; const vertexCount = mesh.getTotalVertices(); if (vertexCount === 0 || !mesh.getVertexBuffer || !mesh.getVertexBuffer(VertexBuffer.PositionKind)) { continue; } // Get correct effect let computeEffect; const defines = []; const attribs = [VertexBuffer.PositionKind]; // Bones if (mesh && mesh.useBones && mesh.computeBonesUsingShaders && mesh.skeleton) { attribs.push(VertexBuffer.MatricesIndicesKind); attribs.push(VertexBuffer.MatricesWeightsKind); if (mesh.numBoneInfluencers > 4) { attribs.push(VertexBuffer.MatricesIndicesExtraKind); attribs.push(VertexBuffer.MatricesWeightsExtraKind); } defines.push("#define NUM_BONE_INFLUENCERS " + mesh.numBoneInfluencers); defines.push("#define BONETEXTURE " + mesh.skeleton.isUsingTextureForMatrices); defines.push("#define BonesPerMesh " + (mesh.skeleton.bones.length + 1)); } else { defines.push("#define NUM_BONE_INFLUENCERS 0"); } // Morph const numMorphInfluencers = mesh.morphTargetManager ? PrepareDefinesAndAttributesForMorphTargets(mesh.morphTargetManager, defines, attribs, mesh, true, // usePositionMorph false, // useNormalMorph false, // useTangentMorph false, // useUVMorph false, // useUV2Morph false // useColorMorph ) : 0; // Baked Vertex Animation const bvaManager = mesh.bakedVertexAnimationManager; if (bvaManager && bvaManager.isEnabled) { defines.push("#define BAKED_VERTEX_ANIMATION_TEXTURE"); PrepareAttributesForBakedVertexAnimation(attribs, mesh, defines); } const join = defines.join("\n"); if (!this._effects[join]) { const uniforms = [ "boneTextureWidth", "mBones", "morphTargetInfluences", "morphTargetCount", "morphTargetTextureInfo", "morphTargetTextureIndices", "bakedVertexAnimationSettings", "bakedVertexAnimationTextureSizeInverted", "bakedVertexAnimationTime", ]; const samplers = ["boneSampler", "morphTargets", "bakedVertexAnimationTexture"]; const computeEffectOptions = { attributes: attribs, uniformsNames: uniforms, uniformBuffersNames: [], samplers: samplers, defines: join, fallbacks: null, onCompiled: null, onError: null, indexParameters: { maxSimultaneousMorphTargets: numMorphInfluencers }, maxSimultaneousLights: 0, transformFeedbackVaryings: ["outPosition"], }; computeEffect = this._engine.createEffect("gpuTransform", computeEffectOptions, this._engine); this._effects[join] = computeEffect; } else { computeEffect = this._effects[join]; } this._compute(mesh, computeEffect); } this._engine.getCaps().parallelShaderCompile = parallelShaderCompile; } _compute(mesh, effect) { const engine = this._engine; // Buffer let targetBuffer; const vertexCount = mesh.getTotalVertices(); if (!this._buffers[mesh.uniqueId]) { const targetData = new Float32Array(vertexCount * 3); targetBuffer = new Buffer(mesh.getEngine(), targetData, true, 3); this._buffers[mesh.uniqueId] = targetBuffer; } else { targetBuffer = this._buffers[mesh.uniqueId]; } // Bind effect.getEngine().enableEffect(effect); mesh._bindDirect(effect, null, true); // Bones BindBonesParameters(mesh, effect); // Morph targets BindMorphTargetParameters(mesh, effect); if (mesh.morphTargetManager && mesh.morphTargetManager.isUsingTextureForTargets) { mesh.morphTargetManager._bind(effect); } // BVA const bvaManager = mesh.bakedVertexAnimationManager; if (bvaManager && bvaManager.isEnabled) { mesh.bakedVertexAnimationManager?.bind(effect, false); } // Update const arrayBuffer = targetBuffer.getData(); engine.bindTransformFeedbackBuffer(targetBuffer.getBuffer()); engine.setRasterizerState(false); engine.beginTransformFeedback(true); engine.drawArraysType(2, 0, vertexCount); engine.endTransformFeedback(); engine.setRasterizerState(true); engine.readTransformFeedbackBuffer(arrayBuffer); engine.bindTransformFeedbackBuffer(null); // Update mesh if (this._meshListCounter === 0) { mesh._refreshBoundingInfo(arrayBuffer, null); } else { const bb = mesh.getBoundingInfo().boundingBox; const extend = extractMinAndMax(arrayBuffer, 0, vertexCount); TransformFeedbackBoundingHelper._Min.copyFrom(bb.minimum).minimizeInPlace(extend.minimum); TransformFeedbackBoundingHelper._Max.copyFrom(bb.maximum).maximizeInPlace(extend.maximum); mesh._refreshBoundingInfoDirect({ minimum: TransformFeedbackBoundingHelper._Min, maximum: TransformFeedbackBoundingHelper._Max }); } } /** @internal */ // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax registerMeshListAsync(meshes) { if (!Array.isArray(meshes)) { meshes = [meshes]; } this._meshList = meshes; this._meshListCounter = 0; return Promise.resolve(); } /** @internal */ processMeshList() { if (this._meshList.length === 0) { return; } this._processMeshList(this._meshList); this._meshListCounter++; } /** @internal */ // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax fetchResultsForMeshListAsync() { this._meshListCounter = 0; return Promise.resolve(); } /** @internal */ dispose() { for (const key in this._buffers) { this._buffers[key].dispose(); } this._buffers = {}; this._effects = {}; this._engine = null; } } TransformFeedbackBoundingHelper._Min = new Vector3(); TransformFeedbackBoundingHelper._Max = new Vector3(); //# sourceMappingURL=transformFeedbackBoundingHelper.js.map