////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// #include #include #include #include ////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// //funcao que retorna o valor minimo entre 3 valores double min(double a, double b, double c) { if(a <= b && a <= c) return (a); else if(b <= a && b <= c) return (b); else return(c); } ////////////////////////////////////////////////////////////// //funcao que inverte um vetor void reverse_vector(vector_3d *v) { v->x = -v->x; v->y = -v->y; v->z = -v->z; } ////////////////////////////////////////////////////////////// //funcao que calcula a distancia entre dois pontos double distance_betwen_points(point_3d p1, point_3d p2) { double dist = 0.0; //calcula a distancia entre os pontos dist = pow(p1.x - p2.x,2.0) + pow(p1.y - p2.y,2.0) + pow(p1.z - p2.z,2.0); dist = sqrt(dist+EPS); return (dist); } ////////////////////////////////////////////////////////////// //funcao que calcula o produto vetorial entre dois vetores void cross_product(vector_3d a, vector_3d b, vector_3d *c) { c->x = a.y*b.z - a.z*b.y; c->y = a.z*b.x - a.x*b.z; c->z = a.x*b.y - a.y*b.x; return; } ////////////////////////////////////////////////////////////// //funcao que calcula o produto escalar entre 2 vetores double scalar(vector_3d a, vector_3d b) { double scalar = 0.0; scalar = a.x*b.x + a.y*b.y + a.z*b.z; return(scalar); } ////////////////////////////////////////////////////////////// //funcao que realiza a projecao ortogonal de um vetor na reta void ortogonal_projection(vector_3d line, vector_3d vector, vector_3d *ortogonal) { double alpha = 0.0; alpha = scalar(line,vector)/(scalar(line,line)+EPS); ortogonal->x = vector.x - alpha*line.x; ortogonal->y = vector.y - alpha*line.y; ortogonal->z = vector.z - alpha*line.z; return; } ////////////////////////////////////////////////////////////// //funcao que realiza a normaliza de um vetor void normalize_vector(vector_3d *vector) { double norma = 0.0; //calcula a norma do vector norma = pow(vector->x,2.0) + pow(vector->y,2.0) + pow(vector->z,2.0); norma = sqrt(norma)+EPS; if(norma == 0.0) return; //divide as coordenadas do vector pela norma vector->x = vector->x/norma; vector->y = vector->y/norma; vector->z = vector->z/norma; return; } ////////////////////////////////////////////////////////////// //funcao que verifica/calcula se ocolorre intersecção entre um // vetor dado e uma esfera double intersection_vector_sphere(point_3d origin, vector_3d ray, sphere *sphere, color *c, vector_3d *normal) { double b = 0.0, t = 0.0, s = 0.0, //valor da solução xadj,yadj,zadj; xadj = origin.x - sphere->x; yadj = origin.y - sphere->y; zadj = origin.z - sphere->z; //normaliza o vector normalize_vector(&ray); //calculo baseado no artigo do roman b = xadj*ray.x + yadj*ray.y + zadj*ray.z; t = b*b - pow(xadj,2.0) - pow(yadj,2.0) - pow(zadj,2.0) + pow(sphere->radius,2.0); if(t < 0) return 0.0; s= -b - sqrt(t); if(s > 0.0) { c->r = sphere->surface.transp.r; c->g = sphere->surface.transp.g; c->b = sphere->surface.transp.b; normal_sphere(*sphere,point_parametric(origin,ray,s),normal); return (s); } s = -b + sqrt(t); if(s > 0.0) { c->r = sphere->surface.transp.r; c->g = sphere->surface.transp.g; c->b = sphere->surface.transp.b; normal_sphere(*sphere,point_parametric(origin,ray,s),normal); return (s); } //nao ocolorreu intersection com a esfera c->r = 0.0; c->g = 0.0; c->b = 0.0; return(0.0); } ////////////////////////////////////////////////////////////// //funcao que retorna a normal de um ponto sobre a surface // da esfera void normal_sphere(sphere sphere, point_3d intersection, vector_3d *normal) { //encontra a normal a surface normal->x = (intersection.x - sphere.x)/sphere.radius; normal->y = (intersection.y - sphere.y)/sphere.radius; normal->z = (intersection.z - sphere.z)/sphere.radius; normalize_vector(normal); } ////////////////////////////////////////////////////////////// //funcao que verifica/calcula se ocolorre intersecção entre um // vetor dado e um CUBE double intersection_vector_cube(point_3d observer, vector_3d ray, cube *cube, color *color, vector_3d *normal) { double s, ss, xhit, yhit, zhit; double xadj,yadj,zadj; //inicia com um valor "infinito" ss = MAX_DOUBLE; normalize_vector(&ray); //translacao xadj = observer.x; yadj = observer.y; zadj = observer.z; if(ray.x != 0) { s = (cube->d - xadj)/(ray.x); if((s > 0) && (s < ss)) { yhit = fabs(yadj + s*ray.y); zhit = fabs(zadj + s*ray.z); if( (yhit < cube->d) && (zhit < cube->d)) { cube->li = 0; ss = s; } } s = (-cube->d - xadj)/(ray.x); if((s > 0) && (s < ss)) { yhit = fabs(yadj + s*ray.y); zhit = fabs(zadj + s*ray.z); if((yhit < cube->d) && (zhit < cube->d)) { cube->li = 1; ss = s; } } } if(ray.y != 0) { s = (cube->d - yadj)/ (ray.y); if((s > 0) && (s < ss)) { xhit = fabs(xadj + s*ray.x); zhit = fabs(zadj + s*ray.z); if((xhit < cube->d) && (zhit < cube->d)) { cube->li = 2; ss = s; } } s = (-cube->d - yadj)/ ray.y; if(s > 0 && s < ss) { xhit = fabs(xadj + s*ray.x); zhit = fabs(zadj + s*ray.z); if(xhit < cube->d && zhit < cube->d) { cube->li = 3; ss = s; } } } if(ray.z != 0) { s = (cube->d - zadj)/ ray.z; if(s > 0 && s < ss) { xhit = fabs(xadj + s*ray.x); yhit = fabs(yadj + s*ray.y); if(xhit < cube->d && yhit < cube->d) { cube->li = 4; ss = s; } } s = (-cube->d - zadj)/ ray.z; if(s > 0 && s < ss) { xhit = fabs(xadj + s*ray.x); yhit = fabs(yadj + s*ray.y); if(xhit < cube->d && yhit < cube->d) { cube->li = 5; ss = s; } } } color->r = cube->surface.transp.r; color->g = cube->surface.transp.g; color->b = cube->surface.transp.b; normal_cube(*cube,point_parametric(observer,ray,ss),normal); if(ss == MAX_DOUBLE) return 0.0; else return ss; } ////////////////////////////////////////////////////////////// //funcao que retorna a normal de um ponto sobre a surface // do CUBE void normal_cube(cube cube, point_3d intersection, vector_3d *normal) { //inicializa o vetor normal normal->x = 0.0; normal->y = 0.0; normal->z = 0.0; switch(cube.li) { case(0): normal->x = 1.0; break; case(1): normal->x = -1.0; break; case(2): normal->y = 1.0; break; case(3): normal->y = -1.0; break; case(4): normal->z = 1.0; break; case(5): normal->z = -1.0; break; } } ////////////////////////////////////////////////////////////// //funcao que verifica/calcula se ocolorre intersecção entre um // vetor dado e um CILINDER double intersection_vector_cilinder(point_3d observer, vector_3d ray, cilinder *cilinder, color *color, vector_3d *normal) { double ox,oy,oz; //coordenadas da camera double vx,vy,vz; //coordenadas do vetor direcao do radius double a,b,c,delta; //variaveis para resolucao da eq. do segundo grau double t1,t2; //armazena as soluções da eq. double y1,y2; //verifica se a coordenada y esta no intervalo da alt double t3,t4; //calcula o valor parametrico da intersection color->r = cilinder->surface.transp.r; color->g = cilinder->surface.transp.g; color->b = cilinder->surface.transp.b; ox = observer.x; oy = observer.y; oz = observer.z; vx = ray.x; vy = ray.y; vz = ray.z; //parametros da eq. segundo grau a = pow(vx,2.0) + pow(vz,2.0); b = 2.0*ox*vx + 2.0*oz*vz; c = pow(ox,2.0) + pow(oz,2.0) - pow(cilinder->radius,2.0); //delta delta = pow(b,2.0) - 4.0*a*c; t1 = t2 = t3 = t4 = 0.0; if(delta >= 0) { t1 = (-b - sqrt(delta))/(2.0*a); t2 = (-b + sqrt(delta))/(2.0*a); } y1 = oy + vy*t1; y2 = oy + vy*t2; if(t1 > 0.0 && y1 < (cilinder->height) && y1 >= 0.0 ) { cilinder->li = BODY; t2 = MAX_DOUBLE; } else if(t2 > 0.0 && y2 <= (cilinder->height) && y2 >= 0.0) { t1 = MAX_DOUBLE; cilinder->li = BODY; } else { t1 = t2 = MAX_DOUBLE; } //intersection com os extremos do cilinders double i1,i2; //verifica se os pontos estao no cilinder //calculo dos coeficientes parametricos //UP t3 = ((cilinder->height-EPS) - oy)/(vy); //DOWN t4 = ((cilinder->y+EPS) - oy)/(vy); if(t3 < 0.0) t3 = MAX_DOUBLE; if(t4 < 0.0) t4 = MAX_DOUBLE; //verifica se está na projecao do circulo i1 = pow(ox+vx*t3,2.0) + pow(oz+vz*t3,2.0); i2 = pow(ox+vx*t4,2.0) + pow(oz+vz*t4,2.0); if(i1 >= pow(cilinder->radius+EPS,2.0)) t3 = MAX_DOUBLE; if(i2 >= pow(cilinder->radius+EPS,2.0)) t4 = MAX_DOUBLE; double lower = min(t1,t2,t3); lower = min(t3,lower,t4); if(lower == MAX_DOUBLE) return 0.0; else if(lower == t3) cilinder->li = UP; else if(lower == t4) cilinder->li = DOWN; else cilinder->li = BODY; normal_cilinder(*cilinder,point_parametric(observer,ray,lower),normal) ; return lower; } //////////////////////////////////////////////////////////////// // funcao que retorna a normal de um ponto sobre o cilindro void normal_cilinder(cilinder cilinder, point_3d intersection, vector_3d *normal) { //caso for no BODY if(cilinder.li == BODY) { normal->x = (intersection.x)/cilinder.radius; normal->y = 0.0; normal->z = (intersection.z)/cilinder.radius; } //caso if(cilinder.li == UP) { normal->x = 0.0; normal->y = 1.0; normal->z = 0.0; } if(cilinder.li == DOWN) { normal->x = 0.0; normal->y = -1.0; normal->z = 0.0; } normalize_vector(normal); } ////////////////////////////////////////////////////////////// // funcao que joga as coordenadas de um vetor 3d para um vetor // de posicoes double * vector_3d_to_vector(vector_3d vec) { double *vector = allocate_vector(); vector[0] = 0.0; vector[1] = vec.x; vector[2] = vec.y; vector[3] = vec.z; return (vector); } ////////////////////////////////////////////////////////////// // funcao que joga as coordenadas de um vetor de posicos // para um vetor 3d void vector_to_vector_3d(double *vector, vector_3d *vec) { vec->x = vector[1]; vec->y = vector[2]; vec->z = vector[3]; return; } ////////////////////////////////////////////////////////////// // funcao que joga as coordenadas de um ponto para um vetor double * point_3d_to_vector(point_3d point) { double *vector = allocate_vector(); vector[0] = 1.0; vector[1] = point.x; vector[2] = point.y; vector[3] = point.z; return (vector); } ////////////////////////////////////////////////////////////// // funcao que joga as coordenadas de um vetor paracilinder um ponto void vector_to_point_3d(double *vector, point_3d *point) { point->x = vector[1]; point->y = vector[2]; point->z = vector[3]; return; } ////////////////////////////////////////////////////////////// // funcao que realiza a troca entre duas diferentes posicoes de // pontos de interseccao void swap_intersection_points(intersection_points *i_points, int index1, int index2) { int type; int index; point_3d point; double parametric; color c; vector_3d normal; //joga o index1 numa variavel auxiliar type = i_points->type[index1]; index = i_points->index[index1]; point.x = i_points->points[index1].x; point.y = i_points->points[index1].y; point.z = i_points->points[index1].z; parametric = i_points->parametric[index1]; c.r = i_points->c[index1].r; c.g = i_points->c[index1].g; c.b = i_points->c[index1].b; normal.x = i_points->normal[index1].x; normal.y = i_points->normal[index1].y; normal.z = i_points->normal[index1].z; //copia o index2 para o index1 i_points->type[index1] = i_points->type[index2]; i_points->index[index1] = i_points->index[index2]; i_points->points[index1].x = i_points->points[index2].x; i_points->points[index1].y = i_points->points[index2].y; i_points->points[index1].z = i_points->points[index2].z; i_points->parametric[index1] = i_points->parametric[index2]; i_points->c[index1].r = i_points->c[index2].r; i_points->c[index1].g = i_points->c[index2].g; i_points->c[index1].b = i_points->c[index2].b; i_points->normal[index1].x = i_points->normal[index2].x; i_points->normal[index1].y = i_points->normal[index2].y; i_points->normal[index1].z = i_points->normal[index2].z; //copia o auxiliar para o index2 i_points->type[index2] = type; i_points->index[index2] = index; i_points->points[index2].x = point.x; i_points->points[index2].y = point.y; i_points->points[index2].z = point.z; i_points->parametric[index2] = parametric; i_points->c[index2].r = c.r; i_points->c[index2].g = c.g; i_points->c[index2].b = c.b; i_points->normal[index2].x = normal.x; i_points->normal[index2].y = normal.y; i_points->normal[index2].z = normal.z; return; } ////////////////////////////////////////////////////////////// //funcao que realiza a ordenação dos pontos de intersecção // conforme a ordem de interseccao void sort_points_intersection(intersection_points *i_points) { int i; int j; int qtd = i_points->qtd; int k = qtd - 1 ; for(i = 0; i < qtd; i++) { for(j = 0; j < k; j++) { if(i_points->parametric[j] > i_points->parametric[j+1]) { swap_intersection_points(i_points,j,j+1); } } } } ////////////////////////////////////////////////////////////// //funcao que inicializa os pontos de intersecção void inicialiaze_points_intersection(intersection_points *i_points) { int i; for(i = 0; i < NUM_POINTS; i++) { i_points->type[i] = 0; i_points->index[i] = 0; i_points->points[i].x = 0.0; i_points->points[i].y = 0.0; i_points->points[i].z = 0.0; i_points->parametric[i] = 0.0; i_points->c[i].r = 0.0; i_points->c[i].g = 0.0; i_points->c[i].b = 0.0; i_points->normal[i].x = 0.0; i_points->normal[i].y = 0.0; i_points->normal[i].z = 0.0; } i_points->qtd = 0; } ////////////////////////////////////////////////////////////// //funcao que retorna o ponto de intersection de um vetor ray // saindo da origin e atingindo algum objeto da cena void scene_intersection(scene *scene, point_3d origin, vector_3d ray, color *colors, int *index, int *type, vector_3d *normal, intersection_points *i_points) { double intersection = 0.0; int i = 0, j = 0, k = 0, l = 0; color c; point_3d observer_transf; vector_3d ray_transf; vector_3d normal_temp; point_3d aux; int count = 0; inicialiaze_points_intersection(i_points); normalize_vector(&ray); //teste a intersection com as SPHERES for(i = 0; i < scene->num_spheres; i++) { intersection = intersection_vector_sphere(origin,ray,&(scene->spheres[i]),&c,&normal_temp); if((intersection > 0.0)) { aux = point_parametric(origin,ray,intersection); i_points->parametric[count] = intersection; i_points->type[count] = SPHERE; i_points->index[count] = i; i_points->c[count].r = c.r; i_points->c[count].g = c.g; i_points->c[count].b = c.b; i_points->normal[count].x = normal_temp.x; i_points->normal[count].y = normal_temp.y; i_points->normal[count].z = normal_temp.z; i_points->points[count].x = aux.x; i_points->points[count].y = aux.y; i_points->points[count].z = aux.z; count++; } } //teste a intersection com os CUBES for(j = 0; j < scene->num_cubes; j++) { double *vector_ray = vector_3d_to_vector(ray); double *vector_ray_transf = allocate_vector(); double *vector_observer = point_3d_to_vector(scene->observer); double *vector_observer_transf = allocate_vector(); mult_matrix_vector(scene->cubes[j].matrix,vector_ray,vector_ray_transf,DIM_MATRIX); mult_matrix_vector(scene->cubes[j].matrix,vector_observer,vector_observer_transf,DIM_MATRIX); vector_to_point_3d(vector_observer_transf,&observer_transf); vector_to_vector_3d(vector_ray_transf,&ray_transf); intersection = intersection_vector_cube(observer_transf,ray_transf,&(scene->cubes[j]),&c,&normal_temp); if((intersection > 0.0) ) { aux = point_parametric(observer_transf,ray_transf,intersection); i_points->parametric[count] = intersection; i_points->type[count] = CUBE; i_points->index[count] = j; i_points->c[count].r = c.r; i_points->c[count].g = c.g; i_points->c[count].b = c.b; i_points->normal[count].x = normal_temp.x; i_points->normal[count].y = normal_temp.y; i_points->normal[count].z = normal_temp.z; i_points->points[count].x = aux.x; i_points->points[count].y = aux.y; i_points->points[count].z = aux.z; count++; } deallocate_vector(vector_ray); deallocate_vector(vector_ray_transf); deallocate_vector(vector_observer); deallocate_vector(vector_observer_transf); } //teste a intersection com os CILINDERS for(k = 0; k < scene->num_cilinders; k++) { double *vector_ray = vector_3d_to_vector(ray); double *vector_ray_transf = allocate_vector(); double *vector_observer = point_3d_to_vector(scene->observer); double *vector_observer_transf = allocate_vector(); mult_matrix_vector(scene->cilinders[k].matrix,vector_ray,vector_ray_transf,DIM_MATRIX); mult_matrix_vector(scene->cilinders[k].matrix,vector_observer,vector_observer_transf,DIM_MATRIX); vector_to_point_3d(vector_observer_transf,&observer_transf); vector_to_vector_3d(vector_ray_transf,&ray_transf); intersection = intersection_vector_cilinder(observer_transf,ray_transf,&(scene->cilinders[k]),&c,&normal_temp); if((intersection > 0.0)) { aux = point_parametric(observer_transf,ray_transf,intersection); i_points->parametric[count] = intersection; i_points->type[count] = CILINDER; i_points->index[count] = k; i_points->c[count].r = c.r; i_points->c[count].g = c.g; i_points->c[count].b = c.b; i_points->normal[count].x = normal_temp.x; i_points->normal[count].y = normal_temp.y; i_points->normal[count].z = normal_temp.z; i_points->points[count].x = aux.x; i_points->points[count].y = aux.y; i_points->points[count].z = aux.z; count++; } deallocate_vector(vector_ray); deallocate_vector(vector_ray_transf); deallocate_vector(vector_observer); deallocate_vector(vector_observer_transf); } for(l = 0; l < scene->num_beziers; l++) { double t; double *vector_ray = vector_3d_to_vector(ray); double *vector_ray_transf = allocate_vector(); double *vector_observer = point_3d_to_vector(scene->observer); double *vector_observer_transf = allocate_vector(); mult_matrix_vector(scene->beziers[l].matrix,vector_ray,vector_ray_transf,DIM_MATRIX); mult_matrix_vector(scene->beziers[l].matrix,vector_observer,vector_observer_transf,DIM_MATRIX); vector_to_point_3d(vector_observer_transf,&observer_transf); vector_to_vector_3d(vector_ray_transf,&ray_transf); intersection = (double)bezier_patch_intersection(scene->beziers[l].bezier,observer_transf,ray_transf,&aux,&normal_temp,&t,X); if((intersection > 0.0)) { i_points->parametric[count] = t; i_points->type[count] = BEZIER; i_points->index[count] = l; i_points->c[count].r = scene->beziers[l].surface.transp.r; i_points->c[count].g = scene->beziers[l].surface.transp.g; i_points->c[count].b = scene->beziers[l].surface.transp.b; i_points->normal[count].x = normal_temp.x; i_points->normal[count].y = normal_temp.y; i_points->normal[count].z = normal_temp.z; i_points->points[count].x = aux.x; i_points->points[count].y = aux.y; i_points->points[count].z = aux.z; count++; } deallocate_vector(vector_ray); deallocate_vector(vector_ray_transf); deallocate_vector(vector_observer); deallocate_vector(vector_observer_transf); } i_points->qtd = count; if(count > 0) sort_points_intersection(i_points); } ///////////////////////////////////////////////////////////// // dado o ray e seu valor parametrico retorna o ponto de // "intersection" point_3d point_parametric(point_3d observer, vector_3d ray, double s) { point_3d intersection; normalize_vector(&ray); intersection.x = observer.x + s*ray.x; intersection.y = observer.y + s*ray.y; intersection.z = observer.z + s*ray.z; return(intersection); } ///////////////////////////////////////////////////////////// // funcao que retorna a normal da intersection baseada nos // parametros calculados void normal_intersection(scene scene, point_3d intersection, int index, int type, vector_3d *normal) { if(type == SPHERE) normal_sphere(scene.spheres[index],intersection,normal); if(type == CUBE) normal_cube(scene.cubes[index],intersection,normal); if(type == CILINDER) normal_cilinder(scene.cilinders[index],intersection,normal); } ///////////////////////////////////////////////////////////// // funcao que retorna os componentes difusos do ponto de // intersection void transparency_intersection(scene *scene, point_3d intersection, int index, int type, color *color) { if(type == SPHERE) { color->r = scene->spheres[index].surface.transp.r; color->g = scene->spheres[index].surface.transp.g; color->b = scene->spheres[index].surface.transp.b; return; } if(type == CUBE) { color->r = scene->cubes[index].surface.transp.r; color->g = scene->cubes[index].surface.transp.g; color->b = scene->cubes[index].surface.transp.b; return; } if(type == CILINDER) { color->r = scene->cilinders[index].surface.transp.r; color->g = scene->cilinders[index].surface.transp.g; color->b = scene->cilinders[index].surface.transp.b; return; } if(type == BEZIER) { color->r = scene->beziers[index].surface.transp.r; color->g = scene->beziers[index].surface.transp.g; color->b = scene->beziers[index].surface.transp.b; return; } } ///////////////////////////////////////////////////////////// // funcao que retorna os componentes difusos do ponto de // intersection void difuse_intersection(scene *scene, point_3d intersection, int index, int type, color *c) { if(type == SPHERE) { c->r = scene->spheres[index].surface.dif.r; c->g = scene->spheres[index].surface.dif.g; c->b = scene->spheres[index].surface.dif.b; return; } if(type == CUBE) { c->r = scene->cubes[index].surface.dif.r; c->g = scene->cubes[index].surface.dif.g; c->b = scene->cubes[index].surface.dif.b; return; } if(type == CILINDER) { c->r = scene->cilinders[index].surface.dif.r; c->g = scene->cilinders[index].surface.dif.g; c->b = scene->cilinders[index].surface.dif.b; return; } if(type == BEZIER) { c->r = scene->beziers[index].surface.dif.r; c->g = scene->beziers[index].surface.dif.g; c->b = scene->beziers[index].surface.dif.b; return; } } ///////////////////////////////////////////////////////////// // funcao que retorna os componentes especulares do ponto de // intersection void specular_intersection(scene *scene, point_3d intersection, int index, int type, color *color) { if(type == SPHERE) { color->r = scene->spheres[index].surface.espec.r; color->g = scene->spheres[index].surface.espec.g; color->b = scene->spheres[index].surface.espec.b; return; } if(type == CUBE) { color->r = scene->cubes[index].surface.espec.r; color->g = scene->cubes[index].surface.espec.g; color->b = scene->cubes[index].surface.espec.b; return; } if(type == CILINDER) { color->r = scene->cilinders[index].surface.espec.r; color->g = scene->cilinders[index].surface.espec.g; color->b = scene->cilinders[index].surface.espec.b; return; } if(type == BEZIER) { color->r = scene->beziers[index].surface.espec.r; color->g = scene->beziers[index].surface.espec.g; color->b = scene->beziers[index].surface.espec.b; return; } } ///////////////////////////////////////////////////////////// // funcao que retorna os componentes especulares do ponto de // intersection void ambient_intersection(scene *scene, point_3d intersection, int index, int type, color *color) { if(type == SPHERE) { color->r = scene->spheres[index].surface.amb.r; color->g = scene->spheres[index].surface.amb.g; color->b = scene->spheres[index].surface.amb.b; return; } if(type == CUBE) { color->r = scene->cubes[index].surface.amb.r; color->g = scene->cubes[index].surface.amb.g; color->b = scene->cubes[index].surface.amb.b; return; } if(type == CILINDER) { color->r = scene->cilinders[index].surface.amb.r; color->g = scene->cilinders[index].surface.amb.g; color->b = scene->cilinders[index].surface.amb.b; return; } if(type == BEZIER) { color->r = scene->beziers[index].surface.amb.r; color->g = scene->beziers[index].surface.amb.g; color->b = scene->beziers[index].surface.amb.b; return; } } ////////////////////////////////////////////////////////////////////////// // funcao que aloca memoria para uma filme void allocate_filme(filme *pelicula, int x, int y, double tc, double d) { pelicula->n_c = x; pelicula->n_l = y; pelicula->dim_cell = tc; pelicula->dist = d; pelicula->pixel = (pixel*)malloc(sizeof(pixel)*x*y);//aloca os pixels de uma imagem return; } ////////////////////////////////////////////////////////////////////////// // funcao que desaloca memoria de um filme void deallocate_filme(filme *pelicula) { //if(pelicula == NULL) return; pelicula->n_c = 0; pelicula->n_l = 0; pelicula->dim_cell = 0; pelicula->dist = 0; if(pelicula->pixel != NULL) free(pelicula->pixel);//desaloca os pixels de uma imagem pelicula->pixel = (pixel*)NULL; return; } ////////////////////////////////////////////////////////////////////////// // funcao que aloca os objetos de uma cena void allocate_scene_objects(scene *scene, int num_spheres, int num_cubes,int num_cilinders, int num_beziers) { scene->num_spheres = num_spheres; scene->num_cubes = num_cubes; scene->num_cilinders = num_cilinders; scene->num_beziers = num_beziers; scene->num_objects = num_spheres + num_cubes + num_cilinders; scene->spheres = (sphere*)malloc(sizeof(sphere)*num_spheres+1); scene->cubes = (cube*)malloc(sizeof(cube)*num_cubes+1); scene->cilinders = (cilinder*)malloc(sizeof(cilinder)*num_cilinders+1); scene->beziers = (bezier*)malloc(sizeof(bezier)*num_beziers+1); if(scene->spheres == NULL || scene->cubes == NULL || scene->cilinders == NULL || scene->beziers == NULL) { printf("\n ERRO DE ALOCACAO - allocate_scene_objects(.) - RAYT.c"); exit(1); } return; } ////////////////////////////////////////////////////////////////////////// // funcao que aloca as luzes de uma cena void allocate_scene_light(scene *scene, int num_lights) { scene->num_lights = num_lights; scene->l = malloc(sizeof(light)*num_lights); return; } ////////////////////////////////////////////////////////////////////////// // funcao que desaloca memoria de uma cena void deallocate_scene(scene *scene) { scene->num_spheres = 0; scene->num_cubes = 0; scene->num_cilinders = 0; scene->num_objects = 0; scene->num_lights = 0; free(scene->spheres); free(scene->cubes); free(scene->cilinders); free(scene->l); return; } ////////////////////////////////////////////////////////////// // funcao que recebe um filme e joga ele para uma imagem float_image_t *filme_to_image(filme *pelicula) { int x,y; float_image_t *img = float_image_new(1,pelicula->n_c,pelicula->n_l); for(x = 0; x < pelicula->n_c; x++) for(y = 0; y < pelicula->n_l; y++) { float *px = float_image_get_sample_address(img,0,x,y); (*px) = pelicula->pixel[x + pelicula->n_c*y].color.g; //(*px) = pelicula->pixel[x + pelicula->n_c*y].color.r; /*px = float_image_get_sample_address(img,1,x,y); (*px) = pelicula->pixel[x + pelicula->n_c*y].color.g; px = float_image_get_sample_address(img,2,x,y); (*px) = pelicula->pixel[x + pelicula->n_c*y].color.b;*/ } //correct_gamma(img,0.3); //ex_write_image(NULL,name_out,img); return img; } ////////////////////////////////////////////////////// // funcao que corrige o gama segundo os parametros void correct_gamma(float_image_t *a,double gamma) { int x = 0; int y = 0; int c = 0; for(x = 0; x < a->sz[1]; x++) for(y = 0; y < a->sz[2]; y++) for(c = 0; c < a->sz[0]; c++) { float *v_bruto = float_image_get_sample_address(a,c,x,y); float v_cor = ((*v_bruto) <= 0.0? 0.0:exp(gamma * log((*v_bruto)) ) ); (*v_bruto) = v_cor; } } ///////////////////////////////////////////////////////////////////////////////////////// // funcao responsavel pelo calculo da cor do objeto color shading(scene *scene, point_3d observer, vector_3d ray, intersection_points *i_points, int index_light) { double k,//utilizado no calcula do raio de reflexao espec,//coeficiente espec dif;//coeficiente difuso vector_3d normal, //normal da interseccao reflexao,//direcao da reflexao l_ray;//raio da luz point_3d intersection; color a,d,e,f,amb; f.r = f.g = f.b = 0.0; //luz transparency_intersection(scene,i_points->points[0],i_points->index[0],i_points->type[0],&a); difuse_intersection(scene,i_points->points[0],i_points->index[0],i_points->type[0],&d); specular_intersection(scene,i_points->points[0],i_points->index[0],i_points->type[0],&e); ambient_intersection(scene,i_points->points[0],i_points->index[0],i_points->type[0],&amb); normal.x = i_points->normal[0].x; normal.y = i_points->normal[0].y; normal.z = i_points->normal[0].z; intersection.x = i_points->points[0].x; intersection.y = i_points->points[0].y; intersection.z = i_points->points[0].z; //calculo do raio de reflexao normalize_vector(&normal); normalize_vector(&ray); k = - 2.0*scalar(ray,normal); reflexao.x = k*normal.x + ray.x; reflexao.y = k*normal.y + ray.y; reflexao.z = k*normal.z + ray.z; normalize_vector(&reflexao); //determina a direcao do raio da luz l_ray.x = (scene->l[index_light].position.x - intersection.x); l_ray.y = (scene->l[index_light].position.y - intersection.y); l_ray.z = (scene->l[index_light].position.z - intersection.z); normalize_vector(&l_ray); //calcula componente dif dif = scalar(normal,l_ray); if(dif > 0.0) { dif = dif*scene->l[index_light].intensity; } //calcula componente espec normalize_vector(&reflexao); espec = scalar(reflexao,ray); if(espec > 0.0) { espec = 1.25*pow(espec,1.0)*scene->l[index_light].intensity; } if(d.r != 0.0 || d.g != 0 || d.b != 0) { f.r = d.r*dif; f.g = d.g*dif; f.b = d.b*dif; } else { int i = 0; double prod_scalar = 0.0; //para ser usado no produtorio f.r = f.g = f.b = 1.0; //printf(" %d ",i_points->qtd); reverse_vector(&ray); for(i = 0; i < i_points->qtd; i++) { transparency_intersection(scene,i_points->points[i],i_points->index[i],i_points->type[i],&a); prod_scalar = scalar(ray,i_points->normal[i]); //printf(" +++ %.3lf +++ ",prod_scalar); f.r *= pow(a.r*scene->l[index_light].intensity,(1.0/(5.0*prod_scalar+5*EPS)));//5 f.g *= pow(a.g*scene->l[index_light].intensity,(1.0/(5.0*prod_scalar+5*EPS))); f.b *= pow(a.b*scene->l[index_light].intensity,(1.0/(5.0*prod_scalar+5*EPS))); //printf(" \n +*+ %lf %lf %lf +*+ ",f.r,f.g,f.b); //printf(" \n ----%lf %lf %lf ---",a.r,a.g,a.b); if(a.r == 0.0 && a.g == 0.0 && a.b == 0.0) { difuse_intersection(scene,i_points->points[i],i_points->index[i],i_points->type[i],&d); dif = scalar(i_points->normal[i],l_ray); f.r += dif*d.r; f.g += dif*d.g; f.b += dif*d.b; printf("\n %lf %lf %lf ",f.r,f.g,f.b); break; } } } //if(f.r > 1.0 || f.r < 0.0) printf("\n %lf ",f.r); f.r += amb.r; f.g += amb.g; f.b += amb.b; if(f.r > 1.0) f.r = 0.99; if(f.g > 1.0) f.g = 0.99; if(f.b > 1.0) f.b = 0.99; if(f.r < 0.0) f.r = 0.001; if(f.g < 0.0) f.g = 0.001; if(f.b < 0.0) f.b = 0.001; return f; } ////////////////////////////////////////////////////////////////////////////// // funcao que recebe os dados e realiza as rotacoes e translações void matrix_transformation(scene *scene, int type, int index) { double tx, ty, tz; //translações double rx, ry, rz; //rotações double *rot_x = allocate_matrix(); double *rot_y = allocate_matrix(); double *rot_z = allocate_matrix(); double *transf = allocate_matrix(); double *aux = allocate_matrix(); double *translation = allocate_matrix(); double *tmp = allocate_matrix(); double *inv = allocate_matrix(); int j = 0; tx = ty = tz = rx = ry = rz = 0.0; if(type == SPHERE) { tx = scene->spheres[index].x; ty = scene->spheres[index].y; tz = scene->spheres[index].z; rx = 0.0; ry = 0.0; rz = 0.0; } if(type == CUBE) { tx = scene->cubes[index].x; ty = scene->cubes[index].y; tz = scene->cubes[index].z; rx = scene->cubes[index].rot_x; ry = scene->cubes[index].rot_y; rz = scene->cubes[index].rot_z; } if(type == CILINDER) { tx = scene->cilinders[index].x; ty = scene->cilinders[index].y; tz = scene->cilinders[index].z; rx = scene->cilinders[index].rot_x; ry = scene->cilinders[index].rot_y; rz = scene->cilinders[index].rot_z; } if(type == BEZIER) { tx = 0.0; ty = 0.0; tz = 0.0; rx = scene->beziers[index].rot_x; ry = scene->beziers[index].rot_y; rz = scene->beziers[index].rot_z; } set_rotation_x_matrix(rot_x,rx); set_rotation_y_matrix(rot_y,ry); set_rotation_z_matrix(rot_z,rz); set_translation_matrix(translation,-tx,-ty,-tz); mult_matrix(rot_x,rot_y,aux,DIM_MATRIX); mult_matrix(aux,rot_z,tmp,DIM_MATRIX); mult_matrix(tmp,translation,transf,DIM_MATRIX); invert_matrix(transf,inv,DIM_MATRIX); if(type == CUBE) { for(j = 0; j < DIM_MATRIX*DIM_MATRIX; j++) { scene->cubes[index].matrix[j] = transf[j]; scene->cubes[index].inv[j] = inv[j]; } } if(type == CILINDER) { for(j = 0; j < DIM_MATRIX*DIM_MATRIX; j++) { scene->cilinders[index].matrix[j] = transf[j]; scene->cilinders[index].inv[j] = inv[j]; } } if(type == BEZIER) { for(j = 0; j < DIM_MATRIX*DIM_MATRIX; j++) { scene->beziers[index].matrix[j] = transf[j]; scene->beziers[index].inv[j] = inv[j]; } } deallocate_matrix(rot_x); deallocate_matrix(rot_y); deallocate_matrix(rot_z); deallocate_matrix(transf); deallocate_matrix(aux); deallocate_matrix(tmp); deallocate_matrix(inv); deallocate_matrix(translation); } ////////////////////////////////////////////////////////////////////////////// // tracador de raios void ray_tracing(scene *scene, float_image_t *img, filme *pelicula, int num_rays) { vector_3d t,s,r,q;//vetores auxiliares int ih, iv; //variavel de loop vector_3d ray; //vetor que armazena os radiuss double intersection; //armazena o valor da intersection color color; //color do pixel int index; //index da bola interceptada int type; //descreve o objeto interceptado vector_3d normal; //normal no ponto de intersection point_3d point_intersection; //ponto de intersection double fator; //recebe o fato de forma intersection_points i_points; //armazena os pontos de interseccao de um raio p/ gerar o efeito de transparencia //calcula a direcao do vetor que vai do scene.observer até o ponto de scene.look_at t.x = scene->observer.x - scene->look_at.x; t.y = scene->observer.y - scene->look_at.y; t.z = scene->observer.z - scene->look_at.z; normalize_vector(&t); //POG - Programacao Orientada a Gambiarra scene->sky.x = 0.0; scene->sky.y = 1.0; scene->sky.z = 0.0; r.x = scene->sky.x; r.y = scene->sky.y; r.z = scene->sky.z; //calcula a direcao do vetor UP ortogonal_projection(t,r,&s); normalize_vector(&s); //calcula o vetor normal aos vetores s e t cross_product(s,t,&r); normalize_vector(&r); for(ih = 0; ih < pelicula->n_c; ih++) for(iv = 0; iv < pelicula->n_l; iv++) { int kh,kv; int nsub = num_rays;//(1 <= 1 ? 2 : 1); double ssub = 1.0/nsub; for(kh = 0; kh < nsub; kh++) for(kv = 0; kv < nsub; kv++) { double hb = (double)(ih + ssub*(kh+0.5))*pelicula->dim_cell - pelicula->n_c*(pelicula->dim_cell/2.0); double vb = (double) pelicula->n_l*(pelicula->dim_cell/2.0) - (iv + ssub*(kv+0.5))*pelicula->dim_cell; //calcula a direcao do vetor q = scene.observer - d*t + h*r + s*v q.x = scene->observer.x - pelicula->dist*t.x + hb*r.x + vb*s.x; q.y = scene->observer.y - pelicula->dist*t.y + hb*r.y + vb*s.y; q.z = scene->observer.z - pelicula->dist*t.z + hb*r.z + vb*s.z; //direcao do radius ray.x = q.x - scene->observer.x; ray.y = q.y - scene->observer.y; ray.z = q.z - scene->observer.z; normalize_vector(&ray); scene_intersection(scene,scene->observer,ray,&color,&index,&type,&normal,&i_points); intersection = i_points.parametric[0]; index = i_points.index[0]; type = i_points.type[0]; normal.x = i_points.normal[0].x; normal.y = i_points.normal[0].y; normal.z = i_points.normal[0].z; color.r = i_points.c[0].r; color.g = i_points.c[0].g; color.b = i_points.c[0].b; normalize_vector(&normal); if(intersection > 0.0) { point_3d observer_transf; vector_3d ray_transf; vector_3d normal_transf; point_3d point_intersection_transf; if(type == CUBE) { double *vector_ray = vector_3d_to_vector(ray); double *vector_ray_transf = allocate_vector(); double *vector_observer = point_3d_to_vector(scene->observer); double *vector_observer_transf = allocate_vector(); mult_matrix_vector(scene->cubes[index].matrix,vector_ray,vector_ray_transf,DIM_MATRIX); mult_matrix_vector(scene->cubes[index].matrix,vector_observer,vector_observer_transf,DIM_MATRIX); vector_to_point_3d(vector_observer_transf,&observer_transf); vector_to_vector_3d(vector_ray_transf,&ray_transf); normalize_vector(&ray_transf); point_intersection = point_parametric(observer_transf,ray_transf,intersection); double *vector_point = point_3d_to_vector(point_intersection); double *vector_point_transf = allocate_vector(); mult_matrix_vector(scene->cubes[index].inv,vector_point,vector_point_transf,DIM_MATRIX); vector_to_point_3d(vector_point_transf,&point_intersection_transf); double *vector_normal = vector_3d_to_vector(normal); double *vector_normal_transf = allocate_vector(); mult_vector_matrix(vector_normal,scene->cubes[index].inv,vector_normal_transf,DIM_MATRIX); vector_to_vector_3d(vector_normal_transf,&normal_transf); normalize_vector(&normal_transf); deallocate_vector(vector_ray); deallocate_vector(vector_ray_transf); deallocate_vector(vector_observer); deallocate_vector(vector_observer_transf); deallocate_vector(vector_normal); deallocate_vector(vector_normal_transf); } else if(type == CILINDER) { double *vector_ray = vector_3d_to_vector(ray); double *vector_ray_transf = allocate_vector(); double *vector_observer = point_3d_to_vector(scene->observer); double *vector_observer_transf = allocate_vector(); mult_matrix_vector(scene->cilinders[index].matrix,vector_ray,vector_ray_transf,DIM_MATRIX); mult_matrix_vector(scene->cilinders[index].matrix,vector_observer,vector_observer_transf,DIM_MATRIX); vector_to_point_3d(vector_observer_transf,&observer_transf); vector_to_vector_3d(vector_ray_transf,&ray_transf); normalize_vector(&ray_transf); point_intersection = point_parametric(observer_transf,ray_transf,intersection); double *vector_point = point_3d_to_vector(point_intersection); double *vector_point_transf = allocate_vector(); mult_matrix_vector(scene->cilinders[index].inv,vector_point,vector_point_transf,DIM_MATRIX); vector_to_point_3d(vector_point_transf,&point_intersection_transf); double *vector_normal = vector_3d_to_vector(normal); double *vector_normal_transf = allocate_vector(); mult_vector_matrix(vector_normal,scene->cilinders[index].inv,vector_normal_transf,DIM_MATRIX); vector_to_vector_3d(vector_normal_transf,&normal_transf); normalize_vector(&normal_transf); deallocate_vector(vector_ray); deallocate_vector(vector_ray_transf); deallocate_vector(vector_observer); deallocate_vector(vector_observer_transf); deallocate_vector(vector_normal); deallocate_vector(vector_normal_transf); } else if(type == BEZIER) { double *vector_ray = vector_3d_to_vector(ray); double *vector_ray_transf = allocate_vector(); double *vector_observer = point_3d_to_vector(scene->observer); double *vector_observer_transf = allocate_vector(); mult_matrix_vector(scene->beziers[index].matrix,vector_ray,vector_ray_transf,DIM_MATRIX); mult_matrix_vector(scene->beziers[index].matrix,vector_observer,vector_observer_transf,DIM_MATRIX); vector_to_point_3d(vector_observer_transf,&observer_transf); vector_to_vector_3d(vector_ray_transf,&ray_transf); normalize_vector(&ray_transf); //observer_transf = scene->observer; //ray_transf = ray; //normal_transf = normal; point_intersection.x = i_points.points[0].x; point_intersection.y = i_points.points[0].y; point_intersection.z = i_points.points[0].z; normal.x = i_points.normal[0].x; normal.y = i_points.normal[0].y; normal.z = i_points.normal[0].z; normalize_vector(&normal); double *vector_point = point_3d_to_vector(point_intersection); double *vector_point_transf = allocate_vector(); mult_matrix_vector(scene->beziers[index].inv,vector_point,vector_point_transf,DIM_MATRIX); vector_to_point_3d(vector_point_transf,&point_intersection_transf); double *vector_normal = vector_3d_to_vector(normal); double *vector_normal_transf = allocate_vector(); mult_vector_matrix(vector_normal,scene->beziers[index].inv,vector_normal_transf,DIM_MATRIX); vector_to_vector_3d(vector_normal_transf,&normal_transf); normalize_vector(&normal_transf); deallocate_vector(vector_ray); deallocate_vector(vector_ray_transf); deallocate_vector(vector_observer); deallocate_vector(vector_observer_transf); deallocate_vector(vector_normal); deallocate_vector(vector_normal_transf); } else { observer_transf = scene->observer; ray_transf = ray; normal_transf = normal; point_intersection_transf = point_parametric(observer_transf,ray_transf,intersection); } fator = scalar(ray_transf,normal_transf); if(fator < 0.0) { fator = 0.0; } //color = shading(scene,scene->observer,ray,&i_points,0); color = shading(scene,observer_transf,ray_transf,&i_points,0); if(color.g < 0.0) color.g = 0.0; if(color.g > 1.0) color.g = 1.0; // if(isnan(color.r)) // { //printf("\n\n ******************************** FR *********************************\n\n"); // exit(1); // } if(isnan(color.g)) { color.g = 0.75; printf("\n\n ******************************** FG *********************************\n\n"); //exit(1); } // if(isnan(color.b)) // { // printf("\n\n ******************************** FB *********************************\n\n"); exit(1); // } // pelicula->pixel[ih+iv*pelicula->n_c].color.r += color.r/(double)pow(nsub,2.0); pelicula->pixel[ih+iv*pelicula->n_c].color.g += color.g/(double)pow(nsub,2.0); //pelicula->pixel[ih+iv*pelicula->n_c].color.b += color.b/(double)pow(nsub,2.0); } else { //pelicula->pixel[ih+iv*pelicula->n_c].color.r = 1.0; pelicula->pixel[ih+iv*pelicula->n_c].color.g = 1.0; //pelicula->pixel[ih+iv*pelicula->n_c].color.b = 1.0; } } } //char name_img[50]; //sprintf(name_img,"img/saida%05d.pgm",rand()); //img = filme_to_image(pelicula); //ex_write_image(NULL,name_img,img); //printf("\n %d %d %d \n",img->sz[0],img->sz[1],img->sz[2]); //exit(1); } ////////////////////////////////////////////////////////////////////////////// // cria uma mascara usando a imagem gerada pelo ray tracer float_image_t *create_mask(float_image_t *image) { int x,y,c; float_image_t *mask = float_image_new(1,image->sz[X],image->sz[Y]); float_image_t *mask_tmp = float_image_new(1,image->sz[X],image->sz[Y]); float_image_t *mask_aux = float_image_new(1,image->sz[X],image->sz[Y]); c = 0; //for(c = 0; c < RGB; c++) { for(x = 0; x < image->sz[X]; x++) { for(y = 0; y < image->sz[Y]; y++) { float *p1 = float_image_get_sample_address(image,c,x,y); float *pmt = float_image_get_sample_address(mask_tmp,c,x,y); float *pm = float_image_get_sample_address(mask,c,x,y); float *pma = float_image_get_sample_address(mask_aux,c,x,y); if((*p1) != 1.0) (*pmt) = 0.0; else (*pmt) = 1.0; (*pm) = 1.0; (*pma) = 1.0; } } } //for(c = 0; c < RGB; c++) { for(x = 1; x < image->sz[X]-1; x++) { for(y = 1; y < image->sz[Y]-1; y++) { float *p1 = float_image_get_sample_address(mask_tmp,c,x,y); float *p2 = float_image_get_sample_address(mask_tmp,c,x+1,y); float *p3 = float_image_get_sample_address(mask_tmp,c,x-1,y); float *p4 = float_image_get_sample_address(mask_tmp,c,x,y+1); float *p5 = float_image_get_sample_address(mask_tmp,c,x,y-1); float *p = float_image_get_sample_address(mask_aux,c,x,y); if( (*p1) == 0.0 || (*p2) == 0.0 || (*p3) == 0.0 || (*p4) == 0.0 || (*p5) == 0.0 ) (*p) = 0.0; else (*p) = 1.0; } } } //for(c = 0; c < RGB; c++) { for(x = 1; x < image->sz[X]-1; x++) { for(y = 1; y < image->sz[Y]-1; y++) { float *p1 = float_image_get_sample_address(mask_aux,c,x,y); float *p2 = float_image_get_sample_address(mask_aux,c,x+0,y); float *p3 = float_image_get_sample_address(mask_aux,c,x-0,y); float *p4 = float_image_get_sample_address(mask_aux,c,x,y+0); float *p5 = float_image_get_sample_address(mask_aux,c,x,y-0); float *p = float_image_get_sample_address(mask,c,x,y); if( (*p1) == 0.0 || (*p2) == 0.0 || (*p3) == 0.0 || (*p4) == 0.0 || (*p5) == 0.0 ) (*p) = 0.0; else (*p) = 1.0; } } } float_image_free(mask_tmp); float_image_free(mask_aux); return mask; } ////////////////////////////////////////////////////////////// //funcao responsavel pela chamada do povray void execute_povray(char *model_name, int id_candidate, int scale, int dim_img_in) { FILE *tmp; char command[500]; char ch; //char model_pov[90]; int dim_img = 0; int count = 0; //calcula o tamanho da imagem a ser gerada dim_img = (dim_img_in)/((int)(pow(2.0,(double)scale))); //cria um arquivo de texto temporario par armazenar o comando tmp = fopen("img/tmp.txt","w"); if(tmp == NULL) { printf("\n ERRO - Criacao Arquivo - execute_povray(img/tmp.txt) - rayT.C\n"); exit(1); } // Mais completo, mas nao funciona fprintf(tmp,"/home/danillorp/usr/bin/povray +FP +Q9 +W%d +H%d +AM1 +A0.0 +R%d +D +SP32 +EP4 +L/home/danillorp/usr/share/povray-3.6/include +L/home/danillorp/Desktop/Doutorado/Pesquisa/POVray/TESTS/tt-fonts +L/home/danillorp/Desktop/Doutorado/Programa/Prototype/povray/TESTS +Imodels/%s_new.pov +O%s%d.ppm; ppmtopgm %s%d.ppm > %s%d.pgm; rm %s%d.ppm; mv %s%d.pgm img",dim_img,dim_img,scale,model_name,model_name,id_candidate,model_name,id_candidate,model_name,id_candidate,model_name,id_candidate,model_name,id_candidate); fclose(tmp); //abri o arquivo de texto temporario para ler o comando tmp = fopen("img/tmp.txt","r"); if(tmp == NULL) { printf("\n ERRO - Leitura do Arquivo - execute_povray(img/tmp.txt) - rayT.C \n"); exit(1); } strcpy(command,""); //realiza a leitura do comando no arquivo de texto temporarario while( (ch = getc(tmp)) != EOF) { command[count] = ch; command[count+1] = '\0'; count++; } fclose(tmp); //executa o comando - povray - e muda a imagem de diretorio FILE *cmd = popen(command,"r"); if(cmd == NULL) { printf("\n ERRO - Execucao do Command - execute_povray() - rayT.C \n"); exit(1); } pclose(cmd); } //////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////// BEZIER.C /////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// //realiza interpolacao linear entre dois pontos void linear_interpolation(point_3d *interpolated, point_3d origin, point_3d destin, double t) { interpolated->x = origin.x + t*(destin.x - origin.x); interpolated->y = origin.y + t*(destin.y - origin.y); interpolated->z = origin.z + t*(destin.z - origin.z); return; } ////////////////////////////////////////////////////////////// //funcao que joga os pontos calculados pela processo de subdivisao numa estrutura auxiliar void points_to_subdivision(bezier_patch *sub1, bezier_patch *sub2, int line, point_3d p1, point_3d p2, point_3d p3, point_3d c, point_3d p4, point_3d p5, point_3d p6) { sub1->control_points[line*DIM_GRID + 0].x = p1.x; sub1->control_points[line*DIM_GRID + 0].y = p1.y; sub1->control_points[line*DIM_GRID + 0].z = p1.z; sub1->control_points[line*DIM_GRID + 1].x = p2.x; sub1->control_points[line*DIM_GRID + 1].y = p2.y; sub1->control_points[line*DIM_GRID + 1].z = p2.z; sub1->control_points[line*DIM_GRID + 2].x = p3.x; sub1->control_points[line*DIM_GRID + 2].y = p3.y; sub1->control_points[line*DIM_GRID + 2].z = p3.z; sub1->control_points[line*DIM_GRID + 3].x = c.x; sub1->control_points[line*DIM_GRID + 3].y = c.y; sub1->control_points[line*DIM_GRID + 3].z = c.z; sub2->control_points[line*DIM_GRID + 0].x = c.x; sub2->control_points[line*DIM_GRID + 0].y = c.y; sub2->control_points[line*DIM_GRID + 0].z = c.z; sub2->control_points[line*DIM_GRID + 1].x = p4.x; sub2->control_points[line*DIM_GRID + 1].y = p4.y; sub2->control_points[line*DIM_GRID + 1].z = p4.z; sub2->control_points[line*DIM_GRID + 2].x = p5.x; sub2->control_points[line*DIM_GRID + 2].y = p5.y; sub2->control_points[line*DIM_GRID + 2].z = p5.z; sub2->control_points[line*DIM_GRID + 3].x = p6.x; sub2->control_points[line*DIM_GRID + 3].y = p6.y; sub2->control_points[line*DIM_GRID + 3].z = p6.z; } ////////////////////////////////////////////////////////////// //realiza a subdivisao do patch de bezier segundo o algoritmo de DeCasteljau void bezier_patch_subdivision(bezier_patch *sub1, bezier_patch *sub2, bezier_patch patch, int dir) { int i = 0; if(dir == X) { point_3d ab[DIM_GRID],bc[DIM_GRID],cd[DIM_GRID], abc[DIM_GRID],bcd[DIM_GRID], abcd[DIM_GRID]; for(i = 0; i < DIM_GRID; i++) { //primeira iteracao linear_interpolation(&ab[i],patch.control_points[(i*DIM_GRID) + 0], patch.control_points[(i*DIM_GRID) + 1], 0.5); linear_interpolation(&bc[i],patch.control_points[(i*DIM_GRID) + 1], patch.control_points[(i*DIM_GRID) + 2], 0.5); linear_interpolation(&cd[i],patch.control_points[(i*DIM_GRID) + 2], patch.control_points[(i*DIM_GRID) + 3], 0.5); //segunda iteracao linear_interpolation(&abc[i],ab[i],bc[i],0.5); linear_interpolation(&bcd[i],bc[i],cd[i],0.5); //tercerceira iteracao linear_interpolation(&abcd[i],abc[i],bcd[i],0.5); /*printf("\n a:[%.1lf,%.1lf,%.1lf] b:[%.1lf,%.1lf,%.1lf] \n c:[%.1lf,%.1lf,%.1lf] c:[%.1lf,%.1lf,%.1lf] \n\n",patch.control_points[(i*DIM_GRID) + 0].x,patch.control_points[(i*DIM_GRID) + 0].y,patch.control_points[(i*DIM_GRID) + 0].z, patch.control_points[(i*DIM_GRID) + 1].x,patch.control_points[(i*DIM_GRID) + 1].y,patch.control_points[(i*DIM_GRID) + 1].z, patch.control_points[(i*DIM_GRID) + 2].x,patch.control_points[(i*DIM_GRID) + 2].y,patch.control_points[(i*DIM_GRID) + 2].z, patch.control_points[(i*DIM_GRID) + 3].x,patch.control_points[(i*DIM_GRID) + 3].y,patch.control_points[(i*DIM_GRID) + 3].z); printf("\n ab:[%.1lf,%.1lf,%.1lf] bc:[%.1lf,%.1lf,%.1lf] cd:[%.1lf,%.1lf,%.1lf]",ab[i].x,ab[i].y,ab[i].z,bc[i].x,bc[i].y,bc[i].z,cd[i].x,cd[i].y,cd[i].z); printf("\n abc:[%.1lf,%.1lf,%.1lf] bcd:[%.1lf,%.1lf,%.1lf]",abc[i].x,abc[i].y,abc[i].z,bcd[i].x,bcd[i].y,bcd[i].z); printf("\n abcd:[%.1lf,%.1lf,%.1lf]",abcd[i].x,abcd[i].y,abcd[i].z); int pqp; scanf("%d",&pqp);*/ //passa os pontos para a estrutura auxiliar points_to_subdivision(sub1,sub2,i,patch.control_points[(i*DIM_GRID)],ab[i],abc[i],abcd[i],bcd[i],cd[i],patch.control_points[(i*DIM_GRID) + 3]); } } else { point_3d ab[DIM_GRID],bc[DIM_GRID],cd[DIM_GRID], abc[DIM_GRID],bcd[DIM_GRID], abcd[DIM_GRID]; for(i = 0; i < DIM_GRID; i++) { //primeira iteracao linear_interpolation(&ab[i],patch.control_points[(0*DIM_GRID) + i], patch.control_points[(1*DIM_GRID) + i], 0.5); linear_interpolation(&bc[i],patch.control_points[(1*DIM_GRID) + i], patch.control_points[(2*DIM_GRID) + i], 0.5); linear_interpolation(&cd[i],patch.control_points[(2*DIM_GRID) + i], patch.control_points[(3*DIM_GRID) + i], 0.5); //segunda iteracao linear_interpolation(&abc[i],ab[i],bc[i],0.5); linear_interpolation(&bcd[i],bc[i],cd[i],0.5); //tercerceira iteracao linear_interpolation(&abcd[i],abc[i],bcd[i],0.5); /*printf("\n a:[%.1lf,%.1lf,%.1lf] b:[%.1lf,%.1lf,%.1lf] \n c:[%.1lf,%.1lf,%.1lf] c:[%.1lf,%.1lf,%.1lf] \n\n",patch.control_points[(i*DIM_GRID) + 0].x,patch.control_points[(i*DIM_GRID) + 0].y,patch.control_points[(i*DIM_GRID) + 0].z, patch.control_points[(i*DIM_GRID) + 1].x,patch.control_points[(i*DIM_GRID) + 1].y,patch.control_points[(i*DIM_GRID) + 1].z, patch.control_points[(i*DIM_GRID) + 2].x,patch.control_points[(i*DIM_GRID) + 2].y,patch.control_points[(i*DIM_GRID) + 2].z, patch.control_points[(i*DIM_GRID) + 3].x,patch.control_points[(i*DIM_GRID) + 3].y,patch.control_points[(i*DIM_GRID) + 3].z); printf("\n ab:[%.1lf,%.1lf,%.1lf] bc:[%.1lf,%.1lf,%.1lf] cd:[%.1lf,%.1lf,%.1lf]",ab[i].x,ab[i].y,ab[i].z,bc[i].x,bc[i].y,bc[i].z,cd[i].x,cd[i].y,cd[i].z); printf("\n abc:[%.1lf,%.1lf,%.1lf] bcd:[%.1lf,%.1lf,%.1lf]",abc[i].x,abc[i].y,abc[i].z,bcd[i].x,bcd[i].y,bcd[i].z); printf("\n abcd:[%.1lf,%.1lf,%.1lf]",abcd[i].x,abcd[i].y,abcd[i].z); //int pqp; scanf("%d",&pqp); */ //passa os pontos para a estrutura auxiliar points_to_subdivision(sub1,sub2,i,patch.control_points[(0*DIM_GRID)+i],ab[i],abc[i],abcd[i],bcd[i],cd[i],patch.control_points[(3*DIM_GRID) + i]); } } } ////////////////////////////////////////////////////////////// //funcao que calcula os dois pontos extremos do bounding box void calculate_bounding_box(bounding_box *box, bezier_patch bezier) { double min_x, min_y, min_z, max_x, max_y, max_z; int i = 0; min_x = min_y = min_z = 1000000.0; max_x = max_y = max_z = -1000000.0; for(i = 0; i < NUM_CONTROL_POINTS; i++) { if(min_x > bezier.control_points[i].x) min_x = bezier.control_points[i].x; if(min_y > bezier.control_points[i].y) min_y = bezier.control_points[i].y; if(min_z > bezier.control_points[i].z) min_z = bezier.control_points[i].z; if(max_x < bezier.control_points[i].x) max_x = bezier.control_points[i].x; if(max_y < bezier.control_points[i].y) max_y = bezier.control_points[i].y; if(max_z < bezier.control_points[i].z) max_z = bezier.control_points[i].z; } box->lim_min.x = (min_x - EPS); box->lim_min.y = (min_y - EPS); box->lim_min.z = (min_z - EPS); box->lim_max.x = (max_x + EPS); box->lim_max.y = (max_y + EPS); box->lim_max.z = (max_z + EPS); return; } ////////////////////////////////////////////////////////////// //funcao boolena que verifica se ocorreu interseccao entre um vector e o box int intersection_matching_box(point_3d origin, vector_3d ray, point_3d lim_min, point_3d lim_max, double *min, double *max) { double tmin, tmax, tymin, tymax, tzmin, tzmax; if (ray.x >= 0.0) { tmin = (lim_min.x - origin.x) / ray.x; tmax = (lim_max.x - origin.x) / ray.x; } else { tmin = (lim_max.x - origin.x) / ray.x; tmax = (lim_min.x - origin.x) / ray.x; } if (ray.y >= 0) { tymin = (lim_min.y - origin.y) / ray.y; tymax = (lim_max.y - origin.y) / ray.y; } else { tymin = (lim_max.y - origin.y) / ray.y; tymax = (lim_min.y - origin.y) / ray.y; } if ( (tmin > tymax+EPS) || (tymin > tmax+EPS) ) { return FALSE; } if (tymin > tmin) tmin = tymin; if (tymax < tmax) tmax = tymax; if (ray.z >= 0) { tzmin = (lim_min.z - origin.z) / ray.z; tzmax = (lim_max.z - origin.z) / ray.z; } else { tzmin = (lim_max.z - origin.z) / ray.z; tzmax = (lim_min.z - origin.z) / ray.z; } if ( (tmin > tzmax+EPS) || (tzmin > tmax+EPS) ) { return FALSE; } if (tzmin > tmin) tmin = tzmin; if (tzmax < tmax) tmax = tzmax; *min = tmin; *max = tmax; return (TRUE); } ////////////////////////////////////////////////////////////// //funcao que copia um bezier patch void copy_bezier_patch(bezier_patch b, bezier_patch *b_copy) { int i = 0; for(i = 0; i < NUM_CONTROL_POINTS; i++) { b_copy->control_points[i].x = b.control_points[i].x; b_copy->control_points[i].y = b.control_points[i].y; b_copy->control_points[i].z = b.control_points[i].z; } return; } ////////////////////////////////////////////////////////////// //funcao que calcula a interseccao entre um raio e um retalho de bezier int bezier_patch_intersection(bezier_patch bezier, point_3d origin, vector_3d ray, point_3d *intersection, vector_3d *normal, double *tmin, int dir) { bounding_box box,box1,box2; bezier_patch b1,b2; double dx,dy; int inter_box1, inter_box2; double min,max; calculate_bounding_box(&box,bezier); if(intersection_matching_box(origin,ray,box.lim_min,box.lim_max,&min,&max) == FALSE) return (FALSE); if(distance_betwen_points(box.lim_min,box.lim_max) >= 0.5) { dx = (box.lim_max.x - box.lim_min.x); dy = (box.lim_max.y - box.lim_min.y); //printf("\n %lf %lf",dx,dy); if(dir == X) { dir = Y; } else { dir = X; } bezier_patch_subdivision(&b1,&b2,bezier,dir); calculate_bounding_box(&box1,b1); calculate_bounding_box(&box2,b2); point_3d p1,p2; double t1,t2; vector_3d n1,n2; inter_box1 = bezier_patch_intersection(b1,origin,ray,&p1,&n1,&t1,dir); inter_box2 = bezier_patch_intersection(b2,origin,ray,&p2,&n2,&t2,dir); //printf("\n "); if(inter_box1 && inter_box2) { if(t1 < t2) { intersection->x = p1.x; intersection->y = p1.y; intersection->z = p1.z; normal->x = n1.x; normal->y = n1.y; normal->z = n1.z; *tmin = t1; } else { intersection->x = p2.x; intersection->y = p2.y; intersection->z = p2.z; normal->x = n2.x; normal->y = n2.y; normal->z = n2.z; *tmin = t2; } return TRUE; } else { if(inter_box1 == TRUE) { intersection->x = p1.x; intersection->y = p1.y; intersection->z = p1.z; normal->x = n1.x; normal->y = n1.y; normal->z = n1.z; *tmin = t1; } else { if(inter_box2 == TRUE) { intersection->x = p2.x; intersection->y = p2.y; intersection->z = p2.z; normal->x = n2.x; normal->y = n2.y; normal->z = n2.z; *tmin = t2; } else { return FALSE; } } return TRUE; } } else { if(distance_betwen_points(box.lim_min,box.lim_max) <= 0.5) { //printf(" **** "); vector_3d a,b; a.x = bezier.control_points[3].x - bezier.control_points[0].x; a.y = bezier.control_points[3].y - bezier.control_points[0].y; a.z = bezier.control_points[3].z - bezier.control_points[0].z; b.x = bezier.control_points[12].x - bezier.control_points[0].x; b.y = bezier.control_points[12].y - bezier.control_points[0].y; b.z = bezier.control_points[12].z - bezier.control_points[0].z; cross_product(a,b,normal); normalize_vector(normal); *tmin = min; if(scalar(ray,*normal) > EPS) reverse_vector(normal); intersection->x = (box.lim_min.x + box.lim_max.x)/2.0; intersection->y = (box.lim_min.y + box.lim_max.y)/2.0; intersection->z = (box.lim_min.z + box.lim_max.z)/2.0; return TRUE; } } return FALSE; }