void SFXXAudioVoice::setCone( F32 innerAngle, F32 outerAngle, F32 outerVolume )
{
   // If the cone is set to 360 then the
   // cone is null and doesn't need to be
   // set on the voice.
   if ( mIsEqual( innerAngle, 360 ) )
   {
      SAFE_DELETE( mEmitter.pCone );
      return;
   }

   if ( !mEmitter.pCone )
   {
      mEmitter.pCone = new X3DAUDIO_CONE;

      // The inner volume is always 1... the overall
      // volume is what scales it.
      mEmitter.pCone->InnerVolume = 1.0f; 

      // We don't use these yet.
      mEmitter.pCone->InnerLPF = 0.0f; 
      mEmitter.pCone->OuterLPF = 0.0f; 
      mEmitter.pCone->InnerReverb = 0.0f; 
      mEmitter.pCone->OuterReverb = 0.0f; 
   }

   mEmitter.pCone->InnerAngle = mDegToRad( innerAngle );
   mEmitter.pCone->OuterAngle = mDegToRad( outerAngle );
   mEmitter.pCone->OuterVolume = outerVolume;
}
Exemplo n.º 2
0
void Point3NormalizeValidator::validateType(SimObject *object, void *typePtr)
{
    Point3F *v = (Point3F *) typePtr;
    const F32 len = v->len();
    if(!mIsEqual(len, 1.0f))
    {
        consoleError(object, "Vector length must be %g", length);
        *v *= length / len;
    }
}
Exemplo n.º 3
0
TEST(MatrixF, MultiplyImplmentations)
{
    F32 m1[16], m2[16], mrC[16];

    // I am not positive that the best way to do this is to use random numbers
    // but I think that using some kind of standard matrix may not always catch
    // all problems.
    for (S32 i = 0; i < 16; i++)
    {
        m1[i] = gRandGen.randF();
        m2[i] = gRandGen.randF();
    }

    // C will be the baseline
    default_matF_x_matF_C(m1, m2, mrC);

#if defined(WIN32) && defined(TORQUE_CPU_X86)
    // Check the CPU info
    U32 cpuProperties = Platform::SystemInfo.processor.properties;
    bool same;

    // Test 3D NOW! if it is available
    F32 mrAMD[16];
    if (cpuProperties & CPU_PROP_3DNOW)
    {
        Athlon_MatrixF_x_MatrixF(m1, m2, mrAMD);

        same = true;
        for (S32 i = 0; i < 16; i++)
            same &= mIsEqual(mrC[i], mrAMD[i]);

        EXPECT_TRUE(same) << "Matrix multiplication verification failed. (C vs. 3D NOW!)";
    }

    // Test SSE if it is available
    F32 mrSSE[16];
    if (cpuProperties & CPU_PROP_SSE)
    {
        SSE_MatrixF_x_MatrixF(m1, m2, mrSSE);

        same = true;
        for (S32 i = 0; i < 16; i++)
            same &= mIsEqual(mrC[i], mrSSE[i]);

        EXPECT_TRUE(same) << "Matrix multiplication verification failed. (C vs. SSE)";
    }

    same = true;
#endif

    // If Altivec exists, test it!
#if defined(__VEC__)
    bool same = false;
    F32 mrVEC[16];

    vec_MatrixF_x_MatrixF(m1, m2, mrVEC);

    for (S32 i = 0; i < 16; i++)
        same &= isEqual(mrC[i], mrVEC[i]);

    EXPECT_TRUE(same) << "Matrix multiplication verification failed. (C vs. Altivec)";
#endif
}
Exemplo n.º 4
0
void Forest::prepRenderImage( SceneRenderState *state )
{
    PROFILE_SCOPE(Forest_RenderCells);

    // TODO: Fix stats.
    /*
    ForestCellVector &theCells = mData->getCells();
    smTotalCells += theCells.size();

    // Don't render if we don't have a grid!
    if ( theCells.empty() )
       return false;
    */

    // Prepare to render.
    GFXTransformSaver saver;

    // Figure out the grid range in the viewing area.
    const bool isReflectPass = state->isReflectPass();

    const F32 cullScale = isReflectPass ? mReflectionLodScalar : 1.0f;

    // If we need to update our cached
    // zone state then do it now.
    if ( mZoningDirty )
    {
        mZoningDirty = false;

        Vector<ForestCell*> cells;
        mData->getCells(  &cells );
        for ( U32 i=0; i < cells.size(); i++ )
            cells[i]->_updateZoning( getSceneManager()->getZoneManager() );
    }

    // TODO: Move these into the TSForestItemData as something we
    // setup once and don't do per-instance.

    // Set up the TS render state.
    TSRenderState rdata;
    rdata.setSceneState( state );

    // Use origin sort on all forest elements as
    // its alot cheaper than the bounds sort.
    rdata.setOriginSort( true );

    // We may have some forward lit materials in
    // the forest, so pass down a LightQuery for it.
    LightQuery lightQuery;
    rdata.setLightQuery( &lightQuery );
    Frustum culler = state->getFrustum();

    // Adjust the far distance if the cull scale has changed.
    if ( !mIsEqual( cullScale, 1.0f ) )
    {
        const F32 visFarDist = culler.getFarDist() * cullScale;
        culler.setFarDist( visFarDist );
    }

    Box3F worldBox;

    // Used for debug drawing.
    GFXDrawUtil* drawer = GFX->getDrawUtil();
    drawer->clearBitmapModulation();

    // Go thru the visible cells.
    const Box3F &cullerBounds = culler.getBounds();
    const Point3F &camPos = state->getDiffuseCameraPosition();

    U32 clipMask;
    smAverageItemsPerCell = 0.0f;
    U32 cellsProcessed = 0;
    ForestCell *cell;

    // First get all the top level cells which
    // intersect the frustum.
    Vector<ForestCell*> cellStack;
    mData->getCells( culler, &cellStack );

    // Get the culling zone state.
    const BitVector &zoneState = state->getCullingState().getZoneVisibilityFlags();

    // Now loop till we run out of cells.
    while ( !cellStack.empty() )
    {
        // Pop off the next cell.
        cell = cellStack.last();
        cellStack.pop_back();

        const Box3F &cellBounds = cell->getBounds();

        // If the cell is empty or its bounds is outside the frustum
        // bounds then we have nothing nothing more to do.
        if ( cell->isEmpty() || !cullerBounds.isOverlapped( cellBounds ) )
            continue;

        // Can we cull this cell entirely?
        clipMask = culler.testPlanes( cellBounds, Frustum::PlaneMaskAll );
        if ( clipMask == -1 )
            continue;

        // Test cell visibility for interior zones.
        const bool visibleInside = !cell->getZoneOverlap().empty() ? zoneState.testAny( cell->getZoneOverlap() ) : false;

        // Test cell visibility for outdoor zone, but only
        // if we need to.
        bool visibleOutside = false;
        if( !cell->mIsInteriorOnly && !visibleInside )
        {
            U32 outdoorZone = SceneZoneSpaceManager::RootZoneId;
            visibleOutside = !state->getCullingState().isCulled( cellBounds, &outdoorZone, 1 );
        }

        // Skip cell if neither visible indoors nor outdoors.
        if( !visibleInside && !visibleOutside )
            continue;

        // Update the stats.
        smAverageItemsPerCell += cell->getItems().size();
        ++cellsProcessed;
        //if ( cell->isLeaf() )
        //++leafCellsProcessed;

        // Get the distance from the camera to the cell bounds.
        F32 dist = cellBounds.getDistanceToPoint( camPos );

        // If the largest item in the cell can be billboarded
        // at the cell distance to the camera... then the whole
        // cell can be billboarded.
        //
        if (  smForceImposters ||
                ( dist > 0.0f && cell->getLargestItem().canBillboard( state, dist ) ) )
        {
            // If imposters are disabled then skip out.
            if ( smDisableImposters )
                continue;

            PROFILE_SCOPE(Forest_RenderBatches);

            // Keep track of how many cells were batched.
            ++smCellsBatched;

            // Ok... everything in this cell should be batched.  First
            // create the batches if we don't have any.
            if ( !cell->hasBatches() )
                cell->buildBatches();

            //if ( drawCells )
            //mCellRenderFlag[ cellIter - theCells.begin() ] = 1;

            // TODO: Light queries for batches?

            // Now render the batches... we pass the culler if the
            // cell wasn't fully visible so that each batch can be culled.
            smCellItemsBatched += cell->renderBatches( state, clipMask != 0 ? &culler : NULL );
            continue;
        }

        // If this isn't a leaf then recurse.
        if ( !cell->isLeaf() )
        {
            cell->getChildren( &cellStack );
            continue;
        }

        // This cell has mixed billboards and mesh based items.
        ++smCellsRendered;

        PROFILE_SCOPE(Forest_RenderItems);

        //if ( drawCells )
        //mCellRenderFlag[ cellIter - theCells.begin() ] = 2;

        // Use the cell bounds as the light query volume.
        //
        // This means all forward lit items in this cell will
        // get the same lights, but it performs much better.
        lightQuery.init( cellBounds );

        // This cell is visible... have it render its items.
        smCellItemsRendered += cell->render( &rdata, clipMask != 0 ? &culler : NULL );
    }

    // Keep track of the average items per cell.
    if ( cellsProcessed > 0 )
        smAverageItemsPerCell /= (F32)cellsProcessed;

    // Got debug drawing to do?
    if ( smDrawCells && state->isDiffusePass() )
    {
        ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
        ri->renderDelegate.bind( this, &Forest::_renderCellBounds );
        ri->type = RenderPassManager::RIT_Editor;
        state->getRenderPass()->addInst( ri );
    }
}