diff --git a/flat.js b/flat.js index cd0b4cf..f7775db 100644 --- a/flat.js +++ b/flat.js @@ -135,43 +135,43 @@ class FlatRenderer { return density; } - createParticles(device) + createBuffers(device) { this.maxDim = 32; this.maxParticles = this.maxDim * this.maxDim; - this.particleStride = 4 * 3; // in elements - this.particles = new Float32Array(this.maxParticles * this.particleStride); + this.particleStride = this.module.instance.exports.particle__stride(); // bytes + this.particlesSize = this.maxParticles * this.particleStride; // bytes this.maxGradientsDim = 32; this.maxGradients = this.maxGradientsDim * this.maxGradientsDim; this.gradientStride = 4 * 2; - this.gradients = new Float32Array(this.maxGradients * this.gradientStride); + + this.particleConfigurationStride = this.module.instance.exports.particle_configuration__stride(); this.particleBuffers = []; this.gradientBuffers = []; - this.particleBindGroups = []; - - this.particleConfiguration = new Float32Array(4 * 4); this.particleConfigurationBuffers = []; + this.particleBindGroups = []; + for (let i = 0; i < 2; i++) { const particleBuffer = device.createBuffer({ label: `particle buffer ${i}`, - size: this.particles.byteLength, + size: this.particlesSize, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST, }); this.particleBuffers.push(particleBuffer); const gradientBuffer = device.createBuffer({ label: `gradient buffer ${i}`, - size: this.gradients.byteLength, + size: 4 * 4 * 2, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST, }); this.gradientBuffers.push(gradientBuffer); const configBuffer = device.createBuffer({ label: `particle configuration buffer ${i}`, - size: this.particleConfiguration.byteLength, + size: this.particleConfigurationStride, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, }); this.particleConfigurationBuffers.push(configBuffer); @@ -192,21 +192,16 @@ class FlatRenderer { }); this.particleBindGroups.push(bindGroup); } - - for (let i = 0; i < this.maxParticles; i++) { - // position - const position = [Math.random(), Math.random()]; - this.particles[i * this.particleStride + 0] = position[0]; - this.particles[i * this.particleStride + 1] = position[1]; - this.particles[i * this.particleStride + 2] = 0.0; - this.particles[i * this.particleStride + 3] = 1.0; - // value.x - this.particles[i * this.particleStride + 4] = test(position); - } } - constructor(device, canvasFormat, viewUniformBuffer, shaderModule) + initializeState() { + + } + + constructor(device, canvasFormat, viewUniformBuffer, shaderModule, module) + { + this.module = module; const label = "flat"; ////////////////////////////////////////////////////////////////////// @@ -296,7 +291,7 @@ class FlatRenderer { // particles ////////////////////////////////////////////////////////////////////// - this.createParticles(device); + this.createBuffers(device); ////////////////////////////////////////////////////////////////////// // bind group @@ -434,10 +429,10 @@ class FlatRenderer { render(device, renderPass, frameNumber, configuration) { // particle update must be before gradient update - this.updateParticles(device, frameNumber, configuration); - this.updateGradients(device, frameNumber, configuration); - this.updateSimulation(device, frameNumber, configuration); - this.updateConfiguration(device, frameNumber, configuration); + //this.updateParticles(device, frameNumber, configuration); + //this.updateGradients(device, frameNumber, configuration); + //this.updateSimulation(device, frameNumber, configuration); + //this.updateConfiguration(device, frameNumber, configuration); renderPass.setPipeline(this.renderPipeline); renderPass.setIndexBuffer(this.buffer, "uint16"); @@ -447,7 +442,7 @@ class FlatRenderer { } } -async function loadFlat(device, canvasFormat, viewUniformBuffer) +async function loadFlat(device, canvasFormat, viewUniformBuffer, module) { const flatWgsl = await getPath("flat.wgsl"); const shaderModule = device.createShaderModule({ @@ -455,7 +450,7 @@ async function loadFlat(device, canvasFormat, viewUniformBuffer) code: flatWgsl, }); - const renderer = new FlatRenderer(device, canvasFormat, viewUniformBuffer, shaderModule); + const renderer = new FlatRenderer(device, canvasFormat, viewUniformBuffer, shaderModule, module); return renderer; } diff --git a/index.js b/index.js index 7d16781..137fd3e 100644 --- a/index.js +++ b/index.js @@ -47,6 +47,7 @@ const module = await WebAssembly.instantiateStreaming(fetch("src/module.wasm"), log: console.log, } }); +module.memory = memory; function createDepthTexture() { return device.createTexture({ @@ -98,7 +99,7 @@ module.instance.exports.camera_init(cameraStateAddress); //const gltfRenderer = await loadGltf(device, canvasFormat, viewUniformBuffer, memory, module); //const lightRenderer = await loadLight(device, canvasFormat, viewUniformBuffer); -const flatRenderer = await loadFlat(device, canvasFormat, viewUniformBuffer); +const flatRenderer = await loadFlat(device, canvasFormat, viewUniformBuffer, module); const KEY = { diff --git a/src/Makefile b/src/Makefile index 6986c8f..8c4872e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -32,6 +32,10 @@ LDFLAGS = \ -Wl,--export=camera_move \ -Wl,--export=camera_init \ -Wl,--export=camera_view_projection \ + -Wl,--export=particle_system__create \ + -Wl,--export=particle_system__update \ + -Wl,--export=particle__stride \ + -Wl,--export=particle_configuration__stride \ -Wl,--import-undefined \ -Wl,--print-map \ -Wl,--import-memory \ @@ -49,7 +53,10 @@ PNG_OBJ = \ $(MINIZ)/miniz_tinfl.o \ memory.o \ node.o \ - camera.o + camera.o \ + fluid/particle.o \ + fluid/particle_system.o \ + fluid/api.o module.wasm: $(PNG_OBJ) clang++ $(CFLAGS) $(LDFLAGS) -o $@ $^ diff --git a/src/builtin_math.h b/src/builtin_math.h new file mode 100644 index 0000000..4841b13 --- /dev/null +++ b/src/builtin_math.h @@ -0,0 +1,26 @@ +#pragma once + +#define acosf(x) __builtin_acosf(x) +#define asinf(x) __builtin_asinf(x) +#define atan2f(x, y) __builtin_atan2f(x, y) +#define atanf(x) __builtin_atanf(x) +#define ceilf(x) __builtin_ceilf(x) +#define cosf(x) __builtin_cosf(x) +#define coshf(x) __builtin_coshf(x) +#define exp2f(x) __builtin_exp2f(x) +#define expf(x) __builtin_expf(x) +#define fabsf(x) __builtin_fabsf(x) +#define floorf(x) __builtin_floorf(x) +#define isinf(x) (false) +#define isnan(x) (false) +#define log10f(x) __builtin_log10f(x) +#define log2f(x) __builtin_log2f(x) +#define logf(x) __builtin_logf(x) +#define modff(x, y) __builtin_modff(x, y) +#define powf(x, y) __builtin_powf(x, y) +#define sinf(x) __builtin_sinf(x) +#define sinhf(x) __builtin_sinhf(x) +#define sqrtf(x) __builtin_sqrtf(x) +#define tanf(x) __builtin_tanf(x) +#define tanhf(x) __builtin_tanhf(x) +#define sign(x) ((x > 0) - (x < 0)) diff --git a/src/directxmath/DirectXMath.h b/src/directxmath/DirectXMath.h index 37b70c1..6abc578 100644 --- a/src/directxmath/DirectXMath.h +++ b/src/directxmath/DirectXMath.h @@ -154,32 +154,9 @@ #endif // !_XM_NO_INTRINSICS_ #include "sal.h" -//#include #define assert(x) -#define isnan(x) (false) -#define floorf(x) __builtin_floorf(x) -#define sqrtf(x) __builtin_sqrtf(x) -#define expf(x) __builtin_expf(x) -#define exp2f(x) __builtin_exp2f(x) -#define logf(x) __builtin_logf(x) -#define log2f(x) __builtin_log2f(x) -#define log10f(x) __builtin_log10f(x) -#define powf(x, y) __builtin_powf(x, y) -#define fabsf(x) __builtin_fabsf(x) -#define sinf(x) __builtin_sinf(x) -#define sinhf(x) __builtin_sinhf(x) -#define tanf(x) __builtin_tanf(x) -#define tanhf(x) __builtin_tanhf(x) -#define cosf(x) __builtin_cosf(x) -#define asinf(x) __builtin_asinf(x) -#define acosf(x) __builtin_acosf(x) -#define coshf(x) __builtin_coshf(x) -#define atanf(x) __builtin_atanf(x) -#define atan2f(x, y) __builtin_atan2f(x, y) -#define isinf(x) (false) -#define ceilf(x) __builtin_ceilf(x) -#define modff(x, y) __builtin_modff(x, y) #include +#include "builtin_math.h" #ifdef _MSC_VER #pragma warning(push) diff --git a/src/fluid/api.cpp b/src/fluid/api.cpp new file mode 100644 index 0000000..16af298 --- /dev/null +++ b/src/fluid/api.cpp @@ -0,0 +1,29 @@ +#include "particle_system.h" +#include "new.h" + +using namespace fluid; + +extern "C" { + ParticleSystem * particle_system__create(int maxParticles) + { + auto particleSystem = New(); + particleSystem->init(maxParticles); + return particleSystem; + } + + void particle_system__update(ParticleSystem * particleSystem) + { + particleSystem->update(); + } + + int particle__stride() + { + return (sizeof (Particle)); + } + + int particle_configuration__stride() + { + return (sizeof (ParticleConfiguration)); + } + +}; diff --git a/src/fluid/particle.cpp b/src/fluid/particle.cpp new file mode 100644 index 0000000..54624bc --- /dev/null +++ b/src/fluid/particle.cpp @@ -0,0 +1,32 @@ +#include "particle.h" + +namespace fluid +{ + void Particle::update(ParticleConfiguration * configuration) + { + XMVECTOR nextPosition = XMLoadFloat4(&position); + XMVECTOR nextVelocity = XMLoadFloat4(&velocity); + + nextVelocity += XMVectorSet(0, 1, 0, 0) * configuration->gravity; + nextPosition += nextVelocity; + + resolveCollision(configuration); + + XMStoreFloat4(&position, nextPosition); + XMStoreFloat4(&velocity, nextVelocity); + } + + void Particle::resolveCollision(ParticleConfiguration * configuration) + { + XMVECTOR halfExtents = XMLoadFloat2(&configuration->halfExtents) - XMVectorReplicate(configuration->particleRadius); + if (fabsf(position.x) > XMVectorGetX(halfExtents)) { + position.x = XMVectorGetX(halfExtents) * sign(position.x); + velocity.x *= -1; + } + if (fabsf(position.y) > XMVectorGetX(halfExtents)) { + position.y = XMVectorGetX(halfExtents) * sign(position.y); + velocity.y *= -1; + } + } + +} diff --git a/src/fluid/particle.h b/src/fluid/particle.h new file mode 100644 index 0000000..4d87e02 --- /dev/null +++ b/src/fluid/particle.h @@ -0,0 +1,17 @@ +#pragma once + +#include "directxmath/DirectXMath.h" +#include "particle_configuration.h" + +namespace fluid { + + struct Particle { + XMFLOAT4 position; + XMFLOAT4 velocity; + XMFLOAT4 value; + + void update(ParticleConfiguration * configuration); + void resolveCollision(ParticleConfiguration * configuration); + }; + +} diff --git a/src/fluid/particle_configuration.h b/src/fluid/particle_configuration.h new file mode 100644 index 0000000..2f68c1c --- /dev/null +++ b/src/fluid/particle_configuration.h @@ -0,0 +1,27 @@ +#pragma once + +#include "directxmath/DirectXMath.h" + +namespace fluid { + + struct ParticleConfiguration { + float particleCount; + float particleRadius; + float particleMass1; + float particleMass2; + + float smoothingRadius; + float lineThickness; + float lineLength; + float _padding1; + + float targetDensity; + float pressure; + float gravity; + float _padding2; + + XMFLOAT2 testSamplePosition; + XMFLOAT2 halfExtents; + }; + +} diff --git a/src/fluid/particle_system.cpp b/src/fluid/particle_system.cpp new file mode 100644 index 0000000..260e1dd --- /dev/null +++ b/src/fluid/particle_system.cpp @@ -0,0 +1,25 @@ +#include "particle_system.h" +#include "new.h" + +namespace fluid { + + void ParticleSystem::init(int maxParticles) + { + this->maxParticles = maxParticles; + configuration = New(); + particles = New(maxParticles); + + for (int i = 0; i < maxParticles; i++) { + XMStoreFloat4(&particles[i].position, XMVectorZero()); + XMStoreFloat4(&particles[i].velocity, XMVectorZero()); + XMStoreFloat4(&particles[i].value, XMVectorZero()); + } + } + + void ParticleSystem::update() + { + for (int i = 0; i < configuration->particleCount; i++) { + particles[i].update(configuration); + } + } +} diff --git a/src/fluid/particle_system.h b/src/fluid/particle_system.h new file mode 100644 index 0000000..39e9803 --- /dev/null +++ b/src/fluid/particle_system.h @@ -0,0 +1,15 @@ +#pragma once + +#include "particle.h" + +namespace fluid { + + struct ParticleSystem { + ParticleConfiguration * configuration; + Particle * particles; + int maxParticles; + + void init(int maxParticles); + void update(); + }; +}; diff --git a/src/new.h b/src/new.h new file mode 100644 index 0000000..88fcbb7 --- /dev/null +++ b/src/new.h @@ -0,0 +1,11 @@ +#pragma once + +#include "memory.h" + +template +T * New(int count = 1) +{ + size_t size = size_t(count) * (sizeof (T)); + T * ptr = reinterpret_cast(mem_alloc(size)); + return ptr; +}