Untitled

mail@pastecode.io avatar
unknown
plain_text
2 years ago
18 kB
2
Indexable
Never
#include <iostream>
#include <vector>
#include<math.h>

#define pi (2*acos(0.0))

using namespace std;

class Point{
public:
    double x;
    double y;
    double z;

    Point(){}

    Point(double x, double y, double z){
        this->x = x;
        this->y = y;
        this->z = z;
    }

    printPoint(){
        cout << " Point : " << x << " " << y << " " << z << endl;
    }
};

class Ray{
public:
    Point start;
    Point dir;

    Ray(Point eye, Point cur_pixel){
        start = eye;
        dir.x = cur_pixel.x - eye.x;
        dir.y = cur_pixel.y - eye.y;
        dir.z = cur_pixel.z - eye.z;

        double length = sqrt( ( dir.x * dir.x ) + ( dir.y * dir.y ) + ( dir.z * dir.z ) );
        dir.x = dir.x / length;
        dir.y = dir.y / length;
        dir.z = dir.z / length;
    }

    void printRay(){
        cout << "Ray start  " << endl;
        start.printPoint() ;
        cout << "Ray dir  " << endl;
        dir.printPoint() ;
    }
};


class Object{
public:
    Point reference_point;
    double height, width, length;
    double color[3];
    double coEfficients[4];
    int shine;

    Object(){
    }

    virtual void draw(){}

    virtual double intersect(Ray *r, double* color, int level){
        return INT_MAX;
    }

    void setLightingColor(double* c){
        c[0] = color[0] * coEfficients[0];
        c[1] = color[1] * coEfficients[0];
        c[2] = color[2] * coEfficients[0];
    }

    void setColor(double c[]){
        this->color[0] = c[0];
        this->color[1] = c[1];
        this->color[2] = c[2];
    }

    void setShine(int shine){
        this->shine = shine;
    }

    void setCoefficients(double coeff[]){
        this->coEfficients[0] = coeff[0];
        this->coEfficients[1] = coeff[1];
        this->coEfficients[2] = coeff[2];
        this->coEfficients[3] = coeff[3];
    }

    virtual void print_object(){
        cout << "Color : " << color[0] << " " << color[1] << " " << color[2] << endl;
        cout << "Coefficients: " << coEfficients[0] << " " << coEfficients[1] << " " << coEfficients[2] << " " << coEfficients[3] << endl;
        cout << "Shine : " << shine << endl;
    }

};

class Sphere : public Object{
public:
    Sphere(Point center, double radius){
        reference_point = center;
        length = radius;
    }

    void draw(){
        // printf("Draw circle\n");
        Point points[100][100];
        int i,j;
        int slices = 12;
        int stacks = 20;
        double h,r;
        double radius = length;
       // cout << "radius : " << radius << endl;
        //generate points
        for(i=0;i<=stacks;i++)
        {
            h=radius*sin(((double)i/(double)stacks)*(pi/2));
            r=radius*cos(((double)i/(double)stacks)*(pi/2));
            for(j=0;j<=slices;j++)
            {
                points[i][j].x=r*cos(((double)j/(double)slices)*2*pi);
                points[i][j].y=r*sin(((double)j/(double)slices)*2*pi);
                points[i][j].z=h;
            }
        }
        //draw quads using generated points
        for(i=0;i<stacks;i++)
        {
            glColor3f(color[0], color[1], color[2]);
            for(j=0;j<slices;j++)
            {
                glBegin(GL_QUADS);{
                    //upper hemisphere
                    glVertex3f(points[i][j].x,points[i][j].y,points[i][j].z);
                    glVertex3f(points[i][j+1].x,points[i][j+1].y,points[i][j+1].z);
                    glVertex3f(points[i+1][j+1].x,points[i+1][j+1].y,points[i+1][j+1].z);
                    glVertex3f(points[i+1][j].x,points[i+1][j].y,points[i+1][j].z);
                    //lower hemisphere
                    glVertex3f(points[i][j].x,points[i][j].y,-points[i][j].z);
                    glVertex3f(points[i][j+1].x,points[i][j+1].y,-points[i][j+1].z);
                    glVertex3f(points[i+1][j+1].x,points[i+1][j+1].y,-points[i+1][j+1].z);
                    glVertex3f(points[i+1][j].x,points[i+1][j].y,-points[i+1][j].z);
                }glEnd();
            }
        }
        // cout<<"drawing is over" << endl;
    }

    double intersect(Ray *r, double* color_in, int level){

        Point r_start_translate( r->start.x - reference_point.x, r->start.y - reference_point.y, r->start.z - reference_point.z);


        double ld = - ( r->dir.x * r_start_translate.x ) - ( r->dir.y * r_start_translate.y ) - ( r->dir.z * r_start_translate.z );
        if(ld < 0 ){
            return INT_MAX;
        }
        double r_start_len = ( r_start_translate.x * r_start_translate.x ) + ( r_start_translate.y * r_start_translate.y ) + ( r_start_translate.z * r_start_translate.z );
        double d_squared = ( r_start_len ) - ( ld * ld );
        if(d_squared > ( length * length ) ){
            return INT_MAX;
        }
        double l_prime = ( length*length ) - d_squared;
        double t1 = ld + l_prime;
        double t2 = ld - l_prime;
        // cout << "intersecting sphere on  " << min(t1, t2) << endl;

        setLightingColor(color_in);


        double t = NULL;
        /*
        if(r_start_len < (length * length) ){
            t = t1;
        }
        else if(r_start_len > ( length * length ) ){
            t = t2;
        }
        else if(t == NULL ){
            t = min(t1, t2);
        }*/
        t = min(t1, t2);
        if( level != 0 ){
            Point intersect_point( r->start.x + ( t * r->dir.x ), r->start.y + ( t * r->dir.y ), r->start.z + ( t * r->dir.z ) );

            double len = sqrt( pow(intersect_point.x, 2) + pow(intersect_point.y, 2) + pow(intersect_point.z, 2) );
            Point normal;
            normal.x = intersect_point.x / len;
            normal.y = intersect_point.y / len;
            normal.z = intersect_point.z / len;

        }


        return t;

    }

    void print_object(){
        cout << "Sphere " << endl;
        cout << "Radius : " << length << endl;
        cout << "Center : " << reference_point.x << reference_point.y << reference_point.z <<endl;
        Object::print_object();

    }
};


class Triangle : public Object{
public:
    Point first, second, third;

    Triangle(Point first, Point second, Point third){
        this->first =  first;
        this->second = second;
        this->third = third;
    }

    void draw(){
        // printf("Draw Triangle\n");

        glColor3f(color[0], color[1], color[2]);
         glBegin(GL_TRIANGLES);
        {
            glVertex3f(first.x, first.y, first.z);
            glVertex3f(second.x, second.y, second.z);
            glVertex3f(third.x, third.y, third.z);
        }
        glEnd();

    }

    void print_object(){
        cout << "First : " << first.x << first.y << first.z <<endl;
        cout << "Second : " << second.x << second.y << second.z <<endl;
        cout << "Third : " << third.x << third.y << third.z <<endl;
        Object::print_object();

    }

    double intersect(Ray *r, double* color_in, int level){

        setLightingColor(color_in);

        double a1 = first.x - second.x;
        double a2 = first.y - second.y;
        double a3 = first.z - second.z;

        double b1 = third.x - second.x;
        double b2 = third.y - second.y;
        double b3 = third.z - second.z;

        double c1 = - r->dir.x;
        double c2 = - r->dir.y;
        double c3 = - r->dir.z;

        double d1 = r->start.x - second.x ;
        double d2 = r->start.y - second.y ;
        double d3 = r->start.z - second.z ;

        double D = a1 * (b2*c3 - c2*b3) + b1 * (c2*a3 - c3*a2) + c1 * (a2*b3 - a3*b2);
        double D1 = d1 * (b2*c3 - c2*b3) + b1 * (c2*d3 - c3*d2) + c1 * (d2*b3 - d3*b2);
        double D2 = a1 * (d2*c3 - c2*d3) + d1 * (c2*a3 - c3*a2) + c1 * (a2*d3 - a3*d2);
        double D3 = a1 * (b2*d3 - d2*b3) + b1 * (d2*a3 - d3*a2) + d1 * (a2*b3 - a3*b2);

        if( D != 0 ){
            double k1 = D1 / D;
            double k2 = D2 / D;
            double t = D3 / D;
            // cout << (k1 + k2 ) << endl;
            if((k1 > 0 ) && (k2 > 0) && ( k1 + k2 <= 1 ) ){
                if(level != 0){
                    Point intersect_point(r->start.x + ( t * r->dir.x ), r->start.y + ( t * r->dir.y ), r->start.z + ( t * r->dir.z ));
                    Point normal;
                    normal.x = ( a2 * b3 ) - ( b2 * a3 );
                    normal.y = ( a3 * b1 ) - ( a1 * b3 );
                    normal.z = ( a1 * b2 ) - ( a2 * b1 );
                    double len = sqrt( pow(normal.x, 2) + pow( normal.y, 2) + pow( normal.z, 2) );
                    normal.x = normal.x / len;
                    normal.y = normal.y / len;
                    normal.z = normal.z / len;
                }

                return t;
            }
        }



        return INT_MAX;

    }

};


class General : public Object{
public:
    vector<double> degree_coeff;

    General( vector<double> coeff){
        this->degree_coeff = coeff;
        /*cout<<"length : " << degree_coeff.size() << endl;
        for(double element : degree_coeff){
            cout<<element << " ";
        }
        cout<<endl;*/
    }

    void draw(){
    }

    double intersect(Ray *r, double* color_in, int level){

        setLightingColor(color_in);


        Point r_start(r->start.x - reference_point.x, r->start.y - reference_point.y, r->start.z - reference_point.z);



        /*r_start.x =  r->start.x ;
        r_start.y =  r->start.y ;
        r_start.z =  r->start.z ;*/

        double a = ( degree_coeff[0] * pow( r->dir.x , 2 ) ) + ( degree_coeff[1] * pow(r->dir.y, 2) ) + (degree_coeff[2] * pow(r->dir.z, 2) ) \
                            + ( degree_coeff[3] * r->dir.x * r->dir.y ) + ( degree_coeff[4] * r->dir.y * r->dir.z ) + ( degree_coeff[5] * r->dir.x * r->dir.z );
        double b = ( 2 * degree_coeff[0] * r_start.x * r->dir.x ) + ( 2* degree_coeff[1] * r_start.y * r->dir.y ) + ( 2* degree_coeff[2] * r_start.z * r->dir.z ) \
                    + ( degree_coeff[3] * ( ( r->dir.x * r_start.y ) + ( r_start.x * r->dir.y ) ) ) + ( degree_coeff[4] * ( ( r->dir.y * r_start.z ) + ( r_start.y * r->dir.z ) ) ) \
                    + ( degree_coeff[5] * ( ( r->dir.z * r_start.x ) + ( r_start.z * r->dir.x ) ) ) + ( degree_coeff[6] * r->dir.x ) + ( degree_coeff[7] * r->dir.y ) + ( degree_coeff[8] * r->dir.z );

        double c = ( degree_coeff[0] * pow( r_start.x , 2 ) ) + ( degree_coeff[1] * pow(r_start.y, 2) ) + (degree_coeff[2] * pow(r_start.z, 2) ) \
                        + ( degree_coeff[3] * r_start.x * r_start.y ) + ( degree_coeff[4] * r_start.y * r_start.z ) + ( degree_coeff[5] * r_start.x * r_start.z ) \
                        + ( degree_coeff[6] * r_start.x ) + ( degree_coeff[7] * r_start.y ) + ( degree_coeff[8] * r_start.z ) + degree_coeff[9];

        double root_squared = ( b * b ) - ( 4 * a * c );
        if(root_squared < 0 ){
            return INT_MAX;
        }
        root_squared = sqrt( root_squared );
        double t1 = ( - b + root_squared ) / ( 2 * a );
        double t2 = ( - b - root_squared ) / ( 2 * a );

        double t = INT_MAX;
        bool not_valid = false;
        Point min_intersect;
        if( t1 > 0 ){
            Point intersect_point(r->start.x + ( t1 * r->dir.x ), r->start.y + ( t1 * r->dir.y ), r->start.z + ( t1 * r->dir.z ));


            if(length != 0 ){
                if( ( intersect_point.x < reference_point.x ) || ( intersect_point.x > ( reference_point.x + length )) ){
                    not_valid = true;
                }
            }


            if(width != 0 ){
                if( ( intersect_point.y < reference_point.y ) || ( intersect_point.y > ( reference_point.y + width )) ){
                    not_valid = true;
                }
            }

            if(height != 0 ){
                if( ( intersect_point.z < reference_point.z ) || ( intersect_point.z > ( reference_point.z + height )) ){
                    not_valid = true;
                }
            }

            if( not_valid == false ){
                min_intersect = intersect_point;
                t = min(t, t1);
            }

        }
        not_valid = false;

         if( t2 > 0 ){
            Point intersect_point( r->start.x + ( t2 * r->dir.x ), r->start.y + ( t2 * r->dir.y ), r->start.z + ( t2 * r->dir.z ) );


            if(length != 0 ){
                if( ( intersect_point.x < reference_point.x ) || ( intersect_point.x > ( reference_point.x + length )) ){
                    not_valid = true;
                }
            }


            if(width != 0 ){
                if( ( intersect_point.y < reference_point.y ) || ( intersect_point.y > ( reference_point.y + width )) ){
                    not_valid = true;
                }
            }

            if(height != 0 ){
                if( ( intersect_point.z < reference_point.z ) || ( intersect_point.z > ( reference_point.z + height )) ){
                    not_valid = true;
                }
            }

            if( not_valid == false ){
                if( t != NULL ){
                    t = min(t, t2);
                    if( t == t2 ){
                        min_intersect = intersect_point;
                    }
                }
                else{
                    min_intersect = intersect_point;
                    t = t2;
                }
            }

        }

       if(level != 0 ){
           Point normal;
           normal.x = ( 2 * coEfficients[0] * min_intersect.x ) + ( coEfficients[3] * min_intersect.y ) + ( coEfficients[5] * min_intersect.z ) + coEfficients[6];
           normal.y = ( 2 * coEfficients[1] * min_intersect.y ) + ( coEfficients[3] * min_intersect.x ) + ( coEfficients[4] * min_intersect.y ) + coEfficients[7];
           normal.z = ( 2 * coEfficients[2] * min_intersect.z ) + ( coEfficients[4] * min_intersect.y ) + ( coEfficients[5] * min_intersect.x ) + coEfficients[8];
           double len = sqrt( pow(normal.x, 2) + pow( normal.y, 2) + pow( normal.z, 2) );
           normal.x = normal.x / len;
           normal.y = normal.y / len;
           normal.z = normal.z / len;

       }


       return t;

    }



};

class PointLight{
public:
    Point light_pos;
    double color[3];

    PointLight(Point pos){
        this->light_pos = pos;
    }

    void setColor(double c[]){
        this->color[0] = c[0];
        this->color[1] = c[1];
        this->color[2] = c[2];
    }
};

class SpotLight{
public:
    PointLight* pl;
    Point light_direction;
    double cutoff_angle;

    SpotLight(PointLight pl, Point light_dir, double angle){
        this-> pl = new PointLight(pl.light_pos);
        this->pl->setColor(pl.color);
        this->light_direction = light_dir;
        this->cutoff_angle = angle;
    }
};


class Floor : public Object{
public:
    double floorwidth;

    Floor(double floorwidth, double tilewidth){
        this->floorwidth = floorwidth;
        reference_point.x = - floorwidth / 2.0;
        reference_point.y = - floorwidth / 2.0;
        reference_point.z = 0;
        length = tilewidth;
    }

    void draw(){
        int i;

        Point cur_point(0, 0, 0);

        double row_color[3] = {color[0], color[1], color[2]};
        // cout << "y : " << cur_point.y << " " << reference_point.y << endl;
        while( cur_point.y <= floorwidth ){

            double col_color[3] = {row_color[0], row_color[1], row_color[2]};
            while(cur_point.x <= floorwidth){
                // cout << "cur point y : " << cur_point.y << endl;
                glColor3f(col_color[0], col_color[1], col_color[2]);
                glBegin(GL_QUADS);{

                glVertex3f(cur_point.x, cur_point.y, 0);
                glVertex3f(cur_point.x + length, cur_point.y, 0);
                glVertex3f(cur_point.x + length, cur_point.y + length, 0);
                glVertex3f(cur_point.x, cur_point.y + length, 0);

                }glEnd();

                cur_point.x = cur_point.x + length;

                col_color[0] = 1 - col_color[0];
                col_color[1] = 1 - col_color[1];
                col_color[2] = 1 - col_color[2];

            }

            cur_point.y = cur_point.y + length;
            cur_point.x = 0;
            row_color[0] = 1 - row_color[0];
            row_color[1] = 1 - row_color[1];
            row_color[2] = 1 - row_color[2];

            // cout << "updated cur point y : " << cur_point.y << endl;

        }



    }

     double intersect(Ray *r, double* color_in, int level){

        double dot_d_n = r->dir.z;

        if( dot_d_n == 0 ){
            return INT_MAX;
        }

        double dot_p_n = reference_point.z * r->dir.z;
        double dot_r0_n = r->start.z - reference_point.z;

        double t = ( dot_p_n - dot_r0_n ) * 1.0 / dot_d_n;

        Point intersection_point( r->start.x + ( t * r->dir.x ),r->start.y + ( t * r->dir.y ), r->start.z + ( t * r->dir.z ) );


        color_in[0] = 1 * coEfficients[0];
        color_in[1] = 1 * coEfficients[0];
        color_in[2] = 1 * coEfficients[0];

        if( ( intersection_point.y >= reference_point.y ) && ( intersection_point.y <= - reference_point.y ) ){
                int col_idx = int( (intersection_point.y - reference_point.y) / length );
                if( ( intersection_point.x >= reference_point.x ) && ( intersection_point.x <= - reference_point.x ) )
                {
                    int row_idx = int( (intersection_point.x - reference_point.x) / length );
                    if( ( row_idx + col_idx ) % 2 == 0){
                        color_in[0] = 0;
                        color_in[1] = 0;
                        color_in[2] = 0;
                    }
                    if(level == 0) return t;
                    // level != 0
                    Point normal(0, 0, 1);

                }
        }

        return INT_MAX;
    }

};




vector<Object*> Objects;
vector<PointLight*> pointLights;
vector<SpotLight*> spotlights;