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