templated vec2. updated a bunch of stuff.
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
#include "../util/grid/grid3.hpp"
|
#include "../util/grid/grid3.hpp"
|
||||||
#include "../util/output/bmpwriter.hpp"
|
#include "../util/output/bmpwriter.hpp"
|
||||||
#include "../util/output/frame.hpp"
|
#include "../util/output/frame.hpp"
|
||||||
@@ -53,10 +55,10 @@ void setup(defaults config, VoxelGrid& grid) {
|
|||||||
std::cout << "Noise grid generation complete!" << std::endl;
|
std::cout << "Noise grid generation complete!" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void livePreview(VoxelGrid& grid, defaults config, Camera cam) {
|
void livePreview(VoxelGrid& grid, defaults& config, const Camera& cam) {
|
||||||
std::lock_guard<std::mutex> lock(PreviewMutex);
|
std::lock_guard<std::mutex> lock(PreviewMutex);
|
||||||
updatePreview = true;
|
updatePreview = true;
|
||||||
frame currentPreviewFrame = grid.renderFrame(cam.posfor.origin, cam.posfor.direction, cam.up, cam.fov, config.outWidth, config.outHeight, frame::colormap::BGR);
|
frame currentPreviewFrame = grid.renderFrame(cam, Vec2i(config.outWidth, config.outHeight), frame::colormap::RGB);
|
||||||
|
|
||||||
glGenTextures(1, &textu);
|
glGenTextures(1, &textu);
|
||||||
glBindTexture(GL_TEXTURE_2D, textu);
|
glBindTexture(GL_TEXTURE_2D, textu);
|
||||||
@@ -68,13 +70,11 @@ void livePreview(VoxelGrid& grid, defaults config, Camera cam) {
|
|||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, currentPreviewFrame.getWidth(), currentPreviewFrame.getHeight(),
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, currentPreviewFrame.getWidth(), currentPreviewFrame.getHeight(),
|
||||||
0, GL_RGB, GL_UNSIGNED_BYTE, currentPreviewFrame.getData().data());
|
0, GL_RGB, GL_UNSIGNED_BYTE, currentPreviewFrame.getData().data());
|
||||||
|
|
||||||
std::cout << "freeing previous frame" << std::endl;
|
|
||||||
//currentPreviewFrame.free();
|
|
||||||
updatePreview = false;
|
updatePreview = false;
|
||||||
textureInitialized = true;
|
textureInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool savePreview(VoxelGrid& grid, defaults config, Camera cam) {
|
bool savePreview(VoxelGrid& grid, defaults& config, const Camera& cam) {
|
||||||
TIME_FUNCTION;
|
TIME_FUNCTION;
|
||||||
|
|
||||||
std::vector<uint8_t> renderBuffer;
|
std::vector<uint8_t> renderBuffer;
|
||||||
@@ -82,7 +82,7 @@ bool savePreview(VoxelGrid& grid, defaults config, Camera cam) {
|
|||||||
size_t height = config.outHeight;
|
size_t height = config.outHeight;
|
||||||
|
|
||||||
// Render the view
|
// Render the view
|
||||||
frame output = grid.renderFrame(cam.posfor.origin, cam.posfor.direction, cam.up, cam.fov, config.outWidth, config.outHeight, frame::colormap::RGB);
|
frame output = grid.renderFrame(cam, Vec2i(config.outWidth, config.outHeight), frame::colormap::RGB);
|
||||||
//grid.renderOut(renderBuffer, width, height, cam);
|
//grid.renderOut(renderBuffer, width, height, cam);
|
||||||
|
|
||||||
// Save to BMP
|
// Save to BMP
|
||||||
@@ -104,6 +104,64 @@ static void glfw_error_callback(int error, const char* description)
|
|||||||
fprintf(stderr, "GLFW Error %d: %s\n", error, description);
|
fprintf(stderr, "GLFW Error %d: %s\n", error, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Camera movement function
|
||||||
|
void handleCameraMovement(GLFWwindow* window, Camera& cam, float deltaTime) {
|
||||||
|
float moveSpeed = 50.0f * deltaTime; // Adjust speed as needed
|
||||||
|
float rotateSpeed = 50.0f * deltaTime; // Rotation speed
|
||||||
|
|
||||||
|
// Get camera vectors
|
||||||
|
Vec3f forward = cam.posfor.direction.normalized();
|
||||||
|
Vec3f up = cam.up.normalized();
|
||||||
|
Vec3f right = forward.cross(up).normalized();
|
||||||
|
|
||||||
|
// Position movement
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) {
|
||||||
|
cam.posfor.origin = cam.posfor.origin + forward * moveSpeed;
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) {
|
||||||
|
cam.posfor.origin = cam.posfor.origin - forward * moveSpeed;
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS) {
|
||||||
|
cam.posfor.origin = cam.posfor.origin - right * moveSpeed;
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS) {
|
||||||
|
cam.posfor.origin = cam.posfor.origin + right * moveSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vertical movement (optional - add with PageUp/PageDown or other keys)
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_PAGE_UP) == GLFW_PRESS) {
|
||||||
|
cam.posfor.origin = cam.posfor.origin + up * moveSpeed;
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_PAGE_DOWN) == GLFW_PRESS) {
|
||||||
|
cam.posfor.origin = cam.posfor.origin - up * moveSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Camera rotation (using WASD or other keys for rotation)
|
||||||
|
// For simplicity, let's add rotation with Q/E for yaw and R/F for pitch
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) {
|
||||||
|
// Rotate left (yaw)
|
||||||
|
float yaw = -rotateSpeed * deltaTime;
|
||||||
|
// You'll need to add rotation logic to your Camera class
|
||||||
|
// For now, let's assume Camera has a rotateYaw method
|
||||||
|
cam.rotateYaw(yaw);
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS) {
|
||||||
|
// Rotate right (yaw)
|
||||||
|
float yaw = rotateSpeed * deltaTime;
|
||||||
|
cam.rotateYaw(yaw);
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS) {
|
||||||
|
// Look up (pitch)
|
||||||
|
float pitch = rotateSpeed * deltaTime;
|
||||||
|
cam.rotatePitch(pitch);
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_F) == GLFW_PRESS) {
|
||||||
|
// Look down (pitch)
|
||||||
|
float pitch = -rotateSpeed * deltaTime;
|
||||||
|
cam.rotatePitch(pitch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
glfwSetErrorCallback(glfw_error_callback);
|
glfwSetErrorCallback(glfw_error_callback);
|
||||||
if (!glfwInit()) {
|
if (!glfwInit()) {
|
||||||
@@ -147,7 +205,7 @@ int main() {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
glfwMakeContextCurrent(window);
|
glfwMakeContextCurrent(window);
|
||||||
glfwSwapInterval(1);
|
glfwSwapInterval(1);
|
||||||
IMGUI_CHECKVERSION();
|
IMGUI_CHECKVERSION();
|
||||||
ImGui::CreateContext();
|
ImGui::CreateContext();
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
@@ -171,14 +229,58 @@ int main() {
|
|||||||
bool gridInitialized = false;
|
bool gridInitialized = false;
|
||||||
|
|
||||||
Camera cam(config.gridWidth, Vec3f(0,0,0), Vec3f(0,1,0), 80);
|
Camera cam(config.gridWidth, Vec3f(0,0,0), Vec3f(0,1,0), 80);
|
||||||
|
|
||||||
|
// Variables for framerate limiting
|
||||||
|
const double targetFrameTime = 1.0 / config.fps; // 30 FPS
|
||||||
|
double lastFrameTime = glfwGetTime();
|
||||||
|
double accumulator = 0.0;
|
||||||
|
|
||||||
|
// For camera movement
|
||||||
|
bool cameraMoved = false;
|
||||||
|
double lastUpdateTime = glfwGetTime();
|
||||||
|
|
||||||
while (!glfwWindowShouldClose(window)) {
|
while (!glfwWindowShouldClose(window)) {
|
||||||
|
double currentTime = glfwGetTime();
|
||||||
|
double deltaTime = currentTime - lastFrameTime;
|
||||||
|
lastFrameTime = currentTime;
|
||||||
|
|
||||||
|
// Accumulate time
|
||||||
|
accumulator += deltaTime;
|
||||||
|
|
||||||
|
// Limit framerate
|
||||||
|
if (accumulator < targetFrameTime) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::duration<double>(targetFrameTime - accumulator));
|
||||||
|
currentTime = glfwGetTime();
|
||||||
|
accumulator = targetFrameTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle camera movement
|
||||||
|
if (gridInitialized) {
|
||||||
|
float frameDeltaTime = static_cast<float>(targetFrameTime); // Use fixed delta for consistent movement
|
||||||
|
handleCameraMovement(window, cam, frameDeltaTime);
|
||||||
|
|
||||||
|
// Check if any camera movement keys are pressed
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS ||
|
||||||
|
glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS ||
|
||||||
|
glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS ||
|
||||||
|
glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS ||
|
||||||
|
glfwGetKey(window, GLFW_KEY_PAGE_UP) == GLFW_PRESS ||
|
||||||
|
glfwGetKey(window, GLFW_KEY_PAGE_DOWN) == GLFW_PRESS ||
|
||||||
|
glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS ||
|
||||||
|
glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS ||
|
||||||
|
glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS ||
|
||||||
|
glfwGetKey(window, GLFW_KEY_F) == GLFW_PRESS) {
|
||||||
|
cameraMoved = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
|
||||||
// Start the Dear ImGui frame
|
// Start the Dear ImGui frame
|
||||||
ImGui_ImplOpenGL3_NewFrame();
|
ImGui_ImplOpenGL3_NewFrame();
|
||||||
ImGui_ImplGlfw_NewFrame();
|
ImGui_ImplGlfw_NewFrame();
|
||||||
ImGui::NewFrame();
|
ImGui::NewFrame();
|
||||||
|
|
||||||
{
|
{
|
||||||
ImGui::Begin("settings");
|
ImGui::Begin("settings");
|
||||||
|
|
||||||
@@ -199,6 +301,22 @@ int main() {
|
|||||||
setup(config, grid);
|
setup(config, grid);
|
||||||
gridInitialized = true;
|
gridInitialized = true;
|
||||||
savePreview(grid, config, cam);
|
savePreview(grid, config, cam);
|
||||||
|
cameraMoved = true; // Force preview update after generation
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display camera position
|
||||||
|
if (gridInitialized) {
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::Text("Camera Position:");
|
||||||
|
ImGui::Text("X: %.2f, Y: %.2f, Z: %.2f",
|
||||||
|
cam.posfor.origin.x,
|
||||||
|
cam.posfor.origin.y,
|
||||||
|
cam.posfor.origin.z);
|
||||||
|
ImGui::Text("Controls:");
|
||||||
|
ImGui::BulletText("Arrow Keys: Move camera");
|
||||||
|
ImGui::BulletText("Page Up/Down: Move vertically");
|
||||||
|
ImGui::BulletText("Q/E: Rotate left/right");
|
||||||
|
ImGui::BulletText("R/F: Rotate up/down");
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
@@ -208,7 +326,7 @@ int main() {
|
|||||||
ImGui::Begin("Preview");
|
ImGui::Begin("Preview");
|
||||||
|
|
||||||
if (gridInitialized && textureInitialized) {
|
if (gridInitialized && textureInitialized) {
|
||||||
ImGui::Image((void*)(intptr_t)textu,ImVec2(config.outWidth, config.outHeight));
|
ImGui::Image((void*)(intptr_t)textu, ImVec2(config.outWidth, config.outHeight));
|
||||||
} else if (gridInitialized) {
|
} else if (gridInitialized) {
|
||||||
ImGui::Text("Preview not generated yet");
|
ImGui::Text("Preview not generated yet");
|
||||||
} else {
|
} else {
|
||||||
@@ -218,11 +336,19 @@ int main() {
|
|||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gridInitialized && updatePreview == false) {
|
// Update preview if camera moved or enough time has passed
|
||||||
livePreview(grid, config, cam);
|
if (gridInitialized && !updatePreview) {
|
||||||
|
double timeSinceLastUpdate = currentTime - lastUpdateTime;
|
||||||
|
if (cameraMoved || timeSinceLastUpdate > 0.1) { // Update at least every 0.1 seconds
|
||||||
|
livePreview(grid, config, cam);
|
||||||
|
lastUpdateTime = currentTime;
|
||||||
|
cameraMoved = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset accumulator for next frame
|
||||||
|
accumulator -= targetFrameTime;
|
||||||
|
|
||||||
// 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);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define GRID3_HPP
|
#define GRID3_HPP
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include "../vectorlogic/vec2.hpp"
|
||||||
#include "../vectorlogic/vec3.hpp"
|
#include "../vectorlogic/vec3.hpp"
|
||||||
#include "../vectorlogic/vec4.hpp"
|
#include "../vectorlogic/vec4.hpp"
|
||||||
#include "../timing_decorator.hpp"
|
#include "../timing_decorator.hpp"
|
||||||
@@ -24,6 +25,38 @@ struct Camera {
|
|||||||
Vec3f up;
|
Vec3f up;
|
||||||
float fov;
|
float fov;
|
||||||
Camera(Vec3f pos, Vec3f viewdir, Vec3f up, float fov = 80) : posfor(Ray3f(pos, viewdir)), up(up), fov(fov) {}
|
Camera(Vec3f pos, Vec3f viewdir, Vec3f up, float fov = 80) : posfor(Ray3f(pos, viewdir)), up(up), fov(fov) {}
|
||||||
|
|
||||||
|
void rotateYaw(float angle) {
|
||||||
|
float cosA = cos(angle);
|
||||||
|
float sinA = sin(angle);
|
||||||
|
|
||||||
|
Vec3f right = posfor.direction.cross(up).normalized();
|
||||||
|
posfor.direction = posfor.direction * cosA + right * sinA;
|
||||||
|
posfor.direction = posfor.direction.normalized();
|
||||||
|
}
|
||||||
|
|
||||||
|
void rotatePitch(float angle) {
|
||||||
|
float cosA = cos(angle);
|
||||||
|
float sinA = sin(angle);
|
||||||
|
|
||||||
|
Vec3f right = posfor.direction.cross(up).normalized();
|
||||||
|
posfor.direction = posfor.direction * cosA + up * sinA;
|
||||||
|
posfor.direction = posfor.direction.normalized();
|
||||||
|
|
||||||
|
up = right.cross(posfor.direction).normalized();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3f forward() const {
|
||||||
|
return (posfor.direction - posfor.origin).normalized();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3f right() const {
|
||||||
|
return forward().cross(up).normalized();
|
||||||
|
}
|
||||||
|
|
||||||
|
float fovRad() const {
|
||||||
|
return fov * (M_PI / 180);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class VoxelGrid {
|
class VoxelGrid {
|
||||||
@@ -207,30 +240,28 @@ public:
|
|||||||
int getDepth() const {
|
int getDepth() const {
|
||||||
return gridSize.z;
|
return gridSize.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
frame renderFrame(const Vec3f& CamPos, const Vec3f& dir, const Vec3f& up, float fov, int outW, int outH, frame::colormap colorformat = frame::colormap::RGB) {
|
frame renderFrame(const Camera& cam, Vec2i resolution, frame::colormap colorformat = frame::colormap::RGB) {
|
||||||
TIME_FUNCTION;
|
TIME_FUNCTION;
|
||||||
Vec3f forward = (dir - CamPos).normalized();
|
Vec3f forward = cam.forward();
|
||||||
Vec3f right = forward.cross(up).normalized();
|
Vec3f right = cam.right();
|
||||||
Vec3f upCor = right.cross(forward).normalized();
|
Vec3f upCor = right.cross(forward).normalized();
|
||||||
float aspect = static_cast<float>(outW) / static_cast<float>(outH);
|
float aspect = resolution.aspect();
|
||||||
float fovRad = radians(fov);
|
float fovRad = cam.fovRad();
|
||||||
float viewH = 2 * tan(fovRad / 2);
|
float viewH = 2 * tan(fovRad / 2);
|
||||||
float viewW = viewH * aspect;
|
float viewW = viewH * aspect;
|
||||||
float maxDist = std::sqrt(gridSize.lengthSquared()) * binSize;
|
float maxDist = std::sqrt(gridSize.lengthSquared()) * binSize;
|
||||||
frame outFrame(outH, outW, frame::colormap::RGB);
|
frame outFrame(resolution.x, resolution.y, frame::colormap::RGB);
|
||||||
std::vector<uint8_t> colorBuffer(outW * outH * 3);
|
std::vector<uint8_t> colorBuffer(resolution.x * resolution.y * 3);
|
||||||
std::cout << "a" << std::endl;
|
|
||||||
#pragma omp parallel for
|
#pragma omp parallel for
|
||||||
for (int y = 0; y < outH; y++) {
|
for (int y = 0; y < resolution.x; y++) {
|
||||||
float v = (static_cast<float>(y) / static_cast<float>(outH - 1)) - 0.5f;
|
float v = (static_cast<float>(y) / static_cast<float>(resolution.x - 1)) - 0.5f;
|
||||||
std::cout << "b";
|
for (int x = 0; x < resolution.y; x++) {
|
||||||
for (int x = 0; x < outW; x++) {
|
|
||||||
std::vector<Vec3i> hitVoxels;
|
std::vector<Vec3i> hitVoxels;
|
||||||
float u = (static_cast<float>(x) / static_cast<float>(outW - 1)) - 0.5f;
|
float u = (static_cast<float>(x) / static_cast<float>(resolution.y - 1)) - 0.5f;
|
||||||
Vec3f rayDirWorld = (forward + right * (u * viewW) + upCor * (v * viewH)).normalized();
|
Vec3f rayDirWorld = (forward + right * (u * viewW) + upCor * (v * viewH)).normalized();
|
||||||
Vec3f rayEnd = CamPos + rayDirWorld * maxDist;
|
Vec3f rayEnd = cam.posfor.origin + rayDirWorld * maxDist;
|
||||||
Vec3d rayStartGrid = CamPos.toDouble() / binSize;
|
Vec3d rayStartGrid = cam.posfor.origin.toDouble() / binSize;
|
||||||
Vec3d rayEndGrid = rayEnd.toDouble() / binSize;
|
Vec3d rayEndGrid = rayEnd.toDouble() / binSize;
|
||||||
voxelTraverse(rayStartGrid, rayEndGrid, hitVoxels);
|
voxelTraverse(rayStartGrid, rayEndGrid, hitVoxels);
|
||||||
Vec3ui8 hitColor(10, 10, 255);
|
Vec3ui8 hitColor(10, 10, 255);
|
||||||
@@ -244,34 +275,31 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::cout << "c";
|
|
||||||
hitVoxels.clear();
|
hitVoxels.clear();
|
||||||
hitVoxels.shrink_to_fit();
|
hitVoxels.shrink_to_fit();
|
||||||
// Set pixel color in buffer
|
// Set pixel color in buffer
|
||||||
switch (colorformat) {
|
switch (colorformat) {
|
||||||
case frame::colormap::RGB: {
|
|
||||||
int idx = (y * outW + x) * 3;
|
|
||||||
colorBuffer[idx + 0] = hitColor.x;
|
|
||||||
colorBuffer[idx + 1] = hitColor.y;
|
|
||||||
colorBuffer[idx + 2] = hitColor.z;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case frame::colormap::BGRA: {
|
case frame::colormap::BGRA: {
|
||||||
int idx = (y * outW + x) * 4;
|
int idx = (y * resolution.y + x) * 4;
|
||||||
colorBuffer[idx + 3] = hitColor.x;
|
colorBuffer[idx + 3] = hitColor.x;
|
||||||
colorBuffer[idx + 2] = hitColor.y;
|
colorBuffer[idx + 2] = hitColor.y;
|
||||||
colorBuffer[idx + 1] = hitColor.z;
|
colorBuffer[idx + 1] = hitColor.z;
|
||||||
colorBuffer[idx + 0] = 255;
|
colorBuffer[idx + 0] = 255;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case frame::colormap::RGB:
|
||||||
|
default: {
|
||||||
|
int idx = (y * resolution.y + x) * 3;
|
||||||
|
colorBuffer[idx + 0] = hitColor.x;
|
||||||
|
colorBuffer[idx + 1] = hitColor.y;
|
||||||
|
colorBuffer[idx + 2] = hitColor.z;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::cout << "b" << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
outFrame.setData(colorBuffer);
|
outFrame.setData(colorBuffer);
|
||||||
std::cout << "d" << std::endl;
|
|
||||||
return outFrame;
|
return outFrame;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,12 +23,12 @@ private:
|
|||||||
return t * t * t * (t * (t * 6 - 15) + 10);
|
return t * t * t * (t * (t * 6 - 15) + 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 GetConstantVector(int v) {
|
Vec2f GetConstantVector(int v) {
|
||||||
int h = v & 3;
|
int h = v & 3;
|
||||||
if (h == 0) return Vec2(1,1);
|
if (h == 0) return Vec2f(1,1);
|
||||||
else if (h == 1) return Vec2(-1,1);
|
else if (h == 1) return Vec2f(-1,1);
|
||||||
else if (h == 2) return Vec2(-1,-1);
|
else if (h == 2) return Vec2f(-1,-1);
|
||||||
else return Vec2(1,-1);
|
else return Vec2f(1,-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3ui8 GetConstantVector3(int v) {
|
Vec3ui8 GetConstantVector3(int v) {
|
||||||
@@ -70,7 +70,8 @@ public:
|
|||||||
initializePermutation();
|
initializePermutation();
|
||||||
}
|
}
|
||||||
|
|
||||||
float permute(Vec2 point) {
|
template<typename T>
|
||||||
|
float permute(Vec2<T> point) {
|
||||||
TIME_FUNCTION;
|
TIME_FUNCTION;
|
||||||
float x = point.x;
|
float x = point.x;
|
||||||
float y = point.y;
|
float y = point.y;
|
||||||
|
|||||||
@@ -5,12 +5,17 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
class Vec2 {
|
class Vec2 {
|
||||||
public:
|
public:
|
||||||
float x, y;
|
T x, y;
|
||||||
|
|
||||||
Vec2() : x(0), y(0) {}
|
Vec2() : x(0), y(0) {}
|
||||||
Vec2(float x, float y) : x(x), y(y) {}
|
Vec2(T x, T y) : x(x), y(y) {}
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
explicit Vec2(const Vec2<U>& other) : x(static_cast<T>(other.x)), y(static_cast<T>(other.y)) {}
|
||||||
|
|
||||||
Vec2& move(const Vec2 newpos) {
|
Vec2& move(const Vec2 newpos) {
|
||||||
x = newpos.x;
|
x = newpos.x;
|
||||||
y = newpos.y;
|
y = newpos.y;
|
||||||
@@ -32,29 +37,34 @@ class Vec2 {
|
|||||||
Vec2 operator/(const Vec2& other) const {
|
Vec2 operator/(const Vec2& other) const {
|
||||||
return Vec2(x / other.x, y / other.y);
|
return Vec2(x / other.x, y / other.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 operator+(float scalar) const {
|
template<typename U>
|
||||||
|
Vec2 operator+(U scalar) const {
|
||||||
return Vec2(x + scalar, y + scalar);
|
return Vec2(x + scalar, y + scalar);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 operator-(float scalar) const {
|
template<typename U>
|
||||||
|
Vec2 operator-(U scalar) const {
|
||||||
return Vec2(x - scalar, y - scalar);
|
return Vec2(x - scalar, y - scalar);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 operator-() const {
|
Vec2 operator-() const {
|
||||||
return Vec2(-x, -y);
|
return Vec2(-x, -y);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 operator*(float scalar) const {
|
template<typename U>
|
||||||
|
Vec2 operator*(U scalar) const {
|
||||||
return Vec2(x * scalar, y * scalar);
|
return Vec2(x * scalar, y * scalar);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 operator/(float scalar) const {
|
template<typename U>
|
||||||
|
Vec2 operator/(U scalar) const {
|
||||||
return Vec2(x / scalar, y / scalar);
|
return Vec2(x / scalar, y / scalar);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2& operator=(float scalar) {
|
template<typename U>
|
||||||
x = y = scalar;
|
Vec2& operator=(U scalar) {
|
||||||
|
x = y = static_cast<T>(scalar);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,57 +92,64 @@ class Vec2 {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2& operator+=(float scalar) {
|
template<typename U>
|
||||||
|
Vec2& operator+=(U scalar) {
|
||||||
x += scalar;
|
x += scalar;
|
||||||
y += scalar;
|
y += scalar;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2& operator-=(float scalar) {
|
template<typename U>
|
||||||
|
Vec2& operator-=(U scalar) {
|
||||||
x -= scalar;
|
x -= scalar;
|
||||||
y -= scalar;
|
y -= scalar;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2& operator*=(float scalar) {
|
template<typename U>
|
||||||
|
Vec2& operator*=(U scalar) {
|
||||||
x *= scalar;
|
x *= scalar;
|
||||||
y *= scalar;
|
y *= scalar;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2& operator/=(float scalar) {
|
template<typename U>
|
||||||
|
Vec2& operator/=(U scalar) {
|
||||||
x /= scalar;
|
x /= scalar;
|
||||||
y /= scalar;
|
y /= scalar;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
float dot(const Vec2& other) const {
|
T dot(const Vec2& other) const {
|
||||||
return x * other.x + y * other.y;
|
return x * other.x + y * other.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
float length() const {
|
template<typename U = float>
|
||||||
return std::sqrt(x * x + y * y);
|
U length() const {
|
||||||
|
return std::sqrt(static_cast<U>(x * x + y * y));
|
||||||
}
|
}
|
||||||
|
|
||||||
float lengthSquared() const {
|
T lengthSquared() const {
|
||||||
return x * x + y * y;
|
return x * x + y * y;
|
||||||
}
|
}
|
||||||
|
|
||||||
float distance(const Vec2& other) const {
|
template<typename U = float>
|
||||||
return (*this - other).length();
|
U distance(const Vec2& other) const {
|
||||||
|
return (*this - other).template length<U>();
|
||||||
}
|
}
|
||||||
|
|
||||||
float distanceSquared(const Vec2& other) const {
|
T distanceSquared(const Vec2& other) const {
|
||||||
Vec2 diff = *this - other;
|
Vec2 diff = *this - other;
|
||||||
return diff.x * diff.x + diff.y * diff.y;
|
return diff.x * diff.x + diff.y * diff.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 normalized() const {
|
template<typename U = float>
|
||||||
float len = length();
|
Vec2<U> normalized() const {
|
||||||
|
auto len = length<U>();
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
return *this / len;
|
return Vec2<U>(static_cast<U>(x) / len, static_cast<U>(y) / len);
|
||||||
}
|
}
|
||||||
return *this;
|
return Vec2<U>(static_cast<U>(x), static_cast<U>(y));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const Vec2& other) const {
|
bool operator==(const Vec2& other) const {
|
||||||
@@ -190,118 +207,155 @@ class Vec2 {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 clamp(float minVal, float maxVal) const {
|
template<typename U>
|
||||||
|
Vec2 clamp(U minVal, U maxVal) const {
|
||||||
return Vec2(
|
return Vec2(
|
||||||
std::clamp(x, minVal, maxVal),
|
std::clamp(x, static_cast<T>(minVal), static_cast<T>(maxVal)),
|
||||||
std::clamp(y, minVal, maxVal)
|
std::clamp(y, static_cast<T>(minVal), static_cast<T>(maxVal))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isZero(float epsilon = 1e-10f) const {
|
template<typename U = float>
|
||||||
return std::abs(x) < epsilon && std::abs(y) < epsilon;
|
bool isZero(U epsilon = static_cast<U>(1e-10)) const {
|
||||||
|
return std::abs(static_cast<U>(x)) < epsilon &&
|
||||||
|
std::abs(static_cast<U>(y)) < epsilon;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool equals(const Vec2& other, float epsilon = 1e-10f) const {
|
template<typename U = float>
|
||||||
return std::abs(x - other.x) < epsilon &&
|
bool equals(const Vec2& other, U epsilon = static_cast<U>(1e-10)) const {
|
||||||
std::abs(y - other.y) < epsilon;
|
return std::abs(static_cast<U>(x - other.x)) < epsilon &&
|
||||||
|
std::abs(static_cast<U>(y - other.y)) < epsilon;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend Vec2 operator+(float scalar, const Vec2& vec) {
|
|
||||||
return Vec2(scalar + vec.x, scalar + vec.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec2 operator-(float scalar, const Vec2& vec) {
|
|
||||||
return Vec2(scalar - vec.x, scalar - vec.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec2 operator*(float scalar, const Vec2& vec) {
|
|
||||||
return Vec2(scalar * vec.x, scalar * vec.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec2 operator/(float scalar, const Vec2& vec) {
|
|
||||||
return Vec2(scalar / vec.x, scalar / vec.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec2 perpendicular() const {
|
Vec2 perpendicular() const {
|
||||||
return Vec2(-y, x);
|
return Vec2(-y, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 reflect(const Vec2& normal) const {
|
template<typename U = float>
|
||||||
return *this - 2.0f * this->dot(normal) * normal;
|
Vec2<U> reflect(const Vec2<U>& normal) const {
|
||||||
|
auto this_f = Vec2<U>(static_cast<U>(x), static_cast<U>(y));
|
||||||
|
return this_f - static_cast<U>(2.0) * this_f.dot(normal) * normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 lerp(const Vec2& other, float t) const {
|
template<typename U = float>
|
||||||
t = std::clamp(t, 0.0f, 1.0f);
|
Vec2<U> lerp(const Vec2<U>& other, U t) const {
|
||||||
return *this + (other - *this) * t;
|
t = std::clamp(t, static_cast<U>(0.0), static_cast<U>(1.0));
|
||||||
|
auto this_f = Vec2<U>(static_cast<U>(x), static_cast<U>(y));
|
||||||
|
return this_f + (other - this_f) * t;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 slerp(const Vec2& other, float t) const {
|
template<typename U = float>
|
||||||
t = std::clamp(t, 0.0f, 1.0f);
|
Vec2<U> slerp(const Vec2<U>& other, U t) const {
|
||||||
float dot = this->dot(other);
|
t = std::clamp(t, static_cast<U>(0.0), static_cast<U>(1.0));
|
||||||
dot = std::clamp(dot, -1.0f, 1.0f);
|
auto this_f = Vec2<U>(static_cast<U>(x), static_cast<U>(y));
|
||||||
|
U dot = this_f.dot(other);
|
||||||
|
dot = std::clamp(dot, static_cast<U>(-1.0), static_cast<U>(1.0));
|
||||||
|
|
||||||
float theta = std::acos(dot) * t;
|
U theta = std::acos(dot) * t;
|
||||||
Vec2 relative = other - *this * dot;
|
auto relative = other - this_f * dot;
|
||||||
relative = relative.normalized();
|
relative = relative.normalized();
|
||||||
|
|
||||||
return (*this * std::cos(theta)) + (relative * std::sin(theta));
|
return (this_f * std::cos(theta)) + (relative * std::sin(theta));
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 rotate(float angle) const {
|
template<typename U = float>
|
||||||
float cosA = std::cos(angle);
|
Vec2<U> rotate(U angle) const {
|
||||||
float sinA = std::sin(angle);
|
U cosA = std::cos(angle);
|
||||||
return Vec2(x * cosA - y * sinA, x * sinA + y * cosA);
|
U sinA = std::sin(angle);
|
||||||
|
return Vec2<U>(
|
||||||
|
static_cast<U>(x) * cosA - static_cast<U>(y) * sinA,
|
||||||
|
static_cast<U>(x) * sinA + static_cast<U>(y) * cosA
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
float angle() const {
|
template<typename U = float>
|
||||||
return std::atan2(y, x);
|
U angle() const {
|
||||||
|
return std::atan2(static_cast<U>(y), static_cast<U>(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
float angleTo(const Vec2& other) const {
|
template<typename U = float>
|
||||||
return std::acos(this->dot(other) / (this->length() * other.length()));
|
U angleTo(const Vec2<U>& other) const {
|
||||||
|
auto this_f = Vec2<U>(static_cast<U>(x), static_cast<U>(y));
|
||||||
|
return std::acos(this_f.dot(other) / (this_f.length() * other.length()));
|
||||||
}
|
}
|
||||||
|
|
||||||
float directionTo(const Vec2& other) const {
|
template<typename U = float>
|
||||||
Vec2 direction = other - *this;
|
U directionTo(const Vec2<U>& other) const {
|
||||||
|
auto this_f = Vec2<U>(static_cast<U>(x), static_cast<U>(y));
|
||||||
|
auto direction = other - this_f;
|
||||||
return direction.angle();
|
return direction.angle();
|
||||||
}
|
}
|
||||||
|
|
||||||
float& operator[](int index) {
|
T& operator[](int index) {
|
||||||
return (&x)[index];
|
return (&x)[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
const float& operator[](int index) const {
|
const T& operator[](int index) const {
|
||||||
return (&x)[index];
|
return (&x)[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string toString() const {
|
std::string toString() const {
|
||||||
return "(" + std::to_string(x) + ", " + std::to_string(y) + ")";
|
return "(" + std::to_string(x) + ", " + std::to_string(y) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& os) {
|
std::ostream& operator<<(std::ostream& os) {
|
||||||
os << toString();
|
os << toString();
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Hash {
|
struct Hash {
|
||||||
std::size_t operator()(const Vec2& v) const {
|
std::size_t operator()(const Vec2& v) const {
|
||||||
return std::hash<float>()(v.x) ^ (std::hash<float>()(v.y) << 1);
|
return std::hash<T>()(v.x) ^ (std::hash<T>()(v.y) << 1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
float aspect() {
|
||||||
|
return static_cast<float>(x) / static_cast<float>(y);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream& os, const Vec2& vec) {
|
template<typename T>
|
||||||
|
inline std::ostream& operator<<(std::ostream& os, const Vec2<T>& vec) {
|
||||||
os << vec.toString();
|
os << vec.toString();
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
auto operator+(U scalar, const Vec2<T>& vec) -> Vec2<decltype(scalar + vec.x)> {
|
||||||
|
using ResultType = decltype(scalar + vec.x);
|
||||||
|
return Vec2<ResultType>(scalar + vec.x, scalar + vec.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
auto operator-(U scalar, const Vec2<T>& vec) -> Vec2<decltype(scalar - vec.x)> {
|
||||||
|
using ResultType = decltype(scalar - vec.x);
|
||||||
|
return Vec2<ResultType>(scalar - vec.x, scalar - vec.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
auto operator*(U scalar, const Vec2<T>& vec) -> Vec2<decltype(scalar * vec.x)> {
|
||||||
|
using ResultType = decltype(scalar * vec.x);
|
||||||
|
return Vec2<ResultType>(scalar * vec.x, scalar * vec.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
auto operator/(U scalar, const Vec2<T>& vec) -> Vec2<decltype(scalar / vec.x)> {
|
||||||
|
using ResultType = decltype(scalar / vec.x);
|
||||||
|
return Vec2<ResultType>(scalar / vec.x, scalar / vec.y);
|
||||||
|
}
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
template<>
|
template<typename T>
|
||||||
struct hash<Vec2> {
|
struct hash<Vec2<T>> {
|
||||||
size_t operator()(const Vec2& v) const {
|
size_t operator()(const Vec2<T>& v) const {
|
||||||
return hash<float>()(v.x) ^ (hash<float>()(v.y) << 1);
|
return hash<T>()(v.x) ^ (hash<T>()(v.y) << 1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using Vec2f = Vec2<float>;
|
||||||
|
using Vec2d = Vec2<double>;
|
||||||
|
using Vec2i = Vec2<int>;
|
||||||
|
using Vec2u = Vec2<unsigned int>;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -17,7 +17,7 @@ public:
|
|||||||
Vec3(T scalar) : x(scalar), y(scalar), z(scalar) {}
|
Vec3(T scalar) : x(scalar), y(scalar), z(scalar) {}
|
||||||
Vec3(float acd[3]) : x(acd[0]), y(acd[1]), z(acd[2]) {}
|
Vec3(float acd[3]) : x(acd[0]), y(acd[1]), z(acd[2]) {}
|
||||||
|
|
||||||
Vec3(const class Vec2& vec2, T z = 0);
|
Vec3(const class Vec2<T>& vec2, T z = 0);
|
||||||
|
|
||||||
Vec3& move(const Vec3& newpos) {
|
Vec3& move(const Vec3& newpos) {
|
||||||
x = newpos.x;
|
x = newpos.x;
|
||||||
|
|||||||
Reference in New Issue
Block a user