/* 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);
	}
}
示例#2
0
/* 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]);
}