Beispiel #1
0
OSG_BASE_DLLMAPPING 
bool intersect(const FrustumVolume &frustum, const Volume &vol, 
               FrustumVolume::PlaneSet &inplanes)
{
    Pnt3f min, max;
    vol.getBounds(min, max);
     
    const Plane             *frust = frustum.getPlanes();
    FrustumVolume::PlaneSet  mask  = 0x1;
   
    // check the box against the 6 planes, adjust the inplanes set
    // accordingly

    for(Int32 i = 0; i < 6; i++, mask <<= 1)
    {
        if((inplanes & mask) != 0)
            continue;
        
        if(frust[i].isOutHalfSpace(min, max))
            return false;
        
        if(frust[i].isInHalfSpace(min, max))
            inplanes |= mask;
    }

    return true;
}
void Camera::getFrustum(FrustumVolume& result, const Viewport& p)
{
    Matrix mv,prt,pr;

    getProjection           (pr , p.getPixelWidth(), p.getPixelHeight());
    getProjectionTranslation(prt, p.getPixelWidth(), p.getPixelHeight());
    getViewing              (mv , p.getPixelWidth(), p.getPixelHeight());

    pr.mult(prt);
    pr.mult(mv );

    result.setPlanes(pr);
}
/*! Calculate the frustum of this camera's visible area (w,h instead port). 
*/
void Camera::getFrustum(FrustumVolume& result, 
                        UInt32  width, UInt32  height)
{
    Matrix mv,prt,pr;
    
    getProjection           (pr , width, height);
    getProjectionTranslation(prt, width, height);
    getViewing              (mv , width, height);

    pr.mult(prt);
    pr.mult(mv );
    
    result.setPlanes(pr);
}
OSG_BASE_DLLMAPPING 
bool intersect(const SphereVolume &sphere, const FrustumVolume &frustum)
{
    const Plane             *frust = frustum.getPlanes();

    //check the center of the sphere with each plane of the frustum
    for(Int32 i = 0; i < 6; i++)
    {
        if(frust[i].distance(sphere.getCenter()) < -sphere.getRadius())
            return false;
    }

    return true;
}
OSG_BASE_DLLMAPPING 
bool intersect(const CylinderVolume &cylinder, const FrustumVolume &frustum)
{
    Pnt3f min, max;
    cylinder.getBounds(min, max);

    const Plane       *frust = frustum.getPlanes();

    // check each point of the box to the 6 planes

    for(Int32 i = 0; i < 6; i++)
    {
        if(frust[i].isOutHalfSpace(min, max))
            return false;
    }

    return true;
}
Beispiel #6
0
OSG_BEGIN_NAMESPACE

OSG_BASE_DLLMAPPING bool
operator ==(const FrustumVolume &lhs, const FrustumVolume &rhs)
{
    return ((static_cast<const Volume &>(lhs) == rhs ) &&
            (lhs.getPlanes()[0] == rhs.getPlanes()[0]) &&
            (lhs.getPlanes()[1] == rhs.getPlanes()[1]) &&
            (lhs.getPlanes()[2] == rhs.getPlanes()[2]) &&
            (lhs.getPlanes()[3] == rhs.getPlanes()[3]) &&
            (lhs.getPlanes()[4] == rhs.getPlanes()[4]) &&
            (lhs.getPlanes()[5] == rhs.getPlanes()[5]));
}
void ShaderShadowMapEngine::handleDirectionalLightEnter(
    DirectionalLight *dirL, RenderAction *ract, SSMEngineData *data)
{
    RenderPartition *parentPart = ract      ->getActivePartition();
    FrustumVolume    camFrust   = parentPart->getFrustum        ();

    Matrix matEyeToWorld  (parentPart->getCameraToWorld());
    Matrix matWorldToLight;
    Matrix matEyeToLight;

    calcDirectionalLightMatrices(matWorldToLight, matEyeToLight,
                                 dirL,            matEyeToWorld );

    // place light camera outside the scene bounding box:
    //  - project camera frustum and scene bounding box into a
    //    coordinate system where the directional light shines
    //    along the -z axis.
    //  - compute 2 AABBs that contain the projected frustum and
    //    scene BB
    //  - width and height of the ortho projection are determined from
    //    the frustum AABB, while near and far are determined by the
    //    scene AABB (offscreen objects cast shadows into the view volume)
          Pnt3f      camVerts  [10];
          Pnt3f      sceneVerts[10];
    const Matrix    &matSceneToWorld = ract->topMatrix ();
          BoxVolume  sceneBB         = ract->getActNode()->getVolume();

    camFrust.getCorners(camVerts  [0], camVerts  [1],
                        camVerts  [2], camVerts  [3],
                        camVerts  [4], camVerts  [5],
                        camVerts  [6], camVerts  [7] );
    sceneBB .getCorners(sceneVerts[0], sceneVerts[1],
                        sceneVerts[2], sceneVerts[3],
                        sceneVerts[4], sceneVerts[5],
                        sceneVerts[6], sceneVerts[7] );

    camVerts  [8].setValues(TypeTraits<Real32>::getMax(),
                            TypeTraits<Real32>::getMax(),
                            TypeTraits<Real32>::getMax() );
    camVerts  [9].setValues(TypeTraits<Real32>::getMin(),
                            TypeTraits<Real32>::getMin(),
                            TypeTraits<Real32>::getMin() );
    sceneVerts[8].setValues(TypeTraits<Real32>::getMax(),
                            TypeTraits<Real32>::getMax(),
                            TypeTraits<Real32>::getMax() );
    sceneVerts[9].setValues(TypeTraits<Real32>::getMin(),
                            TypeTraits<Real32>::getMin(),
                            TypeTraits<Real32>::getMin() );

    for(UInt32 i = 0; i < 8; ++i)
    {
        matWorldToLight.mult(camVerts  [i], camVerts  [i]);

        matSceneToWorld.mult(sceneVerts[i], sceneVerts[i]);
        matWorldToLight.mult(sceneVerts[i], sceneVerts[i]);

        camVerts  [8][0] = osgMin(camVerts  [8][0], camVerts  [i][0]);
        camVerts  [9][0] = osgMax(camVerts  [9][0], camVerts  [i][0]);
        camVerts  [8][1] = osgMin(camVerts  [8][1], camVerts  [i][1]);
        camVerts  [9][1] = osgMax(camVerts  [9][1], camVerts  [i][1]);

        sceneVerts[8][0] = osgMin(sceneVerts[8][0], sceneVerts[i][0]);
        sceneVerts[9][0] = osgMax(sceneVerts[9][0], sceneVerts[i][0]);
        sceneVerts[8][1] = osgMin(sceneVerts[8][1], sceneVerts[i][1]);
        sceneVerts[9][1] = osgMax(sceneVerts[9][1], sceneVerts[i][1]);
        sceneVerts[8][2] = osgMin(sceneVerts[8][2], sceneVerts[i][2]);
        sceneVerts[9][2] = osgMax(sceneVerts[9][2], sceneVerts[i][2]);
    }

    // these points are the corners of the ortho shadow view volume
    Pnt3f lightMin(osgMax(camVerts[8][0], sceneVerts[8][0]),
                   osgMax(camVerts[8][1], sceneVerts[8][1]),
                   -sceneVerts[9][2]);
    
    Pnt3f lightMax(osgMin(camVerts[9][0], sceneVerts[9][0]),
                   osgMin(camVerts[9][1], sceneVerts[9][1]),
                   -sceneVerts[8][2]);

    // enlarge by 2% in x, y, z direction
    lightMin[0] -= (lightMax[0] - lightMin[0]) * 0.01f;
    lightMin[1] -= (lightMax[1] - lightMin[1]) * 0.01f; 
    lightMin[2] -= (lightMax[2] - lightMin[2]) * 0.01f;

    lightMax[0] += (lightMax[0] - lightMin[0]) * 0.01f;
    lightMax[1] += (lightMax[1] - lightMin[1]) * 0.01f;
    lightMax[2] += (lightMax[2] - lightMin[2]) * 0.01f;

    Matrix matLightProj;
    Matrix matLightProjTrans;

    MatrixOrthogonal(matLightProj,
                     lightMin[0], lightMax[0],
                     lightMin[1], lightMax[1],
                     lightMin[2], lightMax[2] );

    updateShadowTexImage  (data);
    updateShadowTexBuffers(data);
    updateRenderTargets   (data);

    Int32 shadowTexUnit = (this->getForceTextureUnit() > 0) ?
                           this->getForceTextureUnit()      : 7;

    ShaderProgram *shadowFP = this->getShadowFragmentProgram();

    if(shadowFP == NULL)
    {
        ShaderProgramUnrecPtr newShadowFP = ShaderProgram::createLocal();
        newShadowFP->setShaderType(GL_FRAGMENT_SHADER);
        newShadowFP->setProgram   (_dirFPCode        );

        newShadowFP->addUniformVariable("SSME_matEyeToLight", matEyeToLight);
        newShadowFP->addUniformVariable("SSME_matLightProj",  matLightProj );
        newShadowFP->addUniformVariable("SSME_texShadow",     shadowTexUnit);

        this->setShadowFragmentProgram(newShadowFP);
        shadowFP = newShadowFP;
    }
    else
    {
        shadowFP->updateUniformVariable("SSME_matEyeToLight", matEyeToLight);
        shadowFP->updateUniformVariable("SSME_matLightProj",  matLightProj );
    }

    commitChanges();

    this->pushPartition(ract);
    {
        RenderPartition   *part   = ract->getActivePartition( );
        Window            *win    = ract->getWindow         ( );
        FrameBufferObject *target = data->getRenderTargets  (0);
        Background        *back   = data->getBackground     ( );

        part->setRenderTarget(target);
        part->setWindow      (win   );

        part->calcViewportDimension(0.f, 0.f, 1.f, 1.f,
                                    target->getWidth (),
                                    target->getHeight() );

        part->setupProjection(matLightProj, matLightProjTrans);
        part->setupViewing   (matWorldToLight                );

        part->setNear        (parentPart->getNear());
        part->setFar         (parentPart->getFar ());

        part->calcFrustum    (                     );

        part->setBackground  (back                 );

        // force material for shadow map generation
        part->overrideMaterial(data->getLightPassMaterials(0),
                               ract->getActNode           ( ) );

        this->recurseFrom(ract, dirL);
        ract->useNodeList(false     );

        // undo override
        part->overrideMaterial(NULL,
                               ract->getActNode           ( ) );
    }
    this->popPartition(ract);
}
// visibility levels
bool RenderPartition::pushVisibility(Node * const pNode)
{
    if(getFrustumCulling() == false)
        return true;

    FrustumVolume::PlaneSet inplanes = _visibilityStack.back();

    if(inplanes == FrustumVolume::P_ALL)
    {
        _visibilityStack.push_back(inplanes);

        return true;
    }

    Color3f col;
    bool result = true;

    FrustumVolume frustum = _oFrustum;
    BoxVolume     vol     = pNode->getVolume();

    // don't mess with infinite volumes
    if(vol.isInfinite() == false)
    {
        pNode->updateVolume();

        vol = pNode->getVolume();

#if 1
        vol.transform(topMatrix());
#else
    // not quite working
        Matrix m = topMatrix();
        m.invert();

        frustum.transform(m);
#endif
    }

    if(_oDrawEnv.getStatCollector() != NULL)
    {
        _oDrawEnv.getStatCollector()->getElem(statCullTestedNodes)->inc();
    }

    if(intersect(frustum, vol, inplanes) == false)
    {
         result = false;

         col.setValuesRGB(1,0,0);

         if(_oDrawEnv.getStatCollector() != NULL)
         {
             _oDrawEnv.getStatCollector()->getElem(statCulledNodes)->inc();
         }
    }
    else
    {
        if(inplanes == FrustumVolume::P_ALL)
        {
            col.setValuesRGB(0,1,0);
        }
        else
        {
            col.setValuesRGB(0,0,1);
        }
    }

    if(getVolumeDrawing())
    {
        dropVolume(this, pNode, col);
    }

    _visibilityStack.push_back(inplanes);

    return result;
}
Beispiel #9
0
/*! \ingroup GrpSystemDrawablesGeometryFunctions
    Draw the given FrustumVolume using direct OpenGL calls by intersecting
    near/far with the pairwise intersection of left/right and top/bottom.
*/
OSG_SYSTEMLIB_DLLMAPPING 
void OSG::drawVolume(const FrustumVolume &volume)
{
    Line lines[4];
    
    // calc the intersection lines between left/right/bottom/top
    if(volume.getLeft().intersect(volume.getTop(), lines[0]) == false)
    {
        FWARNING(("drawVolume(Frustum): left & top parallel ?!?\n"));
        return;
    }
    
    if(volume.getLeft().intersect(volume.getBottom(), lines[1]) == false)
    {
        FWARNING(("drawVolume(Frustum): left & bottom parallel ?!?\n"));
        return;
    }
    
    if(volume.getRight().intersect(volume.getTop(), lines[2]) == false)
    {
        FWARNING(("drawVolume(Frustum): right & top parallel ?!?\n"));
        return;
    }
    
    if(volume.getRight().intersect(volume.getBottom(), lines[3]) == false)
    {
        FWARNING(("drawVolume(Frustum): right & bottom parallel ?!?\n"));
        return;
    }
    
    // calc the intersection points
    Pnt3f pnts[8];
    
    if(volume.getNear().intersectInfinite(lines[0], pnts[0]) == false)
    {
        FWARNING(("drawVolume(Frustum): near & left/top parallel ?!?\n"));
        return;
    }
    
    if(volume.getFar().intersectInfinite(lines[0], pnts[1]) == false)
    {
        FWARNING(("drawVolume(Frustum): far & left/top parallel ?!?\n"));
        return;
    }
    
    if(volume.getNear().intersectInfinite(lines[1], pnts[2]) == false)
    {
        FWARNING(("drawVolume(Frustum): near & left/bottom parallel ?!?\n"));
        return;
    }
    
    if(volume.getFar().intersectInfinite(lines[1], pnts[3]) == false)
    {
        FWARNING(("drawVolume(Frustum): far & left/bottom parallel ?!?\n"));
        return;
    }
    
    if(volume.getNear().intersectInfinite(lines[2], pnts[4]) == false)
    {
        FWARNING(("drawVolume(Frustum): near & right/top parallel ?!?\n"));
        return;
    }
    
    if(volume.getFar().intersectInfinite(lines[2], pnts[5]) == false)
    {
        FWARNING(("drawVolume(Frustum): far & right/top parallel ?!?\n"));
        return;
    }
    
    if(volume.getNear().intersectInfinite(lines[3], pnts[6]) == false)
    {
        FWARNING(("drawVolume(Frustum): near & right/bottom parallel ?!?\n"));
        return;
    }
    
    if(volume.getFar().intersectInfinite(lines[3], pnts[7]) == false)
    {
        FWARNING(("drawVolume(Frustum): far & right/bottom parallel ?!?\n"));
        return;
    }
    
    // got the points, draw them

    glBegin(GL_LINE_LOOP);
    glVertex3fv(pnts[0].getValues());
    glVertex3fv(pnts[1].getValues());
    glVertex3fv(pnts[3].getValues());
    glVertex3fv(pnts[2].getValues());
    glVertex3fv(pnts[6].getValues());
    glVertex3fv(pnts[7].getValues());
    glVertex3fv(pnts[5].getValues());
    glVertex3fv(pnts[4].getValues());
    glEnd();

    glBegin(GL_LINES);
    glVertex3fv(pnts[0].getValues());
    glVertex3fv(pnts[2].getValues());
    glVertex3fv(pnts[1].getValues());
    glVertex3fv(pnts[5].getValues());
    glVertex3fv(pnts[3].getValues());
    glVertex3fv(pnts[7].getValues());
    glVertex3fv(pnts[4].getValues());
    glVertex3fv(pnts[6].getValues());
    glEnd();

    return;
}
/*! Calculate the vertices (\a intVerts) and center (\a intCenter) of
    the intersection of \a fA and \a fB.
 */
void TrapezoidalShadowMapEngine::intersectFrusta(
    const FrustumVolume      &fA,       const FrustumVolume &fB,
          std::vector<Pnt3r> &intVerts,       Pnt3r         &intCenter)
{
    const Plane *planes[12];

    intVerts.clear  (  );
    intVerts.reserve(16);
  
    for(UInt32 i = 0; i < 6; ++i)
    {
        planes[i    ] = &(fA.getPlanes()[i]);
        planes[6 + i] = &(fB.getPlanes()[i]);
    }

    // take all combinations of 3 planes -- but avoid choosing planes
    // we know to be parallel (i.e. near and far of the same frustum), or
    // that are known to intersect outside the frustum (i.e top/bottom,
    // left/right).

    for(UInt32 i = 0; i < 12; ++i)
    {
        // choose initial value of j such that it avoids near and far of fA
        for(UInt32 j = osgMax<UInt32>(2, i + 1); j < 12; ++j)
        {
            // near/far are parallel,
            // left/right always intersect outside the frustum,
            // top/bottom always intersect outside the frustum
            if((i == 6 && j == 7) ||
               (i == 2 && j == 3) || (i ==  8 && j ==  9) ||
               (i == 4 && j == 5) || (i == 10 && j == 11)   )
                continue;

            Line intLine;
            if(planes[i]->intersect(*planes[j], intLine) == false)
                continue;

            for(UInt32 k = j + 1; k < 12; ++k)
            {
                // near/far are parallel,
                // left/right always intersect outside the frustum,
                // top/bottom always intersect outside the frustum
                if((j == 6 && k == 7) ||
                   (j == 2 && k == 3) || (j ==  8 && k ==  9) ||
                   (j == 4 && k == 5) || (j == 10 && k == 11)   )
                    continue;

                Pnt3r intPoint;
                if(planes[k]->intersectInfinite(intLine, intPoint) == false)
                    continue;

                bool intPointValid = true;

                // check the intersection point against all planes to ensure
                // it is in both frusta
                for(UInt32 m = 0; m < 12; ++m)
                {
                    // intPoint is the intersection of planes i, j, k, so
                    // we don't have to test against those
                    if(m == i || m == j || m == k)
                        continue;

                    if(planes[m]->isInHalfSpace(intPoint) == false)
                    {
                        intPointValid = false;
                        break;
                    }
                }

                if(intPointValid == true)
                {
                    intCenter += intPoint.subZero();
                    intVerts.push_back(intPoint);
                }
            }
        }
    }

    intCenter /= intVerts.size();
}
void TrapezoidalShadowMapEngine::handleSpotLightEnter(
    SpotLight *spotL, RenderAction *ract, TSMEngineData *data)
{
    RenderPartition *parentPart = ract->getActivePartition();

    Matrixr matEyeToWorld(parentPart->getCameraToWorld());
    Matrixr matWorldToLight;
    Matrixr matEyeToLight;

    Inherited::calcSpotLightMatrices(matWorldToLight, matEyeToLight,
                                     spotL,           matEyeToWorld );

    Matrixr matLightProj;
    Matrixr matLightFull(matWorldToLight);

    Real    shadowNear = (getShadowNear() != 0.f ? 
                          getShadowNear()       : 
                          parentPart->getNear()  );
    Real    shadowFar  = (getShadowFar () != 0.f ?
                          getShadowFar ()       :
                          parentPart->getFar()   );

    Inherited::calcPointLightRange(
        spotL, 0.01f,
        shadowNear, shadowFar, shadowNear, shadowFar);

    MatrixPerspective(matLightProj,
                      spotL->getSpotCutOff(), 1.f,
                      shadowNear, shadowFar       );

    matLightFull.multLeft(matLightProj);

    Inherited::updateShadowTexImage  (data);
    Inherited::updateShadowTexBuffers(data);
    Inherited::updateRenderTargets   (data);

    const FrustumVolume &eyeFrust   = parentPart->getFrustum();
          FrustumVolume  lightFrust;
          Matrixr        matNT;

    lightFrust.setPlanes(matLightFull);

    bool matNTValid = calcTrapezoidalTransform(matNT,
                                               matEyeToWorld, matLightFull,
                                               eyeFrust,      lightFrust   );

    if(matNTValid == false)
        return;

//    Real           cosSpotCutOff = osgCos(spotL->getSpotCutOff());

    Int32          shadowTexUnit = (this->getForceTextureUnit() >= 0) ?
                                    this->getForceTextureUnit()       : 7;
    ShaderProgram *shadowFP      = this->getShadowFragmentProgram();

    if(shadowFP == NULL)
    {
        ShaderProgramUnrecPtr newShadowFP = ShaderProgram::createLocal();
        newShadowFP->setShaderType(GL_FRAGMENT_SHADER);
        newShadowFP->setProgram   (_spotFPCode       );

        newShadowFP->addUniformVariable("TSME_matEyeToLight", matEyeToLight);
        newShadowFP->addUniformVariable("TSME_matLightProj",  matLightProj );
        newShadowFP->addUniformVariable("TSME_matNT",         matNT        );
        newShadowFP->addUniformVariable("TSME_texShadow",     shadowTexUnit);
        newShadowFP->addUniformVariable("TSME_texShadowSizeInv",
                                        Vec2f(1.f / getWidth (), 
                                              1.f / getHeight() )          );

        this->setShadowFragmentProgram(newShadowFP);
        shadowFP = newShadowFP;
    }
    else
    {
        shadowFP->updateUniformVariable("TSME_matEyeToLight", matEyeToLight);
        shadowFP->updateUniformVariable("TSME_matLightProj",  matLightProj );
        shadowFP->updateUniformVariable("TSME_matNT",         matNT        );
    }

    updateLightPassMaterial(data, 0, matNT);

    commitChanges();
    
    this->pushPartition(ract);
    {
        RenderPartition   *part   = ract->getActivePartition( );
        Window            *win    = ract->getWindow         ( );
        FrameBufferObject *target = data->getRenderTargets  (0);
        Background        *back   = data->getBackground     ( );

        part->setRenderTarget(target);
        part->setWindow      (win   );

        part->calcViewportDimension(0.f, 0.f, 1.f, 1.f,
                                    target->getWidth (),
                                    target->getHeight() );

        part->setupProjection(matLightProj, Matrixr::identity());
        part->setupViewing   (matWorldToLight                  );
        
        part->setNear        (parentPart->getNear());
        part->setFar         (parentPart->getFar ());

        part->setFrustum     (lightFrust           );

        part->setBackground  (back                 );

        part->overrideMaterial(data->getLightPassMaterials(0),
                               ract->getActNode           ( ) );

        this->recurseFrom(ract, spotL);
        ract->useNodeList(false      );

        part->overrideMaterial(NULL,
                               ract->getActNode           ( ) );
    }
    this->popPartition(ract);
}
void TrapezoidalShadowMapEngine::handlePointLightEnter(
    PointLight *pointL, RenderAction *ract, TSMEngineData *data)
{
    RenderPartition *parentPart = ract->getActivePartition();
    
    Matrixr matEyeToWorld(parentPart->getCameraToWorld());  
    Matrixr matLightProj;

    Real    shadowNear = (getShadowNear() != 0.f ? 
                          getShadowNear()       : 
                          parentPart->getNear()  );
    Real    shadowFar  = (getShadowFar () != 0.f ?
                          getShadowFar ()       :
                          parentPart->getFar()   );

    Inherited::calcPointLightRange(
        pointL, 0.01f,
        shadowNear, shadowFar, shadowNear, shadowFar);

    MatrixPerspective(matLightProj, Pi / 4.f, 1.f,
                      shadowNear, shadowFar       );
    
    Matrixr   matWorldToLight;
    Matrixr   matEyeToLight;
    MFMatrixr mfMatNT;

    mfMatNT.resize(6);

    Inherited::calcPointLightMatrices(matWorldToLight, matEyeToLight,
                                      pointL,          matEyeToWorld );

    Inherited::updatePointLightShadowTexImage  (data);
    Inherited::updatePointLightShadowTexBuffers(data);
    Inherited::updatePointLightRenderTargets   (data);

    Int32          shadowTexUnit = (this->getForceTextureUnit() >= 0) ?
                                    this->getForceTextureUnit()       : 7;
    ShaderProgram *shadowFP      = this->getShadowFragmentProgram();

    if(shadowFP == NULL)
    {
        ShaderProgramUnrecPtr newShadowFP = ShaderProgram::createLocal();
        newShadowFP->setShaderType(GL_FRAGMENT_SHADER);
        newShadowFP->setProgram   (_pointFPCode      );
        
        newShadowFP->addUniformVariable("TSME_matEyeToLight", matEyeToLight);
        newShadowFP->addUniformVariable("TSME_matLightProj",  matLightProj );
        newShadowFP->addUniformVariable("TSME_matNT",         mfMatNT      );
        newShadowFP->addUniformVariable("TSME_texShadow",     shadowTexUnit);
        newShadowFP->addUniformVariable("TSME_texShadowSizeInv",
                                        Vec2f(1.f / getWidth (), 
                                              1.f / getHeight() )          );
        
        this->setShadowFragmentProgram(newShadowFP);
        shadowFP = newShadowFP;
    }
    else
    {
        shadowFP->updateUniformVariable("TSME_matEyeToLight", matEyeToLight);
        shadowFP->updateUniformVariable("TSME_matLightProj",  matLightProj );
    }

    const FrustumVolume &eyeFrust = parentPart->getFrustum();

    for(UInt16 faceIdx = 0; faceIdx < 6; ++faceIdx)
    {
        Matrixr matWorldToLightFace (matWorldToLight         );
        matWorldToLightFace.multLeft(_matCubeFaceInv[faceIdx]);

        Matrixr matLightFull(matWorldToLightFace);
        matLightFull.multLeft(matLightProj);

        FrustumVolume lightFrust;
        Matrixr       matNT;

        lightFrust.setPlanes(matLightFull);

        bool matNTValid = 
            calcTrapezoidalTransform(mfMatNT[faceIdx],
                                     matEyeToWorld,    matLightFull,
                                     eyeFrust,         lightFrust   );

        if(matNTValid == false)
        {
            // setup a minimal partition to clear the cube face

            commitChanges();

            this->pushPartition(ract,
                                RenderPartition::CopyNothing,
                                RenderPartition::SimpleCallback);
            {
                RenderPartition   *part   = ract->getActivePartition(       );
                Window            *win    = ract->getWindow         (       );
                FrameBufferObject *target = data->getRenderTargets  (faceIdx);
                Background        *back   = data->getBackground     (       );

                part->setSetupMode(RenderPartition::ViewportSetup  |
                                   RenderPartition::BackgroundSetup );

                part->setRenderTarget(target);
                part->setWindow      (win   );

                part->calcViewportDimension(0.f, 0.f, 1.f, 1.f,
                                            target->getWidth (),
                                            target->getHeight() );
                
                part->setBackground(back);

                RenderPartition::SimpleDrawCallback emptyCubeFaceDraw =
                    boost::bind(
                        &TrapezoidalShadowMapEngine::emptyCubeFaceDrawFunc,
                        this, _1);

                part->dropFunctor(emptyCubeFaceDraw);
            }
            this->popPartition(ract);
        }
        else
        {
            updateLightPassMaterial(data, faceIdx, mfMatNT[faceIdx]);
        
            commitChanges();

            this->pushPartition(ract);
            {
                RenderPartition   *part   = ract->getActivePartition(       );
                Window            *win    = ract->getWindow         (       );
                FrameBufferObject *target = data->getRenderTargets  (faceIdx);
                Background        *back   = data->getBackground     (       );

                part->setRenderTarget(target);
                part->setWindow      (win   );

                part->calcViewportDimension(0.f, 0.f, 1.f, 1.f,
                                            target->getWidth (),
                                            target->getHeight() );

                part->setupProjection(matLightProj, Matrixr::identity());
                part->setupViewing   (matWorldToLightFace              );

                part->setNear        (parentPart->getNear());
                part->setFar         (parentPart->getFar ());
            
                part->setFrustum     (lightFrust           );
                
                part->setBackground  (back                 );

                part->overrideMaterial(data->getLightPassMaterials(faceIdx),
                                       ract->getActNode           (       ) );

                this->recurseFrom(ract, pointL);
                ract->useNodeList(false       );

                part->overrideMaterial(NULL,
                                       ract->getActNode           (       ) );
            }
            this->popPartition(ract);
        }
    }

    shadowFP->updateUniformVariable("TSME_matNT", mfMatNT);
}
bool Line::intersect(const FrustumVolume &frustum ,
                           Real          &enter   ,
                           Real          &exit    ) const
{
    const Real inf = 2u << 16;

    Pnt3r enter_point = _pos + _dir * 0.f;
    Pnt3r exit_point  = _pos + _dir * inf;

    face faces[6];

    const Plane *planes = frustum.getPlanes();

    Line lines[2];

    //ln[0] - intersection of right and top planes
    planes[3].intersect(planes[4], lines[0]); 

    //ln[1] - left and bottom
    planes[2].intersect(planes[5], lines[1]); 
    
    Pnt3r pointA;
    Pnt3r pointB;

    if(!planes[0].intersectInfinite(lines[0],pointA))
        std::cout << "This should never happen (A)!!!!";
                    
    if(!planes[1].intersectInfinite(lines[1],pointB))
        std::cout << "This should never happen (B)!!!!";

    faces[0].point        = pointA; 
    faces[0].inner_vector = pointB - pointA;

    faces[1].point        = pointB; 
    faces[1].inner_vector = pointA - pointB;

    faces[2].point        = pointB; 
    faces[2].inner_vector = pointA - pointB;

    faces[3].point        = pointA; 
    faces[3].inner_vector = pointB - pointA;

    faces[4].point        = pointA; 
    faces[4].inner_vector = pointB - pointA;

    faces[5].point        = pointB; 
    faces[5].inner_vector = pointA - pointB;

    for(Int32 i = 0; i < 6; i++)
    {
        faces[i].inner_normal=planes[i].getNormal();

        if(faces[i].inner_normal.dot(faces[i].inner_vector) < 0.f)
            faces[i].inner_normal=-faces[i].inner_normal;

        Vec3r test_enp = enter_point - faces[i].point;
        Vec3r test_exp = exit_point  - faces[i].point;

        Real value_enp = test_enp.dot(faces[i].inner_normal);
        Real value_exp = test_exp.dot(faces[i].inner_normal);

        if(value_enp < 0.f && value_exp < 0.f) 
            return false;

        if(value_enp > 0.f && value_exp < 0.f) 
            planes[i].intersect(*this, exit_point );

        if(value_enp < 0.f && value_exp > 0.f) 
            planes[i].intersect(*this, enter_point);
    }
    
    Real a;
    
    if((a = (enter_point - _pos).dot(_dir)) != 0.f)
    {
        enter = (enter_point - _pos).dot(enter_point - _pos) / a;
    }
    else 
    {
        enter = 0.f;
    }

    if((a = (exit_point  - _pos).dot(_dir)) != 0.f)
    {
        exit  = (exit_point  - _pos).dot(exit_point  - _pos) / a;
    }
    else
    {
        enter = 0.f;              
    }

    return true;
}