pushing camera eigen update, and other fixes
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
#include "../util/grid/grid3eigen.hpp"
|
#include "../util/grid/grid3eigen.hpp"
|
||||||
#include "../util/output/bmpwriter.hpp"
|
#include "../util/output/bmpwriter.hpp"
|
||||||
@@ -52,41 +53,79 @@ int main() {
|
|||||||
|
|
||||||
// Set point data with larger size for visibility
|
// Set point data with larger size for visibility
|
||||||
// Note: The third parameter is size, which should be radius squared for intersection test
|
// 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++;
|
pointCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Added " << pointCount << " points to the green sphere." << std::endl;
|
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
|
// Render parameters
|
||||||
int width = 800;
|
int width = 2048;
|
||||||
int height = 600;
|
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<float> angleDist(0.0f, 2.0f * M_PI);
|
||||||
|
std::uniform_real_distribution<float> elevationDist(0.1f, M_PI - 0.1f); // Avoid poles
|
||||||
|
std::uniform_real_distribution<float> radiusDist(2.0f, 4.0f); // Distance from sphere
|
||||||
|
|
||||||
// Render frame
|
// Generate and save 15 random views
|
||||||
frame renderedFrame = octree.renderFrame(cameraPos, lookDir, upDir, rightDir, height, width, frame::colormap::RGB);
|
const int numViews = 15;
|
||||||
|
|
||||||
std::cout << "Frame rendered. Dimensions: "
|
for (int viewIndex = 0; viewIndex < numViews; ++viewIndex) {
|
||||||
<< renderedFrame.getWidth() << "x"
|
std::cout << "\nRendering view " << (viewIndex + 1) << " of " << numViews << "..." << std::endl;
|
||||||
<< renderedFrame.getHeight() << std::endl;
|
|
||||||
|
// Generate random spherical coordinates for camera position
|
||||||
// Save as BMP
|
float azimuth = angleDist(gen);
|
||||||
std::string filename = "output/green_sphere.bmp";
|
float elevation = elevationDist(gen);
|
||||||
std::cout << "Saving to " << filename << "..." << std::endl;
|
float camRadius = radiusDist(gen);
|
||||||
|
|
||||||
if (BMPWriter::saveBMP(filename, renderedFrame)) {
|
// Convert to Cartesian coordinates for camera position
|
||||||
std::cout << "Successfully saved green sphere to " << filename << std::endl;
|
float camX = camRadius * sin(elevation) * cos(azimuth);
|
||||||
} else {
|
float camY = camRadius * sin(elevation) * sin(azimuth);
|
||||||
std::cerr << "Failed to save BMP file!" << std::endl;
|
float camZ = camRadius * cos(elevation);
|
||||||
return 1;
|
|
||||||
|
// 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;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1,60 +1,106 @@
|
|||||||
#ifndef camera_hpp
|
#ifndef camera_hpp
|
||||||
#define camera_hpp
|
#define camera_hpp
|
||||||
|
|
||||||
#include <unordered_map>
|
#include "../../eigen/Eigen/Dense"
|
||||||
#include <fstream>
|
#include <cmath>
|
||||||
#include <cstring>
|
|
||||||
#include <memory>
|
|
||||||
#include <array>
|
|
||||||
#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 <vector>
|
|
||||||
#include <algorithm>
|
|
||||||
#include "../basicdefines.hpp"
|
#include "../basicdefines.hpp"
|
||||||
#include <cfloat>
|
|
||||||
|
using Eigen::Vector3f;
|
||||||
|
using Eigen::Matrix3f;
|
||||||
|
|
||||||
struct Camera {
|
struct Camera {
|
||||||
Ray3f posfor;
|
Vector3f origin;
|
||||||
Vec3f up;
|
Vector3f direction;
|
||||||
|
Vector3f up;
|
||||||
float fov;
|
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) {
|
void rotateYaw(float angle) {
|
||||||
float cosA = cos(angle);
|
float cosA = cos(angle);
|
||||||
float sinA = sin(angle);
|
float sinA = sin(angle);
|
||||||
|
|
||||||
Vec3f right = posfor.direction.cross(up).normalized();
|
Vector3f right = direction.cross(up).normalized();
|
||||||
posfor.direction = posfor.direction * cosA + right * sinA;
|
|
||||||
posfor.direction = posfor.direction.normalized();
|
// Rotate around up vector (yaw)
|
||||||
|
Matrix3f rotation;
|
||||||
|
rotation = Eigen::AngleAxisf(angle, up);
|
||||||
|
direction = rotation * direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rotatePitch(float angle) {
|
void rotatePitch(float angle) {
|
||||||
float cosA = cos(angle);
|
// Clamp pitch to avoid gimbal lock
|
||||||
float sinA = sin(angle);
|
Vector3f right = direction.cross(up).normalized();
|
||||||
|
|
||||||
Vec3f right = posfor.direction.cross(up).normalized();
|
// Rotate around right vector (pitch)
|
||||||
posfor.direction = posfor.direction * cosA + up * sinA;
|
Matrix3f rotation;
|
||||||
posfor.direction = posfor.direction.normalized();
|
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 {
|
Vector3f forward() const {
|
||||||
return (posfor.direction - posfor.origin).normalized();
|
return direction.normalized();
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3f right() const {
|
Vector3f right() const {
|
||||||
return forward().cross(up).normalized();
|
return forward().cross(up).normalized();
|
||||||
}
|
}
|
||||||
|
|
||||||
float fovRad() const {
|
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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,12 +4,14 @@
|
|||||||
#include "../../eigen/Eigen/Dense"
|
#include "../../eigen/Eigen/Dense"
|
||||||
#include "../timing_decorator.hpp"
|
#include "../timing_decorator.hpp"
|
||||||
#include "../output/frame.hpp"
|
#include "../output/frame.hpp"
|
||||||
|
#include "camera.hpp"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
#ifdef SSE
|
#ifdef SSE
|
||||||
#include <immintrin.h>
|
#include <immintrin.h>
|
||||||
@@ -35,8 +37,8 @@ public:
|
|||||||
float refraction;
|
float refraction;
|
||||||
float reflection;
|
float reflection;
|
||||||
|
|
||||||
NodeData(const T& data, const PointType& pos, Eigen::Vector3f color, float size = 0.01f, bool active = true) :
|
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), color(color), size(size) {}
|
data(data), position(pos), active(active), visible(visible), color(color), size(size) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OctreeNode {
|
struct OctreeNode {
|
||||||
@@ -120,7 +122,7 @@ private:
|
|||||||
if (node->isLeaf) {
|
if (node->isLeaf) {
|
||||||
node->points.emplace_back(pointData);
|
node->points.emplace_back(pointData);
|
||||||
if (node->points.size() > maxPointsPerNode && depth < maxDepth) {
|
if (node->points.size() > maxPointsPerNode && depth < maxDepth) {
|
||||||
splitNode(node,depth);
|
splitNode(node, depth);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@@ -254,8 +256,8 @@ public:
|
|||||||
root_(std::make_unique<OctreeNode>(minBound, maxBound)), maxPointsPerNode(maxPointsPerNode),
|
root_(std::make_unique<OctreeNode>(minBound, maxBound)), maxPointsPerNode(maxPointsPerNode),
|
||||||
maxDepth(maxDepth), size(0) {}
|
maxDepth(maxDepth), size(0) {}
|
||||||
|
|
||||||
bool set(const T& data, const PointType& pos, Eigen::Vector3f color, float size, bool active) {
|
bool set(const T& data, const PointType& pos, bool visible, Eigen::Vector3f color, float size, bool active) {
|
||||||
auto pointData = std::make_shared<NodeData>(data, pos, color, size, active);
|
auto pointData = std::make_shared<NodeData>(data, pos, visible, color, size, active);
|
||||||
if (insertRecursive(root_.get(), pointData, 0)) {
|
if (insertRecursive(root_.get(), pointData, 0)) {
|
||||||
size++;
|
size++;
|
||||||
return true;
|
return true;
|
||||||
@@ -324,9 +326,12 @@ public:
|
|||||||
}
|
}
|
||||||
return hits;
|
return hits;
|
||||||
}
|
}
|
||||||
|
|
||||||
frame renderFrame(const PointType& origin, PointType& dir, PointType& up, PointType& right, int height,
|
frame renderFrame(const Camera& cam, int height, int width, frame::colormap colorformat = frame::colormap::RGB) {
|
||||||
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);
|
frame outFrame(width, height, colorformat);
|
||||||
std::vector<uint8_t> colorBuffer;
|
std::vector<uint8_t> colorBuffer;
|
||||||
@@ -340,12 +345,11 @@ public:
|
|||||||
}
|
}
|
||||||
colorBuffer.resize(width * height * channels);
|
colorBuffer.resize(width * height * channels);
|
||||||
|
|
||||||
PointType viewDir = dir.normalized();
|
|
||||||
PointType upn = up.normalized();
|
|
||||||
PointType rightn = right.normalized();
|
|
||||||
float aspect = static_cast<float>(width) / height;
|
float aspect = static_cast<float>(width) / height;
|
||||||
float tanfovy = 1.f;
|
float fovRad = cam.fovRad();
|
||||||
float tanfovx = tanfovy * aspect;
|
float tanHalfFov = tan(fovRad * 0.5f);
|
||||||
|
float tanfovy = tanHalfFov;
|
||||||
|
float tanfovx = tanHalfFov * aspect;
|
||||||
|
|
||||||
const Eigen::Vector3f defaultColor(0.1f, 0.2f, 0.4f);
|
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 px = (2.0f * (x + 0.5f) / width - 1.0f) * tanfovx;
|
||||||
float py = (1.0f - 2.0f * (y + 0.5f) / height) * tanfovy;
|
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();
|
rayDir.normalize();
|
||||||
|
|
||||||
std::vector<std::shared_ptr<NodeData>> hits = voxelTraverse(
|
std::vector<std::shared_ptr<NodeData>> hits = voxelTraverse(
|
||||||
|
|||||||
Reference in New Issue
Block a user