added move and more of the particle stuff
This commit is contained in:
@@ -29,42 +29,27 @@ int main() {
|
|||||||
|
|
||||||
for (int frameIdx = 0; frameIdx < TOTAL_FRAMES; ++frameIdx) {
|
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 % 10 == 0) {
|
||||||
if (frameIdx < (TOTAL_FRAMES * 0.9f)) {
|
if (frameIdx < (TOTAL_FRAMES * 0.1f)) {
|
||||||
float t = static_cast<float>(frameIdx) / (TOTAL_FRAMES * 0.9f);
|
float t = static_cast<float>(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<int>(t * 4);
|
int spawnCount = 2 + static_cast<int>(t * 4);
|
||||||
|
sim.spawnParticles(baseParticle, spawnCount);
|
||||||
sim.spawnParticles(baseParticle, spawnCount, currentSize, currentMass);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Physics Step ---
|
|
||||||
sim.applyPhysics();
|
sim.applyPhysics();
|
||||||
|
|
||||||
// --- Render & Save ---
|
|
||||||
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;
|
||||||
|
|
||||||
// Generate LODs for faster/better rendering
|
frame renderedFrame = sim.grid.renderFrame(cam, HEIGHT, WIDTH, frame::colormap::RGB, 5, 4, true, false);
|
||||||
sim.grid.generateLODs();
|
|
||||||
|
|
||||||
// Render frame
|
|
||||||
frame renderedFrame = sim.grid.renderFrame(cam, HEIGHT, WIDTH, frame::colormap::RGB, 4, 4, true, false);
|
|
||||||
|
|
||||||
// Save to BMP
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "output/frame_" << std::setw(4) << std::setfill('0') << frameIdx << ".bmp";
|
ss << "output/frame_" << std::setw(4) << std::setfill('0') << frameIdx << ".bmp";
|
||||||
BMPWriter::saveBMP(ss.str(), renderedFrame);
|
BMPWriter::saveBMP(ss.str(), renderedFrame);
|
||||||
|
|
||||||
|
}
|
||||||
|
if (frameIdx % 100 == 0) {
|
||||||
sim.grid.printStats();
|
sim.grid.printStats();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -647,7 +647,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool inGrid(PointType pos) {
|
bool inGrid(PointType pos) {
|
||||||
return root_.contains(pos);
|
return root_->contains(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool remove(const PointType& pos, float tolerance = 0.0001f) {
|
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) {
|
bool setObjectId(const PointType& pos, int objectId, float tolerance = 0.0001f) {
|
||||||
auto pointData = find(pos, tolerance);
|
auto pointData = find(pos, tolerance);
|
||||||
if (!pointData) return false;
|
if (!pointData) return false;
|
||||||
|
|||||||
@@ -23,14 +23,13 @@
|
|||||||
#include "../stb/stb_image.h"
|
#include "../stb/stb_image.h"
|
||||||
|
|
||||||
struct fluidParticle {
|
struct fluidParticle {
|
||||||
Eigen::Matrix<float, 3, 1> pos;
|
|
||||||
Eigen::Matrix<float, 3, 1> velocity;
|
Eigen::Matrix<float, 3, 1> velocity;
|
||||||
Eigen::Matrix<float, 3, 1> acceleration;
|
Eigen::Matrix<float, 3, 1> acceleration;
|
||||||
Eigen::Matrix<float, 3, 1> forceAccumulator;
|
Eigen::Matrix<float, 3, 1> forceAccumulator;
|
||||||
float density;
|
float density = 0.0f;
|
||||||
float pressure;
|
float pressure = 0.0f;
|
||||||
float viscosity;
|
float viscosity = 25.0f;
|
||||||
float restitution;
|
float restitution = 500.0f;
|
||||||
float mass;
|
float mass;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -108,17 +107,21 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void spawnParticles(fluidParticle toSpawn, int count) {
|
void spawnParticles(fluidParticle toSpawn, int count, bool resize = true) {
|
||||||
TIME_FUNCTION;
|
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++) {
|
for (int i = 0; i < count; i++) {
|
||||||
Eigen::Matrix<float, 3, 1> pos = posGen();
|
Eigen::Matrix<float, 3, 1> pos = posGen();
|
||||||
int id = nextObjectId++;
|
int id = nextObjectId++;
|
||||||
|
|
||||||
Eigen::Vector3f color = buildGradient(toSpawn.mass / 1000, gradientmap);
|
grid.set(toSpawn, pos, true, color, size, true, id, (toSpawn.mass > 100) : true ? false, 1);
|
||||||
grid.set(toSpawn, pos, true, color, 1, true, id, false);
|
|
||||||
idposMap[id] = pos;
|
idposMap[id] = pos;
|
||||||
}
|
}
|
||||||
newMass -= newMass / 10;
|
if (resize){
|
||||||
|
newMass -= newMass * .01;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void applyPressureDensity() {
|
void applyPressureDensity() {
|
||||||
@@ -172,27 +175,39 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void replaceLost() {
|
void replaceLost() {
|
||||||
int toReplace = 0;
|
std::vector<size_t> idsToRemove;
|
||||||
#pragma omp parallel for
|
|
||||||
for (auto& point : idposMap) {
|
for (auto& point : idposMap) {
|
||||||
if (!grid.inGrid(point.second)) {
|
if (!grid.inGrid(point.second)) {
|
||||||
grid.remove(point.second);
|
idsToRemove.push_back(point.first);
|
||||||
toReplace++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fluidParticle newParticles;
|
|
||||||
newParticles.mass = newMass;
|
for (size_t id : idsToRemove) {
|
||||||
spawnParticles(newParticles, toReplace);
|
grid.remove(idposMap[id]);
|
||||||
|
idposMap.erase(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!idsToRemove.empty()) {
|
||||||
|
fluidParticle newParticles;
|
||||||
|
newParticles.mass = newMass;
|
||||||
|
spawnParticles(newParticles, idsToRemove.size(), false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void applyPhysics() {
|
void applyPhysics() {
|
||||||
TIME_FUNCTION;
|
TIME_FUNCTION;
|
||||||
///TODO:
|
applyPressureDensity();
|
||||||
// apply velocity to have particle move
|
applyForce();
|
||||||
// use mass of neighboring particles to change direction towards them
|
|
||||||
// ressure pushes particles away if they are too close
|
for (auto& point : idposMap) {
|
||||||
// resitution controls how much pressure builds up based on how close particles are
|
auto node = grid.find(point.second);
|
||||||
// have to find a way to have a clump use their combined mass instead of individual mass.
|
if (!node) continue;
|
||||||
//if a particle leaves the grid, destroy it and spawn a new one
|
Eigen::Matrix<float, 3, 1> acceleration = node->data.forceAccumulator / node->data.mass;
|
||||||
|
node->data.velocity += acceleration * config.TIMESTEP;
|
||||||
|
Eigen::Matrix<float, 3, 1> newPos = point.second + (node->data.velocity * config.TIMESTEP);
|
||||||
|
idposMap[point.first] = newPos;
|
||||||
|
grid.move(point.second, newPos);
|
||||||
|
}
|
||||||
|
replaceLost();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user