so much debugging only to find I was looking in the wrong place.

This commit is contained in:
Yggdrasil75
2026-02-06 10:05:12 -05:00
parent 17e4cdf1a5
commit 73eaa63dfb
3 changed files with 104 additions and 28 deletions

View File

@@ -5,7 +5,7 @@ int main() {
fluidSim sim; fluidSim sim;
// Simulation settings // Simulation settings
const int TOTAL_FRAMES = 100; const int TOTAL_FRAMES = 10000;
const int WIDTH = 800; const int WIDTH = 800;
const int HEIGHT = 600; const int HEIGHT = 600;
@@ -29,8 +29,8 @@ int main() {
for (int frameIdx = 0; frameIdx < TOTAL_FRAMES; ++frameIdx) { for (int frameIdx = 0; frameIdx < TOTAL_FRAMES; ++frameIdx) {
if (frameIdx % 1 == 0) {
if (frameIdx < (TOTAL_FRAMES * 0.1f)) { if (frameIdx < (TOTAL_FRAMES * 0.1f)) {
if (frameIdx % 1 == 0) {
//float t = static_cast<float>(frameIdx) / (TOTAL_FRAMES * 0.9f); //float t = static_cast<float>(frameIdx) / (TOTAL_FRAMES * 0.9f);
int spawnCount = 2; // + static_cast<int>(t * 4); int spawnCount = 2; // + static_cast<int>(t * 4);
sim.spawnParticles(baseParticle, spawnCount); sim.spawnParticles(baseParticle, spawnCount);
@@ -39,6 +39,26 @@ int main() {
sim.applyPhysics(); sim.applyPhysics();
if (frameIdx % 1 == 0) {
std::cout << "Rendering ultrafast Frame " << frameIdx << " / " << TOTAL_FRAMES << std::endl;
frame renderedFrame = sim.grid.fastRenderFrame(cam, HEIGHT, WIDTH, frame::colormap::RGB);
std::stringstream ss;
ss << "output/ufframe_" << std::setw(4) << std::setfill('0') << frameIdx << ".bmp";
BMPWriter::saveBMP(ss.str(), renderedFrame);
}
if (frameIdx % 10 == 0) {
std::cout << "Rendering quick Frame " << frameIdx << " / " << TOTAL_FRAMES << std::endl;
frame renderedFrame = sim.grid.renderFrame(cam, HEIGHT, WIDTH, frame::colormap::RGB, 1, 1, true, false);
std::stringstream ss;
ss << "output/qframe_" << std::setw(4) << std::setfill('0') << frameIdx << ".bmp";
BMPWriter::saveBMP(ss.str(), renderedFrame);
}
if (frameIdx % 50 == 0) { if (frameIdx % 50 == 0) {
std::cout << "Rendering Frame " << frameIdx << " / " << TOTAL_FRAMES << std::endl; std::cout << "Rendering Frame " << frameIdx << " / " << TOTAL_FRAMES << std::endl;
@@ -49,7 +69,7 @@ int main() {
BMPWriter::saveBMP(ss.str(), renderedFrame); BMPWriter::saveBMP(ss.str(), renderedFrame);
} }
if (frameIdx % 100 == 0) { if (frameIdx % 500 == 0) {
sim.grid.printStats(); sim.grid.printStats();
} }
} }

View File

@@ -795,10 +795,14 @@ public:
bool move(const PointType& pos, const PointType& newPos) { bool move(const PointType& pos, const PointType& newPos) {
auto pointData = find(pos); auto pointData = find(pos);
if (!pointData) return false; if (!pointData) return false;
if (!remove(pos)) return false; bool success = set(pointData->data, newPos, pointData->visible, pointData->color, pointData->size,
return set(pointData->data, pointData->position, pointData->visible, pointData->color, pointData->size,
pointData->active, pointData->objectId, pointData->light, pointData->emittance, pointData->active, pointData->objectId, pointData->light, pointData->emittance,
pointData->refraction, pointData->reflection, pointData->shape); pointData->refraction, pointData->reflection, pointData->shape);
if (success) {
remove(pos);
return true;
}
return false;
} }
bool setObjectId(const PointType& pos, int objectId, float tolerance = 0.0001f) { bool setObjectId(const PointType& pos, int objectId, float tolerance = 0.0001f) {

View File

@@ -29,16 +29,16 @@ struct fluidParticle {
float density = 0.0f; float density = 0.0f;
float pressure = 0.0f; float pressure = 0.0f;
Eigen::Matrix<float, 3, 1> pressureForce; Eigen::Matrix<float, 3, 1> pressureForce;
float viscosity = 25.0f; float viscosity = 0.5f;
Eigen::Matrix<float, 3, 1> viscosityForce; Eigen::Matrix<float, 3, 1> viscosityForce;
float restitution = 500.0f; float restitution = 5.0f;
float mass; float mass;
}; };
struct gridConfig { struct gridConfig {
float gridSizeCube = 4096; float gridSizeCube = 4096;
const float SMOOTHING_RADIUS = 1024.0f; const float SMOOTHING_RADIUS = 1024.0f;
const float REST_DENSITY = 0.5f; const float REST_DENSITY = 0.00005f;
const float TIMESTEP = 0.016f; const float TIMESTEP = 0.016f;
const float G_ATTRACTION = 50.0f; const float G_ATTRACTION = 50.0f;
}; };
@@ -51,6 +51,14 @@ Eigen::Matrix<float, 3, 1> posGen() {
return Eigen::Matrix<float, 3, 1>(dist(gen),dist(gen),dist(gen)); return Eigen::Matrix<float, 3, 1>(dist(gen),dist(gen),dist(gen));
} }
Eigen::Matrix<float, 3, 1> velGen() {
static std::random_device rd;
static std::mt19937 gen(rd());
static std::normal_distribution<float> dist(0.0f, 1.0f);
return Eigen::Matrix<float, 3, 1>(dist(gen),dist(gen),dist(gen));
}
float W_poly6(Eigen::Vector3f rv, float h) { float W_poly6(Eigen::Vector3f rv, float h) {
float r = rv.squaredNorm(); float r = rv.squaredNorm();
@@ -189,17 +197,17 @@ public:
int id = nextObjectId++; int id = nextObjectId++;
grid.set(toSpawn, pos, true, color, size, true, id, (toSpawn.mass > 100) ? true : false, 1); grid.set(toSpawn, pos, true, color, size, true, id, (toSpawn.mass > 100) ? true : false, 1);
idposMap[id] = pos; idposMap.emplace(id, pos);
} }
if (resize){ if (resize){
newMass *= 0.99f; newMass *= 0.999f;
} }
} }
float sphKernel(Eigen::Vector3f rv) { float sphKernel(Eigen::Vector3f rv) {
float r = rv.norm(); float r = rv.norm();
if (r < closeThresh) return W_spiky(rv, config.SMOOTHING_RADIUS); if (r < closeThresh) return W_spiky(rv, config.G_ATTRACTION);
else return W_poly6(rv,config.SMOOTHING_RADIUS); else return W_poly6(rv,config.G_ATTRACTION);
} }
void computeDensities() { void computeDensities() {
@@ -218,21 +226,27 @@ public:
} }
void applyPressure() { void applyPressure() {
// std::cout << "points to consider: " << idposMap.size();
size_t pointcounter = 0;
for (auto& point : idposMap) { for (auto& point : idposMap) {
// std::cout << " point: " << pointcounter++;
auto node = grid.find(point.second); auto node = grid.find(point.second);
if (!node) { if (!node) {
// std::cout << " point is missing" << std::endl;
continue; continue;
} }
// std::cout << "nd: " << node->data.density; // std::cout << " nd: " << node->data.density;
// std::cout << "nr: " << node->data.restitution; // std::cout << " nr: " << node->data.restitution;
// std::cout << "crd: " << config.REST_DENSITY; // std::cout << " crd: " << config.REST_DENSITY;
node->data.pressure = node->data.restitution * (node->data.density - config.REST_DENSITY); node->data.pressure = node->data.restitution * (node->data.density - config.REST_DENSITY);
std::cout << std::endl; // std::cout << std::endl << std::endl;
} }
for (auto& point : idposMap) { for (auto& point : idposMap) {
// std::cout << " point: " << pointcounter++;
auto node = grid.find(point.second); auto node = grid.find(point.second);
if (!node) { if (!node) {
// std::cout << " point is missing" << std::endl;
continue; continue;
} }
Eigen::Vector3f pressureForce = Eigen::Vector3f::Zero(); Eigen::Vector3f pressureForce = Eigen::Vector3f::Zero();
@@ -242,15 +256,15 @@ public:
if (node == neighbor) continue; if (node == neighbor) continue;
Eigen::Vector3f rv = node->position - neighbor->position; Eigen::Vector3f rv = node->position - neighbor->position;
Eigen::Vector3f gradW = gradW_spiky(rv, config.SMOOTHING_RADIUS); Eigen::Vector3f gradW = gradW_spiky(rv, config.SMOOTHING_RADIUS);
// std::cout << "np: " << node->data.pressure; // std::cout << " np: " << node->data.pressure;
// std::cout << "np2: " << neighbor->data.pressure; // std::cout << " np2: " << neighbor->data.pressure;
// std::cout << "nd: " << neighbor->data.density; // std::cout << " nd: " << neighbor->data.density;
float scalarP = (node->data.pressure + neighbor->data.pressure) / (2.0f * neighbor->data.density); float scalarP = (node->data.pressure + neighbor->data.pressure) / (2.0f * neighbor->data.density);
pressureForce -= neighbor->data.mass * scalarP * gradW; pressureForce -= neighbor->data.mass * scalarP * gradW;
} }
node->data.pressureForce = pressureForce; node->data.pressureForce = pressureForce;
// std::cout << "pressure: " << pressureForce.norm(); // std::cout << " pressure: " << pressureForce.norm() << std::endl;
} }
} }
@@ -259,18 +273,42 @@ public:
auto node = grid.find(point.second); auto node = grid.find(point.second);
if (!node) continue; if (!node) continue;
Eigen::Vector3f viscosityForce = Eigen::Vector3f::Zero(); Eigen::Vector3f viscosityForce = Eigen::Vector3f::Zero();
if (node->data.velocity == Eigen::Vector3f::Zero()) node->data.velocity = velGen();
std::vector<std::shared_ptr<Octree<fluidParticle>::NodeData>> neighbors = grid.findInRadius(point.second, config.SMOOTHING_RADIUS); std::vector<std::shared_ptr<Octree<fluidParticle>::NodeData>> neighbors = grid.findInRadius(point.second, config.SMOOTHING_RADIUS);
for (auto& neighbor : neighbors) { for (auto& neighbor : neighbors) {
Eigen::Vector3f rv = node->position - neighbor->position; Eigen::Vector3f rv = node->position - neighbor->position;
Eigen::Vector3f velDiff = neighbor->data.velocity - node->data.velocity; Eigen::Vector3f velDiff = neighbor->data.velocity - node->data.velocity;
float lapW = lapW_visc(rv, config.SMOOTHING_RADIUS); float lapW = lapW_visc(rv, config.SMOOTHING_RADIUS);
// std::cout << "nv: " << node->data.viscosity;
// std::cout << "nm: " << neighbor->data.mass;
// std::cout << "veldiff: " << velDiff.norm();
// std::cout << "nd: " << neighbor->data.density;
// std::cout << "lapl: " << lapW;
viscosityForce += node->data.viscosity * neighbor->data.mass * (velDiff / neighbor->data.density) * lapW; viscosityForce += node->data.viscosity * neighbor->data.mass * (velDiff / neighbor->data.density) * lapW;
} }
node->data.viscosityForce = viscosityForce; node->data.viscosityForce = viscosityForce;
// std::cout << "viscosity: " << viscosityForce; // std::cout << "viscosity: " << viscosityForce.norm() << std::endl;
}
} }
Eigen::Vector3f applyMutualGravity(std::shared_ptr<Octree<fluidParticle>::NodeData>& node) {
Eigen::Vector3f gravityForce = Eigen::Vector3f::Zero();
std::vector<std::shared_ptr<Octree<fluidParticle>::NodeData>> neighbors = grid.findInRadius(node->position, config.SMOOTHING_RADIUS);
for (auto& neighbor : neighbors) {
if (node == neighbor) continue;
Eigen::Vector3f dir = neighbor->position - node->position;
float dist = dir.norm();
if (dist > EPSILON) {
dir.normalize();
float forceMag = (config.G_ATTRACTION * node->data.mass * neighbor->data.mass) / (dist * dist);
gravityForce += dir * forceMag;
}
}
return gravityForce;
} }
void applyForce() { void applyForce() {
@@ -279,7 +317,10 @@ public:
if (!node) continue; if (!node) continue;
Eigen::Vector3f internalForces = node->data.pressureForce + node->data.viscosityForce; Eigen::Vector3f internalForces = node->data.pressureForce + node->data.viscosityForce;
Eigen::Vector3f acceleration = (internalForces / node->data.mass); Eigen::Vector3f acceleration = (internalForces / node->data.mass);
node->data.forceAccumulator = acceleration * config.TIMESTEP; Eigen::Vector3f gravity = applyMutualGravity(node);
// std::cout << "gravity: " << gravity.norm();
node->data.forceAccumulator = (acceleration + gravity) / node->data.mass;
// node->data.forceAccumulator = node->data.pressureForce + node->data.viscosityForce;
} }
} }
@@ -314,12 +355,23 @@ public:
if (!node) continue; if (!node) continue;
Eigen::Matrix<float, 3, 1> acceleration = node->data.forceAccumulator; Eigen::Matrix<float, 3, 1> acceleration = node->data.forceAccumulator;
//std::cout << acceleration; //std::cout << acceleration;
node->data.velocity += acceleration; node->data.velocity += acceleration * config.TIMESTEP;
Eigen::Matrix<float, 3, 1> newPos = point.second + (node->data.velocity); Eigen::Matrix<float, 3, 1> newPos = point.second + (node->data.velocity);
Eigen::Vector3f oldPos = point.second;
// std::cout << "moving " << (newPos - node->position).norm();
// grid.update(oldPos, newPos, node->data, node->visible, node->color, node->size,
// node->active, node->objectId, node->light, node->emittance,
// node->refraction, node->reflection, node->shape);
if (grid.move(oldPos, newPos)) {
auto newpoint = grid.find(newPos);
if (!newpoint) std::cout << "failed to move" << std::endl;
// auto oldpoint = grid.find(oldPos);
// if (!oldpoint) std::cout << "still at old position" << std::endl;
idposMap[point.first] = newPos; idposMap[point.first] = newPos;
std::cout << "moving " << (newPos - node->position).norm() << std::endl; // std::cout << "moved" << std::endl;
grid.move(node->position, newPos); } // else std::cout << "failed to move" << std::endl;
} }
// std::cout << std::endl;
replaceLost(); replaceLost();
} }
}; };