Write a c program to apply various 3D transformations on a 3D object and then apply parallel and perspective projection on it.
C program that demonstrates how to apply 3D transformations on a 3D object and then perform parallel and perspective projections, as well as with following transformations:
- Translation
- Scaling
- Rotation
After applying the transformations, we will then project the object onto a 2D plane using two types of projections:
- Parallel Projection
- Perspective Projection
We'll represent 3D points using homogeneous coordinates, and for projection, we'll transform the 3D coordinates into 2D by using the appropriate transformation matrices.
#include <stdio.h>
#include <graphics.h>
#include <math.h>
#define MAX_VERTICES 20
// Structure to represent a point in homogeneous coordinates (x, y, z, 1)
typedef struct {
float x, y, z, w;
} Point;
// Function to multiply a point by a transformation matrix
Point multiplyMatrix(Point p, float matrix[4][4]) {
Point result;
result.x = matrix[0][0] * p.x + matrix[0][1] * p.y + matrix[0][2] * p.z + matrix[0][3] * p.w;
result.y = matrix[1][0] * p.x + matrix[1][1] * p.y + matrix[1][2] * p.z + matrix[1][3] * p.w;
result.z = matrix[2][0] * p.x + matrix[2][1] * p.y + matrix[2][2] * p.z + matrix[2][3] * p.w;
result.w = matrix[3][0] * p.x + matrix[3][1] * p.y + matrix[3][2] * p.z + matrix[3][3] * p.w;
return result;
}
// Function to translate a point by (tx, ty, tz)
void translate(float tx, float ty, float tz, float matrix[4][4]) {
matrix[0][0] = 1; matrix[0][1] = 0; matrix[0][2] = 0; matrix[0][3] = tx;
matrix[1][0] = 0; matrix[1][1] = 1; matrix[1][2] = 0; matrix[1][3] = ty;
matrix[2][0] = 0; matrix[2][1] = 0; matrix[2][2] = 1; matrix[2][3] = tz;
matrix[3][0] = 0; matrix[3][1] = 0; matrix[3][2] = 0; matrix[3][3] = 1;
}
// Function to scale a point by (sx, sy, sz)
void scale(float sx, float sy, float sz, float matrix[4][4]) {
matrix[0][0] = sx; matrix[0][1] = 0; matrix[0][2] = 0; matrix[0][3] = 0;
matrix[1][0] = 0; matrix[1][1] = sy; matrix[1][2] = 0; matrix[1][3] = 0;
matrix[2][0] = 0; matrix[2][1] = 0; matrix[2][2] = sz; matrix[2][3] = 0;
matrix[3][0] = 0; matrix[3][1] = 0; matrix[3][2] = 0; matrix[3][3] = 1;
}
// Function to rotate a point around the X-axis by an angle
void rotateX(float angle, float matrix[4][4]) {
float rad = angle * M_PI / 180.0;
matrix[0][0] = 1; matrix[0][1] = 0; matrix[0][2] = 0; matrix[0][3] = 0;
matrix[1][0] = 0; matrix[1][1] = cos(rad); matrix[1][2] = -sin(rad); matrix[1][3] = 0;
matrix[2][0] = 0; matrix[2][1] = sin(rad); matrix[2][2] = cos(rad); matrix[2][3] = 0;
matrix[3][0] = 0; matrix[3][1] = 0; matrix[3][2] = 0; matrix[3][3] = 1;
}
// Function to rotate a point around the Y-axis by an angle
void rotateY(float angle, float matrix[4][4]) {
float rad = angle * M_PI / 180.0;
matrix[0][0] = cos(rad); matrix[0][1] = 0; matrix[0][2] = sin(rad); matrix[0][3] = 0;
matrix[1][0] = 0; matrix[1][1] = 1; matrix[1][2] = 0; matrix[1][3] = 0;
matrix[2][0] = -sin(rad); matrix[2][1] = 0; matrix[2][2] = cos(rad); matrix[2][3] = 0;
matrix[3][0] = 0; matrix[3][1] = 0; matrix[3][2] = 0; matrix[3][3] = 1;
}
// Function to rotate a point around the Z-axis by an angle
void rotateZ(float angle, float matrix[4][4]) {
float rad = angle * M_PI / 180.0;
matrix[0][0] = cos(rad); matrix[0][1] = -sin(rad); matrix[0][2] = 0; matrix[0][3] = 0;
matrix[1][0] = sin(rad); matrix[1][1] = cos(rad); matrix[1][2] = 0; matrix[1][3] = 0;
matrix[2][0] = 0; matrix[2][1] = 0; matrix[2][2] = 1; matrix[2][3] = 0;
matrix[3][0] = 0; matrix[3][1] = 0; matrix[3][2] = 0; matrix[3][3] = 1;
}
// Function for Parallel Projection (ignores depth)
Point parallelProjection(Point p) {
Point result;
result.x = p.x;
result.y = p.y;
result.z = p.z;
return result;
}
// Function for Perspective Projection (using a simple perspective formula)
Point perspectiveProjection(Point p, float d) {
Point result;
result.x = (d * p.x) / p.z;
result.y = (d * p.y) / p.z;
result.z = p.z;
return result;
}
// Function to plot the 3D object (in 2D)
void plot3DObject(Point object[], int n) {
for (int i = 0; i < n - 1; i++) {
line(object[i].x, object[i].y, object[i + 1].x, object[i + 1].y);
}
line(object[n - 1].x, object[n - 1].y, object[0].x, object[0].y);
}
int main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, ""); // Initialize graphics mode
int n;
Point object[MAX_VERTICES];
// Input the number of vertices of the 3D object (polygon)
printf("Enter the number of vertices of the 3D object: ");
scanf("%d", &n);
// Input the coordinates of the 3D object
printf("Enter the coordinates of the object vertices (x y z):\n");
for (int i = 0; i < n; i++) {
printf("Vertex %d: ", i + 1);
scanf("%f %f %f", &object[i].x, &object[i].y, &object[i].z);
object[i].w = 1; // Homogeneous coordinate (w = 1 for 3D)
}
// Plot the original object
setcolor(WHITE);
plot3DObject(object, n);
// Perform transformations
int choice;
printf("\nChoose the transformation to apply:\n");
printf("1. Translation\n");
printf("2. Scaling\n");
printf("3. Rotation\n");
printf("Enter your choice: ");
scanf("%d", &choice);
float matrix[4][4] = { 0 };
Point transformedObject[MAX_VERTICES];
switch (choice) {
case 1: {
float tx, ty, tz;
printf("Enter translation vector (tx, ty, tz): ");
scanf("%f %f %f", &tx, &ty, &tz);
translate(tx, ty, tz, matrix);
break;
}
case 2: {
float sx, sy, sz;
printf("Enter scaling factors (sx, sy, sz): ");
scanf("%f %f %f", &sx, &sy, &sz);
scale(sx, sy, sz, matrix);
break;
}
case 3: {
float angle, ax;
printf("Enter rotation axis (1 for X-axis, 2 for Y-axis, 3 for Z-axis): ");
scanf("%f", &ax);
printf("Enter rotation angle (in degrees): ");
scanf("%f", &angle);
if (ax == 1)
rotateX(angle, matrix);
else if (ax == 2)
rotateY(angle, matrix);
else if (ax == 3)
rotateZ(angle, matrix);
break;
}
default:
printf("Invalid choice\n");
closegraph();
return 0;
}
// Apply the transformation to all vertices of the object
for (int i = 0; i < n; i++) {
transformedObject[i] = multiplyMatrix(object[i], matrix);
}
// Perform parallel projection
Point parallelProjected[MAX_VERTICES];
for (int i = 0; i < n; i++) {
parallelProjected[i] = parallelProjection(transformedObject[i]);
}
// Plot the parallel projection of the transformed object
setcolor(RED);
plot3DObject(parallelProjected, n);
// Perform perspective projection
float d = 300; // Distance of the observer
Point perspectiveProjected[MAX_VERTICES];
for (int i = 0; i < n; i++) {
perspectiveProjected[i] = perspectiveProjection(transformedObject[i], d);
}
// Plot the perspective projection of the transformed object
setcolor(GREEN);
plot3DObject(perspectiveProjected, n);
// Wait for the user to press a key before closing the graphics window
getch();
closegraph();
return 0;
}