mirror of
https://github.com/StepanovPlaton/C3DGraphicEngine.git
synced 2026-04-03 20:30:42 +04:00
Initial commit
This commit is contained in:
246
utils/utils.c
Normal file
246
utils/utils.c
Normal file
@@ -0,0 +1,246 @@
|
||||
#include "utils.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
// === Vectors ===
|
||||
void vector_substruct(int size, float v1[size], float v2[size], float r[size]) {
|
||||
for (int i = 0; i < size; i++)
|
||||
r[i] = v1[i] - v2[i];
|
||||
}
|
||||
void cross_product_vectors(float v1[3], float v2[3], float r[3]) {
|
||||
r[0] = v1[1] * v2[2] - v1[2] * v2[1];
|
||||
r[1] = v1[2] * v2[0] - v1[0] * v2[2];
|
||||
r[2] = v1[0] * v2[1] - v1[1] * v2[0];
|
||||
}
|
||||
float dot_product_vectors(float v1[3], float v2[3]) {
|
||||
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
|
||||
}
|
||||
void vector_normalize(int size, float coordinates[size]) {
|
||||
float divider = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
divider += coordinates[i] * coordinates[i];
|
||||
divider = sqrt(divider);
|
||||
float new_coordinates[size];
|
||||
for (int i = 0; i < size; i++)
|
||||
coordinates[i] /= divider;
|
||||
}
|
||||
void print_vector(int size, float vector[size]) {
|
||||
printf("(");
|
||||
for (int i = 0; i < size; i++) {
|
||||
printf("%f", vector[i]);
|
||||
if (i != size - 1)
|
||||
printf(",\t");
|
||||
}
|
||||
printf(")\n");
|
||||
}
|
||||
|
||||
// === Matrices ===
|
||||
void print_matrix(int size, float matrix[size][size]) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
printf("(");
|
||||
for (int j = 0; j < size; j++) {
|
||||
printf("%f", matrix[i][j]);
|
||||
if (j != size - 1)
|
||||
printf(",\t");
|
||||
}
|
||||
printf(")\n");
|
||||
}
|
||||
}
|
||||
void matrix_mult_matrix(int size, float matrix1[size][size],
|
||||
float matrix2[size][size], float result[size][size]) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
for (int j = 0; j < size; j++) {
|
||||
result[i][j] = 0;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
for (int j = 0; j < size; j++) {
|
||||
for (int k = 0; k < size; k++) {
|
||||
result[i][j] += matrix1[i][k] * matrix2[k][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void matrix_mult_vector(int size, float matrix[size][size], float vector[size],
|
||||
float result[size]) {
|
||||
for (int i = 0; i < size; i++)
|
||||
result[i] = 0;
|
||||
for (int i = 0; i < size; i++) {
|
||||
for (int j = 0; j < size; j++) {
|
||||
result[i] += matrix[i][j] * vector[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
void create_axis_rotate_matrix(int axis, float angle,
|
||||
float rotate_matrix[3][3]) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
rotate_matrix[i][j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
float cos_angle = cosf(angle);
|
||||
float sin_angle = sinf(angle);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
if (i == axis || j == axis) {
|
||||
if (i == j)
|
||||
rotate_matrix[i][j] = 1;
|
||||
else
|
||||
rotate_matrix[i][j] = 0;
|
||||
} else {
|
||||
if (i == j) {
|
||||
rotate_matrix[i][j] = cos_angle;
|
||||
} else {
|
||||
if ((i < j && axis == 2) || (i > j && axis != 2)) {
|
||||
rotate_matrix[i][j] = sin_angle;
|
||||
} else {
|
||||
rotate_matrix[i][j] = -sin_angle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void create_rotate_matrix(float rotate_speed[3], float rotate_matrix[3][3]) {
|
||||
float x_rotate[3][3];
|
||||
create_axis_rotate_matrix(0, rotate_speed[0], x_rotate);
|
||||
float y_rotate[3][3];
|
||||
create_axis_rotate_matrix(1, rotate_speed[1], y_rotate);
|
||||
float z_rotate[3][3];
|
||||
create_axis_rotate_matrix(2, rotate_speed[2], z_rotate);
|
||||
float xy_rotate[3][3];
|
||||
matrix_mult_matrix(3, x_rotate, y_rotate, xy_rotate);
|
||||
matrix_mult_matrix(3, xy_rotate, z_rotate, rotate_matrix);
|
||||
}
|
||||
|
||||
// === Points in scene ===
|
||||
void transform_point(Point3D *point, int size,
|
||||
float translate_matrix[size][size]) {
|
||||
float new_coordinates[3];
|
||||
float old_coordinates[] = {point->coordinates[0], point->coordinates[1],
|
||||
point->coordinates[2], 1.0f};
|
||||
matrix_mult_vector(size, translate_matrix, old_coordinates, new_coordinates);
|
||||
for (int i = 0; i < 3; i++)
|
||||
point->coordinates[i] = new_coordinates[i];
|
||||
}
|
||||
void create_translate_matrix(Point3D *position, float translate_matrix[4][4],
|
||||
int k) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
translate_matrix[i][j] = 0;
|
||||
if (i == j)
|
||||
translate_matrix[i][j] = 1;
|
||||
else if (j == 3)
|
||||
translate_matrix[i][j] = position->coordinates[i] * k;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// === Points on screen ===
|
||||
ScreenPoint convert_to_screen_point(Point3D *point, Screen *screen) {
|
||||
float tmp[] = {point->coordinates[0], point->coordinates[1],
|
||||
point->coordinates[2], 1.0f};
|
||||
float point_projection_view[4];
|
||||
matrix_mult_vector(4, *(screen->render_matrix), tmp, point_projection_view);
|
||||
|
||||
float perspective_coordinates[3] = {
|
||||
point_projection_view[0] / point_projection_view[3],
|
||||
point_projection_view[1] / point_projection_view[3],
|
||||
point_projection_view[2] / point_projection_view[3],
|
||||
};
|
||||
ScreenPoint spoint = {
|
||||
.coordinates = {((perspective_coordinates[0] + 1.0f) / 2.0f) *
|
||||
(float)screen->width,
|
||||
((perspective_coordinates[1] + 1.0f) / 2.0f) *
|
||||
(float)screen->height}};
|
||||
return spoint;
|
||||
}
|
||||
|
||||
void draw_line(Screen *screen, ScreenPoint *sp1, ScreenPoint *sp2) {
|
||||
MoveToEx(*(screen->hdc), sp1->coordinates[0], sp1->coordinates[1], NULL);
|
||||
LineTo(*(screen->hdc), sp2->coordinates[0], sp2->coordinates[1]);
|
||||
}
|
||||
|
||||
// === Camera ===
|
||||
void create_view_matrix(Camera *camera, float view_matrix[4][4]) {
|
||||
float forward[3];
|
||||
vector_substruct(3, camera->position.coordinates, camera->target.coordinates,
|
||||
forward);
|
||||
vector_normalize(3, forward);
|
||||
float right[3];
|
||||
cross_product_vectors(camera->up, forward, right);
|
||||
vector_normalize(3, right);
|
||||
|
||||
float up[3];
|
||||
cross_product_vectors(forward, right, up);
|
||||
vector_normalize(3, up);
|
||||
|
||||
float *vectors[] = {right, up, forward};
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
view_matrix[i][j] = 0;
|
||||
if (i == 3) {
|
||||
if (j == 3)
|
||||
view_matrix[i][j] = 1;
|
||||
} else if (j == 3) {
|
||||
view_matrix[i][j] =
|
||||
-1 * dot_product_vectors(vectors[i], camera->position.coordinates);
|
||||
} else {
|
||||
view_matrix[i][j] = vectors[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void create_projection_matrix(Camera *camera, float projection_matrix[4][4]) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
projection_matrix[i][j] = 0;
|
||||
}
|
||||
}
|
||||
float f = 1 / tan(camera->fov / 2);
|
||||
projection_matrix[0][0] = f / camera->aspect_ratio;
|
||||
projection_matrix[1][1] = f;
|
||||
projection_matrix[2][2] = (camera->max_distance + camera->min_distance) /
|
||||
(camera->min_distance - camera->max_distance);
|
||||
projection_matrix[3][2] = -1;
|
||||
projection_matrix[2][3] = (2 * camera->max_distance * camera->min_distance) /
|
||||
(camera->min_distance - camera->max_distance);
|
||||
}
|
||||
|
||||
// === Composite objects ===
|
||||
void transform_object(const Object *object, int size,
|
||||
float translate_matrix[size][size]) {
|
||||
for (int i = 0; i < object->number_of_points; i++) {
|
||||
transform_point(&(object->points[i]), size, translate_matrix);
|
||||
}
|
||||
}
|
||||
void draw_object(const Object *object, Screen *screen) {
|
||||
for (int i = 0; i < object->number_of_edges; i++) {
|
||||
Point3D point1 = object->points[object->edges[i][0]];
|
||||
ScreenPoint screen_point1 = convert_to_screen_point(&point1, screen);
|
||||
Point3D point2 = object->points[object->edges[i][1]];
|
||||
ScreenPoint screen_point2 = convert_to_screen_point(&point2, screen);
|
||||
draw_line(screen, &screen_point1, &screen_point2);
|
||||
}
|
||||
}
|
||||
Point3D calculate_centroid(const Object *object) {
|
||||
Point3D centroid = {{0.0f, 0.0f, 0.0f}};
|
||||
|
||||
for (int i = 0; i < object->number_of_points; i++) {
|
||||
centroid.coordinates[0] += object->points[i].coordinates[0];
|
||||
centroid.coordinates[1] += object->points[i].coordinates[1];
|
||||
centroid.coordinates[2] += object->points[i].coordinates[2];
|
||||
}
|
||||
|
||||
float inv_n = 1.0f / (float)object->number_of_points;
|
||||
centroid.coordinates[0] *= inv_n;
|
||||
centroid.coordinates[1] *= inv_n;
|
||||
centroid.coordinates[2] *= inv_n;
|
||||
|
||||
return centroid;
|
||||
}
|
||||
80
utils/utils.h
Normal file
80
utils/utils.h
Normal file
@@ -0,0 +1,80 @@
|
||||
#ifndef OBJECTS_H
|
||||
#define OBJECTS_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
// === Vectors ===
|
||||
void vector_substruct(int size, float v1[size], float v2[size], float r[size]);
|
||||
void cross_product_vectors(float v1[3], float v2[3], float r[3]);
|
||||
float dot_product_vectors(float v1[3], float v2[3]);
|
||||
void vector_normalize(int size, float coordinates[size]);
|
||||
void print_vector(int size, float vector[size]);
|
||||
|
||||
// === Matrix ===
|
||||
void print_matrix(int size, float matrix[size][size]);
|
||||
void matrix_mult_matrix(int size, float matrix1[size][size],
|
||||
float matrix2[size][size], float result[size][size]);
|
||||
void matrix_mult_vector(int size, float matrix[size][size], float vector[size],
|
||||
float result[size]);
|
||||
|
||||
void create_axis_rotate_matrix(int axis, float angle,
|
||||
float rotate_matrix[3][3]);
|
||||
void create_rotate_matrix(float rotate_speed[3], float rotate_matrix[3][3]);
|
||||
|
||||
// === Point in scene ===
|
||||
struct Point3D {
|
||||
float coordinates[3];
|
||||
};
|
||||
typedef struct Point3D Point3D;
|
||||
void transform_point(Point3D *point, int size,
|
||||
float translate_matrix[size][size]);
|
||||
void create_translate_matrix(Point3D *position, float translate_matrix[4][4],
|
||||
int k);
|
||||
|
||||
// === Screen summary ===
|
||||
struct Screen {
|
||||
int width;
|
||||
int height;
|
||||
HDC *hdc;
|
||||
float (*render_matrix)[4][4];
|
||||
};
|
||||
typedef struct Screen Screen;
|
||||
|
||||
// === Point on screen ===
|
||||
struct ScreenPoint {
|
||||
int coordinates[2];
|
||||
};
|
||||
typedef struct ScreenPoint ScreenPoint;
|
||||
ScreenPoint convert_to_screen_point(Point3D *point, Screen *screen);
|
||||
void draw_line(Screen *screen, ScreenPoint *sp1, ScreenPoint *sp2);
|
||||
|
||||
// === Camera in scene ===
|
||||
struct Camera {
|
||||
Point3D position;
|
||||
Point3D target;
|
||||
float up[3];
|
||||
float fov;
|
||||
float max_distance;
|
||||
float min_distance;
|
||||
float aspect_ratio;
|
||||
};
|
||||
typedef struct Camera Camera;
|
||||
void create_view_matrix(Camera *camera, float view_matrix[4][4]);
|
||||
void create_projection_matrix(Camera *camera, float projection_matrix[4][4]);
|
||||
|
||||
// === Composite object in scene ===
|
||||
struct Object {
|
||||
Point3D *points;
|
||||
int (*edges)[2];
|
||||
int number_of_points;
|
||||
int number_of_edges;
|
||||
Point3D *position;
|
||||
float (*rotate_speed)[3];
|
||||
};
|
||||
typedef struct Object Object;
|
||||
void transform_object(const Object *object, int size,
|
||||
float translate_matrix[size][size]);
|
||||
void draw_object(const Object *object, Screen *screen);
|
||||
Point3D calculate_centroid(const Object *object);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user