Exemplo n.º 1
0
///////////////////////////////////////////////////////////////////////////////
///  private constant  ObtenirCouleurSurIntersection \n
///  Description : Obtient la couleur à un point d'intersection en particulier
///                Calcule les contributions colorées de toutes les lumières, avec
///                les modèles de Phong et de Gouraud. Aussi, dépendemment des
///                propriétés de la surface en intersection, on réfléchi ou in 
///                réfracte le rayon courant.
///                current ray.
///
///  @param [in]       Rayon const CRayon &    Le rayon à tester
///  @param [in]       Intersection const Scene::CIntersection &    L'ntersection spécifiée
///
///  @return const CCouleur La couleur à l'intersection donnée
///
///  @author Olivier Dionne 
///  @date   13/08/2008
///
///////////////////////////////////////////////////////////////////////////////
const CCouleur CScene::ObtenirCouleurSurIntersection( const CRayon& Rayon, const CIntersection& Intersection ) const
{
    CCouleur  Result = Intersection.ObtenirSurface()->ObtenirCouleur() * Intersection.ObtenirSurface()->ObtenirCoeffAmbiant();
    CVecteur3 IntersectionPoint = Rayon.ObtenirOrigine()+ Intersection.ObtenirDistance() * Rayon.ObtenirDirection();
    
    // Calculer les contribution colorées des toutes les lumières dans la scène
    CCouleur LumiereContributions = CCouleur::NOIR;
    CRayon   LumiereRayon;
    for( LumiereIterator uneLumiere = m_Lumieres.begin(); uneLumiere != m_Lumieres.end(); uneLumiere++ )
    {
        // Initialise le rayon de lumière (ou rayon d'ombre)
        LumiereRayon.AjusterOrigine( IntersectionPoint );
        LumiereRayon.AjusterDirection( ( *uneLumiere )->GetPosition() - IntersectionPoint );
        LumiereRayon.AjusterEnergie( 1 );
        LumiereRayon.AjusterIndiceRefraction( 1 );

        if( CVecteur3::ProdScal( LumiereRayon.ObtenirDirection(), Intersection.ObtenirNormale() ) > 0 )
        {
            // Obtenir la couleur à partir de la lumière
            CCouleur Filter         = ObtenirFiltreDeSurface( LumiereRayon );
            CCouleur LumiereCouleur = ( *uneLumiere )->ObtenirCouleur() * Filter;

            // Ajouter la contribution de Gouraud
            REAL GouraudFactor = ( *uneLumiere )->GetIntensity() * Intersection.ObtenirSurface()->ObtenirCoeffDiffus() *
                CVecteur3::ProdScal( Intersection.ObtenirNormale(), LumiereRayon.ObtenirDirection() );
            Result += Intersection.ObtenirSurface()->ObtenirCouleur() * GouraudFactor * LumiereCouleur;

            // ...
        }
    }

    return Result;
}
Exemplo n.º 2
0
///////////////////////////////////////////////////////////////////////////////
///  public virtual  Intersection \n
///  Description : Effectue l'intersection Rayon/Triangle
///
///  @param [in]       Rayon const CRayon &    Le rayon à tester
///
///  @return Scene::CIntersection Le résultat de l'ntersection
///
///  @author Olivier Dionne 
///  @date   13/08/2008
///
///////////////////////////////////////////////////////////////////////////////
CIntersection CTriangle::Intersection( const CRayon& Rayon )
{
    CIntersection Result;

    // Tomas Akenine-Moller and Eric Haines "Real-Time Rendering 2nd Ed." 2002, p.581
    // http://jgt.akpeters.com/papers/MollerTrumbore97/code.html

    CVecteur3 Edge1 = m_Pts[ 1 ] - m_Pts[ 0 ];
    CVecteur3 Edge2 = m_Pts[ 2 ] - m_Pts[ 0 ];

    // Commencer par le calcul du déterminant - aussi utilisé pour calculer U
    CVecteur3 VecP = CVecteur3::ProdVect( Rayon.ObtenirDirection(), Edge2 );
    // Si le déterminant est près de 0, le rayon se trouve dans le PLAN du triangle
    REAL Det  = CVecteur3::ProdScal( Edge1, VecP );

    if( Abs<REAL>( Det ) < EPSILON )
        return Result;
    else
    {
        REAL InvDet = RENDRE_REEL( 1.0 ) / Det;
        
        // Calculer la distance entre point0 et l'origine du rayon
        CVecteur3 VecS = Rayon.ObtenirOrigine() - m_Pts[ 0 ];
        // Calculer le paramètre U pour tester les frontières
        REAL u = CVecteur3::ProdScal( VecS, VecP ) * InvDet;
        if ( u < 0 || u > 1 )
            return Result;
        else
        {
            CVecteur3 VecQ = CVecteur3::ProdVect( VecS, Edge1 );

            // Calculer le paramètre V pour tester les frontières
            REAL v = CVecteur3::ProdScal( Rayon.ObtenirDirection(), VecQ ) * InvDet;
            if( v < 0 || u + v > 1 )
                return Result;
            else
            {
                Result.AjusterSurface( this );
                Result.AjusterDistance( CVecteur3::ProdScal( Edge2, VecQ ) * InvDet );
                Result.AjusterNormale( m_Normale );
            }
        }
    }

    return Result;
}
Exemplo n.º 3
0
///////////////////////////////////////////////////////////////////////////////
///  public virtual  Intersection \n
///  Description : Effectue l'intersection Rayon/Triangle
///
///  @param [in]       Rayon const CRayon &    Le rayon à tester
///
///  @return Scene::CIntersection Le résultat de l'ntersection
///
///  @author Olivier Dionne 
///  @date   13/08/2008
///
///////////////////////////////////////////////////////////////////////////////
CIntersection CTriangle::Intersection(const CRayon& Rayon)
{
	CIntersection Result;

	// À COMPLÉTER ... 

	// Voici deux références pour acomplir le développement :
	// 1) Tomas Akenine-Moller and Eric Haines "Real-Time Rendering 2nd Ed." 2002, p.581
	// 2) Son article: http://www.graphics.cornell.edu/pubs/1997/MT97.pdf

	// Notez que la normale du triangle est déjà calculée lors du prétraitement
	// il suffit que de la passer à la structure d'intersection.
	CVecteur3 edge1 = m_Pts[1] - m_Pts[0];
	CVecteur3 edge2 = m_Pts[2] - m_Pts[0];
	CVecteur3 pvec = CVecteur3::ProdVect(Rayon.ObtenirDirection(), edge2);
	REAL det = CVecteur3::ProdScal(edge1, pvec);

	if (det < EPSILON)
		return Result;

	CVecteur3 tvec = Rayon.ObtenirOrigine() - m_Pts[0];

	REAL U = CVecteur3::ProdScal(tvec, pvec);

	if ((U < EPSILON) || (U > det))
		return Result;

	CVecteur3 qvec = CVecteur3::ProdVect(tvec, edge1);

	REAL V = CVecteur3::ProdScal(Rayon.ObtenirDirection(), qvec);

	if ((V < EPSILON) || (U + V > det))
		return Result;

	REAL t = CVecteur3::ProdScal(edge2, qvec) / det;
	Result.AjusterDistance(t);
	Result.AjusterSurface(this);
	if (CVecteur3::ProdScal(m_Normale, Rayon.ObtenirDirection()) > EPSILON) {
		Result.AjusterNormale(-m_Normale);
	}
	else {
		Result.AjusterNormale(m_Normale);
	}
	return Result;
}
Exemplo n.º 4
0
///////////////////////////////////////////////////////////////////////////////
///  public virtual  Intersection \n
///  Description : Effectue l'intersection Rayon/Quadrique
///
///  @param [in]       Rayon const CRayon &    Le rayon à tester
///
///  @return Scene::CIntersection Le résultat de l'ntersection
///
///  @author Olivier Dionne 
///  @date   13/08/2008
///
///////////////////////////////////////////////////////////////////////////////
CIntersection CQuadrique::Intersection( const CRayon& Rayon )
{
    CIntersection Result;

    // algorithme d'intersection tiré de ... 
    // Eric Haines, Paul Heckbert "An Introduction to Rayon Tracing",
    // Academic Press, Edited by Andrw S. Glassner, pp.68-73 & 288-293

    CVecteur3 RayonDirection = Rayon.ObtenirDirection();
    CVecteur3 RayonOrigin    = Rayon.ObtenirOrigine();

    const REAL ACoeff = RayonDirection.x * ( m_Quadratique.x * RayonDirection.x   +
                                             m_Mixte.z       * RayonDirection.y   +
                                             m_Mixte.y       * RayonDirection.z ) +
                        RayonDirection.y * ( m_Quadratique.y * RayonDirection.y   +
                                             m_Mixte.x       * RayonDirection.z ) +
                        RayonDirection.z * ( m_Quadratique.z * RayonDirection.z );

    const REAL BCoeff = RayonDirection.x * ( m_Quadratique.x * RayonOrigin.x + RENDRE_REEL( 0.5 )                     *
                                           ( m_Mixte.z * RayonOrigin.y + m_Mixte.y * RayonOrigin.z + m_Lineaire.x ) ) +
                        RayonDirection.y * ( m_Quadratique.y * RayonOrigin.y + RENDRE_REEL( 0.5 )                     * 
                                           ( m_Mixte.z * RayonOrigin.x + m_Mixte.x * RayonOrigin.z + m_Lineaire.y ) ) +
                        RayonDirection.z * ( m_Quadratique.z * RayonOrigin.z + RENDRE_REEL( 0.5 )                     * 
                                           ( m_Mixte.y * RayonOrigin.x + m_Mixte.x * RayonOrigin.y + m_Lineaire.z ) );

    const REAL CCoeff = RayonOrigin.x * ( m_Quadratique.x * RayonOrigin.x   +
                                          m_Mixte.z       * RayonOrigin.y   +
                                          m_Mixte.y       * RayonOrigin.z   +
                                          m_Lineaire.x                    ) +
                        RayonOrigin.y * ( m_Quadratique.y * RayonOrigin.y   +
                                          m_Mixte.x       * RayonOrigin.z   +
                                          m_Lineaire.y                    ) +
                        RayonOrigin.z * ( m_Quadratique.z * RayonOrigin.z   +
                                          m_Lineaire.z                    ) +
                        m_Cst;

    
    if( ACoeff != 0.0 )
    {
        REAL Ka    = -BCoeff / ACoeff;
        REAL Kb    =  CCoeff / ACoeff;
        REAL Delta = Ka * Ka - Kb;

        if( Delta > 0 )
        {
            Delta   = sqrt( Delta );
            REAL T0 = Ka - Delta;
            REAL T1 = Ka + Delta;

            REAL Distance = Min<REAL>( T0, T1 );
            if( Distance < EPSILON )
                Distance = Max<REAL>( T0, T1 );
            
            if( !( Distance < 0 ) )
            {
                Result.AjusterDistance( Distance );
                Result.AjusterSurface( this );

                // Calcule la normale de surface
                CVecteur3 HitPt = RayonOrigin + Distance * RayonDirection;
                
                CVecteur3 Normal;
                Normal.x = RENDRE_REEL( 2.0 ) * m_Quadratique.x * HitPt.x +
                           m_Mixte.y * HitPt.z                            +
                           m_Mixte.z * HitPt.y                            +
                           m_Lineaire.x;

                Normal.y = RENDRE_REEL( 2.0 ) * m_Quadratique.y * HitPt.y +
                           m_Mixte.x * HitPt.z                            +
                           m_Mixte.z * HitPt.x                            +
                           m_Lineaire.y;

                Normal.z = RENDRE_REEL( 2.0 ) * m_Quadratique.z * HitPt.z +
                           m_Mixte.x * HitPt.y                            +
                           m_Mixte.y * HitPt.x                            +
                           m_Lineaire.z;

                Result.AjusterNormale( CVecteur3::Normaliser( Normal ) );
            }
        }
    }
    else
    {
        Result.AjusterSurface ( this );
        Result.AjusterDistance( -RENDRE_REEL( 0.5 ) * ( CCoeff / BCoeff ) );
        Result.AjusterNormale ( CVecteur3::Normaliser( m_Lineaire ) );
    }

    return Result;
}
Exemplo n.º 5
0
///////////////////////////////////////////////////////////////////////////////
///  public virtual  Intersection \n
///  Description : Effectue l'intersection Rayon/Quadrique
///
///  @param [in]       Rayon const CRayon &    Le rayon à tester
///
///  @return Scene::CIntersection Le résultat de l'ntersection
///
///  @author Olivier Dionne 
///  @date   13/08/2008
///
///////////////////////////////////////////////////////////////////////////////
CIntersection CQuadrique::Intersection( const CRayon& Rayon )
{
    CIntersection Result;

	float a, b, c, d, e, f, g, h, i, j;
	float A, B, C;
	float t0, t1, tf;
	const CVecteur3 rd = Rayon.ObtenirDirection();
	const CVecteur3 r0 = Rayon.ObtenirOrigine();

	/*a = m_Quadratique[0];
	e = m_Quadratique[1];
	h = m_Quadratique[2];

	b = m_Mixte[0];
	c = m_Mixte[1];
	f = m_Mixte[2];

	d = m_Lineaire[0];
	g = m_Lineaire[1];
	i = m_Lineaire[2];

	j = m_Cst;

	A = a * rd.x * rd.x + 2 * b * rd.x * rd.y + 2 * c * rd.x * rd.z +
		e * rd.y * rd.y + 2 * f * rd.y * rd.z + h * rd.z * rd.z;

	B = 2 * (a * r0.x * rd.x + b * (r0.x * rd.y + rd.x * r0.y) + c * (r0.x * rd.z + rd.x * r0.z) +
		d * rd.x + e * r0.y * rd.y + f * (r0.y * rd.z + rd.y * r0.z) + g * rd.y +
		h * r0.z * rd.z + i * rd.z);

	C = a * r0.x * r0.x + 2 * b * r0.x * r0.y + 2 * c * r0.x * r0.z + 2 * d * r0.x +
		e * r0.y * r0.y + 2 * f * r0.y * r0.z + 2 * g * r0.y +
		h * r0.z * r0.z + 2 * i * r0.z + j;*/

    a = m_Quadratique[0];
    b = m_Quadratique[1];
    c = m_Quadratique[2];

    d = m_Mixte[0];
    e = m_Mixte[1];
    f = m_Mixte[2];

    g = m_Lineaire[0];
    h = m_Lineaire[1];
    i = m_Lineaire[2];

    j = m_Cst;

    A = a * rd.x * rd.x + b * rd.y * rd.y + c * rd.z * rd.z + d * rd.x * rd.y +
        e * rd.x * rd.z + f * rd.y * rd.z;

    B = 2 * a * r0.x * rd.x + 2 * b * r0.y * rd.y + 2 * c * r0.z * rd.z + 
        d * (r0.x * rd.y + r0.y * rd.x) + e * (r0.x * rd.z) + f * (r0.y * rd.z + rd.y * r0.z) +
        g * rd.x + h * rd.y + i * rd.z;

    C = a * r0.x * r0.x + b * r0.y * r0.y + c * r0.z * r0.z + d * r0.x * r0.y +
        e * r0.x * r0.z + f * r0.y * r0.z + g * r0.x + h * r0.y + i * r0.z + j;

    if (A == 0.f)
    {
        tf = -C / B;
    }
    else
    {
        float discriminant = B * B - 4 * A * C;
        if (discriminant < 0)
        {
            return Result;
        }
        else
        {
            tf = (-B - sqrt(discriminant)) / (2 * A);
            if (tf < 0)
            {
                tf = (-B + sqrt(discriminant)) / (2 * A);
                if (tf < 0)
                    return Result;
            }

        }
    }

    CVecteur3 intersection(r0 + rd * tf);
    Result.AjusterDistance(CVecteur3::Norme(intersection - r0));

    CVecteur3 normale;
    normale.x =  (2 * a * intersection.x + d * intersection.y + e * intersection.z) + g;
    normale.y =  (d * intersection.x + 2 * b * intersection.y + f * intersection.z) + h;
    normale.z =  (e * intersection.x + f * intersection.y + 2 * c * intersection.z) + i;
    normale = CVecteur3::Normaliser(normale);

    Result.AjusterNormale(CVecteur3::ProdScal(normale, rd) > 0 ? -normale : normale);
    Result.AjusterSurface(this);

    return Result;
}