//Foley capítulo 15.10, fórmula 15.17 Intersection Cilindro::Intercepta(const Raio& r_vis, IntersectionMode mode, float threshold) { float a, b, c, delta; Intersection intersection; // valores intermediários float t1, t2; // esticamentos (t*r_vis) do raio que interceptam o cilindro Ponto_3D P1, P2; // Pontos em que o raio intercepta o cilindro (podem ser coincidentes) Vetor_3D K = Vetor_3D(r_vis.X0() - centro.X(), 0, r_vis.Z0() - centro.Z()); Vetor_3D direcao = Vetor_3D(r_vis.Direcao()); direcao.setY(0); // montando a equação do 2º grau at2 + bt + c = 0 a = direcao.produtoEscalar(direcao); b = 2*(direcao.produtoEscalar(K)); c = K.produtoEscalar(K) - raio*raio; delta = b*b - 4*a*c; if (delta >= 0) { t1 = (-b - sqrt(delta)) /(2*a); t2 = (-b + sqrt(delta)) /(2*a); P1 = P2 = r_vis.Origem(); P1 += r_vis.Direcao()*t1; P2 += r_vis.Direcao()*t2; // Verifica se pelo menos um dos pontos está dentro do cilindro if ( (ALTURA_OK(P1, centro, altura)) || (ALTURA_OK(P2, centro, altura)) ) { intersection = Intersection::nearest( Intersection(this, t1), Intersection(this, t2), threshold); } } return intersection; }
Intersection PlanoY::Intercepta(const Raio& r_vis, IntersectionMode mode, float threshold) { float x,z; float t = (a - r_vis.Y0()) / r_vis.Dy(); Intersection lastIntersection; if ( t <0) return lastIntersection; x = r_vis.X0() + t * r_vis.Dx(); if (INSIDE(x,bmin,bmax)) { z = r_vis.Z0() + t *r_vis.Dz(); if (INSIDE(z,cmin,cmax)) { lastIntersection.setValues(this, t); return lastIntersection; } } return lastIntersection; }
Intersection Cone::Intercepta(const Raio& r_vis, IntersectionMode mode, float threshold) { float a, b, c, delta; Intersection intersection; // valores intermediários Vetor_3D K = Vetor_3D(r_vis.X0() - centro.X(), r_vis.Y0() - centro.Y(), r_vis.Z0() - centro.Z()); // montando a equação do 2º grau at2 + bt + c = 0 // equação para o cone: a = pow(r_vis.Direcao().X(), 2) + pow(r_vis.Direcao().Z(), 2) - pow(r_vis.Direcao().Z(), 2); b = 2*((r_vis.Direcao().X() * K.X()) + (r_vis.Direcao().Z() * K.Y()) - (r_vis.Direcao().Z() * K.Z)); c = pow(K.X(), 2) + pow(K.Y(), 2) - pow(K.Z(), 2); delta = b*b - 4*a*c; if (delta >= 0) { float t_plus = (-b + sqrt(delta)) /(2*a); float t_minus = (-b - sqrt(delta)) /(2*a); Ponto_3D p_plus( r_vis.Origem().X() + r_vis.Direcao().X()*t_plus , r_vis.Origem().Y() + r_vis.Direcao().Y()*t_plus , r_vis.Origem().Z() + r_vis.Direcao().Z()*t_plus ); Ponto_3D p_minus( r_vis.Origem().X() + r_vis.Direcao().X()*t_minus , r_vis.Origem().Y() + r_vis.Direcao().Y()*t_minus , r_vis.Origem().Z() + r_vis.Direcao().Z()*t_minus ); bool p_plus_dentro_do_intervalo = false; bool p_minus_dentro_do_intervalo = false; if ((p_plus.Y() < (centro.Y() + altura/2.0)) && (p_minus.Y() > (centro.Y() - altura/2.0))) p_plus_dentro_do_intervalo = true; if ((p_minus.Y() < (centro.Y() + altura/2.0)) && (p_minus.Y() > (centro.Y() - altura/2.0))) p_minus_dentro_do_intervalo = true; if (p_plus_dentro_do_intervalo && p_minus_dentro_do_intervalo){ intersection = Intersection::nearest( Intersection(this, t_plus), Intersection(this, t_minus), threshold); } else if (p_plus_dentro_do_intervalo){ intersection.setValues(this, t_plus); } else if (p_minus_dentro_do_intervalo){ intersection.setValues(this, t_minus); } } return intersection; }