cgfs:perspective
#include <raylib.h>
#include <cmath>
#include <iterator>
#include <vector>
#include "vmath.h"
int const Cw = 600;
int const Ch = 600;
float const Vw = 1.0;
float const Vh = 1.0;
float const ProjectionPlaneZ = 1.0;
using vec2 = vmath::vec2<float>;
using vec3 = vmath::vec3<float>;
void PutPixel(int x, int y, Color const &color) {
DrawPixel(x + Cw / 2, -y + Ch / 2, color);
}
template <typename Iter>
requires std::output_iterator<Iter, float>
void Interpolate(int i0, float d0, int i1, float d1, Iter out) {
if (i0 == i1) {
*out = d0;
return;
}
auto a = (d1 - d0) / (i1 - i0);
auto d = d0;
for (int i = i0; i <= i1; ++i) {
*out++ = d;
d += a;
}
}
void DrawLine(vec2 const &p0, vec2 const &p1, Color const &color) {
auto x0 = p0.x;
auto y0 = p0.y;
auto x1 = p1.x;
auto y1 = p1.y;
if (std::abs(x1 - x0) > std::abs(y1 - y0)) {
if (x0 > x1) {
std::swap(x0, x1);
std::swap(y0, y1);
}
auto i0 = static_cast<int>(std::floor(x0));
auto i1 = static_cast<int>(std::floor(x1));
auto ys = std::vector<float>(i1 - i0 + 1);
Interpolate(i0, y0, i1, y1, ys.begin());
for (int i = i0; i <= i1; ++i) {
PutPixel(i, ys[i - i0], color);
}
} else {
if (y0 > y1) {
std::swap(y0, y1);
std::swap(x0, x1);
}
auto i0 = static_cast<int>(std::floor(y0));
auto i1 = static_cast<int>(std::floor(y1));
auto xs = std::vector<float>(i1 - i0 + 1);
Interpolate(i0, x0, i1, x1, xs.begin());
for (int i = i0; i <= i1; ++i) {
PutPixel(xs[i - i0], i, color);
}
}
}
vec2 ViewportToCanvas(float x, float y) {
return {x * Cw / Vw, y * Ch / Vh};
}
vec2 ProjectVertex(vec3 const &v) {
return ViewportToCanvas(v.x * ProjectionPlaneZ / v.z,
v.y * ProjectionPlaneZ / v.z);
}
int main() {
InitWindow(Cw, Ch, "Perspective Projection");
// front
auto vAf = vec3{-1, 1, 4};
auto vBf = vec3{1, 1, 4};
auto vCf = vec3{1, -1, 4};
auto vDf = vec3{-1, -1, 4};
// back
auto vAb = vec3{-1, 1, 6};
auto vBb = vec3{1, 1, 6};
auto vCb = vec3{1, -1, 6};
auto vDb = vec3{-1, -1, 6};
while (!WindowShouldClose()) {
BeginDrawing();
ClearBackground(WHITE);
DrawLine(ProjectVertex(vAf), ProjectVertex(vBf), BLUE);
DrawLine(ProjectVertex(vBf), ProjectVertex(vCf), BLUE);
DrawLine(ProjectVertex(vCf), ProjectVertex(vDf), BLUE);
DrawLine(ProjectVertex(vDf), ProjectVertex(vAf), BLUE);
DrawLine(ProjectVertex(vAb), ProjectVertex(vBb), RED);
DrawLine(ProjectVertex(vBb), ProjectVertex(vCb), RED);
DrawLine(ProjectVertex(vCb), ProjectVertex(vDb), RED);
DrawLine(ProjectVertex(vDb), ProjectVertex(vAb), RED);
DrawLine(ProjectVertex(vAf), ProjectVertex(vAb), GREEN);
DrawLine(ProjectVertex(vBf), ProjectVertex(vBb), GREEN);
DrawLine(ProjectVertex(vCf), ProjectVertex(vCb), GREEN);
DrawLine(ProjectVertex(vDf), ProjectVertex(vDb), GREEN);
EndDrawing();
}
}
cgfs/perspective.txt · 最終更新: 2024/07/12 03:20 by freemikan