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; }
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; } }
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 }
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 ); } }