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; }