making a proper widget.
This commit is contained in:
@@ -71,7 +71,7 @@ public:
|
|||||||
void update() {
|
void update() {
|
||||||
if (isRunning) {
|
if (isRunning) {
|
||||||
if (sim.getParticleCount() < (size_t)totalParticleCap) {
|
if (sim.getParticleCount() < (size_t)totalParticleCap) {
|
||||||
sim.spawnParticles(baseParticle, particlesToSpawnPerFrame);
|
sim.spawnParticles(baseParticle, particlesToSpawnPerFrame);
|
||||||
}
|
}
|
||||||
sim.applyPhysics();
|
sim.applyPhysics();
|
||||||
}
|
}
|
||||||
|
|||||||
212
tests/planet.cpp
Normal file
212
tests/planet.cpp
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
#ifndef PLANET_CPP
|
||||||
|
#define PLANET_CPP
|
||||||
|
|
||||||
|
#include "../util/sim/planet.hpp"
|
||||||
|
#include "../util/grid/camera.hpp"
|
||||||
|
#include "../util/noise/pnoise2.hpp"
|
||||||
|
#include "../util/noise/pnoise.cpp"
|
||||||
|
|
||||||
|
class planetSimUI {
|
||||||
|
private:
|
||||||
|
planetsim sim;
|
||||||
|
Camera cam;
|
||||||
|
bool isRunning = false;
|
||||||
|
|
||||||
|
// Texture Management
|
||||||
|
GLuint textu = 0;
|
||||||
|
std::mutex PreviewMutex;
|
||||||
|
bool updatePreview = false;
|
||||||
|
bool textureInitialized = false;
|
||||||
|
frame currentPreviewFrame;
|
||||||
|
int outWidth = 512;
|
||||||
|
int outHeight = 512;
|
||||||
|
float fps = 60;
|
||||||
|
int rayCount = 3;
|
||||||
|
int reflectCount = 4;
|
||||||
|
bool slowRender = false;
|
||||||
|
float lodDist = 4096.0f;
|
||||||
|
float lodDropoff = 0.001f;
|
||||||
|
bool globalIllumination = false;
|
||||||
|
bool useLod = true;
|
||||||
|
std::map<int, bool> keyStates;
|
||||||
|
float deltaTime = 0.16f;
|
||||||
|
bool orbitEquator = false;
|
||||||
|
float rotationRadius = 2500;
|
||||||
|
float angle = 0.0f;
|
||||||
|
const float ω = (std::pow(M_PI, 2) / 30) / 10;
|
||||||
|
|
||||||
|
public:
|
||||||
|
planetSimUI() {
|
||||||
|
cam.origin = v3(4000, 4000, 4000);
|
||||||
|
cam.direction = (v3(0,0,0) - cam.origin).normalized();
|
||||||
|
cam.up = v3(0,1,0);
|
||||||
|
cam.fov = 60;
|
||||||
|
cam.rotationSpeed = M_1_PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
~planetSimUI() {
|
||||||
|
if (textu != 0) {
|
||||||
|
glDeleteTextures(1, &textu);
|
||||||
|
}
|
||||||
|
sim.grid.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderUI(GLFWwindow* window) {
|
||||||
|
ImGui::Begin("Planet Simulation");
|
||||||
|
if (orbitEquator) {
|
||||||
|
angle += cam.rotationSpeed * deltaTime * ω;
|
||||||
|
|
||||||
|
cam.origin[0] = sim.config.center[0] + rotationRadius * cosf(angle);
|
||||||
|
cam.origin[1] = sim.config.center[1];
|
||||||
|
cam.origin[2] = sim.config.center[2] + rotationRadius * sinf(angle);
|
||||||
|
|
||||||
|
v3 target(sim.config.center);
|
||||||
|
cam.direction = (target - cam.origin).normalized();
|
||||||
|
}
|
||||||
|
glfwPollEvents();
|
||||||
|
for (int i = GLFW_KEY_SPACE; i <= GLFW_KEY_LAST; i++) {
|
||||||
|
keyStates[i] = (glfwGetKey(window, i) == GLFW_PRESS);
|
||||||
|
}
|
||||||
|
if (keyStates[GLFW_KEY_W]) cam.moveForward(deltaTime);
|
||||||
|
if (keyStates[GLFW_KEY_S]) cam.moveBackward(deltaTime);
|
||||||
|
if (keyStates[GLFW_KEY_A]) cam.moveLeft(deltaTime);
|
||||||
|
if (keyStates[GLFW_KEY_D]) cam.moveRight(deltaTime);
|
||||||
|
if (keyStates[GLFW_KEY_Z]) cam.moveUp(deltaTime);
|
||||||
|
if (keyStates[GLFW_KEY_X]) cam.moveDown(deltaTime);
|
||||||
|
if (keyStates[GLFW_KEY_Q]) cam.rotateYaw(deltaTime);
|
||||||
|
if (keyStates[GLFW_KEY_R]) cam.rotateYaw(-deltaTime);
|
||||||
|
|
||||||
|
if (ImGui::CollapsingHeader("Base Configuration", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||||
|
ImGui::DragFloat("Radius", &sim.config.radius, 1.0f, 10.0f, 10000.0f);
|
||||||
|
ImGui::InputInt("Surface Points", &sim.config.surfacePoints);
|
||||||
|
ImGui::DragFloat("Voxel Size", &sim.config.voxelSize, 0.1f, 0.1f, 100.0f);
|
||||||
|
ImGui::ColorEdit3("Base Color", sim.config.color.data());
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
if (ImGui::Button("1. Generate Fib Sphere", ImVec2(-1, 40))) {
|
||||||
|
sim.generateFibSphere();
|
||||||
|
}
|
||||||
|
ImGui::Text("Current Step: %d", sim.config.currentStep);
|
||||||
|
ImGui::Text("Nodes: %zu", sim.config.surfaceNodes.size());
|
||||||
|
}
|
||||||
|
if (ImGui::Button("Apply Tectonics")) {
|
||||||
|
simulateTectonics();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::CollapsingHeader("Physics Parameters")) {
|
||||||
|
ImGui::DragFloat("Gravity (G)", &sim.config.G_ATTRACTION, 0.1f);
|
||||||
|
ImGui::DragFloat("Time Step", &sim.config.TIMESTEP, 0.001f, 0.0001f, 0.1f);
|
||||||
|
ImGui::DragFloat("Viscosity", &sim.config.dampingFactor, 0.001f, 0.0f, 1.0f);
|
||||||
|
ImGui::DragFloat("Pressure Stiffness", &sim.config.pressureStiffness, 10.0f);
|
||||||
|
ImGui::DragInt("Num Plates", &sim.config.numPlates, 1, 1, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::CollapsingHeader("Tectonic Simulation")) {
|
||||||
|
ImGui::DragInt("Num Plates", &sim.config.numPlates, 1, 1, 100);
|
||||||
|
ImGui::DragFloat("Plate Randomness", &sim.config.plateRandom, 0.01f, 0.0f, 2.0f);
|
||||||
|
ImGui::DragInt("Smoothing Passes", &sim.config.smoothingPasses, 1, 0, 10);
|
||||||
|
ImGui::DragFloat("Mountain Height", &sim.config.mountHeight, 1.0f, 0.0f, 1000.0f);
|
||||||
|
ImGui::DragFloat("Valley Depth", &sim.config.valleyDepth, 1.0f, -1000.0f, 0.0f);
|
||||||
|
ImGui::DragFloat("Transform Roughness", &sim.config.transformRough, 1.0f, 0.0f, 500.0f);
|
||||||
|
ImGui::DragInt("Stress Passes", &sim.config.stressPasses, 1, 0, 20);
|
||||||
|
|
||||||
|
if (ImGui::Button("2. Simulate Tectonics", ImVec2(-1, 40))) {
|
||||||
|
simulateTectonics();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::CollapsingHeader("Camera Controls")) {
|
||||||
|
ImGui::DragFloat3("Origin", cam.origin.data());
|
||||||
|
ImGui::DragFloat3("Direction", cam.direction.data(), 0.0001f, -1.0f, 1.0f);
|
||||||
|
ImGui::DragFloat("Movement Speed", &cam.movementSpeed, 0.1f, 1.0f, 500.0f);
|
||||||
|
ImGui::DragFloat("Rotation Speed", &cam.rotationSpeed, M_1_PI, M_1_PI, M_PI);
|
||||||
|
ImGui::InputFloat("Rotation Distance", &rotationRadius, 10, 100);
|
||||||
|
|
||||||
|
ImGui::Checkbox("Use Slower Render", &slowRender);
|
||||||
|
|
||||||
|
if (ImGui::Button("Focus on Planet")) {
|
||||||
|
v3 target(sim.config.center);
|
||||||
|
v3 newDir = (target - cam.origin).normalized();
|
||||||
|
cam.direction = newDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::Button(orbitEquator ? "Stop Equator" : "Orbit Equator")) orbitEquator = !orbitEquator;
|
||||||
|
}
|
||||||
|
|
||||||
|
livePreview();
|
||||||
|
if (textureInitialized) {
|
||||||
|
float aspect = (float)currentPreviewFrame.getWidth() / (float)currentPreviewFrame.getHeight();
|
||||||
|
float availWidth = ImGui::GetContentRegionAvail().x;
|
||||||
|
ImGui::Image((void*)(intptr_t)textu, ImVec2(availWidth, availWidth / aspect));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void applyNoise(const NoisePreviewState& noiseState) {
|
||||||
|
TIME_FUNCTION;
|
||||||
|
auto triplanarNoise = [&](const Eigen::Vector3f& pos) -> float {
|
||||||
|
PNoise2 gen(noiseState.masterSeed);
|
||||||
|
|
||||||
|
Eigen::Vector3f n = pos.normalized();
|
||||||
|
Eigen::Vector3f blend = n.cwiseAbs();
|
||||||
|
float sum = blend.x() + blend.y() + blend.z();
|
||||||
|
blend /= sum;
|
||||||
|
|
||||||
|
Eigen::Vector3f offsetPos = pos + Eigen::Vector3f(noiseState.offset[0], noiseState.offset[1], 0.0f);
|
||||||
|
float vXY = sim.evaluate2DStack(Eigen::Vector2f(offsetPos.x(), offsetPos.y()), noiseState, gen);
|
||||||
|
float vXZ = sim.evaluate2DStack(Eigen::Vector2f(offsetPos.x(), offsetPos.z()), noiseState, gen);
|
||||||
|
float vYZ = sim.evaluate2DStack(Eigen::Vector2f(offsetPos.y(), offsetPos.z()), noiseState, gen);
|
||||||
|
|
||||||
|
// Blend results
|
||||||
|
return vYZ * blend.x() + vXZ * blend.y() + vXY * blend.z();
|
||||||
|
};
|
||||||
|
sim._applyNoise(triplanarNoise);
|
||||||
|
}
|
||||||
|
|
||||||
|
void livePreview() {
|
||||||
|
std::lock_guard<std::mutex> lock(PreviewMutex);
|
||||||
|
updatePreview = true;
|
||||||
|
|
||||||
|
sim.grid.setLODMinDistance(lodDist);
|
||||||
|
sim.grid.setLODFalloff(lodDropoff);
|
||||||
|
|
||||||
|
if (slowRender) {
|
||||||
|
currentPreviewFrame = sim.grid.renderFrame(cam, outWidth, outHeight, frame::colormap::RGB, rayCount, reflectCount, globalIllumination, useLod);
|
||||||
|
} else {
|
||||||
|
currentPreviewFrame = sim.grid.fastRenderFrame(cam, outWidth, outHeight, frame::colormap::RGB);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (textu == 0) {
|
||||||
|
glGenTextures(1, &textu);
|
||||||
|
}
|
||||||
|
glBindTexture(GL_TEXTURE_2D, textu);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, currentPreviewFrame.getWidth(), currentPreviewFrame.getHeight(),
|
||||||
|
0, GL_RGB, GL_UNSIGNED_BYTE, currentPreviewFrame.getData().data());
|
||||||
|
|
||||||
|
updatePreview = false;
|
||||||
|
textureInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetView() {
|
||||||
|
cam.origin = Vector3f(sim.config.gridSizeCube, sim.config.gridSizeCube, sim.config.gridSizeCube);
|
||||||
|
Vector3f center(sim.config.gridSizeCube / 2.0f, sim.config.gridSizeCube / 2.0f, sim.config.gridSizeCube / 2.0f);
|
||||||
|
cam.lookAt(center);
|
||||||
|
}
|
||||||
|
|
||||||
|
void simulateTectonics() {
|
||||||
|
sim.assignSeeds();
|
||||||
|
// sim.growPlatesCellular();
|
||||||
|
sim.growPlatesRandom();
|
||||||
|
//sim.fixBoundaries();
|
||||||
|
sim.extraplateste();
|
||||||
|
sim.finalizeApplyResults();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
138
tests/ptest.cpp
Normal file
138
tests/ptest.cpp
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// Include GLAD/GLFW
|
||||||
|
// Ensure these are in your include path
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
// ImGui
|
||||||
|
#include "imgui.h"
|
||||||
|
#include "imgui_impl_glfw.h"
|
||||||
|
#include "imgui_impl_opengl3.h"
|
||||||
|
|
||||||
|
// Include your implementation files
|
||||||
|
// (Unity build style as requested)
|
||||||
|
#include "../util/noise/pnoise.cpp"
|
||||||
|
#include "planet.cpp"
|
||||||
|
#include "../util/basicdefines.hpp"
|
||||||
|
|
||||||
|
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
|
||||||
|
glViewport(0, 0, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void glfw_error_callback(int error, const char* description)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "GLFW Error %d: %s\n", error, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
glfwSetErrorCallback(glfw_error_callback);
|
||||||
|
if (!glfwInit())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
#if defined(IMGUI_IMPL_OPENGL_ES2)
|
||||||
|
// GL ES 2.0 + GLSL 100 (WebGL 1.0)
|
||||||
|
const char* glsl_version = "#version 100";
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||||
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
|
||||||
|
#elif defined(IMGUI_IMPL_OPENGL_ES3)
|
||||||
|
// GL ES 3.0 + GLSL 300 es (WebGL 2.0)
|
||||||
|
const char* glsl_version = "#version 300 es";
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||||
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
// GL 3.2 + GLSL 150
|
||||||
|
const char* glsl_version = "#version 150";
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
||||||
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
|
||||||
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac
|
||||||
|
#else
|
||||||
|
// GL 3.0 + GLSL 130
|
||||||
|
const char* glsl_version = "#version 130";
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||||
|
//glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
|
||||||
|
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // 3.0+ only
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool application_not_closed = true;
|
||||||
|
GLFWwindow* window = glfwCreateWindow((int)(1280), (int)(800), "StupidSim", nullptr, nullptr);
|
||||||
|
if (window == nullptr) {
|
||||||
|
glfwTerminate();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
glfwMakeContextCurrent(window);
|
||||||
|
glfwSwapInterval(1);
|
||||||
|
IMGUI_CHECKVERSION();
|
||||||
|
ImGui::CreateContext();
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
(void)io;
|
||||||
|
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||||
|
ImGui::StyleColorsDark();
|
||||||
|
ImGuiStyle& style = ImGui::GetStyle();
|
||||||
|
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
ImGui_ImplGlfw_InstallEmscriptenCallbacks(window, "#canvas");
|
||||||
|
#endif
|
||||||
|
ImGui_ImplOpenGL3_Init(glsl_version);
|
||||||
|
|
||||||
|
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||||
|
|
||||||
|
planetSimUI planetApp;
|
||||||
|
NoisePreviewState noiseState;
|
||||||
|
|
||||||
|
if (noiseState.layers.empty()) {
|
||||||
|
NoiseLayer defaultLayer;
|
||||||
|
strcpy(defaultLayer.name, "Base Terrain");
|
||||||
|
defaultLayer.type = NoiseType::Fractal;
|
||||||
|
noiseState.layers.push_back(defaultLayer);
|
||||||
|
}
|
||||||
|
updateNoiseTexture(noiseState);
|
||||||
|
|
||||||
|
while (!glfwWindowShouldClose(window)) {
|
||||||
|
glfwPollEvents();
|
||||||
|
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
ImGui_ImplOpenGL3_NewFrame();
|
||||||
|
ImGui_ImplGlfw_NewFrame();
|
||||||
|
ImGui::NewFrame();
|
||||||
|
|
||||||
|
ImGui::GetMainViewport();
|
||||||
|
drawNoiseLab(noiseState);
|
||||||
|
planetApp.renderUI(window);
|
||||||
|
|
||||||
|
ImGui::Begin("Integration Control");
|
||||||
|
ImGui::Text("Bridge: Noise Lab -> Planet Sim");
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
ImGui::TextColored(ImVec4(0.5f, 0.8f, 1.0f, 1.0f), "Current Noise Layers: %zu", noiseState.layers.size());
|
||||||
|
|
||||||
|
if (ImGui::Button("APPLY CURRENT NOISE TO PLANET", ImVec2(-1, 50))) {
|
||||||
|
planetApp.applyNoise(noiseState);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::End();
|
||||||
|
|
||||||
|
ImGui::Render();
|
||||||
|
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||||
|
|
||||||
|
glfwSwapBuffers(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui_ImplOpenGL3_Shutdown();
|
||||||
|
ImGui_ImplGlfw_Shutdown();
|
||||||
|
ImGui::DestroyContext();
|
||||||
|
|
||||||
|
glfwDestroyWindow(window);
|
||||||
|
glfwTerminate();
|
||||||
|
|
||||||
|
FunctionTimer::printStats(FunctionTimer::Mode::ENHANCED);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -957,9 +957,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool set(const T& data, const PointType& pos, bool visible, Eigen::Vector3f color, float size, bool active,
|
bool set(const T& data, const PointType& pos, bool visible, Eigen::Vector3f color, float size, bool active,
|
||||||
int objectId = -1, bool light = false, float emittance = 0.0f, float refraction = 0.0f,
|
int objectId = -1, int subId = 0, bool light = false, float emittance = 0.0f, float refraction = 0.0f,
|
||||||
float reflection = 0.0f) {
|
float reflection = 0.0f) {
|
||||||
auto pointData = std::make_shared<NodeData>(data, pos, visible, color, size, active, objectId,
|
auto pointData = std::make_shared<NodeData>(data, pos, visible, color, size, active, objectId, subId,
|
||||||
light, emittance, refraction, reflection);
|
light, emittance, refraction, reflection);
|
||||||
if (insertRecursive(root_.get(), pointData, 0)) {
|
if (insertRecursive(root_.get(), pointData, 0)) {
|
||||||
this->size++;
|
this->size++;
|
||||||
@@ -1073,14 +1073,10 @@ public:
|
|||||||
|
|
||||||
if (!remove(oldPos, tolerance)) return false;
|
if (!remove(oldPos, tolerance)) return false;
|
||||||
|
|
||||||
bool res = set(newData, newPos,
|
bool res = set(newData, newPos, newVisible,
|
||||||
newVisible,
|
|
||||||
newColor != Eigen::Vector3f(1.0f, 1.0f, 1.0f) ? newColor : pointData->color,
|
newColor != Eigen::Vector3f(1.0f, 1.0f, 1.0f) ? newColor : pointData->color,
|
||||||
newSize > 0 ? newSize : pointData->size,
|
newSize > 0 ? newSize : pointData->size,
|
||||||
newActive,
|
newActive, targetObjId, finalSubId, newLight,
|
||||||
targetObjId,
|
|
||||||
finalSubId,
|
|
||||||
newLight,
|
|
||||||
newEmittance > 0 ? newEmittance : pointData->emittance,
|
newEmittance > 0 ? newEmittance : pointData->emittance,
|
||||||
newRefraction >= 0 ? newRefraction : pointData->refraction,
|
newRefraction >= 0 ? newRefraction : pointData->refraction,
|
||||||
newReflection >= 0 ? newReflection : pointData->reflection);
|
newReflection >= 0 ? newReflection : pointData->reflection);
|
||||||
|
|||||||
93
util/jsonhelper.hpp
Normal file
93
util/jsonhelper.hpp
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
#ifndef JSONHELPER_HPP
|
||||||
|
#define JSONHELPER_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
|
namespace JsonHelper {
|
||||||
|
|
||||||
|
// Helper to get string value between quotes
|
||||||
|
inline std::string parseString(const std::string& json, const std::string& key) {
|
||||||
|
size_t pos = json.find("\"" + key + "\"");
|
||||||
|
if (pos == std::string::npos) return "";
|
||||||
|
pos = json.find(":", pos);
|
||||||
|
if (pos == std::string::npos) return "";
|
||||||
|
size_t start = json.find("\"", pos);
|
||||||
|
if (start == std::string::npos) return "";
|
||||||
|
size_t end = json.find("\"", start + 1);
|
||||||
|
if (end == std::string::npos) return "";
|
||||||
|
return json.substr(start + 1, end - start - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to get raw non-string value (int, float, bool)
|
||||||
|
inline std::string parseRaw(const std::string& json, const std::string& key) {
|
||||||
|
size_t pos = json.find("\"" + key + "\"");
|
||||||
|
if (pos == std::string::npos) return "";
|
||||||
|
pos = json.find(":", pos);
|
||||||
|
if (pos == std::string::npos) return "";
|
||||||
|
pos++; // skip ':'
|
||||||
|
|
||||||
|
while (pos < json.length() && std::isspace(json[pos])) pos++;
|
||||||
|
size_t end = pos;
|
||||||
|
while (end < json.length() && json[end] != ',' && json[end] != '}' && json[end] != ']' && !std::isspace(json[end])) end++;
|
||||||
|
|
||||||
|
return json.substr(pos, end - pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int parseInt(const std::string& json, const std::string& key, int defaultVal = 0) {
|
||||||
|
std::string raw = parseRaw(json, key);
|
||||||
|
if (raw.empty()) return defaultVal;
|
||||||
|
try { return std::stoi(raw); } catch(...) { return defaultVal; }
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float parseFloat(const std::string& json, const std::string& key, float defaultVal = 0.0f) {
|
||||||
|
std::string raw = parseRaw(json, key);
|
||||||
|
if (raw.empty()) return defaultVal;
|
||||||
|
try { return std::stof(raw); } catch(...) { return defaultVal; }
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool parseBool(const std::string& json, const std::string& key, bool defaultVal = false) {
|
||||||
|
std::string raw = parseRaw(json, key);
|
||||||
|
if (raw.empty()) return defaultVal;
|
||||||
|
return raw == "true" || raw == "1";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to extract JSON objects out of a JSON array
|
||||||
|
inline std::vector<std::string> parseArray(const std::string& json, const std::string& key) {
|
||||||
|
std::vector<std::string> items;
|
||||||
|
size_t pos = json.find("\"" + key + "\"");
|
||||||
|
if (pos == std::string::npos) return items;
|
||||||
|
pos = json.find(":", pos);
|
||||||
|
if (pos == std::string::npos) return items;
|
||||||
|
pos = json.find("[", pos);
|
||||||
|
if (pos == std::string::npos) return items;
|
||||||
|
|
||||||
|
int depth = 0;
|
||||||
|
size_t start = 0;
|
||||||
|
bool inString = false;
|
||||||
|
|
||||||
|
for (size_t i = pos + 1; i < json.length(); ++i) {
|
||||||
|
if (json[i] == '"' && (i == 0 || json[i-1] != '\\')) {
|
||||||
|
inString = !inString;
|
||||||
|
}
|
||||||
|
if (!inString) {
|
||||||
|
if (json[i] == '{') {
|
||||||
|
if (depth == 0) start = i;
|
||||||
|
depth++;
|
||||||
|
} else if (json[i] == '}') {
|
||||||
|
depth--;
|
||||||
|
if (depth == 0) {
|
||||||
|
items.push_back(json.substr(start, i - start + 1));
|
||||||
|
}
|
||||||
|
} else if (json[i] == ']') {
|
||||||
|
if (depth == 0) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -6,8 +6,11 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "./pnoise2.hpp"
|
#include "./pnoise2.hpp"
|
||||||
|
#include "../jsonhelper.hpp"
|
||||||
#include "../timing_decorator.hpp"
|
#include "../timing_decorator.hpp"
|
||||||
#include "../../imgui/imgui.h"
|
#include "../../imgui/imgui.h"
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
@@ -194,11 +197,94 @@ inline void updateNoiseTexture(NoisePreviewState& state) {
|
|||||||
state.needsUpdate = false;
|
state.needsUpdate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void saveNoiseState(const NoisePreviewState& state, const std::string& filename) {
|
||||||
|
std::ofstream out(filename);
|
||||||
|
if (!out) return;
|
||||||
|
|
||||||
|
out << "{\n";
|
||||||
|
out << " \"masterSeed\": " << state.masterSeed << ",\n";
|
||||||
|
out << " \"offsetX\": " << state.offset[0] << ",\n";
|
||||||
|
out << " \"offsetY\": " << state.offset[1] << ",\n";
|
||||||
|
out << " \"layers\": [\n";
|
||||||
|
|
||||||
|
for (size_t i = 0; i < state.layers.size(); ++i) {
|
||||||
|
const auto& l = state.layers[i];
|
||||||
|
out << " {\n";
|
||||||
|
out << " \"enabled\": " << (l.enabled ? "true" : "false") << ",\n";
|
||||||
|
out << " \"name\": \"" << l.name << "\",\n";
|
||||||
|
out << " \"type\": " << (int)l.type << ",\n";
|
||||||
|
out << " \"blend\": " << (int)l.blend << ",\n";
|
||||||
|
out << " \"seedOffset\": " << l.seedOffset << ",\n";
|
||||||
|
out << " \"scale\": " << l.scale << ",\n";
|
||||||
|
out << " \"strength\": " << l.strength << ",\n";
|
||||||
|
out << " \"octaves\": " << l.octaves << ",\n";
|
||||||
|
out << " \"persistence\": " << l.persistence << ",\n";
|
||||||
|
out << " \"lacunarity\": " << l.lacunarity << ",\n";
|
||||||
|
out << " \"ridgeOffset\": " << l.ridgeOffset << "\n";
|
||||||
|
out << " }" << (i < state.layers.size() - 1 ? "," : "") << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
out << " ]\n";
|
||||||
|
out << "}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void loadNoiseState(NoisePreviewState& state, const std::string& filename) {
|
||||||
|
std::ifstream in(filename);
|
||||||
|
if (!in) return;
|
||||||
|
|
||||||
|
std::stringstream buffer;
|
||||||
|
buffer << in.rdbuf();
|
||||||
|
std::string json = buffer.str();
|
||||||
|
|
||||||
|
state.masterSeed = JsonHelper::parseInt(json, "masterSeed", 1337);
|
||||||
|
state.offset[0] = JsonHelper::parseFloat(json, "offsetX", 0.0f);
|
||||||
|
state.offset[1] = JsonHelper::parseFloat(json, "offsetY", 0.0f);
|
||||||
|
|
||||||
|
auto layerStrs = JsonHelper::parseArray(json, "layers");
|
||||||
|
state.layers.clear();
|
||||||
|
|
||||||
|
for (const auto& lStr : layerStrs) {
|
||||||
|
NoiseLayer l;
|
||||||
|
l.enabled = JsonHelper::parseBool(lStr, "enabled", true);
|
||||||
|
std::string name = JsonHelper::parseString(lStr, "name");
|
||||||
|
if (!name.empty()) {
|
||||||
|
std::strncpy(l.name, name.c_str(), 31);
|
||||||
|
l.name[31] = '\0';
|
||||||
|
}
|
||||||
|
l.type = (NoiseType)JsonHelper::parseInt(lStr, "type", 0);
|
||||||
|
l.blend = (BlendMode)JsonHelper::parseInt(lStr, "blend", 0);
|
||||||
|
l.seedOffset = JsonHelper::parseInt(lStr, "seedOffset", 0);
|
||||||
|
l.scale = JsonHelper::parseFloat(lStr, "scale", 0.02f);
|
||||||
|
l.strength = JsonHelper::parseFloat(lStr, "strength", 1.0f);
|
||||||
|
l.octaves = JsonHelper::parseInt(lStr, "octaves", 4);
|
||||||
|
l.persistence = JsonHelper::parseFloat(lStr, "persistence", 0.5f);
|
||||||
|
l.lacunarity = JsonHelper::parseFloat(lStr, "lacunarity", 2.0f);
|
||||||
|
l.ridgeOffset = JsonHelper::parseFloat(lStr, "ridgeOffset", 1.0f);
|
||||||
|
|
||||||
|
state.layers.push_back(l);
|
||||||
|
}
|
||||||
|
state.needsUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
inline void drawNoiseLab(NoisePreviewState& noiseState) {
|
inline void drawNoiseLab(NoisePreviewState& noiseState) {
|
||||||
ImGui::Begin("2D Noise Lab");
|
ImGui::Begin("2D Noise Lab");
|
||||||
|
|
||||||
// Master Controls
|
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
|
static char filenameBuffer[128] = "output/noise_preset.json";
|
||||||
|
ImGui::InputText("File", filenameBuffer, sizeof(filenameBuffer));
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Save JSON")) {
|
||||||
|
saveNoiseState(noiseState, filenameBuffer);
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Load JSON")) {
|
||||||
|
loadNoiseState(noiseState, filenameBuffer);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
changed |= ImGui::InputInt("Master Seed", &noiseState.masterSeed);
|
changed |= ImGui::InputInt("Master Seed", &noiseState.masterSeed);
|
||||||
changed |= ImGui::DragFloat2("Pan Offset", noiseState.offset, 1.0f);
|
changed |= ImGui::DragFloat2("Pan Offset", noiseState.offset, 1.0f);
|
||||||
|
|
||||||
@@ -254,7 +340,7 @@ inline void drawNoiseLab(NoisePreviewState& noiseState) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (open) {
|
if (open) {
|
||||||
ImGui::Checkbox("##enabled", &layer.enabled);
|
if (ImGui::Checkbox("##enabled", &layer.enabled)) changed = true;
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::InputText("##name", layer.name, 32);
|
ImGui::InputText("##name", layer.name, 32);
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <limits>
|
#include <limits>
|
||||||
#include "../../eigen/Eigen/Core"
|
#include "../../eigen/Eigen/Core"
|
||||||
#include "../timing_decorator.hpp"
|
#include "../timing_decorator.hpp"
|
||||||
|
#include "../basicdefines.hpp"
|
||||||
|
|
||||||
class PNoise2 {
|
class PNoise2 {
|
||||||
private:
|
private:
|
||||||
|
|||||||
315
util/sim/planet.hpp
Normal file
315
util/sim/planet.hpp
Normal file
@@ -0,0 +1,315 @@
|
|||||||
|
#ifndef PLANET_HPP
|
||||||
|
#define PLANET_HPP
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
#include <atomic>
|
||||||
|
#include <mutex>
|
||||||
|
#include <cmath>
|
||||||
|
#include <random>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <queue>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "../grid/grid3eigen.hpp"
|
||||||
|
#include "../timing_decorator.cpp"
|
||||||
|
|
||||||
|
#include "../imgui/imgui.h"
|
||||||
|
#include "../imgui/backends/imgui_impl_glfw.h"
|
||||||
|
#include "../imgui/backends/imgui_impl_opengl3.h"
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
#include "../stb/stb_image.h"
|
||||||
|
|
||||||
|
using v3 = Eigen::Vector3f;
|
||||||
|
const float Φ = M_PI * (3.0f - std::sqrt(5.0f));
|
||||||
|
|
||||||
|
enum class PlateType {
|
||||||
|
CONTINENTAL,
|
||||||
|
OCEANIC,
|
||||||
|
MIXED
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Particle {
|
||||||
|
float noiseDisplacement = 0.0f;
|
||||||
|
int plateID = -1;
|
||||||
|
Eigen::Vector3f basePos;
|
||||||
|
Eigen::Vector3f currentPos;
|
||||||
|
float plateDisplacement = 0.0f;
|
||||||
|
float temperature = -1;
|
||||||
|
float water = -1;
|
||||||
|
Eigen::Vector3f originColor;
|
||||||
|
bool surface = false;
|
||||||
|
|
||||||
|
//gravity factors:
|
||||||
|
Eigen::Matrix<float, 3, 1> velocity;
|
||||||
|
Eigen::Matrix<float, 3, 1> acceleration;
|
||||||
|
Eigen::Matrix<float, 3, 1> forceAccumulator;
|
||||||
|
float density = 0.0f;
|
||||||
|
float pressure = 0.0f;
|
||||||
|
Eigen::Matrix<float, 3, 1> pressureForce;
|
||||||
|
float viscosity = 0.5f;
|
||||||
|
Eigen::Matrix<float, 3, 1> viscosityForce;
|
||||||
|
float restitution = 5.0f;
|
||||||
|
float mass;
|
||||||
|
bool isStatic = false;
|
||||||
|
float soundSpeed = 100.0f;
|
||||||
|
|
||||||
|
std::unordered_map<int, float> neighbors;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct planetConfig {
|
||||||
|
Eigen::Vector3f center = Eigen::Vector3f(0,0,0);
|
||||||
|
float radius = 1024.0f;
|
||||||
|
Eigen::Vector3f color = Eigen::Vector3f(0, 1, 0);
|
||||||
|
|
||||||
|
float voxelSize = 10.0f;
|
||||||
|
int surfacePoints = 50000;
|
||||||
|
|
||||||
|
int currentStep = 0;
|
||||||
|
|
||||||
|
float displacementStrength = 200.0f;
|
||||||
|
std::vector<Particle> surfaceNodes;
|
||||||
|
float noiseStrength = 1.0f;
|
||||||
|
int numPlates = 15;
|
||||||
|
float plateRandom = 0.6f;
|
||||||
|
int smoothingPasses = 3;
|
||||||
|
float mountHeight = 250.0f;
|
||||||
|
float valleyDepth = -150.0f;
|
||||||
|
float transformRough = 80.0f;
|
||||||
|
int stressPasses = 5;
|
||||||
|
float maxElevationRatio = 0.25f;
|
||||||
|
float gridSizeCube = 16384;
|
||||||
|
float SMOOTHING_RADIUS = 1024.0f;
|
||||||
|
float REST_DENSITY = 0.00005f;
|
||||||
|
float TIMESTEP = 0.016f;
|
||||||
|
float G_ATTRACTION = 50.0f;
|
||||||
|
float gravitySoftening = 10.0f;
|
||||||
|
float pressureStiffness = 50000.0f;
|
||||||
|
float coreRepulsionRadius = 1000.0f;
|
||||||
|
float coreRepulsionStiffness = 100000.0f;
|
||||||
|
float dampingFactor = 0.98f;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PlateConfig {
|
||||||
|
int plateId;
|
||||||
|
Eigen::Vector3f plateEulerPole;
|
||||||
|
Eigen::Vector3f direction;
|
||||||
|
float angularVelocity;
|
||||||
|
float thickness;
|
||||||
|
float density;
|
||||||
|
float rigidity;
|
||||||
|
float temperature;
|
||||||
|
Eigen::Vector3f debugColor;
|
||||||
|
PlateType ptype;
|
||||||
|
};
|
||||||
|
|
||||||
|
class planetsim {
|
||||||
|
public:
|
||||||
|
planetConfig config;
|
||||||
|
Octree<Particle> grid;
|
||||||
|
std::vector<PlateConfig> plates;
|
||||||
|
std::mt19937 rng = std::mt19937(42);
|
||||||
|
|
||||||
|
planetsim() {
|
||||||
|
config = planetConfig();
|
||||||
|
grid = Octree<Particle>({-config.gridSizeCube,-config.gridSizeCube,-config.gridSizeCube,},{config.gridSizeCube,config.gridSizeCube,config.gridSizeCube});
|
||||||
|
}
|
||||||
|
|
||||||
|
float evaluate2DStack(const Eigen::Vector2f& point, const NoisePreviewState& state, PNoise2& gen) {
|
||||||
|
float finalValue = 0.0f;
|
||||||
|
Eigen::Vector2f p = point;
|
||||||
|
|
||||||
|
for (const auto& layer : state.layers) {
|
||||||
|
if (!layer.enabled) continue;
|
||||||
|
|
||||||
|
Eigen::Vector2f samplePoint = p * layer.scale;
|
||||||
|
|
||||||
|
samplePoint += Eigen::Vector2f((float)layer.seedOffset * 10.5f, (float)layer.seedOffset * -10.5f);
|
||||||
|
|
||||||
|
if (layer.blend == BlendMode::DomainWarp) {
|
||||||
|
if (layer.type == NoiseType::CurlNoise) {
|
||||||
|
Eigen::Vector2f flow = gen.curlNoise(samplePoint);
|
||||||
|
p += flow * layer.strength * 100.0f;
|
||||||
|
} else {
|
||||||
|
float warpX = sampleNoiseLayer(gen, layer.type, samplePoint, layer);
|
||||||
|
float warpY = sampleNoiseLayer(gen, layer.type, samplePoint + Eigen::Vector2f(5.2f, 1.3f), layer);
|
||||||
|
p += Eigen::Vector2f(warpX, warpY) * layer.strength * 100.0f;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
float nVal = sampleNoiseLayer(gen, layer.type, samplePoint, layer);
|
||||||
|
|
||||||
|
switch (layer.blend) {
|
||||||
|
case BlendMode::Replace: finalValue = nVal * layer.strength; break;
|
||||||
|
case BlendMode::Add: finalValue += nVal * layer.strength; break;
|
||||||
|
case BlendMode::Subtract: finalValue -= nVal * layer.strength; break;
|
||||||
|
case BlendMode::Multiply: finalValue *= (nVal * layer.strength); break;
|
||||||
|
case BlendMode::Max: finalValue = std::max(finalValue, nVal * layer.strength); break;
|
||||||
|
case BlendMode::Min: finalValue = std::min(finalValue, nVal * layer.strength); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float norm = std::tanh(finalValue);
|
||||||
|
return norm;
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateFibSphere() {
|
||||||
|
TIME_FUNCTION;
|
||||||
|
grid.clear();
|
||||||
|
config.surfaceNodes.clear();
|
||||||
|
for (int i = 0; i < config.surfacePoints; i++) {
|
||||||
|
float y = 1.0f - (i * 2.0f) / (config.surfacePoints - 1);
|
||||||
|
float radiusY = std::sqrt(1.0f- y * y);
|
||||||
|
float Θ = Φ * i;
|
||||||
|
float x = std::cos(Θ) * radiusY;
|
||||||
|
float z = std::sin(Θ) * radiusY;
|
||||||
|
|
||||||
|
v3 dir(x, y, z);
|
||||||
|
v3 pos = config.center + dir * config.radius;
|
||||||
|
Particle pt;
|
||||||
|
pt.basePos = pos;
|
||||||
|
pt.currentPos = pos;
|
||||||
|
pt.originColor = config.color;
|
||||||
|
pt.noiseDisplacement = 0.0f;
|
||||||
|
pt.surface = true;
|
||||||
|
config.surfaceNodes.emplace_back(pt);
|
||||||
|
grid.set(pt, pt.currentPos, true, pt.originColor, config.voxelSize, true, 1, 0, false, 0.0f, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
config.currentStep = 1;
|
||||||
|
std::cout << "Step 1 done. base sphere generated" << std::endl;
|
||||||
|
buildAdjacencyList();
|
||||||
|
grid.save("output/fibSphere");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void _applyNoise(std::function<float(const Eigen::Vector3f&)> noiseFunc) {
|
||||||
|
for (auto& p : config.surfaceNodes) {
|
||||||
|
Eigen::Vector3f oldPos = p.currentPos;
|
||||||
|
float displacementValue = noiseFunc(p.basePos);
|
||||||
|
p.noiseDisplacement = displacementValue;
|
||||||
|
Eigen::Vector3f normal = p.basePos.normalized();
|
||||||
|
p.currentPos = p.basePos + (normal * displacementValue * config.displacementStrength);
|
||||||
|
|
||||||
|
grid.update(oldPos, p.currentPos, p, true, p.originColor, config.voxelSize, true, -2, false, 0.0f, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void assignSeeds() {
|
||||||
|
plates.clear();
|
||||||
|
plates.resize(config.numPlates);
|
||||||
|
float sphereSurfaceArea = 4.0f * M_PI * config.radius * config.radius;
|
||||||
|
float averageAreaPerPlate = sphereSurfaceArea / config.numPlates;
|
||||||
|
float minDistance = std::sqrt(averageAreaPerPlate) * 0.4f;
|
||||||
|
std::vector<int> selectedSeedIndices;
|
||||||
|
std::uniform_int_distribution<int> distNode(0, config.surfaceNodes.size() - 1);
|
||||||
|
for (int i = 0; i < config.numPlates; ++i) {
|
||||||
|
int attempts = 1000;
|
||||||
|
bool foundValidSeed = false;
|
||||||
|
int seedid = distNode(rng);
|
||||||
|
plates[i].plateId = i;
|
||||||
|
|
||||||
|
|
||||||
|
while (!foundValidSeed && attempts > 0) {
|
||||||
|
int seedIndex = distNode(rng);
|
||||||
|
|
||||||
|
bool tooClose = false;
|
||||||
|
for (int selectedIndex : selectedSeedIndices) {
|
||||||
|
const auto& existingSeed = config.surfaceNodes[selectedIndex];
|
||||||
|
const auto& candidateSeed = config.surfaceNodes[seedIndex];
|
||||||
|
|
||||||
|
float dot = existingSeed.basePos.normalized().dot(candidateSeed.basePos.normalized());
|
||||||
|
float angle = std::acos(std::clamp(dot, -1.0f, 1.0f));
|
||||||
|
float distanceOnSphere = angle * config.radius;
|
||||||
|
|
||||||
|
if (distanceOnSphere < minDistance) {
|
||||||
|
tooClose = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tooClose || selectedSeedIndices.empty()) {
|
||||||
|
selectedSeedIndices.push_back(seedIndex);
|
||||||
|
plates[i].plateId = i;
|
||||||
|
config.surfaceNodes[seedIndex].plateID = i;
|
||||||
|
float colorVal = static_cast<float>(seedid) / config.surfaceNodes.size();
|
||||||
|
plates[i].debugColor = v3(colorVal,colorVal,colorVal);
|
||||||
|
foundValidSeed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
attempts--;
|
||||||
|
}
|
||||||
|
if (!foundValidSeed) {
|
||||||
|
int seedIndex = distNode(rng);
|
||||||
|
selectedSeedIndices.push_back(seedIndex);
|
||||||
|
plates[i].plateId = i;
|
||||||
|
float colorVal = static_cast<float>(seedIndex) / config.surfaceNodes.size();
|
||||||
|
plates[i].debugColor = v3(colorVal,colorVal,colorVal);
|
||||||
|
config.surfaceNodes[seedIndex].plateID = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void buildAdjacencyList() {
|
||||||
|
TIME_FUNCTION;
|
||||||
|
for (int i = 0; i < config.surfaceNodes.size(); i++) {
|
||||||
|
Particle in = config.surfaceNodes[i];
|
||||||
|
v3 inn = in.basePos.normalized();
|
||||||
|
for (int j = 1; j < config.surfaceNodes.size(); j++) {
|
||||||
|
if (i == j) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto ij = config.surfaceNodes[j];
|
||||||
|
if (ij.neighbors.contains(i)){
|
||||||
|
in.neighbors[j] = ij.neighbors[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
v3 ijn = ij.basePos.normalized();
|
||||||
|
float cosangle = inn.dot(ijn);
|
||||||
|
float angle = std::acos(cosangle);
|
||||||
|
|
||||||
|
in.neighbors[j] = angle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void growPlatesRandom() {
|
||||||
|
TIME_FUNCTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
void growPlatesCellular() {
|
||||||
|
TIME_FUNCTION;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void fixBoundaries() {
|
||||||
|
TIME_FUNCTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
void extraplateste() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void boundaryStress() {
|
||||||
|
TIME_FUNCTION;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void finalizeApplyResults() {
|
||||||
|
TIME_FUNCTION;
|
||||||
|
float maxAllowedDisp = config.radius * config.maxElevationRatio;
|
||||||
|
|
||||||
|
for (auto& p : config.surfaceNodes) {
|
||||||
|
Eigen::Vector3f oldPos = p.currentPos;
|
||||||
|
grid.update(oldPos, p.currentPos, p, true, plates[p.plateID].debugColor, config.voxelSize, true, -2, false, 0.0f, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
std::cout << "Finalize apply results completed." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user