#include #include #include #include #include "objetos.hpp" Objeto_3D::Objeto_3D( FILE *fp ) { fscanf( fp, " %d ", &indice_textura ); } Esfera::Esfera( FILE *fp ) : Objeto_3D( fp ) { fscanf( fp, " %f ", &raio ); centro.read( fp ); } Esfera::Esfera(int _indice_textura, float _raio, Vetor_3D _centro) : Objeto_3D ( _indice_textura ) { raio = _raio; centro.Copia( _centro ); } //Foley capítulo 15.10, fórmula 15.17 float Esfera::Intercepta( Raio r_vis ) { float distx, disty, distz, a, b, c, delta, raiz1, raiz2; // valores intermediários distx = r_vis.X0() - centro.X(); disty = r_vis.Y0() - centro.Y(); distz = r_vis.Z0() - centro.Z(); // montando a equação do 2º grau at2 + bt + c = 0 a = SQR(r_vis.Dx()) + SQR(r_vis.Dy()) + SQR(r_vis.Dz()); b = 2 * ( r_vis.Dx() * distx + r_vis.Dy() * disty + r_vis.Dz() * distz ); c = SQR(distx) + SQR(disty) + SQR(distz) - SQR(raio); // Calculando Delta delta = SQR(b) - 4*a*c; // Retornando t (se não existir t retornar valor negativo que será ignorado) if ( delta < 1 ) return(-1); // raiz1 = ( -b - (float)sqrt(delta) ) / (2*a); // raiz2 = ( -b + (float)sqrt(delta) ) / (2*a); delta = (float)sqrt(delta); a*=2; raiz1 = ( -b - delta ) / a; raiz2 = ( -b + delta ) / a; return(MINI(raiz1,raiz2)); // ATENÇÃO!!! // Como escolho a interseção de menor valor, podem ocorrer // exceções que não são bem tratadas. Por exemplo, uma // esfera que contenha a camara e a tela de projeção. // neste caso, será retornada a interseção t<0, mesmo havendo // um t>1, que deveria ser retornado. } Vetor_3D Esfera::Normal( Vetor_3D ponto ) { ponto.Subtrai(centro); ponto.Normaliza(); return ponto; } Cor_rgb Esfera::Cor_difusa( Vetor_3D ponto, Material*mat ) { Imagem *img = mat->Texture(); if (!img) { return mat->Cor_difusa(); } else { return img->GetPixel( 1, 1 ); } } float PlanoX::Intercepta( Raio r_vis ) { float t,y,z; //calcula-se o t da interseção do raio com o plano t = (a - r_vis.X0()) / r_vis.Dx(); if (t<0) return(-1); //se o t for maior que zero, verifica-se o ponto de interseção está //entre os limites que definem o segmento de plano y = r_vis.Y0() + t * r_vis.Dy(); if (INSIDE(y,bmin,bmax)) { z = r_vis.Z0() + t*r_vis.Dz(); if (INSIDE(z,cmin,cmax)) return(t); } return(-1); } float PlanoY::Intercepta( Raio r_vis ) { float t,x,z; t = (a - r_vis.Y0()) / r_vis.Dy(); if (t<0) return(-1); 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)) return(t); } return(-1); } float PlanoZ::Intercepta( Raio r_vis ) { float t,x,y; t = (a - r_vis.Z0()) / r_vis.Dz(); if (t<0) return(-1); x = r_vis.X0() + t * r_vis.Dx(); if (INSIDE(x,bmin,bmax)) { y = r_vis.Y0() + t*r_vis.Dy(); if (INSIDE(y,cmin,cmax)) return(t); } return(-1); } CaixaParalela::CaixaParalela( FILE *fp ) : Objeto_3D( fp ) { extremo_inferior.read( fp ); extremo_superior.read( fp ); DefineFaces(); } CaixaParalela::CaixaParalela( int _indice_textura, Vetor_3D _extremo_inferior, Vetor_3D _extremo_superior ) : Objeto_3D ( _indice_textura ) { extremo_inferior.Copia(_extremo_inferior); extremo_superior.Copia(_extremo_superior); DefineFaces(); } void CaixaParalela::DefineFaces() { float xmin, ymin, zmin, xmax, ymax, zmax; xmin = extremo_inferior.X(); ymin = extremo_inferior.Y(); zmin = extremo_inferior.Z(); xmax = extremo_superior.X(); ymax = extremo_superior.Y(); zmax = extremo_superior.Z(); px1 = new PlanoX( xmin, ymin, ymax, zmin, zmax ); px2 = new PlanoX( xmax, ymin, ymax, zmin, zmax ); py1 = new PlanoY( ymin, xmin, xmax, zmin, zmax ); py2 = new PlanoY( ymax, xmin, xmax, zmin, zmax ); pz1 = new PlanoZ( zmin, xmin, xmax, ymin, ymax ); pz2 = new PlanoZ( zmax, xmin, xmax, ymin, ymax ); } CaixaParalela::~CaixaParalela() { delete( px1 ); delete( px2 ); delete( py1 ); delete( py2 ); delete( pz1 ); delete( pz2 ); } // Chama a função Intercepta de cada um dos seis planos. // Pega o menor t (maior que zero) entre todos. float CaixaParalela::Intercepta( Raio r_vis ) { float t,t_menor=-1; t = px1->Intercepta( r_vis ); if ( t>0 && ( tIntercepta( r_vis ); if ( t>0 && ( tIntercepta( r_vis ); if ( t>0 && ( tIntercepta( r_vis ); if ( t>0 && ( tIntercepta( r_vis ); if ( t>0 && ( tIntercepta( r_vis ); if ( t>0 && ( t0 && v2>0 && v3>0 ) || ( v1<0 && v2<0 && v3<0 ) ) return (t); else return (-1); } } Vetor_3D Triangulo::Normal( Vetor_3D ponto ) { return (normal); Vetor_3D temp; temp.Atribui( -normal.X(), -normal.Y(), -normal.Z() ); return temp; }