Merge branch 'master' of https://github.com/yggdrasil75/stupidsimcpp
I forgot to pull. woops
This commit is contained in:
63
makefile
63
makefile
@@ -1,35 +1,52 @@
|
|||||||
# Compiler and flags
|
|
||||||
CXX := g++
|
|
||||||
CXXFLAGS := -std=c++23 -O3 -march=native -I./imgui
|
|
||||||
LDFLAGS := -L./imgui -limgui -lstb -lGL
|
|
||||||
PKG_FLAGS := $(shell pkg-config --cflags --libs glfw3)
|
|
||||||
|
|
||||||
# Directories
|
# Directories
|
||||||
BIN_DIR := ./bin
|
BIN_DIR := ./bin
|
||||||
SRC_DIR := ./tests
|
SRC_DIR := ./tests
|
||||||
|
IMGUI_DIR = ./imgui
|
||||||
|
OBJ_DIR := $(BIN_DIR)/obj
|
||||||
|
STB_DIR := ./stb
|
||||||
|
|
||||||
|
# Compiler and flags
|
||||||
|
CXX := g++
|
||||||
|
CXXFLAGS = -std=c++23 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends -I$(STB_DIR)
|
||||||
|
#CXXFLAGS += -g -Wall -Wformat
|
||||||
|
CXXFLAGS += `pkg-config --cflags glfw3`
|
||||||
|
CFLAGS = $(CXXFLAGS)
|
||||||
|
LDFLAGS := -L./imgui -limgui -lGL
|
||||||
|
LINUX_GL_LIBS = -lGL
|
||||||
|
PKG_FLAGS := $(LINUX_GL_LIBS) `pkg-config --static --cflags --libs glfw3`
|
||||||
|
CXXFLAGS += $(PKG_FLAGS)
|
||||||
|
|
||||||
# Source files
|
# Source files
|
||||||
SRC := $(SRC_DIR)/g2chromatic2.cpp
|
SRC := $(SRC_DIR)/g2chromatic2.cpp
|
||||||
TARGET := $(BIN_DIR)/g2gradc
|
SRC += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
|
||||||
|
SRC += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl3.cpp
|
||||||
|
SRC += $(SRC_DIR)/stb_image.cpp
|
||||||
|
OBJS = $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(basename $(notdir $(SRC)))))
|
||||||
|
UNAME_S := $(shell uname -s)
|
||||||
|
EXE := $(BIN_DIR)/g2gradc
|
||||||
|
|
||||||
# Default target
|
$(shell mkdir -p $(OBJ_DIR))
|
||||||
all: $(TARGET)
|
|
||||||
|
|
||||||
# Create binary directory if it doesn't exist
|
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
|
||||||
$(BIN_DIR):
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
@mkdir -p $(BIN_DIR)
|
|
||||||
|
|
||||||
# Build target
|
$(OBJ_DIR)/%.o: %.cpp
|
||||||
$(TARGET): $(SRC) | $(BIN_DIR)
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
$(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(PKG_FLAGS)
|
|
||||||
|
|
||||||
# Run the program
|
$(OBJ_DIR)/%.o: $(IMGUI_DIR)/%.cpp
|
||||||
run: $(TARGET)
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
./$(TARGET)
|
|
||||||
|
$(OBJ_DIR)/%.o: $(IMGUI_DIR)/backends/%.cpp
|
||||||
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
$(OBJ_DIR)/%.o: $(STB_DIR)/%.cpp
|
||||||
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
all: $(EXE)
|
||||||
|
@echo Build complete for $(ECHO_MESSAGE)
|
||||||
|
|
||||||
|
$(EXE): $(OBJS)
|
||||||
|
$(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS)
|
||||||
|
|
||||||
# Clean build artifacts
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(BIN_DIR)
|
rm -f $(EXE) $(OBJS)
|
||||||
|
|
||||||
# Phony targets
|
|
||||||
.PHONY: all run clean
|
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
std::mutex m;
|
std::mutex m;
|
||||||
std::atomic<bool> isGenerating{false};
|
std::atomic<bool> isGenerating{false};
|
||||||
@@ -28,7 +29,15 @@ std::future<void> generationFuture;
|
|||||||
std::mutex previewMutex;
|
std::mutex previewMutex;
|
||||||
std::atomic<bool> updatePreview{false};
|
std::atomic<bool> updatePreview{false};
|
||||||
frame currentPreviewFrame;
|
frame currentPreviewFrame;
|
||||||
GLuint previewTexture = 0;
|
GLuint textu = 0;
|
||||||
|
std::string previewText;
|
||||||
|
|
||||||
|
struct Shared {
|
||||||
|
std::mutex mutex;
|
||||||
|
Grid2 grid;
|
||||||
|
bool hasNewFrame = false;
|
||||||
|
int currentFrame = 0;
|
||||||
|
};
|
||||||
|
|
||||||
struct AnimationConfig {
|
struct AnimationConfig {
|
||||||
int width = 1024;
|
int width = 1024;
|
||||||
@@ -69,12 +78,22 @@ void Preview(Grid2& grid) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void livePreview(GLFWwindow* window, Grid2& grid) {
|
void livePreview(const Grid2& grid) {
|
||||||
// frame Frame = grid.getGridAsFrame(frame::colormap::RGB);
|
std::lock_guard<std::mutex> lock(previewMutex);
|
||||||
// int image_width = Frame.getWidth();
|
|
||||||
// int image_height = Frame.getHeight();
|
currentPreviewFrame = grid.getGridAsFrame(frame::colormap::RGBA);
|
||||||
// auto data = reinterpret_cast<char*>(Frame.getData());
|
|
||||||
// uint8_t* image_data = stbi_load_from_memory((const unsigned char*)data, (int)data.size(), &image_width, &image_height, 3, 4);
|
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);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, textu);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, currentPreviewFrame.getWidth(), currentPreviewFrame.getHeight(),
|
||||||
|
0, GL_RGBA, GL_UNSIGNED_BYTE, currentPreviewFrame.getData().data());
|
||||||
|
|
||||||
|
updatePreview = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::tuple<size_t, Vec2, Vec4>> pickSeeds(Grid2 grid, AnimationConfig config) {
|
std::vector<std::tuple<size_t, Vec2, Vec4>> pickSeeds(Grid2 grid, AnimationConfig config) {
|
||||||
@@ -201,10 +220,16 @@ bool exportavi(std::vector<frame> frames, AnimationConfig config) {
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mainLogic(const AnimationConfig& config, Grid2& grid) {
|
void mainLogic(const AnimationConfig& config, Shared& state) {
|
||||||
isGenerating = true;
|
isGenerating = true;
|
||||||
try {
|
try {
|
||||||
grid = setup(config);
|
Grid2 grid = setup(config);
|
||||||
|
{
|
||||||
|
std:: lock_guard<std::mutex> lock(state.mutex);
|
||||||
|
state.grid = grid;
|
||||||
|
state.hasNewFrame = true;
|
||||||
|
state.currentFrame = 0;
|
||||||
|
}
|
||||||
Preview(grid);
|
Preview(grid);
|
||||||
std::vector<std::tuple<size_t, Vec2, Vec4>> seeds = pickSeeds(grid, config);
|
std::vector<std::tuple<size_t, Vec2, Vec4>> seeds = pickSeeds(grid, config);
|
||||||
std::vector<frame> frames;
|
std::vector<frame> frames;
|
||||||
@@ -218,16 +243,21 @@ void mainLogic(const AnimationConfig& config, Grid2& grid) {
|
|||||||
|
|
||||||
expandPixel(grid,config,seeds);
|
expandPixel(grid,config,seeds);
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(state.mutex);
|
||||||
|
state.grid = grid;
|
||||||
|
state.hasNewFrame = true;
|
||||||
|
state.currentFrame = i;
|
||||||
|
|
||||||
// Print compression info for this frame
|
// Print compression info for this frame
|
||||||
if (i % 10 == 0 ) {
|
if (i % 10 == 0 ) {
|
||||||
frame bgrframe;
|
frame bgrframe;
|
||||||
std::cout << "Processing frame " << i + 1 << "/" << config.totalFrames << std::endl;
|
std::cout << "Processing frame " << i + 1 << "/" << config.totalFrames << std::endl;
|
||||||
bgrframe = grid.getGridAsFrame(frame::colormap::BGR);
|
bgrframe = grid.getGridAsFrame(frame::colormap::BGR);
|
||||||
bgrframe.printCompressionStats();
|
|
||||||
frames.push_back(bgrframe);
|
frames.push_back(bgrframe);
|
||||||
//bgrframe.decompress();
|
//bgrframe.decompress();
|
||||||
//BMPWriter::saveBMP(std::format("output/grayscalesource.{}.bmp", i), bgrframe);
|
//BMPWriter::saveBMP(std::format("output/grayscalesource.{}.bmp", i), bgrframe);
|
||||||
bgrframe.compressFrameLZ78();
|
bgrframe.compressFrameLZ78();
|
||||||
|
bgrframe.printCompressionStats();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exportavi(frames,config);
|
exportavi(frames,config);
|
||||||
@@ -296,7 +326,7 @@ int main() {
|
|||||||
//ImGui::SetNextWindowSize(ImVec2(1110,667));
|
//ImGui::SetNextWindowSize(ImVec2(1110,667));
|
||||||
//auto beg = ImGui::Begin("Gradient thing", &window);
|
//auto beg = ImGui::Begin("Gradient thing", &window);
|
||||||
//if (beg) {
|
//if (beg) {
|
||||||
std::cout << "stuff breaks at 223" << std::endl;
|
// std::cout << "stuff breaks at 223" << std::endl;
|
||||||
bool application_not_closed = true;
|
bool application_not_closed = true;
|
||||||
//float main_scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor());
|
//float main_scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor());
|
||||||
GLFWwindow* window = glfwCreateWindow((int)(1280), (int)(800), "Chromatic gradient generator thing", nullptr, nullptr);
|
GLFWwindow* window = glfwCreateWindow((int)(1280), (int)(800), "Chromatic gradient generator thing", nullptr, nullptr);
|
||||||
@@ -306,7 +336,7 @@ int main() {
|
|||||||
glfwSwapInterval(1);
|
glfwSwapInterval(1);
|
||||||
//IMGUI_CHECKVERSION(); //this might be more important than I realize. but cant run with it so currently ignoring.
|
//IMGUI_CHECKVERSION(); //this might be more important than I realize. but cant run with it so currently ignoring.
|
||||||
ImGui::CreateContext();
|
ImGui::CreateContext();
|
||||||
std::cout << "context created" << std::endl;
|
// std::cout << "context created" << std::endl;
|
||||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||||
ImGui::StyleColorsDark();
|
ImGui::StyleColorsDark();
|
||||||
@@ -322,7 +352,7 @@ int main() {
|
|||||||
ImGui_ImplOpenGL3_Init(glsl_version);
|
ImGui_ImplOpenGL3_Init(glsl_version);
|
||||||
|
|
||||||
|
|
||||||
std::cout << "created glfw window" << std::endl;
|
// std::cout << "created glfw window" << std::endl;
|
||||||
|
|
||||||
|
|
||||||
// Our state
|
// Our state
|
||||||
@@ -336,7 +366,10 @@ int main() {
|
|||||||
static int i4 = 8;
|
static int i4 = 8;
|
||||||
|
|
||||||
std::future<void> mainlogicthread;
|
std::future<void> mainlogicthread;
|
||||||
|
Shared state;
|
||||||
Grid2 grid;
|
Grid2 grid;
|
||||||
|
AnimationConfig config;
|
||||||
|
previewText = "Please generate";
|
||||||
while (!glfwWindowShouldClose(window)) {
|
while (!glfwWindowShouldClose(window)) {
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
|
||||||
@@ -354,94 +387,90 @@ int main() {
|
|||||||
ImGui::SliderInt("framecount", &i3, 10, 5000);
|
ImGui::SliderInt("framecount", &i3, 10, 5000);
|
||||||
ImGui::SliderInt("numSeeds", &i4, 0, 10);
|
ImGui::SliderInt("numSeeds", &i4, 0, 10);
|
||||||
|
|
||||||
// Disable button while generating
|
|
||||||
if (isGenerating) {
|
if (isGenerating) {
|
||||||
ImGui::BeginDisabled();
|
ImGui::BeginDisabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::Button("Generate Animation")) {
|
if (ImGui::Button("Generate Animation")) {
|
||||||
AnimationConfig config = AnimationConfig(i1, i2, i3, f, i4);
|
config = AnimationConfig(i1, i2, i3, f, i4);
|
||||||
mainlogicthread = std::async(std::launch::async, mainLogic, config, std::ref(grid));
|
mainlogicthread = std::async(std::launch::async, mainLogic, config, std::ref(state));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isGenerating) {
|
if (isGenerating) {
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
|
|
||||||
// Show cancel button and progress indicator
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("Cancel")) {
|
if (ImGui::Button("Cancel")) {
|
||||||
cancelGeneration();
|
cancelGeneration();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optional: Show a progress indicator
|
// Check for new frames from the generation thread
|
||||||
ImGui::Text("Generating...");
|
bool hasNewFrame = false;
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(state.mutex);
|
||||||
|
if (state.hasNewFrame) {
|
||||||
|
livePreview(state.grid);
|
||||||
|
state.hasNewFrame = false;
|
||||||
|
previewText = "Generating... Frame: " + std::to_string(state.currentFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Text(previewText.c_str());
|
||||||
|
|
||||||
|
if (textu != 0) {
|
||||||
|
ImVec2 imageSize = ImVec2(config.width * 0.3f, config.height * 0.3f); // Scale down for preview
|
||||||
|
ImVec2 uv_min = ImVec2(0.0f, 0.0f);
|
||||||
|
ImVec2 uv_max = ImVec2(1.0f, 1.0f);
|
||||||
|
ImGui::Image((void*)(intptr_t)textu, imageSize, uv_min, uv_max);
|
||||||
|
} else {
|
||||||
|
ImGui::Text("Generating preview...");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ImGui::Text("No preview available");
|
||||||
|
ImGui::Text("Start generation to see live preview");
|
||||||
}
|
}
|
||||||
//ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); // is this broken or is it just cause I have no refresh buffer in this loop?
|
//std::cout << "sleeping" << std::endl;
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
//std::cout << "ending" << std::endl;
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImGui::NewFrame();
|
|
||||||
// {
|
|
||||||
// ImGui::Begin("Live Preview");
|
|
||||||
|
|
||||||
// if (previewTexture != 0) {
|
|
||||||
// // Get available space
|
|
||||||
// ImVec2 availableSize = ImGui::GetContentRegionAvail();
|
|
||||||
|
|
||||||
// // Maintain aspect ratio (assuming square or config width/height)
|
|
||||||
// float aspectRatio = static_cast<float>(currentPreviewFrame.getWidth()) /
|
|
||||||
// static_cast<float>(currentPreviewFrame.getHeight());
|
|
||||||
|
|
||||||
// ImVec2 imageSize;
|
|
||||||
// if (availableSize.x / aspectRatio <= availableSize.y) {
|
|
||||||
// imageSize.x = availableSize.x;
|
|
||||||
// imageSize.y = availableSize.x / aspectRatio;
|
|
||||||
// } else {
|
|
||||||
// imageSize.y = availableSize.y;
|
|
||||||
// imageSize.x = availableSize.y * aspectRatio;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// ImGui::Image((ImTextureID)(intptr_t)previewTexture, imageSize);
|
|
||||||
|
|
||||||
// ImGui::Text("Frame: %dx%d", currentPreviewFrame.getWidth(), currentPreviewFrame.getHeight());
|
|
||||||
// if (isGenerating) {
|
|
||||||
// ImGui::TextColored(ImVec4(0, 1, 0, 1), "Generating...");
|
|
||||||
// } else {
|
|
||||||
// ImGui::Text("Ready");
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// ImGui::Text("No preview available");
|
|
||||||
// ImGui::Text("Start generation to see live preview");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// ImGui::End();
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
// std::cout << "ending frame" << std::endl;
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
int display_w, display_h;
|
int display_w, display_h;
|
||||||
glfwGetFramebufferSize(window, &display_w, &display_h);
|
glfwGetFramebufferSize(window, &display_w, &display_h);
|
||||||
glViewport(0, 0, display_w, display_h);
|
glViewport(0, 0, display_w, display_h);
|
||||||
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
|
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
// std::cout << "rendering" << std::endl;
|
||||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||||
|
|
||||||
glfwSwapBuffers(window);
|
glfwSwapBuffers(window);
|
||||||
//mainlogicthread.join();
|
//mainlogicthread.join();
|
||||||
|
|
||||||
|
// std::cout << "swapping buffers" << std::endl;
|
||||||
}
|
}
|
||||||
cancelGeneration();
|
cancelGeneration();
|
||||||
|
|
||||||
|
|
||||||
|
// std::cout << "shutting down" << std::endl;
|
||||||
ImGui_ImplOpenGL3_Shutdown();
|
ImGui_ImplOpenGL3_Shutdown();
|
||||||
ImGui_ImplGlfw_Shutdown();
|
ImGui_ImplGlfw_Shutdown();
|
||||||
ImGui::DestroyContext();
|
ImGui::DestroyContext();
|
||||||
|
|
||||||
|
// std::cout << "destroying" << std::endl;
|
||||||
glfwDestroyWindow(window);
|
glfwDestroyWindow(window);
|
||||||
if (previewTexture != 0) {
|
if (textu != 0) {
|
||||||
glDeleteTextures(1, &previewTexture);
|
glDeleteTextures(1, &textu);
|
||||||
previewTexture = 0;
|
textu = 0;
|
||||||
}
|
}
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
FunctionTimer::printStats(FunctionTimer::Mode::ENHANCED);
|
FunctionTimer::printStats(FunctionTimer::Mode::ENHANCED);
|
||||||
|
|
||||||
|
// std::cout << "printing" << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
//I need this: https://raais.github.io/ImStudio/
|
//I need this: https://raais.github.io/ImStudio/
|
||||||
|
|||||||
2
tests/stb_image.cpp
Normal file
2
tests/stb_image.cpp
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include "stb_image.h"
|
||||||
@@ -67,7 +67,7 @@ public:
|
|||||||
return Positions.bucket_count();
|
return Positions.bucket_count();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool empty() {
|
bool empty() const {
|
||||||
return Positions.empty();
|
return Positions.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,7 +194,9 @@ protected:
|
|||||||
//TODO: spatial map
|
//TODO: spatial map
|
||||||
SpatialGrid spatialGrid;
|
SpatialGrid spatialGrid;
|
||||||
float spatialCellSize = 2.0f;
|
float spatialCellSize = 2.0f;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
bool usable = false;
|
||||||
//get position from id
|
//get position from id
|
||||||
Vec2 getPositionID(size_t id) const {
|
Vec2 getPositionID(size_t id) const {
|
||||||
Vec2 it = Positions.at(id);
|
Vec2 it = Positions.at(id);
|
||||||
@@ -459,6 +461,7 @@ public:
|
|||||||
shrinkIfNeeded();
|
shrinkIfNeeded();
|
||||||
updateNeighborMap();
|
updateNeighborMap();
|
||||||
|
|
||||||
|
usable = true;
|
||||||
return getAllIDs();
|
return getAllIDs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -621,6 +624,78 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void getGridRegionAsRGBA(const Vec2& minCorner, const Vec2& maxCorner,
|
||||||
|
int& width, int& height, std::vector<uint8_t>& rgbData) const {
|
||||||
|
TIME_FUNCTION;
|
||||||
|
// std::cout << "excessdebug g2.483" << std::endl;
|
||||||
|
// Calculate dimensions
|
||||||
|
width = static_cast<int>(maxCorner.x - minCorner.x);
|
||||||
|
height = static_cast<int>(maxCorner.y - minCorner.y);
|
||||||
|
|
||||||
|
if (width <= 0 || height <= 0) {
|
||||||
|
width = height = 0;
|
||||||
|
rgbData.clear();
|
||||||
|
rgbData.shrink_to_fit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// std::cout << "excessdebug g2.494" << std::endl;
|
||||||
|
|
||||||
|
// Initialize RGB data (3 bytes per pixel: R, G, B)
|
||||||
|
std::vector<Vec4> rgbaBuffer(width * height, Vec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||||
|
|
||||||
|
// For each position in the grid, find the corresponding pixel
|
||||||
|
for (const auto& [id, pos] : Positions) {
|
||||||
|
// std::cout << "excessdebug g2.501." << id << std::endl;
|
||||||
|
size_t size = Sizes.at(id);
|
||||||
|
|
||||||
|
// Calculate pixel coordinates
|
||||||
|
int pixelXm = static_cast<int>(pos.x - size/2 - minCorner.x);
|
||||||
|
int pixelXM = static_cast<int>(pos.x + size/2 - minCorner.x);
|
||||||
|
int pixelYm = static_cast<int>(pos.y - size/2 - minCorner.y);
|
||||||
|
int pixelYM = static_cast<int>(pos.y + size/2 - minCorner.y);
|
||||||
|
|
||||||
|
pixelXm = std::max(0, pixelXm);
|
||||||
|
pixelXM = std::min(width - 1, pixelXM);
|
||||||
|
pixelYm = std::max(0, pixelYm);
|
||||||
|
pixelYM = std::min(height - 1, pixelYM);
|
||||||
|
// std::cout << "excessdebug g2.514." << id << std::endl;
|
||||||
|
|
||||||
|
// Ensure within bounds
|
||||||
|
if (pixelXM >= minCorner.x && pixelXm < width && pixelYM >= minCorner.y && pixelYm < height) {
|
||||||
|
// std::cout << "excessdebug g2.518." << id << " - (" << pixelXm << "," << pixelYM << ")" << std::endl;
|
||||||
|
const Vec4& color = Colors.at(id);
|
||||||
|
float srcAlpha = color.a;
|
||||||
|
float invSrcAlpha = 1.0f - srcAlpha;
|
||||||
|
for (int py = pixelYm; py <= pixelYM; ++py){
|
||||||
|
for (int px = pixelXm; px <= pixelXM; ++px){
|
||||||
|
// std::cout << "excessdebug g2.524." << id << " - (" << py << "," << px << ")" << std::endl;
|
||||||
|
int index = (py * width + px);
|
||||||
|
Vec4 dest = rgbaBuffer[index];
|
||||||
|
|
||||||
|
dest.r = color.r * srcAlpha + dest.r; // * invSrcAlpha;
|
||||||
|
dest.g = color.g * srcAlpha + dest.g; // * invSrcAlpha;
|
||||||
|
dest.b = color.b * srcAlpha + dest.b; // * invSrcAlpha;
|
||||||
|
dest.a = srcAlpha + dest.a; // * invSrcAlpha;
|
||||||
|
rgbaBuffer[index] = dest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rgbData.resize(rgbaBuffer.size() * 4);
|
||||||
|
for (int i = 0; i < rgbaBuffer.size(); ++i) {
|
||||||
|
const Vec4& color = rgbaBuffer[i];
|
||||||
|
int bgrIndex = i * 4;
|
||||||
|
|
||||||
|
// Convert from [0,1] to [0,255] and store as RGB
|
||||||
|
rgbData[bgrIndex + 0] = static_cast<unsigned char>(color.r * 255);
|
||||||
|
rgbData[bgrIndex + 1] = static_cast<unsigned char>(color.g * 255);
|
||||||
|
rgbData[bgrIndex + 2] = static_cast<unsigned char>(color.b * 255);
|
||||||
|
rgbData[bgrIndex + 2] = static_cast<unsigned char>(color.a * 255);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//get full as rgb/bgr
|
//get full as rgb/bgr
|
||||||
void getGridAsRGB(int& width, int& height, std::vector<uint8_t>& rgbData) {
|
void getGridAsRGB(int& width, int& height, std::vector<uint8_t>& rgbData) {
|
||||||
Vec2 minCorner, maxCorner;
|
Vec2 minCorner, maxCorner;
|
||||||
@@ -646,6 +721,17 @@ public:
|
|||||||
return resultFrame;
|
return resultFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frame getGridRegionAsFrameRGBA(const Vec2& minCorner, const Vec2& maxCorner) const {
|
||||||
|
TIME_FUNCTION;
|
||||||
|
int width, height;
|
||||||
|
std::vector<uint8_t> rgbData;
|
||||||
|
getGridRegionAsRGBA(minCorner, maxCorner, width, height, rgbData);
|
||||||
|
|
||||||
|
frame resultFrame(width, height, frame::colormap::RGB);
|
||||||
|
resultFrame.setData(rgbData);
|
||||||
|
return resultFrame;
|
||||||
|
}
|
||||||
|
|
||||||
// Get region as frame (BGR format)
|
// Get region as frame (BGR format)
|
||||||
frame getGridRegionAsFrameBGR(const Vec2& minCorner, const Vec2& maxCorner) const {
|
frame getGridRegionAsFrameBGR(const Vec2& minCorner, const Vec2& maxCorner) const {
|
||||||
TIME_FUNCTION;
|
TIME_FUNCTION;
|
||||||
@@ -659,7 +745,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get entire grid as frame with specified format
|
// Get entire grid as frame with specified format
|
||||||
frame getGridAsFrame(frame::colormap format = frame::colormap::RGB) {
|
frame getGridAsFrame(frame::colormap format = frame::colormap::RGB) const {
|
||||||
TIME_FUNCTION;
|
TIME_FUNCTION;
|
||||||
Vec2 minCorner, maxCorner;
|
Vec2 minCorner, maxCorner;
|
||||||
getBoundingBox(minCorner, maxCorner);
|
getBoundingBox(minCorner, maxCorner);
|
||||||
@@ -669,6 +755,9 @@ public:
|
|||||||
case frame::colormap::RGB:
|
case frame::colormap::RGB:
|
||||||
Frame = std::move(getGridRegionAsFrameRGB(minCorner, maxCorner));
|
Frame = std::move(getGridRegionAsFrameRGB(minCorner, maxCorner));
|
||||||
break;
|
break;
|
||||||
|
case frame::colormap::RGBA:
|
||||||
|
Frame = std::move(getGridRegionAsFrameRGBA(minCorner, maxCorner));
|
||||||
|
break;
|
||||||
case frame::colormap::BGR:
|
case frame::colormap::BGR:
|
||||||
Frame = std::move(getGridRegionAsFrameBGR(minCorner, maxCorner));
|
Frame = std::move(getGridRegionAsFrameBGR(minCorner, maxCorner));
|
||||||
break;
|
break;
|
||||||
@@ -708,7 +797,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//get bounding box
|
//get bounding box
|
||||||
void getBoundingBox(Vec2& minCorner, Vec2& maxCorner) {
|
void getBoundingBox(Vec2& minCorner, Vec2& maxCorner) const {
|
||||||
TIME_FUNCTION;
|
TIME_FUNCTION;
|
||||||
if (Positions.empty()) {
|
if (Positions.empty()) {
|
||||||
minCorner = Vec2(0, 0);
|
minCorner = Vec2(0, 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user