woops
This commit is contained in:
1
glm
Submodule
1
glm
Submodule
Submodule glm added at 8f6213d379
322
latlonv.cpp
322
latlonv.cpp
@@ -1,322 +0,0 @@
|
|||||||
#include <imgui.h>
|
|
||||||
#include <imgui_impl_glfw.h>
|
|
||||||
#include <imgui_impl_opengl3.h>
|
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
#include <vector>
|
|
||||||
#include <cmath>
|
|
||||||
#include <random>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
struct Voxel {
|
|
||||||
float density;
|
|
||||||
unsigned char material; // 0: air, 1: rock, 2: dirt, 3: grass
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PlanetConfig {
|
|
||||||
int resolution = 64;
|
|
||||||
float radius = 10.0f;
|
|
||||||
float noiseScale = 0.1f;
|
|
||||||
float amplitude = 1.0f;
|
|
||||||
int seed = 42;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SphericalVoxelPlanet {
|
|
||||||
private:
|
|
||||||
std::vector<Voxel> voxels;
|
|
||||||
PlanetConfig config;
|
|
||||||
std::vector<float> distanceField;
|
|
||||||
GLuint textureID;
|
|
||||||
|
|
||||||
public:
|
|
||||||
SphericalVoxelPlanet() : textureID(0) {
|
|
||||||
generate();
|
|
||||||
}
|
|
||||||
|
|
||||||
~SphericalVoxelPlanet() {
|
|
||||||
if (textureID) {
|
|
||||||
glDeleteTextures(1, &textureID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert spherical to Cartesian coordinates
|
|
||||||
static glm::vec3 sphericalToCartesian(float lat, float lon, float dist) {
|
|
||||||
float latRad = glm::radians(lat);
|
|
||||||
float lonRad = glm::radians(lon);
|
|
||||||
return glm::vec3(
|
|
||||||
dist * cos(latRad) * cos(lonRad),
|
|
||||||
dist * cos(latRad) * sin(lonRad),
|
|
||||||
dist * sin(latRad)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3D noise function for spherical coordinates
|
|
||||||
float sphericalNoise(float lat, float lon, float r, int seed) {
|
|
||||||
glm::vec3 pos = sphericalToCartesian(lat, lon, 1.0f);
|
|
||||||
pos *= config.noiseScale;
|
|
||||||
pos.x += seed;
|
|
||||||
|
|
||||||
// Simple noise function
|
|
||||||
float fx = pos.x * 12.9898f + pos.y * 78.233f + pos.z * 137.631f;
|
|
||||||
return glm::fract(sin(fx) * 43758.5453f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void generate() {
|
|
||||||
int res = config.resolution;
|
|
||||||
voxels.resize(res * res * res);
|
|
||||||
distanceField.resize(res * res * res);
|
|
||||||
|
|
||||||
float latStep = 180.0f / res;
|
|
||||||
float lonStep = 360.0f / res;
|
|
||||||
float distStep = config.radius * 2.0f / res;
|
|
||||||
|
|
||||||
for (int i = 0; i < res; i++) { // latitude
|
|
||||||
float lat = -90.0f + i * latStep;
|
|
||||||
float latRad = glm::radians(lat);
|
|
||||||
|
|
||||||
for (int j = 0; j < res; j++) { // longitude
|
|
||||||
float lon = j * lonStep;
|
|
||||||
|
|
||||||
for (int k = 0; k < res; k++) { // distance from center
|
|
||||||
float dist = k * distStep;
|
|
||||||
float normalizedDist = dist / (config.radius * 2.0f);
|
|
||||||
|
|
||||||
int idx = i * res * res + j * res + k;
|
|
||||||
|
|
||||||
// Base density (sphere)
|
|
||||||
float baseDensity = config.radius - dist;
|
|
||||||
|
|
||||||
// Add noise based on latitude and longitude
|
|
||||||
float noise = sphericalNoise(lat, lon, dist, config.seed);
|
|
||||||
float altitude = 1.0f - std::abs(lat / 90.0f); // Poles are higher
|
|
||||||
|
|
||||||
float finalDensity = baseDensity + noise * config.amplitude * altitude;
|
|
||||||
|
|
||||||
distanceField[idx] = finalDensity;
|
|
||||||
|
|
||||||
// Assign material based on density and position
|
|
||||||
if (finalDensity > 0.5f) {
|
|
||||||
if (k > res * 0.9f) { // Surface
|
|
||||||
voxels[idx].material = 3; // Grass
|
|
||||||
} else if (k > res * 0.7f) {
|
|
||||||
voxels[idx].material = 2; // Dirt
|
|
||||||
} else {
|
|
||||||
voxels[idx].material = 1; // Rock
|
|
||||||
}
|
|
||||||
voxels[idx].density = 1.0f;
|
|
||||||
} else {
|
|
||||||
voxels[idx].material = 0; // Air
|
|
||||||
voxels[idx].density = 0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateTexture();
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateTexture() {
|
|
||||||
int res = config.resolution;
|
|
||||||
std::vector<unsigned char> textureData(res * res * res * 3);
|
|
||||||
|
|
||||||
for (int i = 0; i < res; i++) {
|
|
||||||
for (int j = 0; j < res; j++) {
|
|
||||||
for (int k = 0; k < res; k++) {
|
|
||||||
int idx = i * res * res + j * res + k;
|
|
||||||
int texIdx = (i * res * res + j * res + k) * 3;
|
|
||||||
|
|
||||||
switch (voxels[idx].material) {
|
|
||||||
case 0: // Air
|
|
||||||
textureData[texIdx] = 0;
|
|
||||||
textureData[texIdx + 1] = 0;
|
|
||||||
textureData[texIdx + 2] = 0;
|
|
||||||
break;
|
|
||||||
case 1: // Rock
|
|
||||||
textureData[texIdx] = 100;
|
|
||||||
textureData[texIdx + 1] = 100;
|
|
||||||
textureData[texIdx + 2] = 100;
|
|
||||||
break;
|
|
||||||
case 2: // Dirt
|
|
||||||
textureData[texIdx] = 101;
|
|
||||||
textureData[texIdx + 1] = 67;
|
|
||||||
textureData[texIdx + 2] = 33;
|
|
||||||
break;
|
|
||||||
case 3: // Grass
|
|
||||||
textureData[texIdx] = 34;
|
|
||||||
textureData[texIdx + 1] = 139;
|
|
||||||
textureData[texIdx + 2] = 34;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (textureID == 0) {
|
|
||||||
glGenTextures(1, &textureID);
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_3D, textureID);
|
|
||||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, res, res, res, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderUI() {
|
|
||||||
ImGui::Begin("Planet Generator");
|
|
||||||
|
|
||||||
if (ImGui::SliderInt("Resolution", &config.resolution, 32, 128)) {
|
|
||||||
generate();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::SliderFloat("Radius", &config.radius, 5.0f, 20.0f)) {
|
|
||||||
generate();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::SliderFloat("Noise Scale", &config.noiseScale, 0.01f, 0.5f)) {
|
|
||||||
generate();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::SliderFloat("Amplitude", &config.amplitude, 0.0f, 3.0f)) {
|
|
||||||
generate();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::SliderInt("Seed", &config.seed, 0, 1000)) {
|
|
||||||
generate();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::Button("Randomize Seed")) {
|
|
||||||
config.seed = rand() % 1000;
|
|
||||||
generate();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderPlanet() {
|
|
||||||
// Simple raycasting visualization using distance field
|
|
||||||
// This is a basic implementation - for better results, implement proper raycasting
|
|
||||||
ImDrawList* drawList = ImGui::GetBackgroundDrawList();
|
|
||||||
ImVec2 center = ImGui::GetIO().DisplaySize * 0.5f;
|
|
||||||
float displaySize = std::min(ImGui::GetIO().DisplaySize.x, ImGui::GetIO().DisplaySize.y) * 0.4f;
|
|
||||||
|
|
||||||
int slices = 32;
|
|
||||||
float angleStep = 2.0f * 3.14159f / slices;
|
|
||||||
|
|
||||||
// Draw planet outline
|
|
||||||
for (int i = 0; i < slices; i++) {
|
|
||||||
float angle1 = i * angleStep;
|
|
||||||
float angle2 = (i + 1) % slices * angleStep;
|
|
||||||
|
|
||||||
ImVec2 p1 = center + ImVec2(cos(angle1) * displaySize, sin(angle1) * displaySize);
|
|
||||||
ImVec2 p2 = center + ImVec2(cos(angle2) * displaySize, sin(angle2) * displaySize);
|
|
||||||
|
|
||||||
drawList->AddLine(p1, p2, IM_COL32(255, 255, 255, 255));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw some sample voxels
|
|
||||||
int res = config.resolution;
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
for (int j = 0; j < 8; j++) {
|
|
||||||
float lat = -90.0f + 180.0f * (i / 7.0f);
|
|
||||||
float lon = 360.0f * (j / 7.0f);
|
|
||||||
|
|
||||||
// Find surface voxel
|
|
||||||
for (int k = res - 1; k >= 0; k--) {
|
|
||||||
int idx = (i * res / 8) * res * res + (j * res / 8) * res + k;
|
|
||||||
if (voxels[idx].material != 0) {
|
|
||||||
// Convert spherical to screen coordinates
|
|
||||||
float latRad = glm::radians(lat);
|
|
||||||
float lonRad = glm::radians(lon);
|
|
||||||
float dist = (k / (float)res) * config.radius * 2.0f;
|
|
||||||
|
|
||||||
float screenDist = (dist / (config.radius * 2.0f)) * displaySize;
|
|
||||||
ImVec2 pos = center + ImVec2(
|
|
||||||
cos(latRad) * cos(lonRad) * screenDist,
|
|
||||||
sin(latRad) * screenDist
|
|
||||||
);
|
|
||||||
|
|
||||||
// Color based on material
|
|
||||||
ImU32 color;
|
|
||||||
switch (voxels[idx].material) {
|
|
||||||
case 1: color = IM_COL32(100, 100, 100, 255); break;
|
|
||||||
case 2: color = IM_COL32(101, 67, 33, 255); break;
|
|
||||||
case 3: color = IM_COL32(34, 139, 34, 255); break;
|
|
||||||
default: color = IM_COL32(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (color != 0) {
|
|
||||||
drawList->AddCircleFilled(pos, 2.0f, color);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
// GLFW initialization
|
|
||||||
if (!glfwInit()) return -1;
|
|
||||||
|
|
||||||
GLFWwindow* window = glfwCreateWindow(1280, 720, "Voxel Planet Generator", NULL, NULL);
|
|
||||||
if (!window) {
|
|
||||||
glfwTerminate();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
glfwMakeContextCurrent(window);
|
|
||||||
glfwSwapInterval(1);
|
|
||||||
|
|
||||||
// ImGui initialization
|
|
||||||
IMGUI_CHECKVERSION();
|
|
||||||
ImGui::CreateContext();
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
|
|
||||||
ImGui::StyleColorsDark();
|
|
||||||
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
|
||||||
ImGui_ImplOpenGL3_Init("#version 130");
|
|
||||||
|
|
||||||
SphericalVoxelPlanet planet;
|
|
||||||
|
|
||||||
// Main loop
|
|
||||||
while (!glfwWindowShouldClose(window)) {
|
|
||||||
glfwPollEvents();
|
|
||||||
|
|
||||||
// Start ImGui frame
|
|
||||||
ImGui_ImplOpenGL3_NewFrame();
|
|
||||||
ImGui_ImplGlfw_NewFrame();
|
|
||||||
ImGui::NewFrame();
|
|
||||||
|
|
||||||
// Render UI
|
|
||||||
planet.renderUI();
|
|
||||||
|
|
||||||
// Clear screen
|
|
||||||
int display_w, display_h;
|
|
||||||
glfwGetFramebufferSize(window, &display_w, &display_h);
|
|
||||||
glViewport(0, 0, display_w, display_h);
|
|
||||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
|
||||||
|
|
||||||
// Render planet
|
|
||||||
planet.renderPlanet();
|
|
||||||
|
|
||||||
// Render ImGui
|
|
||||||
ImGui::Render();
|
|
||||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
|
||||||
|
|
||||||
glfwSwapBuffers(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cleanup
|
|
||||||
ImGui_ImplOpenGL3_Shutdown();
|
|
||||||
ImGui_ImplGlfw_Shutdown();
|
|
||||||
ImGui::DestroyContext();
|
|
||||||
|
|
||||||
glfwDestroyWindow(window);
|
|
||||||
glfwTerminate();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user