diff --git a/projects/wobble_bobble/shaders/particle.inc b/projects/wobble_bobble/shaders/particle.inc index 266e5e013e1836f5354d7561e76d33efe4b520bd..dbe0254e4a36f57b6d39d6e4375120875140dba4 100644 --- a/projects/wobble_bobble/shaders/particle.inc +++ b/projects/wobble_bobble/shaders/particle.inc @@ -25,6 +25,9 @@ struct Particle { #define SIM_TYPE_HYPERELASTIC 0 #define SIM_TYPE_FLUID 1 +#define SIM_MODE_RANDOM 0 +#define SIM_MODE_ORDERED 1 + struct Simulation { float density; float size; @@ -35,6 +38,7 @@ struct Simulation { float K; float E; float gamma; + int mode; }; const float PI = 3.1415926535897932384626433832795; diff --git a/projects/wobble_bobble/src/main.cpp b/projects/wobble_bobble/src/main.cpp index 6d38f72b149895fc81b7e00147b9271e292bdb56..d15d3a6a1283db89326bcb3faa80eeacfaf5a018 100644 --- a/projects/wobble_bobble/src/main.cpp +++ b/projects/wobble_bobble/src/main.cpp @@ -25,6 +25,9 @@ struct Particle { #define SIM_TYPE_HYPERELASTIC 0 #define SIM_TYPE_FLUID 1 +#define SIM_MODE_RANDOM 0 +#define SIM_MODE_ORDERED 1 + struct Simulation { float density; float size; @@ -35,6 +38,7 @@ struct Simulation { float K; float E; float gamma; + int mode; }; struct Physics { @@ -66,26 +70,46 @@ float randomFloat(float min, float max) { return min + (max - min) * dist(random_dev) / static_cast<float>(RAND_MAX); } +float mod(float x, float y) { + return x - std::floor(x / y) * y; +} + void distributeParticlesCube(Particle *particles, size_t count, const glm::vec3& center, float radius, - float mass, const glm::vec3& velocity) { + float mass, const glm::vec3& velocity, bool random) { + const float side = cube_radius(static_cast<float>(count)) * 2.0f; + float volume = 0.0f; for (size_t i = 0; i < count; i++) { - glm::vec3 offset( - randomFloat(-1.0f, +1.0f), - randomFloat(-1.0f, +1.0f), - randomFloat(-1.0f, +1.0f) - ); + glm::vec3 offset; - offset *= radius; + if (random) { + offset.x = randomFloat(-1.0f, +1.0f); + offset.y = randomFloat(-1.0f, +1.0f); + offset.z = randomFloat(-1.0f, +1.0f); + } else { + const float s = static_cast<float>(i) + 0.5f; + + offset.x = 2.0f * mod(s, side) / side - 1.0f; + offset.y = 2.0f * mod(s / side, side) / side - 1.0f; + offset.z = 2.0f * mod(s / side / side, side) / side - 1.0f; + } - const float ax = std::abs(offset.x); - const float ay = std::abs(offset.y); - const float az = std::abs(offset.z); + offset *= radius; - const float a = std::max(std::max(ax, ay), az); + float size = 0.0f; - const float size = (radius - a); + if (random) { + const float ax = std::abs(offset.x); + const float ay = std::abs(offset.y); + const float az = std::abs(offset.z); + + const float a = std::max(std::max(ax, ay), az); + + size = (radius - a); + } else { + size = 2.0f * radius / side; + } particles[i].position = center + offset; particles[i].size = size; @@ -106,22 +130,45 @@ void distributeParticlesCube(Particle *particles, size_t count, const glm::vec3& } void distributeParticlesSphere(Particle *particles, size_t count, const glm::vec3& center, float radius, - float mass, const glm::vec3& velocity) { + float mass, const glm::vec3& velocity, bool random) { + const float side = sphere_radius(static_cast<float>(count)) * 2.0f; + float volume = 0.0f; for (size_t i = 0; i < count; i++) { - glm::vec3 offset ( - randomFloat(-1.0f, +1.0f), - randomFloat(-1.0f, +1.0f), - randomFloat(-1.0f, +1.0f) - ); + glm::vec3 offset; + + if (random) { + offset.x = randomFloat(-1.0f, +1.0f); + offset.y = randomFloat(-1.0f, +1.0f); + offset.z = randomFloat(-1.0f, +1.0f); + + if (glm::length(offset) > 0.0f) + offset = glm::normalize(offset); + + offset *= randomFloat(0.0f, 1.0f); + } else { + const float range = 0.5f * side; + const float s = static_cast<float>(i) + 0.5f; + + float a = mod(s, range) / range; + float b = mod(s / range, M_PI * range); + float c = mod(s / range / M_PI / range, M_PI * range * 2.0f); + + offset.x = a * std::sin(c) * std::sin(b); + offset.y = a * std::cos(b); + offset.z = a * std::cos(c) * std::sin(b); + } - if (glm::length(offset) > 0.0f) - offset = glm::normalize(offset); + offset *= radius; - offset *= randomFloat(0.0f, radius); + float size = 0.0f; - const float size = (radius - glm::length(offset)); + if (random) { + size = (radius - glm::length(offset)); + } else { + size = 2.0f * radius / side; + } particles[i].position = center + offset; particles[i].size = size; @@ -186,7 +233,7 @@ vkcv::ComputePipelineHandle createComputePipeline(vkcv::Core& core, vkcv::shader } void resetParticles(vkcv::Buffer<Particle>& particles, const glm::vec3& velocity, - float density, float size, int form) { + float density, float size, int form, int mode) { std::vector<Particle> particles_vec (particles.getCount()); switch (form) { @@ -197,7 +244,8 @@ void resetParticles(vkcv::Buffer<Particle>& particles, const glm::vec3& velocity glm::vec3(0.5f), size, density * sphere_volume(size), - velocity + velocity, + (mode == 0) ); break; case SIM_FORM_CUBE: @@ -207,7 +255,8 @@ void resetParticles(vkcv::Buffer<Particle>& particles, const glm::vec3& velocity glm::vec3(0.5f), size, density * sphere_volume(size), - velocity + velocity, + (mode == 0) ); break; default: @@ -298,8 +347,9 @@ int main(int argc, const char **argv) { sim->K = 2.2f; sim->E = 35.0f; sim->gamma = 1.330f; + sim->mode = SIM_MODE_RANDOM; - resetParticles(particles, initialVelocity, sim->density, sim->size, sim->form); + resetParticles(particles, initialVelocity, sim->density, sim->size, sim->form, sim->mode); vkcv::shader::GLSLCompiler compiler; @@ -760,8 +810,11 @@ int main(int argc, const char **argv) { gui.beginGUI(); ImGui::Begin("Settings"); + ImGui::BeginGroup(); + ImGui::Combo("Mode", &(sim->mode), "Random\0Ordered", 2); ImGui::Combo("Form", &(sim->form), "Sphere\0Cube", 2); ImGui::Combo("Type", &(sim->type), "Hyperelastic\0Fluid", 2); + ImGui::EndGroup(); ImGui::Spacing(); @@ -797,7 +850,7 @@ int main(int argc, const char **argv) { ImGui::DragFloat3("Initial Velocity", reinterpret_cast<float*>(&initialVelocity), 0.001f); ImGui::SameLine(0.0f, 10.0f); if (ImGui::Button("Reset##particle_velocity")) { - resetParticles(particles, initialVelocity, sim->density, sim->size, sim->form); + resetParticles(particles, initialVelocity, sim->density, sim->size, sim->form, sim->mode); } ImGui::End();