diff --git a/tests/fluidsim.cpp b/tests/fluidsim.cpp index 4fb8d14..b9c03c2 100644 --- a/tests/fluidsim.cpp +++ b/tests/fluidsim.cpp @@ -29,42 +29,27 @@ int main() { for (int frameIdx = 0; frameIdx < TOTAL_FRAMES; ++frameIdx) { - // --- Spawning Logic --- - // Spawn throughout the simulation (e.g., until 90% completion) if (frameIdx % 10 == 0) { - if (frameIdx < (TOTAL_FRAMES * 0.9f)) { + if (frameIdx < (TOTAL_FRAMES * 0.1f)) { float t = static_cast(frameIdx) / (TOTAL_FRAMES * 0.9f); - - // Linear interpolation for Mass: Heavy (10.0) -> Light (0.5) - float currentMass = (1.0f - t) * 10.0f + t * 0.5f; - - // Linear interpolation for Size: Large (12.0) -> Small (2.0) - float currentSize = (1.0f - t) * 12.0f + t * 2.0f; - - // Number of particles to spawn this frame (can increase as they get smaller) int spawnCount = 2 + static_cast(t * 4); - - sim.spawnParticles(baseParticle, spawnCount, currentSize, currentMass); + sim.spawnParticles(baseParticle, spawnCount); } } - // --- Physics Step --- sim.applyPhysics(); - // --- Render & Save --- if (frameIdx % 50 == 0) { std::cout << "Rendering Frame " << frameIdx << " / " << TOTAL_FRAMES << std::endl; - // Generate LODs for faster/better rendering - sim.grid.generateLODs(); - - // Render frame - frame renderedFrame = sim.grid.renderFrame(cam, HEIGHT, WIDTH, frame::colormap::RGB, 4, 4, true, false); + frame renderedFrame = sim.grid.renderFrame(cam, HEIGHT, WIDTH, frame::colormap::RGB, 5, 4, true, false); - // Save to BMP std::stringstream ss; ss << "output/frame_" << std::setw(4) << std::setfill('0') << frameIdx << ".bmp"; BMPWriter::saveBMP(ss.str(), renderedFrame); + + } + if (frameIdx % 100 == 0) { sim.grid.printStats(); } } diff --git a/util/grid/grid3eigen.hpp b/util/grid/grid3eigen.hpp index 9ceee59..53a5125 100644 --- a/util/grid/grid3eigen.hpp +++ b/util/grid/grid3eigen.hpp @@ -647,7 +647,7 @@ public: } bool inGrid(PointType pos) { - return root_.contains(pos); + return root_->contains(pos); } bool remove(const PointType& pos, float tolerance = 0.0001f) { @@ -792,6 +792,15 @@ public: } } + bool move(const PointType& pos, const PointType& newPos) { + auto pointData = find(pos); + if (!pointData) return false; + if (!remove(pos)) return false; + return set(pointData->data, pointData->position, pointData->visible, pointData->color, pointData->size, + pointData->active, pointData->objectId, pointData->light, pointData->emittance, + pointData->refraction, pointData->reflection, pointData->shape); + } + bool setObjectId(const PointType& pos, int objectId, float tolerance = 0.0001f) { auto pointData = find(pos, tolerance); if (!pointData) return false; diff --git a/util/sim/fluidsim.hpp b/util/sim/fluidsim.hpp index 504a5d3..841e664 100644 --- a/util/sim/fluidsim.hpp +++ b/util/sim/fluidsim.hpp @@ -23,14 +23,13 @@ #include "../stb/stb_image.h" struct fluidParticle { - Eigen::Matrix pos; Eigen::Matrix velocity; Eigen::Matrix acceleration; Eigen::Matrix forceAccumulator; - float density; - float pressure; - float viscosity; - float restitution; + float density = 0.0f; + float pressure = 0.0f; + float viscosity = 25.0f; + float restitution = 500.0f; float mass; }; @@ -108,17 +107,21 @@ public: } - void spawnParticles(fluidParticle toSpawn, int count) { + void spawnParticles(fluidParticle toSpawn, int count, bool resize = true) { TIME_FUNCTION; + float size = toSpawn.mass / 10; + Eigen::Vector3f color = buildGradient(toSpawn.mass / 1000, gradientmap); + std::cout << "spawning " << count << " particles with a mass of " << toSpawn.mass << " and a size of " << size << std::endl; for (int i = 0; i < count; i++) { Eigen::Matrix pos = posGen(); int id = nextObjectId++; - Eigen::Vector3f color = buildGradient(toSpawn.mass / 1000, gradientmap); - grid.set(toSpawn, pos, true, color, 1, true, id, false); + grid.set(toSpawn, pos, true, color, size, true, id, (toSpawn.mass > 100) : true ? false, 1); idposMap[id] = pos; } - newMass -= newMass / 10; + if (resize){ + newMass -= newMass * .01; + } } void applyPressureDensity() { @@ -172,27 +175,39 @@ public: } void replaceLost() { - int toReplace = 0; - #pragma omp parallel for + std::vector idsToRemove; for (auto& point : idposMap) { if (!grid.inGrid(point.second)) { - grid.remove(point.second); - toReplace++; + idsToRemove.push_back(point.first); } } - fluidParticle newParticles; - newParticles.mass = newMass; - spawnParticles(newParticles, toReplace); + + for (size_t id : idsToRemove) { + grid.remove(idposMap[id]); + idposMap.erase(id); + } + + if (!idsToRemove.empty()) { + fluidParticle newParticles; + newParticles.mass = newMass; + spawnParticles(newParticles, idsToRemove.size(), false); + } } void applyPhysics() { TIME_FUNCTION; - ///TODO: - // apply velocity to have particle move - // use mass of neighboring particles to change direction towards them - // ressure pushes particles away if they are too close - // resitution controls how much pressure builds up based on how close particles are - // have to find a way to have a clump use their combined mass instead of individual mass. - //if a particle leaves the grid, destroy it and spawn a new one + applyPressureDensity(); + applyForce(); + + for (auto& point : idposMap) { + auto node = grid.find(point.second); + if (!node) continue; + Eigen::Matrix acceleration = node->data.forceAccumulator / node->data.mass; + node->data.velocity += acceleration * config.TIMESTEP; + Eigen::Matrix newPos = point.second + (node->data.velocity * config.TIMESTEP); + idposMap[point.first] = newPos; + grid.move(point.second, newPos); + } + replaceLost(); } };