home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <math.h>
- #include <stdlib.h>
- #include <dos.h>
- #include <conio.h>
- #include <i86.h>
- #include <string.h>
- #include <math.h>
- #include "vesalint.h"
- #include "affine.c"
-
- #define RES_X 320
- #define RES_Y 200
- #define MID_X 160
- #define MID_Y 100
-
- #define MAX_ITER 4
- #define RADI_LUZ 25
-
- #define ESFERA 0
- #define PLANO 1
- #define CILINDRO 2
-
- #pragma aux Set_Mode=\
- "int 10h"\
- modify [ax]\
- parm [ax]
-
- // rutina para interpolar la imagen para aumentarla
- void interpola(unsigned char *pant)
- {
- int x,y;
- pant+=3;
- for (y=1;y<MID_Y;y++)
- {
- for (x=1;x<MID_X;x++)
- {
- pant[0]=(pant[-3]+pant[3])>>1;
- pant[1]=(pant[-2]+pant[4])>>1;
- pant[2]=(pant[-1]+pant[5])>>1;
- pant+=6;
- }
- pant+=3;
- for (x=1;x<MID_X;x++)
- {
- pant[0]=(pant[-RES_X*3 ]+pant[ RES_X*3 ])>>1;
- pant[1]=(pant[-RES_X*3+1]+pant[ RES_X*3+1])>>1;
- pant[2]=(pant[-RES_X*3+2]+pant[ RES_X*3+2])>>1;
- pant[3]=(pant[-RES_X*3 ]+pant[-RES_X*3+6]+pant[RES_X*3 ]+pant[RES_X*3+6])>>2;
- pant[4]=(pant[-RES_X*3+1]+pant[-RES_X*3+7]+pant[RES_X*3+1]+pant[RES_X*3+7])>>2;
- pant[5]=(pant[-RES_X*3+2]+pant[-RES_X*3+8]+pant[RES_X*3+2]+pant[RES_X*3+8])>>2;
- pant+=6;
- }
- pant[0]=(pant[-RES_X*3 ]+pant[ RES_X*3 ])>>1;
- pant[1]=(pant[-RES_X*3+1]+pant[ RES_X*3+1])>>1;
- pant[2]=(pant[-RES_X*3+2]+pant[ RES_X*3+2])>>1;
- pant+=9;
- }
- for (x=1;x<MID_X;x++)
- {
- pant[0]=(pant[-3]+pant[3])>>1;
- pant[1]=(pant[-2]+pant[4])>>1;
- pant[2]=(pant[-1]+pant[5])>>1;
- pant+=6;
- }
- }
-
- typedef struct RT_camera
- {
- VECTOR pos;
- VECTOR target;
- float roll;
- float d;
- }RT_CAMERA;
-
- typedef struct RT_object
- {
- int tipo;
-
- // Propiedades "fisicas" del objeto
-
- VECTOR ambient,diffuse,specular;
- float brillo,reflex;
-
- // Propiedades si el objeto es ESFERA
-
- VECTOR pos;
- float radi;
-
- // Propiedades si el objeto es PLANO
-
- VECTOR EjeX,EjeY,EjeZ;
- float d;
-
- // Si el objeto es un cilindro (infinito) utiliza radi, EjeZ y pos
-
- }RT_OBJECT;
-
- typedef struct RT_luz
- {
- VECTOR pos;
- VECTOR color;
- }RT_LUZ;
-
- typedef struct RT_escena
- {
- int num_luz,num_objetos,num_camera;
- RT_OBJECT *objetos;
- RT_LUZ *luces;
- RT_CAMERA *cameras;
- VECTOR ambient;
-
- }RT_ESCENA;
-
- VECTOR get_normal (RT_OBJECT *objeto, VECTOR pos)
- {
- VECTOR normal;
- switch (objeto->tipo)
- {
- case ESFERA :
- normal=mul_vtr(1/objeto->radi,vtr_sub_vtr(pos,objeto->pos));
- break;
- case PLANO :
- normal=objeto->EjeZ;
- break;
- case CILINDRO:
- normal=vtr_sub_vtr(pos,objeto->pos);
- normal=mul_vtr(1/objeto->radi,vtr_sub_vtr(normal,mul_vtr(vtr_dot_mul_vtr(normal,objeto->EjeZ),objeto->EjeZ)));
- break;
- }
- return normal;
- }
-
- float get_intersect (RT_OBJECT *objeto, VECTOR ori_rayo, VECTOR dir_rayo)
- {
- VECTOR v_calc;
- float bpart,disc,disc2;
-
- float t,t1,t2;
- switch (objeto->tipo)
- {
- case ESFERA :
- v_calc=vtr_sub_vtr(objeto->pos,ori_rayo);
- bpart=vtr_dot_mul_vtr (v_calc,dir_rayo);
- disc=bpart*bpart-mod_vtr2(v_calc)+objeto->radi*objeto->radi;
- if (disc>0)
- {
- disc=sqrt(disc);
- t1=bpart+disc;
- t2=bpart-disc;
- if (t2>t1) t=t1;
- else t=t2;
- }
- else t=-1;
- break;
- case PLANO :
- disc=vtr_dot_mul_vtr (objeto->EjeZ,dir_rayo);
- if (disc!=0)
- {
- t=-(vtr_dot_mul_vtr (objeto->EjeZ,ori_rayo)+objeto->d)/disc;
- }
- else t=-1;
- break;
-
- case CILINDRO :
- dir_rayo=vtr_sub_vtr(dir_rayo,mul_vtr(vtr_dot_mul_vtr(dir_rayo,objeto->EjeZ),objeto->EjeZ));
- disc2=mod_vtr2(dir_rayo);
- if (disc2!=0)
- {
- v_calc=vtr_sub_vtr(ori_rayo,objeto->pos);
- v_calc=vtr_sub_vtr(v_calc,mul_vtr(vtr_dot_mul_vtr(v_calc,objeto->EjeZ),objeto->EjeZ));
- bpart=vtr_dot_mul_vtr (v_calc,dir_rayo);
- disc=bpart*bpart+(objeto->radi*objeto->radi-mod_vtr2(v_calc))*disc2;
- if (disc>0)
- {
- disc=sqrt(disc);
- disc2=1/disc2;
- t1=(-bpart+disc)*disc2;
- t2=(-bpart-disc)*disc2;
- if (t2>t1) t=t1;
- else t=t2;
- }
- else t=-1;
- }
- else t=-1;
- break;
- }
- return t;
- }
-
- int rayo_sombra(RT_ESCENA *esc, VECTOR origen, VECTOR rayo, float max_t,int ori_object)
- {
- float t;
- int sc;
- for (sc=0;sc<esc->num_objetos;sc++)
- if (sc!=ori_object)
- {
- t=get_intersect(&esc->objetos[sc],origen,rayo);
- if ((t>0)&&(t<max_t)) return 1;
- }
- return 0;
- }
-
- VECTOR rayo_luz (RT_ESCENA *esc, VECTOR origen, VECTOR ray, int iter, int ori_object)
- {
- int sc,lc,min_object;
- float bpart,disc,t,min_t,cos_alfa,cos_beta,mod_luz;
- VECTOR posicion,normal,v_luz,color,add_col,col_ref,ray_ref;
- VECTOR zero_color={0,0,0};
- VECTOR v_calc;
-
- min_t=1000000.0;
- min_object=-1;
- for (sc=0;sc<esc->num_objetos;sc++)
- if (sc!=ori_object)
- {
- t=get_intersect(&esc->objetos[sc],origen,ray);
- if ((t>0)&&(t<min_t)) {min_t=t; min_object=sc;}
- }
- if (min_object>=0) // Si el rayo da con alguna esfera...
- {
- posicion=vtr_add_vtr(origen,mul_vtr(min_t,ray));
- normal=get_normal(&esc->objetos[min_object],posicion);
- ray_ref=vtr_sub_vtr(ray,mul_vtr(2*vtr_dot_mul_vtr(ray,normal),normal));
- color=vtr_dir_mul_vtr(esc->objetos[min_object].ambient,esc->ambient);
- for (lc=0;lc<esc->num_luz;lc++)
- {
- v_luz=vtr_sub_vtr(esc->luces[lc].pos,posicion);
- mod_luz=mod_vtr(v_luz); //esta es la distancia a la que se encuentra la luz
- v_luz=mul_vtr(1/mod_luz,v_luz);
- cos_alfa=vtr_dot_mul_vtr(v_luz,normal);
- if (cos_alfa>0)
- if (!rayo_sombra(esc,posicion,v_luz,mod_luz,min_object))
- {
-
- cos_beta=vtr_dot_mul_vtr(ray_ref,v_luz);
- if (cos_beta>0)
- add_col=mul_vtr(exp(esc->objetos[min_object].brillo*(cos_beta-1)),
- esc->objetos[min_object].specular);
- else
- add_col=zero_color;
- add_col=vtr_add_vtr(mul_vtr(cos_alfa,esc->objetos[min_object].diffuse),add_col);
- add_col=vtr_dir_mul_vtr(esc->luces[lc].color,add_col);
- color=vtr_add_vtr(color,add_col);
- }
- }
- // si hace falta, se lanza un rayo reflejado
- if (iter<MAX_ITER){
- col_ref=rayo_luz(esc,posicion,ray_ref,iter+1,min_object);
- color=vtr_add_vtr(mul_vtr(esc->objetos[min_object].reflex,col_ref),
- mul_vtr(1-esc->objetos[min_object].reflex,color));}
- }
- else color=esc->ambient;
- // else color=zero_color;
-
- // Calculos para representar las luces
- if (iter==0)
- for (lc=0;lc<esc->num_luz;lc++)
- {
- v_calc=vtr_sub_vtr(esc->luces[lc].pos,origen);
- bpart=vtr_dot_mul_vtr (v_calc,ray);
- disc=bpart*bpart-mod_vtr2(v_calc)+RADI_LUZ*RADI_LUZ;
- if ((disc>0)&&(bpart>0.1)&&(bpart<min_t))
- {
- disc=sqrt(disc);
- color=vtr_add_vtr(color,mul_vtr(disc/RADI_LUZ,esc->luces[lc].color));
- }
- }
-
- return (color);
- }
-
- void RT_render(RT_ESCENA *esc, unsigned char *dest)
- {
- int xc,yc,ppos;
- VECTOR v_col,origen,direccion,v_dir;
-
- VECTOR X_axe, Y_axe, Z_axe;
- VECTOR X_axep, Y_axep;
- VECTOR right = {1.0,0.0,0.0};
- VECTOR down = {0.0,1.0,0.0};
- VECTOR deep = {0.0,0.0,-1.0};
- float angle;
-
- // Calculamos el sistema de ejes para la camara
-
- Z_axe=unit_vtr(vtr_sub_vtr(esc->cameras->target,esc->cameras->pos));
- angle=vtr_dot_mul_vtr(Z_axe,down);
- if ((angle<1.0)&&(angle>-1.0))
- {
- X_axe=unit_vtr(vtr_cross_mul_vtr(down,Z_axe));
- Y_axe=unit_vtr(vtr_cross_mul_vtr(Z_axe,X_axe));
- }
- else
- {
- X_axe=right;
- Y_axe=deep;
- }
-
- X_axep=mul_vtr(cos(esc->cameras->roll),X_axe);
- Y_axep=mul_vtr(sin(esc->cameras->roll),Y_axe);
- X_axep=vtr_add_vtr(X_axep,Y_axep);
- X_axe=mul_vtr(-sin(esc->cameras->roll),X_axe);
- Y_axe=mul_vtr(cos(esc->cameras->roll),Y_axe);
- Y_axep=vtr_add_vtr(X_axe,Y_axe);
-
- // Lanzamos los rayos utilizando los ejes de la camara
-
- origen=esc->cameras->pos;
- v_dir=vtr_add_vtr(mul_vtr(-MID_Y,Y_axep),mul_vtr(-MID_X,X_axep));
- v_dir=vtr_add_vtr(v_dir,mul_vtr(esc->cameras->d,Z_axe));
-
- ppos=0;
- for (yc=-MID_Y;yc<MID_Y;yc+=2)
- {
- for (xc=-MID_X;xc<MID_X;xc+=2)
- {
- direccion=unit_vtr(v_dir);
- v_dir=vtr_add_vtr(mul_vtr(2,X_axep),v_dir);
- v_col=rayo_luz(esc,origen,direccion,0,-1);
-
- dest[ppos ]=min(v_col.v3,254);
- dest[ppos+1]=min(v_col.v2,254);
- dest[ppos+2]=min(v_col.v1,254);
-
- ppos+=6;
- }
- v_dir=vtr_add_vtr(v_dir,mul_vtr(-RES_X,X_axep));
- v_dir=vtr_add_vtr(mul_vtr(2,Y_axep),v_dir);
- ppos+=RES_X*3;
- }
- interpola(dest);
- }
-
- RT_ESCENA *ray_testing;
- unsigned char *Virtpant1;
- unsigned char *Virtpant2;
-
- void main(int argc, char *argv[])
- {
- float movi=0;
- int c;
-
- Virtpant1=malloc(RES_X*RES_Y*3);
- Virtpant2=malloc(RES_X*RES_Y*3);
- for (c=0;c<RES_X*RES_Y*3;c++)
- Virtpant1[c]=0;
-
- // Definiciones de los objetos, luces y camara de la escena
-
- ray_testing=malloc(sizeof(RT_ESCENA));
- ray_testing->num_objetos =4;
- ray_testing->num_camera =1;
- ray_testing->num_luz =2;
- ray_testing->objetos=malloc(sizeof (RT_OBJECT)*ray_testing->num_objetos);
- ray_testing->cameras=malloc(sizeof (RT_CAMERA)*ray_testing->num_camera);
- ray_testing->luces =malloc(sizeof (RT_LUZ )*ray_testing->num_luz);
- ray_testing->ambient.v1=0;
- ray_testing->ambient.v2=64;
- ray_testing->ambient.v3=32;
-
- ray_testing->objetos[0].tipo=ESFERA;
- ray_testing->objetos[0].pos.v1=100;
- ray_testing->objetos[0].pos.v2=60;
- ray_testing->objetos[0].pos.v3=850;
- ray_testing->objetos[0].radi=100;
- ray_testing->objetos[0].ambient.v1=0;
- ray_testing->objetos[0].ambient.v2=0;
- ray_testing->objetos[0].ambient.v3=0.2;
- ray_testing->objetos[0].diffuse.v1=0;
- ray_testing->objetos[0].diffuse.v2=0.25;
- ray_testing->objetos[0].diffuse.v3=0.5;
- ray_testing->objetos[0].specular.v1=1;
- ray_testing->objetos[0].specular.v2=1;
- ray_testing->objetos[0].specular.v3=1;
- ray_testing->objetos[0].brillo=10;
- ray_testing->objetos[0].reflex=0.3;
-
- ray_testing->objetos[1].tipo=ESFERA;
- ray_testing->objetos[1].pos.v1=0;
- ray_testing->objetos[1].pos.v2=0;
- ray_testing->objetos[1].pos.v3=1000;
- ray_testing->objetos[1].radi=175;
- ray_testing->objetos[1].ambient.v1=0.2;
- ray_testing->objetos[1].ambient.v2=0;
- ray_testing->objetos[1].ambient.v3=0;
- ray_testing->objetos[1].diffuse.v1=0.6;
- ray_testing->objetos[1].diffuse.v2=0.25;
- ray_testing->objetos[1].diffuse.v3=0;
- ray_testing->objetos[1].specular.v1=1;
- ray_testing->objetos[1].specular.v2=0.8;
- ray_testing->objetos[1].specular.v3=0.8;
- ray_testing->objetos[1].brillo=20;
- ray_testing->objetos[1].reflex=0.3;
-
- ray_testing->objetos[2].tipo=PLANO;
- ray_testing->objetos[2].EjeZ.v1=0;
- ray_testing->objetos[2].EjeZ.v2=-1;
- ray_testing->objetos[2].EjeZ.v3=0;
- ray_testing->objetos[2].d=100;
- ray_testing->objetos[2].radi=175;
- ray_testing->objetos[2].ambient.v1=0.2;
- ray_testing->objetos[2].ambient.v2=0;
- ray_testing->objetos[2].ambient.v3=0.2;
- ray_testing->objetos[2].diffuse.v1=0.7;
- ray_testing->objetos[2].diffuse.v2=0.20;
- ray_testing->objetos[2].diffuse.v3=0.7;
- ray_testing->objetos[2].specular.v1=1;
- ray_testing->objetos[2].specular.v2=.8;
- ray_testing->objetos[2].specular.v3=1;
- ray_testing->objetos[2].brillo=50;
- ray_testing->objetos[2].reflex=0.5;
-
- ray_testing->objetos[3].tipo=CILINDRO;
- ray_testing->objetos[3].pos.v1=-250;
- ray_testing->objetos[3].pos.v2=0;
- ray_testing->objetos[3].pos.v3=700;
- ray_testing->objetos[3].EjeZ.v1=0;
- ray_testing->objetos[3].EjeZ.v2=-1;
- ray_testing->objetos[3].EjeZ.v3=0;
- ray_testing->objetos[3].radi=60;
- ray_testing->objetos[3].ambient.v1=0.2;
- ray_testing->objetos[3].ambient.v2=0.3;
- ray_testing->objetos[3].ambient.v3=0;
- ray_testing->objetos[3].diffuse.v1=0.8;
- ray_testing->objetos[3].diffuse.v2=0.8;
- ray_testing->objetos[3].diffuse.v3=0;
- ray_testing->objetos[3].specular.v1=0.9;
- ray_testing->objetos[3].specular.v2=0.8;
- ray_testing->objetos[3].specular.v3=0.7;
- ray_testing->objetos[3].brillo=50;
- ray_testing->objetos[3].reflex=0.3;
-
- ray_testing->luces[0].pos.v1=300;
- ray_testing->luces[0].pos.v2=0;
- ray_testing->luces[0].pos.v3=500;
- ray_testing->luces[0].color.v1=200;
- ray_testing->luces[0].color.v2=0;
- ray_testing->luces[0].color.v3=0;
-
- ray_testing->luces[1].pos.v1=200;
- ray_testing->luces[1].pos.v2=-200;
- ray_testing->luces[1].pos.v3=800;
- ray_testing->luces[1].color.v1=255;
- ray_testing->luces[1].color.v2=255;
- ray_testing->luces[1].color.v3=255;
-
- ray_testing->cameras[0].pos.v1=0;
- ray_testing->cameras[0].pos.v2=0;
- ray_testing->cameras[0].pos.v3=0;
- ray_testing->cameras[0].target.v1=0;
- ray_testing->cameras[0].target.v2=0;
- ray_testing->cameras[0].target.v3=1000;
- ray_testing->cameras[0].roll=0;
- ray_testing->cameras[0].d=256*RES_X/320;
-
- // Incicializacion del modo de video
-
- Active.Screen.Width=320;
- Active.Screen.Height=200;
- Active.Screen.bpp=32;
-
- Active.Work.Width=RES_X;
- Active.Work.Height=RES_Y;
- Active.Work.bpp=24;
-
- Active.EnableLFB=1;
-
- if (!InitSetMode())
- {
- Active.Screen.bpp=24;
- if (!InitSetMode())
- {
- Active.Screen.bpp=16;
- if (!InitSetMode())
- {
- Active.Screen.bpp=15;
- if (!InitSetMode())
- {
- Active.Screen.bpp=-1;
- Active.Screen.Height*=2;
- InitSetMode();
- }
- }
- }
- }
-
- movi=0;
- while (!kbhit())
- {
- // Calculos para "animar" los elementos de la escena
-
- ray_testing->cameras[0].pos.v1=800*sin(movi/80.0);
- ray_testing->cameras[0].pos.v2=-200*(1-cos(movi/40.0));
- ray_testing->cameras[0].pos.v3=1000*(1-cos(movi/80.0));
- ray_testing->cameras[0].roll=0.5*sin(movi/20.0);
- ray_testing->objetos[0].pos.v1=300*cos(movi/35.0);
- ray_testing->objetos[0].pos.v3=850+300*sin(movi/35.0);
- ray_testing->objetos[3].EjeZ.v2=-cos(movi/50.0);
- ray_testing->objetos[3].EjeZ.v1=-sin(movi/50.0);
- movi++;
-
- RT_render(ray_testing,Virtpant1);
- Flip(Virtpant1);
- }
- getch();
- Set_Mode(0x3);
- Free_Memory();
- printf("[#] Salio\n");
- }
-
-
-