diff --git a/Source/obj/Camera.cpp b/Source/obj/Camera.cpp index 220d3cc..a21735a 100644 --- a/Source/obj/Camera.cpp +++ b/Source/obj/Camera.cpp @@ -1,5 +1,6 @@ #include "Camera.h" #include "../shape/Line.h" +#include Camera::Camera(double focalLength, double x, double y, double z) : focalLength(focalLength), x(x), y(y), z(z) {} @@ -7,49 +8,84 @@ std::vector> Camera::draw(WorldObject& object) { std::vector> shapes; for (auto& edge : object.edges) { - // rotate around x-axis - double cosValue = std::cos(object.rotateX); - double sinValue = std::sin(object.rotateX); - double y2 = cosValue * edge.y1 - sinValue * edge.z1; - double z2 = sinValue * edge.y1 + cosValue * edge.z1; + Vector2 start = project(object.rotateX, object.rotateY, object.rotateZ, edge.x1, edge.y1, edge.z1); + Vector2 end = project(object.rotateX, object.rotateY, object.rotateZ, edge.x2, edge.y2, edge.z2); - // rotate around y-axis - cosValue = std::cos(object.rotateY); - sinValue = std::sin(object.rotateY); - double x2 = cosValue * edge.x1 + sinValue * z2; - double z3 = -sinValue * edge.x1 + cosValue * z2; - - // rotate around z-axis - cosValue = cos(object.rotateZ); - sinValue = sin(object.rotateZ); - double x3 = cosValue * x2 - sinValue * y2; - double y3 = sinValue * x2 + cosValue * y2; - - double startX = x3 * focalLength / (z3 - z) + x; - double startY = y3 * focalLength / (z3 - z) + y; - - // rotate around x-axis - cosValue = std::cos(object.rotateX); - sinValue = std::sin(object.rotateX); - y2 = cosValue * edge.y2 - sinValue * edge.z2; - z2 = sinValue * edge.y2 + cosValue * edge.z2; - - // rotate around y-axis - cosValue = std::cos(object.rotateY); - sinValue = std::sin(object.rotateY); - x2 = cosValue * edge.x2 + sinValue * z2; - z3 = -sinValue * edge.x2 + cosValue * z2; - - // rotate around z-axis - cosValue = cos(object.rotateZ); - sinValue = sin(object.rotateZ); - x3 = cosValue * x2 - sinValue * y2; - y3 = sinValue * x2 + cosValue * y2; - - double endX = x3 * focalLength / (z3 - z) + x; - double endY = y3 * focalLength / (z3 - z) + y; - - shapes.push_back(std::make_unique(startX, startY, endX, endY)); + shapes.push_back(std::make_unique(start.x, start.y, end.x, end.y)); } return shapes; } + +void Camera::findZPos(WorldObject& object) { + x = 0.0; + y = 0.0; + z = 0.0; + + std::vector vertices; + + int stepsMade = 0; + while (maxVertexValue(vertices) > VERTEX_VALUE_THRESHOLD && stepsMade < MAX_NUM_STEPS) { + z += CAMERA_MOVE_INCREMENT; + vertices = sampleVerticesInRender(object); + stepsMade++; + } +} + +std::vector Camera::sampleVerticesInRender(WorldObject& object) { + double rotation = 2.0 * std::numbers::pi / SAMPLE_RENDER_SAMPLES; + + std::vector vertices; + + double oldRotateX = object.rotateX; + double oldRotateY = object.rotateY; + double oldRotateZ = object.rotateZ; + + for (int i = 0; i < SAMPLE_RENDER_SAMPLES - 1; i++) { + for (size_t j = 0; j < std::min(VERTEX_SAMPLES, object.vertices.size()); j++) { + double x = object.vertices[j].v[0]; + double y = object.vertices[j].v[1]; + double z = object.vertices[j].v[2]; + vertices.push_back(project(object.rotateX, object.rotateY, object.rotateZ, x, y, z)); + } + object.rotateY += rotation; + object.rotateZ += rotation; + } + + return vertices; +} + +double Camera::maxVertexValue(std::vector& vertices) { + if (vertices.empty()) { + return std::numeric_limits::infinity(); + } + double max = 0.0; + for (auto& vertex : vertices) { + max = std::max(max, std::max(std::abs(vertex.x), std::abs(vertex.y))); + } + return max; +} + +Vector2 Camera::project(double objRotateX, double objRotateY, double objRotateZ, double x, double y, double z) { + // rotate around x-axis + double cosValue = std::cos(objRotateX); + double sinValue = std::sin(objRotateX); + double y2 = cosValue * y - sinValue * z; + double z2 = sinValue * y + cosValue * z; + + // rotate around y-axis + cosValue = std::cos(objRotateY); + sinValue = std::sin(objRotateY); + double x2 = cosValue * x + sinValue * z2; + double z3 = -sinValue * x + cosValue * z2; + + // rotate around z-axis + cosValue = cos(objRotateZ); + sinValue = sin(objRotateZ); + double x3 = cosValue * x2 - sinValue * y2; + double y3 = sinValue * x2 + cosValue * y2; + + double start = x3 * focalLength / (z3 - z) + x; + double end = y3 * focalLength / (z3 - z) + y; + + return Vector2(start, end); +} diff --git a/Source/obj/Camera.h b/Source/obj/Camera.h index 279bca8..e646b97 100644 --- a/Source/obj/Camera.h +++ b/Source/obj/Camera.h @@ -3,13 +3,25 @@ #include #include "WorldObject.h" #include "../shape/Shape.h" +#include "../shape/Vector2.h" class Camera { public: Camera(double focalLength, double x, double y, double z); std::vector> draw(WorldObject& object); + void findZPos(WorldObject& object); private: + const double VERTEX_VALUE_THRESHOLD = 1.0; + const double CAMERA_MOVE_INCREMENT = -0.1; + const int SAMPLE_RENDER_SAMPLES = 50; + const size_t VERTEX_SAMPLES = 1000; + const int MAX_NUM_STEPS = 1000; + double focalLength; double x, y, z; + + std::vector sampleVerticesInRender(WorldObject& object); + double maxVertexValue(std::vector& vertices); + Vector2 project(double objRotateX, double objRotateY, double objRotateZ, double x, double y, double z); }; \ No newline at end of file diff --git a/Source/obj/WorldObject.h b/Source/obj/WorldObject.h index cf597d9..8d3f3da 100644 --- a/Source/obj/WorldObject.h +++ b/Source/obj/WorldObject.h @@ -56,8 +56,8 @@ public: double rotateX = 0.0, rotateY = 0.0, rotateZ = 0.0; std::vector edges; -private: std::vector vertices; +private: std::vector texcoords; std::vector normals; std::vector parameters; diff --git a/Source/parser/FileParser.cpp b/Source/parser/FileParser.cpp index fdc0feb..8a669ad 100644 --- a/Source/parser/FileParser.cpp +++ b/Source/parser/FileParser.cpp @@ -6,7 +6,8 @@ FileParser::FileParser() {} void FileParser::parse(juce::String extension, std::unique_ptr stream) { if (extension == ".obj") { object = std::make_unique(*stream); - camera = std::make_unique(1.0, 0, 0, -0.1); + camera = std::make_unique(1.0, 0, 0, 0.0); + camera->findZPos(*object); } }