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.

98 lines 4 kB
import { Matrix, Vector3 } from "../Maths/math.vector.js"; import { TextureTools } from "../Misc/textureTools.js"; const FlowVector = new Vector3(0, 0, 0); const ScaledFlowVector = new Vector3(0, 0, 0); const ScreenPos = new Vector3(0, 0, 0); /** * Class used to represent a particle flow map. * #5DM02T#7 * GPUParts: #5DM02T#12 (webgl2) * GPUParts: #5DM02T#13 (webgpu) */ export class FlowMap { /** * Create a new flow map. * @param width defines the width of the flow map * @param height defines the height of the flow map * @param data defines the data of the flow map */ constructor(width, height, data) { this.width = width; this.height = height; this.data = data; } processFlowable(flowable, strength = 1, flowMapSamplePosOrTransformationMatrix) { if (!flowMapSamplePosOrTransformationMatrix) { return; } // Convert world pos to screen pos if (flowMapSamplePosOrTransformationMatrix instanceof Matrix) { Vector3.TransformCoordinatesToRef(flowable.position, flowMapSamplePosOrTransformationMatrix, ScreenPos); } else { ScreenPos.x = flowMapSamplePosOrTransformationMatrix.x; ScreenPos.y = flowMapSamplePosOrTransformationMatrix.y; ScreenPos.z = flowMapSamplePosOrTransformationMatrix.z; } const u = ScreenPos.x * 0.5 + 0.5; const v = 1.0 - (ScreenPos.y * 0.5 + 0.5); const x = Math.floor(u * this.width); const y = Math.floor(v * this.height); // Clamp if (x < 0 || x >= this.width || y < 0 || y >= this.height) { return; } const index = (y * this.width + x) * 4; const r = this.data[index]; const g = this.data[index + 1]; const b = this.data[index + 2]; const a = this.data[index + 3]; const fx = (r / 255.0) * 2.0 - 1.0; const fy = (g / 255.0) * 2.0 - 1.0; const fz = (b / 255.0) * 2.0 - 1.0; const localStrength = a / 255.0; FlowVector.set(fx, fy, fz); FlowVector.scaleToRef(strength * localStrength, ScaledFlowVector); flowable.direction.addInPlace(ScaledFlowVector); // Update IFlowable velocity } /** @internal */ _processParticle(particle, strength = 1, matrix) { this.processFlowable(particle, strength, matrix); } /** * Creates a FlowMap from a url. * @param url The url of the image to load * @returns a promise that resolves to a FlowMap object */ static async FromUrlAsync(url) { return await new Promise((resolve, reject) => { const flowCanvas = document.createElement("canvas"); const flowCtx = flowCanvas.getContext("2d"); let flowImageData = null; const flowMapImage = new Image(); flowMapImage.crossOrigin = "anonymous"; // If loading from another domain flowMapImage.src = url; flowMapImage.onerror = (e) => { reject(new Error(`Failed to load image: ${url} : ${e}`)); }; flowMapImage.onload = () => { flowCanvas.width = flowMapImage.width; flowCanvas.height = flowMapImage.height; flowCtx.drawImage(flowMapImage, 0, 0); flowImageData = flowCtx.getImageData(0, 0, flowCanvas.width, flowCanvas.height); resolve(new FlowMap(flowCanvas.width, flowCanvas.height, flowImageData.data)); }; }); } /** * Load from a texture * @param texture defines the source texture * @returns a promise fulfilled when image data is loaded */ static async ExtractFromTextureAsync(texture) { const data = await TextureTools.GetTextureDataAsync(texture); const { width, height } = texture.getSize(); return new FlowMap(width, height, new Uint8ClampedArray(data)); } } //# sourceMappingURL=flowMap.js.map