direct render tris, and moving some stuff out of main.
This commit is contained in:
@@ -37,7 +37,7 @@ struct defaults {
|
|||||||
float lodDropoff = 0.1;
|
float lodDropoff = 0.1;
|
||||||
PNoise2 noise = PNoise2(42);
|
PNoise2 noise = PNoise2(42);
|
||||||
|
|
||||||
int meshResolution = 32;
|
int meshResolution = 128;
|
||||||
float meshIsoLevel = 0.4f;
|
float meshIsoLevel = 0.4f;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -82,12 +82,6 @@ std::vector<double> renderFrameTimes;
|
|||||||
int frameHistoryIndex = 0;
|
int frameHistoryIndex = 0;
|
||||||
bool firstFrameMeasured = false;
|
bool firstFrameMeasured = false;
|
||||||
|
|
||||||
// Stats update timer
|
|
||||||
std::chrono::steady_clock::time_point lastStatsUpdate;
|
|
||||||
const std::chrono::seconds STATS_UPDATE_INTERVAL(60);
|
|
||||||
std::string cachedStats;
|
|
||||||
bool statsNeedUpdate = true;
|
|
||||||
|
|
||||||
Scene scene;
|
Scene scene;
|
||||||
bool meshNeedsUpdate = false;
|
bool meshNeedsUpdate = false;
|
||||||
|
|
||||||
@@ -188,13 +182,6 @@ void addStar(const defaults& config, const stardefaults& starconf, Octree<int>&
|
|||||||
meshNeedsUpdate = true;
|
meshNeedsUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateStatsCache(Octree<int>& grid) {
|
|
||||||
std::stringstream gridstats;
|
|
||||||
grid.printStats(gridstats);
|
|
||||||
cachedStats = gridstats.str();
|
|
||||||
lastStatsUpdate = std::chrono::steady_clock::now();
|
|
||||||
statsNeedUpdate = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void livePreview(Octree<int>& grid, defaults& config, const Camera& cam) {
|
void livePreview(Octree<int>& grid, defaults& config, const Camera& cam) {
|
||||||
std::lock_guard<std::mutex> lock(PreviewMutex);
|
std::lock_guard<std::mutex> lock(PreviewMutex);
|
||||||
@@ -204,7 +191,7 @@ void livePreview(Octree<int>& grid, defaults& config, const Camera& cam) {
|
|||||||
if (meshNeedsUpdate) {
|
if (meshNeedsUpdate) {
|
||||||
scene.clear();
|
scene.clear();
|
||||||
std::shared_ptr<Mesh> planetMesh = grid.generateMesh(1, config.meshIsoLevel, config.meshResolution);
|
std::shared_ptr<Mesh> planetMesh = grid.generateMesh(1, config.meshIsoLevel, config.meshResolution);
|
||||||
std::shared_ptr<Mesh> starMesh = grid.generateMesh(2, config.meshIsoLevel, config.meshResolution);
|
std::shared_ptr<Mesh> starMesh = grid.generateMesh(2, config.meshIsoLevel, config.meshResolution / 4);
|
||||||
|
|
||||||
scene.addMesh(planetMesh);
|
scene.addMesh(planetMesh);
|
||||||
scene.addMesh(starMesh);
|
scene.addMesh(starMesh);
|
||||||
@@ -213,7 +200,6 @@ void livePreview(Octree<int>& grid, defaults& config, const Camera& cam) {
|
|||||||
// planetMesh.setIsoLevel(config.meshIsoLevel);
|
// planetMesh.setIsoLevel(config.meshIsoLevel);
|
||||||
// planetMesh.update(grid);
|
// planetMesh.update(grid);
|
||||||
meshNeedsUpdate = false;
|
meshNeedsUpdate = false;
|
||||||
statsNeedUpdate = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto renderStart = std::chrono::high_resolution_clock::now();
|
auto renderStart = std::chrono::high_resolution_clock::now();
|
||||||
@@ -254,10 +240,6 @@ void livePreview(Octree<int>& grid, defaults& config, const Camera& cam) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto now = std::chrono::steady_clock::now();
|
auto now = std::chrono::steady_clock::now();
|
||||||
if (statsNeedUpdate || (now - lastStatsUpdate) > STATS_UPDATE_INTERVAL) {
|
|
||||||
updateStatsCache(grid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (textu == 0) {
|
if (textu == 0) {
|
||||||
glGenTextures(1, &textu);
|
glGenTextures(1, &textu);
|
||||||
}
|
}
|
||||||
@@ -404,13 +386,10 @@ int main() {
|
|||||||
float deltaTime = 0.016f;
|
float deltaTime = 0.016f;
|
||||||
renderFrameTimes.resize(FRAME_HISTORY_SIZE, 0.0);
|
renderFrameTimes.resize(FRAME_HISTORY_SIZE, 0.0);
|
||||||
|
|
||||||
lastStatsUpdate = std::chrono::steady_clock::now();
|
|
||||||
statsNeedUpdate = true;
|
|
||||||
bool worldPreview = false;
|
bool worldPreview = false;
|
||||||
|
|
||||||
if (grid.load("output/Treegrid.yggs")) {
|
if (grid.load("output/Treegrid.yggs")) {
|
||||||
gridInitialized = true;
|
gridInitialized = true;
|
||||||
updateStatsCache(grid);
|
|
||||||
resetView(cam, config.gridSizecube);
|
resetView(cam, config.gridSizecube);
|
||||||
meshNeedsUpdate = true;
|
meshNeedsUpdate = true;
|
||||||
}
|
}
|
||||||
@@ -565,7 +544,7 @@ int main() {
|
|||||||
createSphere(config, sphereConf, grid);
|
createSphere(config, sphereConf, grid);
|
||||||
addStar(config, starConf, grid);
|
addStar(config, starConf, grid);
|
||||||
gridInitialized = true;
|
gridInitialized = true;
|
||||||
statsNeedUpdate = true;
|
scene.updateStats();
|
||||||
|
|
||||||
resetView(cam, config.gridSizecube);
|
resetView(cam, config.gridSizecube);
|
||||||
grid.generateLODs();
|
grid.generateLODs();
|
||||||
@@ -585,53 +564,8 @@ int main() {
|
|||||||
fluidUI.renderUI();
|
fluidUI.renderUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
scene.drawSceneWindow("Planet Preview", cam, 0.01, 1000);
|
||||||
ImGui::Begin("Planet Preview");
|
scene.drawGridStats();
|
||||||
if (worldPreview) {
|
|
||||||
if (gridInitialized) {
|
|
||||||
livePreview(grid, config, cam);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gridInitialized && textureInitialized) {
|
|
||||||
ImGui::Image((void*)(intptr_t)textu, ImVec2(config.outWidth, config.outHeight));
|
|
||||||
} else if (gridInitialized) {
|
|
||||||
ImGui::Text("Preview not generated yet");
|
|
||||||
} else {
|
|
||||||
ImGui::Text("No grid generated");
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::Text("Render Performance:");
|
|
||||||
if (renderFPS > 0) {
|
|
||||||
// Color code based on FPS
|
|
||||||
ImVec4 fpsColor;
|
|
||||||
if (renderFPS >= 30.0) {
|
|
||||||
fpsColor = ImVec4(0.0f, 1.0f, 0.0f, 1.0f); // Green for good FPS
|
|
||||||
} else if (renderFPS >= 15.0) {
|
|
||||||
fpsColor = ImVec4(1.0f, 1.0f, 0.0f, 1.0f); // Yellow for okay FPS
|
|
||||||
} else {
|
|
||||||
fpsColor = ImVec4(1.0f, 0.0f, 0.0f, 1.0f); // Red for poor FPS
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::TextColored(fpsColor, "FPS: %.1f", renderFPS);
|
|
||||||
ImGui::Text("Frame time: %.1f ms", avgRenderFrameTime * 1000.0);
|
|
||||||
|
|
||||||
// Simple progress bar for frame time
|
|
||||||
ImGui::Text("%.1f/100 ms", avgRenderFrameTime * 1000.0);
|
|
||||||
|
|
||||||
// Show latest frame time
|
|
||||||
ImGui::Text("Latest: %.1f ms", renderFrameTime * 1000.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::Separator();
|
|
||||||
|
|
||||||
if (gridInitialized) {
|
|
||||||
auto now = std::chrono::steady_clock::now();
|
|
||||||
if ((now - lastStatsUpdate) > STATS_UPDATE_INTERVAL) updateStatsCache(grid);
|
|
||||||
ImGui::TextUnformatted(cachedStats.c_str());
|
|
||||||
}
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
ImGui::Begin("controls");
|
ImGui::Begin("controls");
|
||||||
|
|||||||
@@ -9,10 +9,16 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <chrono>
|
||||||
#include "../../eigen/Eigen/Dense"
|
#include "../../eigen/Eigen/Dense"
|
||||||
#include "../../eigen/Eigen/Geometry"
|
#include "../../eigen/Eigen/Geometry"
|
||||||
#include "./camera.hpp"
|
#include "./camera.hpp"
|
||||||
#include "../output/frame.hpp"
|
#include "../output/frame.hpp"
|
||||||
|
#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 Vector2f = Eigen::Vector2f;
|
using Vector2f = Eigen::Vector2f;
|
||||||
using Vector3f = Eigen::Vector3f;
|
using Vector3f = Eigen::Vector3f;
|
||||||
@@ -236,13 +242,26 @@ public:
|
|||||||
outFrame.setData(buffer, colorformat);
|
outFrame.setData(buffer, colorformat);
|
||||||
return outFrame;
|
return outFrame;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
void printStats(std::ostream& os = std::cout) const {
|
||||||
|
os << "========================================\n";
|
||||||
|
os << " Mesh STATS \n";
|
||||||
|
os << "========================================\n";
|
||||||
|
os << "Structure:\n";
|
||||||
|
os << " Total Vertices : " << _vertices.size() << "\n";
|
||||||
|
os << " Total Tris : " << _tris.size() << "\n";
|
||||||
|
os << " Total Polys : " << _polys.size() << "\n";
|
||||||
|
os << " colors : " << _colors.size() << "\n";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class Scene {
|
class Scene {
|
||||||
private:
|
private:
|
||||||
std::vector<std::shared_ptr<Mesh>> _meshes;
|
std::vector<std::shared_ptr<Mesh>> _meshes;
|
||||||
|
std::string cachedStats;
|
||||||
|
std::chrono::steady_clock::time_point lastStatsUpdate;
|
||||||
|
bool statsNeedUpdate = true;
|
||||||
|
const std::chrono::seconds STATS_UPDATE_INTERVAL{60};
|
||||||
public:
|
public:
|
||||||
Scene() {}
|
Scene() {}
|
||||||
|
|
||||||
@@ -268,6 +287,115 @@ public:
|
|||||||
|
|
||||||
return Mesh::rasterizeTriangles(allTriangles, width, height, colorformat);
|
return Mesh::rasterizeTriangles(allTriangles, width, height, colorformat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drawSceneWindow(const char* windowTitle, Camera& cam, float nearClip = 0.1f, float farClip = 1000.0f, bool showFps = true) {
|
||||||
|
ImGui::Begin(windowTitle);
|
||||||
|
|
||||||
|
// Get the position and size of the content area within the ImGui window
|
||||||
|
ImVec2 canvas_p = ImGui::GetCursorScreenPos();
|
||||||
|
ImVec2 canvas_sz = ImGui::GetContentRegionAvail();
|
||||||
|
|
||||||
|
if (canvas_sz.x < 1.0f || canvas_sz.y < 1.0f) {
|
||||||
|
ImGui::End();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||||
|
|
||||||
|
// Clip drawing to the specific window area
|
||||||
|
draw_list->PushClipRect(canvas_p, ImVec2(canvas_p.x + canvas_sz.x, canvas_p.y + canvas_sz.y), true);
|
||||||
|
|
||||||
|
// Draw background
|
||||||
|
draw_list->AddRectFilled(canvas_p, ImVec2(canvas_p.x + canvas_sz.x, canvas_p.y + canvas_sz.y), IM_COL32(20, 20, 20, 255));
|
||||||
|
|
||||||
|
// Collect and project triangles
|
||||||
|
std::vector<Triangle2D> allTriangles;
|
||||||
|
for (auto& mesh : _meshes) {
|
||||||
|
std::vector<Triangle2D> meshTris = mesh->project_2d(cam, (int)canvas_sz.y, (int)canvas_sz.x, nearClip, farClip);
|
||||||
|
allTriangles.insert(allTriangles.end(), meshTris.begin(), meshTris.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort by depth (Painter's Algorithm)
|
||||||
|
std::sort(allTriangles.begin(), allTriangles.end(), [](const Triangle2D& a, const Triangle2D& b) {
|
||||||
|
return a.depth > b.depth;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Draw triangles
|
||||||
|
for (const auto& tri : allTriangles) {
|
||||||
|
ImVec2 p1(canvas_p.x + tri.a.x(), canvas_p.y + tri.a.y());
|
||||||
|
ImVec2 p2(canvas_p.x + tri.b.x(), canvas_p.y + tri.b.y());
|
||||||
|
ImVec2 p3(canvas_p.x + tri.c.x(), canvas_p.y + tri.c.y());
|
||||||
|
|
||||||
|
// Simple culling optimization
|
||||||
|
// float minX = std::min({p1.x, p2.x, p3.x});
|
||||||
|
// float minY = std::min({p1.y, p2.y, p3.y});
|
||||||
|
// float maxX = std::max({p1.x, p2.x, p3.x});
|
||||||
|
// float maxY = std::max({p1.y, p2.y, p3.y});
|
||||||
|
|
||||||
|
// if (maxX < canvas_p.x || minX > canvas_p.x + canvas_sz.x ||
|
||||||
|
// maxY < canvas_p.y || minY > canvas_p.y + canvas_sz.y) {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// float r = std::clamp(tri.color.x(), 0.0f, 1.0f);
|
||||||
|
// float g = std::clamp(tri.color.y(), 0.0f, 1.0f);
|
||||||
|
// float b = std::clamp(tri.color.z(), 0.0f, 1.0f);
|
||||||
|
|
||||||
|
ImU32 col = ImGui::ColorConvertFloat4ToU32(ImVec4(tri.color.x(), tri.color.y(), tri.color.z(), 1.0f));
|
||||||
|
draw_list->AddTriangleFilled(p1, p2, p3, col);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw FPS Counter
|
||||||
|
if (showFps) {
|
||||||
|
char fpsText[32];
|
||||||
|
snprintf(fpsText, sizeof(fpsText), "FPS: %.1f", ImGui::GetIO().Framerate);
|
||||||
|
|
||||||
|
ImVec2 txtSz = ImGui::CalcTextSize(fpsText);
|
||||||
|
// Position: Top Right with 10px padding
|
||||||
|
ImVec2 txtPos = ImVec2(canvas_p.x + canvas_sz.x - txtSz.x - 10.0f, canvas_p.y + 10.0f);
|
||||||
|
|
||||||
|
// Semi-transparent background for text
|
||||||
|
draw_list->AddRectFilled(
|
||||||
|
ImVec2(txtPos.x - 5.0f, txtPos.y - 2.0f),
|
||||||
|
ImVec2(txtPos.x + txtSz.x + 5.0f, txtPos.y + txtSz.y + 2.0f),
|
||||||
|
IM_COL32(0, 0, 0, 150),
|
||||||
|
4.0f
|
||||||
|
);
|
||||||
|
|
||||||
|
draw_list->AddText(txtPos, IM_COL32(255, 255, 255, 255), fpsText);
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_list->PopClipRect();
|
||||||
|
|
||||||
|
// Invisible button to handle inputs over the viewport area
|
||||||
|
ImGui::InvisibleButton("viewport_btn", canvas_sz);
|
||||||
|
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void printStats(std::ostream& os = std::cout) const {
|
||||||
|
os << "========================================\n";
|
||||||
|
os << " Scene STATS \n";
|
||||||
|
os << "========================================\n";
|
||||||
|
for (auto m : _meshes) {
|
||||||
|
m->printStats(os);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawGridStats() {
|
||||||
|
auto now = std::chrono::steady_clock::now();
|
||||||
|
if ((now - lastStatsUpdate) > STATS_UPDATE_INTERVAL || statsNeedUpdate) {
|
||||||
|
std::stringstream meshStats;
|
||||||
|
printStats(meshStats);
|
||||||
|
cachedStats = meshStats.str();
|
||||||
|
lastStatsUpdate = std::chrono::steady_clock::now();
|
||||||
|
statsNeedUpdate = false;
|
||||||
|
}
|
||||||
|
ImGui::TextUnformatted(cachedStats.c_str());
|
||||||
|
}
|
||||||
|
void updateStats() {
|
||||||
|
statsNeedUpdate = true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user