From c0d15a0b9f8d11d1e13a330bd0f0130aad0907f5 Mon Sep 17 00:00:00 2001 From: Yggdrasil75 Date: Tue, 27 Jan 2026 16:11:09 -0500 Subject: [PATCH] pushing camera eigen update, and other fixes --- tests/g3etest.cpp | 89 ++++++++++++++++++++++--------- util/grid/camera.hpp | 110 +++++++++++++++++++++++++++------------ util/grid/grid3eigen.hpp | 32 +++++++----- 3 files changed, 160 insertions(+), 71 deletions(-) diff --git a/tests/g3etest.cpp b/tests/g3etest.cpp index 089b4df..942f644 100644 --- a/tests/g3etest.cpp +++ b/tests/g3etest.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "../util/grid/grid3eigen.hpp" #include "../util/output/bmpwriter.hpp" @@ -52,41 +53,79 @@ int main() { // Set point data with larger size for visibility // Note: The third parameter is size, which should be radius squared for intersection test - octree.set(i, pos, greenColor, 1.f, true); + octree.set(i, pos, true, greenColor, 1.0, true); pointCount++; } std::cout << "Added " << pointCount << " points to the green sphere." << std::endl; - // Set camera parameters - PointType cameraPos(0.0f, 0.0f, 3.0f); // camera position - PointType lookDir(0.0f, 0.0f, -1.0f); // looking at sphere - PointType upDir(0.0f, 1.0f, 0.0f); // up direction - PointType rightDir(1.0f, 0.0f, 0.0f); // right direction - // Render parameters - int width = 800; - int height = 600; + int width = 2048; + int height = 2048; - std::cout << "Rendering frame..." << std::endl; + // Set up random number generator for camera positions + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution angleDist(0.0f, 2.0f * M_PI); + std::uniform_real_distribution elevationDist(0.1f, M_PI - 0.1f); // Avoid poles + std::uniform_real_distribution radiusDist(2.0f, 4.0f); // Distance from sphere - // Render frame - frame renderedFrame = octree.renderFrame(cameraPos, lookDir, upDir, rightDir, height, width, frame::colormap::RGB); + // Generate and save 15 random views + const int numViews = 15; - std::cout << "Frame rendered. Dimensions: " - << renderedFrame.getWidth() << "x" - << renderedFrame.getHeight() << std::endl; - - // Save as BMP - std::string filename = "output/green_sphere.bmp"; - std::cout << "Saving to " << filename << "..." << std::endl; - - if (BMPWriter::saveBMP(filename, renderedFrame)) { - std::cout << "Successfully saved green sphere to " << filename << std::endl; - } else { - std::cerr << "Failed to save BMP file!" << std::endl; - return 1; + for (int viewIndex = 0; viewIndex < numViews; ++viewIndex) { + std::cout << "\nRendering view " << (viewIndex + 1) << " of " << numViews << "..." << std::endl; + + // Generate random spherical coordinates for camera position + float azimuth = angleDist(gen); + float elevation = elevationDist(gen); + float camRadius = radiusDist(gen); + + // Convert to Cartesian coordinates for camera position + float camX = camRadius * sin(elevation) * cos(azimuth); + float camY = camRadius * sin(elevation) * sin(azimuth); + float camZ = camRadius * cos(elevation); + + // Camera looks at the origin (center of sphere) + Vector3f cameraPos(camX, camY, camZ); + Vector3f lookAt(0.0f, 0.0f, 0.0f); + + // Calculate camera direction (from position to lookAt) + Vector3f cameraDir = (lookAt - cameraPos).normalized(); + + // Calculate up vector (avoid gimbal lock) + Vector3f worldUp(0.0f, 1.0f, 0.0f); + Vector3f right = cameraDir.cross(worldUp).normalized(); + Vector3f cameraUp = right.cross(cameraDir).normalized(); + + // Create camera + Camera cam(cameraPos, cameraDir, cameraUp, 80); + + // Render frame + frame renderedFrame = octree.renderFrame(cam, height, width, frame::colormap::RGB); + + std::cout << "Frame rendered. Dimensions: " + << renderedFrame.getWidth() << "x" + << renderedFrame.getHeight() << std::endl; + + // Save as BMP + std::string filename = "output/green_sphere_view_" + std::to_string(viewIndex + 1) + ".bmp"; + std::cout << "Saving to " << filename << "..." << std::endl; + + if (BMPWriter::saveBMP(filename, renderedFrame)) { + std::cout << "Successfully saved view to " << filename << std::endl; + + // Print camera position for reference + std::cout << "Camera position: (" << camX << ", " << camY << ", " << camZ << ")" << std::endl; + } else { + std::cerr << "Failed to save BMP file: " << filename << std::endl; + } + + // Small delay to ensure unique random seeds + std::this_thread::sleep_for(std::chrono::milliseconds(10)); } + std::cout << "\nAll " << numViews << " views have been saved to the output directory." << std::endl; + return 0; } \ No newline at end of file diff --git a/util/grid/camera.hpp b/util/grid/camera.hpp index 9879c2e..fa1ab3f 100644 --- a/util/grid/camera.hpp +++ b/util/grid/camera.hpp @@ -1,60 +1,106 @@ #ifndef camera_hpp #define camera_hpp -#include -#include -#include -#include -#include -#include "../vectorlogic/vec2.hpp" -#include "../vectorlogic/vec3.hpp" -#include "../vectorlogic/vec4.hpp" -#include "../timing_decorator.hpp" -#include "../output/frame.hpp" -#include "../noise/pnoise2.hpp" -#include "../vecmat/mat4.hpp" -#include "../vecmat/mat3.hpp" -#include -#include +#include "../../eigen/Eigen/Dense" +#include #include "../basicdefines.hpp" -#include + +using Eigen::Vector3f; +using Eigen::Matrix3f; struct Camera { - Ray3f posfor; - Vec3f up; + Vector3f origin; + Vector3f direction; + Vector3f up; float fov; - Camera(Vec3f pos, Vec3f viewdir, Vec3f up, float fov = 80) : posfor(Ray3f(pos, viewdir)), up(up), fov(fov) {} + + Camera(const Vector3f& pos, const Vector3f& viewdir, const Vector3f& up, float fov = 80) + : origin(pos), direction(viewdir), up(up.normalized()), 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(); + Vector3f right = direction.cross(up).normalized(); + + // Rotate around up vector (yaw) + Matrix3f rotation; + rotation = Eigen::AngleAxisf(angle, up); + direction = rotation * direction; } void rotatePitch(float angle) { - float cosA = cos(angle); - float sinA = sin(angle); + // Clamp pitch to avoid gimbal lock + Vector3f right = direction.cross(up).normalized(); - Vec3f right = posfor.direction.cross(up).normalized(); - posfor.direction = posfor.direction * cosA + up * sinA; - posfor.direction = posfor.direction.normalized(); + // Rotate around right vector (pitch) + Matrix3f rotation; + rotation = Eigen::AngleAxisf(angle, right); + direction = rotation * direction; + direction.normalize(); - up = right.cross(posfor.direction).normalized(); + // Recalculate up vector to maintain orthogonality + up = right.cross(direction).normalized(); } - Vec3f forward() const { - return (posfor.direction - posfor.origin).normalized(); + Vector3f forward() const { + return direction.normalized(); } - Vec3f right() const { + Vector3f right() const { return forward().cross(up).normalized(); } float fovRad() const { - return fov * (M_PI / 180); + return fov * (M_PI / 180.0f); + } + + // Additional useful methods + void moveForward(float distance) { + origin += forward() * distance; + } + + void moveRight(float distance) { + origin += right() * distance; + } + + void moveUp(float distance) { + origin += up * distance; + } + + // Get view matrix (lookAt matrix) + Eigen::Matrix4f getViewMatrix() const { + Vector3f f = forward(); + Vector3f r = right(); + Vector3f u = up; + + Eigen::Matrix4f view = Eigen::Matrix4f::Identity(); + + view(0, 0) = r.x(); view(0, 1) = r.y(); view(0, 2) = r.z(); + view(1, 0) = u.x(); view(1, 1) = u.y(); view(1, 2) = u.z(); + view(2, 0) = -f.x(); view(2, 1) = -f.y(); view(2, 2) = -f.z(); + + view(0, 3) = -r.dot(origin); + view(1, 3) = -u.dot(origin); + view(2, 3) = f.dot(origin); + + return view; + } + + // Get projection matrix (perspective) + Eigen::Matrix4f getProjectionMatrix(float aspectRatio, float nearPlane = 0.1f, float farPlane = 100.0f) const { + float fovrad = fovRad(); + float tanHalfFov = tan(fovrad / 2.0f); + + Eigen::Matrix4f projection = Eigen::Matrix4f::Zero(); + + projection(0, 0) = 1.0f / (aspectRatio * tanHalfFov); + projection(1, 1) = 1.0f / tanHalfFov; + projection(2, 2) = -(farPlane + nearPlane) / (farPlane - nearPlane); + projection(3, 2) = -1.0f; + projection(2, 3) = -(2.0f * farPlane * nearPlane) / (farPlane - nearPlane); + + return projection; } }; diff --git a/util/grid/grid3eigen.hpp b/util/grid/grid3eigen.hpp index 2fb5287..d47427e 100644 --- a/util/grid/grid3eigen.hpp +++ b/util/grid/grid3eigen.hpp @@ -4,12 +4,14 @@ #include "../../eigen/Eigen/Dense" #include "../timing_decorator.hpp" #include "../output/frame.hpp" +#include "camera.hpp" #include #include #include #include #include #include +#include #ifdef SSE #include @@ -35,8 +37,8 @@ public: float refraction; float reflection; - NodeData(const T& data, const PointType& pos, Eigen::Vector3f color, float size = 0.01f, bool active = true) : - data(data), position(pos), active(active), color(color), size(size) {} + NodeData(const T& data, const PointType& pos, bool visible, Eigen::Vector3f color, float size = 0.01f, bool active = true) : + data(data), position(pos), active(active), visible(visible), color(color), size(size) {} }; struct OctreeNode { @@ -120,7 +122,7 @@ private: if (node->isLeaf) { node->points.emplace_back(pointData); if (node->points.size() > maxPointsPerNode && depth < maxDepth) { - splitNode(node,depth); + splitNode(node, depth); } return true; } else { @@ -254,8 +256,8 @@ public: root_(std::make_unique(minBound, maxBound)), maxPointsPerNode(maxPointsPerNode), maxDepth(maxDepth), size(0) {} - bool set(const T& data, const PointType& pos, Eigen::Vector3f color, float size, bool active) { - auto pointData = std::make_shared(data, pos, color, size, active); + bool set(const T& data, const PointType& pos, bool visible, Eigen::Vector3f color, float size, bool active) { + auto pointData = std::make_shared(data, pos, visible, color, size, active); if (insertRecursive(root_.get(), pointData, 0)) { size++; return true; @@ -324,9 +326,12 @@ public: } return hits; } - - frame renderFrame(const PointType& origin, PointType& dir, PointType& up, PointType& right, int height, - int width, frame::colormap colorformat = frame::colormap::RGB) { + + frame renderFrame(const Camera& cam, int height, int width, frame::colormap colorformat = frame::colormap::RGB) { + PointType origin = cam.origin; + PointType dir = cam.direction.normalized(); + PointType up = cam.up.normalized(); + PointType right = cam.right(); frame outFrame(width, height, colorformat); std::vector colorBuffer; @@ -340,12 +345,11 @@ public: } colorBuffer.resize(width * height * channels); - PointType viewDir = dir.normalized(); - PointType upn = up.normalized(); - PointType rightn = right.normalized(); float aspect = static_cast(width) / height; - float tanfovy = 1.f; - float tanfovx = tanfovy * aspect; + float fovRad = cam.fovRad(); + float tanHalfFov = tan(fovRad * 0.5f); + float tanfovy = tanHalfFov; + float tanfovx = tanHalfFov * aspect; const Eigen::Vector3f defaultColor(0.1f, 0.2f, 0.4f); @@ -355,7 +359,7 @@ public: float px = (2.0f * (x + 0.5f) / width - 1.0f) * tanfovx; float py = (1.0f - 2.0f * (y + 0.5f) / height) * tanfovy; - PointType rayDir = viewDir + (rightn * px) + (upn * py); + PointType rayDir = dir + (right * px) + (up * py); rayDir.normalize(); std::vector> hits = voxelTraverse(