示例#1
0
文件: APE.cpp 项目: certik/nektar
void APE::v_ExtraFldOutput(
    std::vector<Array<OneD, NekDouble> > &fieldcoeffs,
    std::vector<std::string>             &variables)
{
    UpdateBasefield();

    const int nCoeffs = m_fields[0]->GetNcoeffs();

    for (int i = 0; i < m_spacedim + 2; i++)
    {
        variables.push_back(m_basefield_names[i]);

        Array<OneD, NekDouble> tmpFwd(nCoeffs);
        m_fields[0]->FwdTrans(m_basefield[i], tmpFwd);
        fieldcoeffs.push_back(tmpFwd);
    }
}
bool ProjectedShadow::_updateDecal( const SceneRenderState *state )
{
    PROFILE_SCOPE( ProjectedShadow_UpdateDecal );

    if ( !LIGHTMGR )
        return false;

    // Get the position of the decal first.
    const Box3F &objBox = mParentObject->getObjBox();
    const Point3F boxCenter = objBox.getCenter();
    Point3F decalPos = boxCenter;
    const MatrixF &renderTransform = mParentObject->getRenderTransform();
    {
        // Set up the decal position.
        // We use the object space box center
        // multiplied by the render transform
        // of the object to ensure we benefit
        // from interpolation.
        MatrixF t( renderTransform );
        t.setColumn(2,Point3F::UnitZ);
        t.mulP( decalPos );
    }

    if ( mDecalInstance )
    {
        mDecalInstance->mPosition = decalPos;
        if ( !shouldRender( state ) )
            return false;
    }

    // Get the sunlight for the shadow projection.
    // We want the LightManager to return NULL if it can't
    // get the "real" sun, so we specify false for the useDefault parameter.
    LightInfo *lights[4] = {0};
    LightQuery query;
    query.init( mParentObject->getWorldSphere() );
    query.getLights( lights, 4 );

    Point3F pos = renderTransform.getPosition();

    Point3F lightDir( 0, 0, 0 );
    Point3F tmp( 0, 0, 0 );
    F32 weight = 0;
    F32 range = 0;
    U32 lightCount = 0;
    F32 dist = 0;
    F32 fade = 0;
    for ( U32 i = 0; i < 4; i++ )
    {
        // If we got a NULL light,
        // we're at the end of the list.
        if ( !lights[i] )
            break;

        if ( !lights[i]->getCastShadows() )
            continue;

        if ( lights[i]->getType() != LightInfo::Point )
            tmp = lights[i]->getDirection();
        else
            tmp = pos - lights[i]->getPosition();

        range = lights[i]->getRange().x;
        dist = ( (tmp.lenSquared()) / ((range * range) * 0.5f));
        weight = mClampF( 1.0f - ( tmp.lenSquared() / (range * range)), 0.00001f, 1.0f );

        if ( lights[i]->getType() == LightInfo::Vector )
            fade = getMax( fade, 1.0f );
        else
            fade = getMax( fade, mClampF( 1.0f - dist, 0.00001f, 1.0f ) );

        lightDir += tmp * weight;
        lightCount++;
    }

    lightDir.normalize();

    // No light... no shadow.
    if ( !lights[0] )
        return false;

    // Has the light direction
    // changed since last update?
    bool lightDirChanged = !mLastLightDir.equal( lightDir );

    // Has the parent object moved
    // or scaled since the last update?
    bool hasMoved = !mLastObjectPosition.equal( mParentObject->getRenderPosition() );
    bool hasScaled = !mLastObjectScale.equal( mParentObject->getScale() );

    // Set the last light direction
    // to the current light direction.
    mLastLightDir = lightDir;
    mLastObjectPosition = mParentObject->getRenderPosition();
    mLastObjectScale = mParentObject->getScale();


    // Temps used to generate
    // tangent vector for DecalInstance below.
    VectorF right( 0, 0, 0 );
    VectorF fwd( 0, 0, 0 );
    VectorF tmpFwd( 0, 0, 0 );

    U32 idx = lightDir.getLeastComponentIndex();

    tmpFwd[idx] = 1.0f;

    right = mCross( tmpFwd, lightDir );
    fwd = mCross( lightDir, right );
    right = mCross( fwd, lightDir );

    right.normalize();

    // Set up the world to light space
    // matrix, along with proper position
    // and rotation to be used as the world
    // matrix for the render to texture later on.
    static MatrixF sRotMat(EulerF( 0.0f, -(M_PI_F/2.0f), 0.0f));
    mWorldToLight.identity();
    MathUtils::getMatrixFromForwardVector( lightDir, &mWorldToLight );
    mWorldToLight.setPosition( ( pos + boxCenter ) - ( ( (mRadius * smDepthAdjust) + 0.001f ) * lightDir ) );
    mWorldToLight.mul( sRotMat );
    mWorldToLight.inverse();

    // Get the shapebase datablock if we have one.
    ShapeBaseData *data = NULL;
    if ( mShapeBase )
        data = static_cast<ShapeBaseData*>( mShapeBase->getDataBlock() );

    // We use the object box's extents multiplied
    // by the object's scale divided by 2 for the radius
    // because the object's worldsphere radius is not
    // rotationally invariant.
    mRadius = (objBox.getExtents() * mParentObject->getScale()).len() * 0.5f;

    if ( data )
        mRadius *= data->shadowSphereAdjust;

    // Create the decal if we don't have one yet.
    if ( !mDecalInstance )
        mDecalInstance = gDecalManager->addDecal( decalPos,
                         lightDir,
                         right,
                         mDecalData,
                         1.0f,
                         0,
                         PermanentDecal | ClipDecal | CustomDecal );

    if ( !mDecalInstance )
        return false;

    mDecalInstance->mVisibility = fade;

    // Setup decal parameters.
    mDecalInstance->mSize = mRadius * 2.0f;
    mDecalInstance->mNormal = -lightDir;
    mDecalInstance->mTangent = -right;
    mDecalInstance->mRotAroundNormal = 0;
    mDecalInstance->mPosition = decalPos;
    mDecalInstance->mDataBlock = mDecalData;

    // If the position of the world
    // space box center is the same
    // as the decal's position, and
    // the light direction has not
    // changed, we don't need to clip.
    bool shouldClip = lightDirChanged || hasMoved || hasScaled;

    // Now, check and see if the object is visible.
    const Frustum &frust = state->getCullingFrustum();
    if ( frust.isCulled( SphereF( mDecalInstance->mPosition, mDecalInstance->mSize * mDecalInstance->mSize ) ) && !shouldClip )
        return false;

    F32 shadowLen = 10.0f;
    if ( data )
        shadowLen = data->shadowProjectionDistance;

    const Point3F &boxExtents = objBox.getExtents();


    mShadowLength = shadowLen * mParentObject->getScale().z;

    // Set up clip depth, and box half
    // offset for decal clipping.
    Point2F clipParams(  mShadowLength, (boxExtents.x + boxExtents.y) * 0.25f );

    bool render = false;
    bool clipSucceeded = true;

    // Clip!
    if ( shouldClip )
    {
        clipSucceeded = gDecalManager->clipDecal( mDecalInstance,
                        NULL,
                        &clipParams );
    }

    // If the clip failed,
    // we'll return false in
    // order to keep from
    // unnecessarily rendering
    // into the texture.  If
    // there was no reason to clip
    // on this update, we'll assume we
    // should update the texture.
    render = clipSucceeded;

    // Tell the DecalManager we've changed this decal.
    gDecalManager->notifyDecalModified( mDecalInstance );

    return render;
}