/* Aplica o modelo de iluminação para o cálculo da cor do vértice corrente. * * Argumentos de entrada: * 'vertex_ec' : Localização do vértice representada no sistema de coordenadas da câmera (eye coordinates, EC). * 'unit_normal_ec' : Vetor normal à superfície representado no sistema de coordenadas da câmera (EC). Assume-se que * a norma deste vetor é igual a 1.0f. * 'base_color' : Cor base para o vértice. Utilizada quando a iluminação está desabilitada. * 'lighting_enabled' : Indica se a iluminação está habilitada. * 'material_ambient' : Cor da componente ambiente do material. * 'material_diffuse' : Cor da componente difusa do material. * 'material_specular' : Cor da componente especular do material. * 'material_shininess': Expoente que define o tamanho do brilho especular do material. * 'light_ec' : Localização da fonte de luz no sistema de coordenadas da câmera (EC). * 'light_ambient' : Intensidade da componente ambiente da fonte de luz. * 'light_diffuse' : Intensidade da componente difusa da fonte de luz. * 'light_specular' : Intensidade da componente especular da fonte de luz. * * Argumentos de saída: * 'vertex_color' : Cor do vértice corrente. É igual a 'base_color' caso a iluminação esteja desabilitada ou é * calculada por meio de modelo de reflexão de Blin-Phong, caso contrário. */ void vertex_lighting(const location_struct &vertex_ec, const direction_struct &unit_normal_ec, const color_struct &base_color, bool lighting_enabled, const color_struct &material_ambient, const color_struct &material_diffuse, const color_struct &material_specular, float material_shininess, const location_struct &light_ec, const color_struct &light_ambient, const color_struct &light_diffuse, const color_struct &light_specular, color_struct &vertex_color) { // Calcular 'vertex_color'. direction_struct S = direction_struct(); direction_struct V = direction_struct(); direction_struct H = direction_struct(); if(lighting_enabled) { //Diffuse S.x = light_ec.x - vertex_ec.x; S.y = light_ec.y - vertex_ec.y; S.z = light_ec.z - vertex_ec.z; normalize(S); float dotProductDiffuse = dotProduct (S, unit_normal_ec); color_struct lightDiffuse = color_struct(); lightDiffuse.r = light_diffuse.r * material_diffuse.r * maxV(dotProductDiffuse, 0.0f); lightDiffuse.g = light_diffuse.g * material_diffuse.g * maxV(dotProductDiffuse, 0.0f); lightDiffuse.b = light_diffuse.b * material_diffuse.b * maxV(dotProductDiffuse, 0.0f); lightDiffuse.a = light_diffuse.a * material_diffuse.a * maxV(dotProductDiffuse, 0.0f); //Specular V.x = - vertex_ec.x; V.y = - vertex_ec.y; V.z = - vertex_ec.z; normalize(V); H.x = S.x + V.x; H.y = S.y + V.y; H.z = S.z + V.z; normalize(H); float dotProductSpecular = dotProduct(H, unit_normal_ec); color_struct lightSpecular = color_struct(); lightSpecular.r = light_specular.r * material_specular.r * pow(maxV(dotProductSpecular, 0.0f), material_shininess); lightSpecular.g = light_specular.g * material_specular.g * pow(maxV(dotProductSpecular, 0.0f), material_shininess); lightSpecular.b = light_specular.b * material_specular.b * pow(maxV(dotProductSpecular, 0.0f), material_shininess); lightSpecular.a = light_specular.a * material_specular.a * pow(maxV(dotProductSpecular, 0.0f), material_shininess); //Ambient color_struct lightAmbient = color_struct(); lightAmbient.r = light_ambient.r * material_ambient.r; lightAmbient.g = light_ambient.g * material_ambient.g; lightAmbient.b = light_ambient.b * material_ambient.b; lightAmbient.a = light_ambient.a * material_ambient.a; //Result vertex_color = color_struct(lightDiffuse.r + lightSpecular.r + lightAmbient.r, lightDiffuse.g + lightSpecular.g + lightAmbient.g, lightDiffuse.b + lightSpecular.b + lightAmbient.b, 1.0f); } else { vertex_color = color_struct(base_color); } }
/* Monta triângulos a partir das listas de propriedades de vértices informadas. Esta rotina também é responsável por realizar * o recorte (clipping) das primitivas que não estão completamente contidas no volume de visualização (frustum) e a supressão * (culling) de triângulos conforme a orientação assumida para as faces dos modelos geométricos. * * Argumentos de entrada: * 'vertices_cc' : Lista de localização de vértices no sistema de coordenadas de recorte (clip coordinates, CC). * O tamanho desta lista é sempre um múltiplo de três, sendo que cada trio corresponde aos * vértices de um triângulo. * 'vertices_texcoords' : Lista de coordenadas de textura dos vértices. Os elementos desta lista possuem relação * um-para-um com os elementos de 'vertices_cc'. * 'vertices_texture_ids' : Lista de identificadores de textura dos vértices. Os elementos desta lista possuem relação * um-para-um com os elementos de 'vertices_cc'. Os três vértices de um mesmo triângulo possuem * o mesmo identificador de textura. * 'backface_culling_enabled': Indica se a supressão de faces traseiras está habilitada. * 'front_face_orientation' : Orientação assumida para as faces frontais, podendo ser sentido horário (clockwise, * 'cw_orientation') ou sentido anti-horário (counterclockwise, 'ccw_orientation'). * * Argumentos de saída: * 'primitives' : Lista de triângulos completamente contidos no volume de visualização e orientadas conforme ap * convensão para faces frontais, caso a supressão de faces traseiras esteja habilitada. */ void make_triangles(const std::vector<location_struct> &vertices_cc, const std::vector<color_struct> &vertices_colors, const std::vector<texcoord_struct> &vertices_texcoords, const std::vector<int> &vertices_texture_ids, bool backface_culling_enabled, orientation_type front_face_orientation, std::vector<triangle_struct> &primitives) { // Calcular 'primitives'. bool pertence = true; std::vector<triangle_struct> result; triangle_struct tmp = triangle_struct(); for(int i = 0; i < vertices_cc.size(); i++){ int aux = i%3; tmp.color[aux].r = vertices_colors[i].r; tmp.color[aux].g = vertices_colors[i].g; tmp.color[aux].b = vertices_colors[i].b; tmp.color[aux].a = vertices_colors[i].a; tmp.texcoord[aux].u = vertices_texcoords[i].u; tmp.texcoord[aux].v = vertices_texcoords[i].v; tmp.vertex_cc[aux].x = vertices_cc[i].x; tmp.vertex_cc[aux].y = vertices_cc[i].y; tmp.vertex_cc[aux].z = vertices_cc[i].z; tmp.vertex_cc[aux].w = vertices_cc[i].w; tmp.texture_id = vertices_texture_ids[i]; if(!((vertices_cc[i].x > -vertices_cc[i].w && vertices_cc[i].x < vertices_cc[i].w) && (vertices_cc[i].y > -vertices_cc[i].w && vertices_cc[i].y < vertices_cc[i].w) && (vertices_cc[i].z > -vertices_cc[i].w && vertices_cc[i].z < vertices_cc[i].w)) && pertence) pertence = false; if(aux == 2) if(pertence){ result.push_back(tmp); }else pertence = true; } if(backface_culling_enabled){ direction_struct normal, left, right; if(front_face_orientation == 0){ for(int i = 0; i < result.size(); i++){ left = direction_struct(result[i].vertex_cc[1].x - result[i].vertex_cc[0].x, result[i].vertex_cc[1].y - result[i].vertex_cc[0].y, result[i].vertex_cc[1].z - result[i].vertex_cc[0].z); right = direction_struct(result[i].vertex_cc[2].x - result[i].vertex_cc[0].x, result[i].vertex_cc[2].y - result[i].vertex_cc[0].y, result[i].vertex_cc[2].z - result[i].vertex_cc[0].z); normal = direction_struct(left.y*right.z - left.z*right.y, left.z*right.x - left.x*right.z, left.x*right.y - left.y*right.x); float angle = dot(normal, direction_struct(result[i].vertex_cc[0].x, result[i].vertex_cc[0].y, result[i].vertex_cc[0].z)); if(angle < 0) primitives.push_back(result[i]); } }else{ for(int i = 0; i < result.size(); i++){ left = direction_struct(result[i].vertex_cc[1].x - result[i].vertex_cc[0].x, result[i].vertex_cc[1].y - result[i].vertex_cc[0].y, result[i].vertex_cc[1].z - result[i].vertex_cc[0].z); right = direction_struct(result[i].vertex_cc[2].x - result[i].vertex_cc[0].x, result[i].vertex_cc[2].y - result[i].vertex_cc[0].y, result[i].vertex_cc[2].z - result[i].vertex_cc[0].z); normal = direction_struct(left.y*right.z - left.z*right.y, left.z*right.x - left.x*right.z, left.x*right.y - left.y*right.x); float angle = dot(normal, direction_struct(result[i].vertex_cc[0].x, result[i].vertex_cc[0].y, result[i].vertex_cc[0].z)); if(angle > 0) primitives.push_back(result[i]); } } }else for(int i = 0; i < result.size(); i++) primitives.push_back(result[i]); }