This C++ code defines a 3D transformation system using SDL for rendering, which consists of classes and functions for representing points, vectors, and matrices, as well as applying transformations such as rotation, translation, and connection drawing. The system uses the SDL library for rendering and includes functions for calculating dot products, applying composite transformations, and getting rotation matrices.
npm run import -- "opengl frame"
#include <vector>
#include <cmath>
#include <SDL.h>
class Point {
public:
double x, y, z;
Point() {
this->x = 0;
this->y = 0;
this->z = 0;
}
Point(double x, double y, double z) {
this->x = x;
this->y = y;
this->z = z;
}
Point(double x, double y) {
this->x = x;
this->y = y;
this->z = 0;
}
double operator[](int i) const {
if (i == 0) return this->x;
if (i == 1) return this->y;
return this->z;
}
double& operator[](int i) {
if (i == 0) return this->x;
if (i == 1) return this->y;
return this->z;
}
};
typedef std::vector<double> Vector;
typedef std::vector<Vector> Matrix;
Matrix dot(const Matrix& a, const Matrix& b) {
Matrix result = Matrix(a.size(), Vector(b[0].size(), 0));
for (int i=0; i<a.size(); i++) {
for (int j=0; j<b[0].size(); j++) {
for (int k=0; k<b.size(); k++) {
result[i][j] += a[i][k] * b[k][j];
}
}
}
return result;
}
Point transform(const Matrix& matrix, const Point& point) {
Matrix p = {{point.x}, {point.y}, {point.z}};
Matrix r = dot(matrix, p);
return Point(r[0][0], r[1][0], r[2][0]);
}
Point translate(const Point& shift, const Point& point) {
return Point(
point.x + shift.x,
point.y + shift.y,
point.z + shift.z
);
}
void connect(SDL_Renderer* const renderer, const std::vector<Point> &points, int i, int j) {
SDL_RenderDrawLine(
renderer,
points[i].x,
points[i].y,
points[j].x,
points[j].y
);
}
Matrix getRotationMatrix() {
double alpha = 0.001;
Matrix rotationX = {
{1, 0, 0},
{0, cos(alpha), -sin(alpha)},
{0, sin(alpha), cos(alpha)}
};
double beta = 0.002;
Matrix rotationY = {
{cos(beta), 0, sin(beta)},
{0, 1, 0},
{-sin(beta), 0, cos(beta)}
};
double gamma = 0.003;
Matrix rotationZ = {
{cos(gamma), -sin(gamma), 0},
{sin(gamma), cos(gamma), 0},
{0, 0, 1}
};
return dot(rotationZ, dot(rotationY, rotationX));
}
#if __cplusplus
extern "C" {
#endif
int WIDTH = 1000;
int HEIGHT = 800;
static bool first = false;
static SDL_Renderer* renderer;
std::vector<Point> points;
Matrix rotationXYZ;
Point screenShift;
Point screenShiftOpposite;
void beginFrame(int windowId) {
SDL_Window *window = SDL_GetWindowFromID(windowId);
SDL_Event event;
while(SDL_PollEvent(&event)){
if(event.type == SDL_QUIT) {
SDL_DestroyWindow(window);
SDL_Quit();
return;
}
}
if(!first) {
first = true;
renderer = SDL_CreateRenderer(
window,
-1,
SDL_RENDERER_ACCELERATED
);
points = {
Point(-1, 1, 1),
Point(1, 1, 1),
Point(1, -1, 1),
Point(-1, -1, 1),
Point(-1, 1, -1),
Point(1, 1, -1),
Point(1, -1, -1),
Point(-1, -1, -1)
};
screenShift = Point(WIDTH / 2, HEIGHT / 2);
screenShiftOpposite = Point(-WIDTH / 2, -HEIGHT / 2);
int scale = 200;
for (Point& p : points) {
p.x = (scale * p.x + screenShift.x);
p.y = (scale * p.y + screenShift.y);
p.z = (scale * p.z + screenShift.z);
}
rotationXYZ = getRotationMatrix();
}
for (Point &p : points) {
p = translate(screenShiftOpposite, p);
p = transform(rotationXYZ, p);
p = translate(screenShift, p);
}
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
for (int i=0; i<4; i++) {
connect(renderer, points, i, (i + 1) % 4);
connect(renderer, points, i + 4, ((i + 1) % 4) + 4);
connect(renderer, points, i, i + 4);
}
SDL_RenderPresent(renderer);
SDL_Delay(3);
}
void endFrame(int windowId) {
SDL_Window *window = SDL_GetWindowFromID(windowId);
SDL_GL_SwapWindow(window);
}
#if __cplusplus
}
#endif
cpp
#include <vector>
#include <cmath>
#include <SDL.h>
// Define a 2D and 3D vector class
class Vector2D {
public:
double x, y;
Vector2D() : x(0), y(0) {}
Vector2D(double x, double y) : x(x), y(y) {}
double& operator[](int i) {
if (i == 0) return x;
return y;
}
double operator[](int i) const {
if (i == 0) return x;
return y;
}
};
class Vector3D {
public:
double x, y, z;
Vector3D() : x(0), y(0), z(0) {}
Vector3D(double x, double y, double z) : x(x), y(y), z(z) {}
double& operator[](int i) {
if (i == 0) return x;
if (i == 1) return y;
return z;
}
double operator[](int i) const {
if (i == 0) return x;
if (i == 1) return y;
return z;
}
};
// Define a 2D and 3D point class
class Point2D {
public:
Vector2D coords;
Point2D() {}
Point2D(double x, double y) : coords(x, y) {}
Vector2D operator[](int i) const {
return coords;
}
};
class Point3D {
public:
Vector3D coords;
Point3D() {}
Point3D(double x, double y, double z) : coords(x, y, z) {}
Vector3D operator[](int i) const {
return coords;
}
};
// Define a 3D matrix class
class Matrix3D {
public:
std::vector<std::vector<double>> data;
Matrix3D(size_t rows, size_t cols) : data(rows, std::vector<double>(cols, 0)) {}
double& operator()(size_t i, size_t j) {
return data[i][j];
}
double operator()(size_t i, size_t j) const {
return data[i][j];
}
};
// Function to multiply two 3D matrices
Matrix3D dot(const Matrix3D& a, const Matrix3D& b) {
Matrix3D result(a.rows(), b.cols());
for (size_t i = 0; i < a.rows(); ++i) {
for (size_t j = 0; j < b.cols(); ++j) {
for (size_t k = 0; k < a.cols(); ++k) {
result(i, j) += a(i, k) * b(k, j);
}
}
}
return result;
}
// Function to transform a 3D point using a rotation matrix
Point3D transform(const Matrix3D& matrix, const Point3D& point) {
Matrix3D p({1, 0, 0},
{0, 1, 0},
{0, 0, 1});
for (size_t i = 0; i < 3; ++i) {
p(i, 0) = point[i];
}
Matrix3D r = dot(matrix, p);
return Point3D(r(0, 0), r(1, 0), r(2, 0));
}
// Function to translate a point
Point3D translate(const Point3D& point, const Vector3D& offset) {
return Point3D(point[0] + offset[0], point[1] + offset[1], point[2] + offset[2]);
}
// Function to render a frame
void renderFrame(SDL_Renderer* renderer, const std::vector<Point3D>& points, const Matrix3D& rotationMatrix, const Point3D& screenShift, const Point3D& screenShiftOpposite) {
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
for (const auto& point : points) {
point = translate(screenShiftOpposite, point);
point = transform(rotationMatrix, point);
point = translate(screenShift, point);
connect(renderer, points, std::distance(points.begin(), std::find(points.begin(), points.end(), point)), std::distance(points.begin(), std::find(points.begin(), points.end(), *(std::next(std::find(points.begin(), points.end(), point))))));
}
SDL_RenderPresent(renderer);
SDL_Delay(3);
}
// Function to get the rotation matrix
Matrix3D getRotationMatrix() {
double alpha = 0.001;
Matrix3D rotationX({1, 0, 0,
0, cos(alpha), -sin(alpha),
0, sin(alpha), cos(alpha)});
double beta = 0.002;
Matrix3D rotationY({cos(beta), 0, sin(beta),
0, 1, 0,
-sin(beta), 0, cos(beta)});
double gamma = 0.003;
Matrix3D rotationZ({cos(gamma), -sin(gamma), 0,
sin(gamma), cos(gamma), 0,
0, 0, 1});
return dot(rotationZ, dot(rotationY, rotationX));
}
// Function to connect two points
void connect(SDL_Renderer* renderer, const std::vector<Point3D>& points, int i, int j) {
SDL_RenderDrawLine(renderer, points[i].coords[0], points[i].coords[1], points[j].coords[0], points[j].coords[1]);
}
int main() {
// Initialize SDL
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1000, 800, 0);
// Create renderer
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
// Define points
std::vector<Point3D> points = {
{1, 1, 1},
{1, -1, 1},
{1, -1, -1},
{1, 1, -1},
{1, 1, 1},
{1, -1, -1},
{1, -1, 1},
{1, 1, -1},
{1, -1, 1},
{1, 1, -1},
{-1, -1, -1},
{-1, -1, 1},
{-1, 1, -1},
{-1, 1, 1},
{-1, -1, -1},
{-1, -1, 1},
{-1, 1, -1},
{-1, 1, 1}
};
// Define rotation matrix
Matrix3D rotationMatrix = getRotationMatrix();
// Define screen shift
Point3D screenShift(WIDTH / 2, HEIGHT / 2, 0);
Point3D screenShiftOpposite(-WIDTH / 2, -HEIGHT / 2, 0);
// Render frames
int frame = 0;
while (true) {
renderFrame(renderer, points, rotationMatrix, screenShift, screenShiftOpposite);
frame++;
}
// Clean up
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
Overview
This code defines a 3D transformation system using C++ and the SDL library for rendering.
Classes and Functions
point[i]
.std::vector<double>
and std::vector<std::vector<double>>
, respectively, used to represent vectors and matrices.Notes
transform
function assumes that the input matrix represents a composite transformation (rotation followed by translation).getRotationMatrix
function returns a matrix that represents a rotation around the x, y, and z axes. However, the angles used in the matrix definitions (alpha, beta, gamma) are very small (0.001, 0.002, 0.003), which may not produce noticeable rotation.