F32 afxEase::eq(F32 t, F32 a, F32 b, F32 ein, F32 eout) { if (t == 0.0) return a; if (t == 1.0) return b; F32 ab = b - a; F32 ee = eout - ein + 1.0; // ease in section if (t <= ein) { F32 tin = t/ein; return a + (mSin(M_PI_F*(tin - 1.0)) + M_PI_F*tin)*ab*ein*(1.0/M_PI_F)/ee; } // middle linear section else if (t <= eout) { return a + ab*(2.0*t - ein)/ee; } // ease out section else { F32 iout = 1.0 - eout; F32 g = (t - eout)*M_PI_F/iout; return ((mSin(g) + g)*(iout)/M_PI_F + 2.0*eout - ein)*ab/ee + a; } }
F32 afxEase::t(F32 t, F32 ein, F32 eout) { if (t == 0.0) return 0.0; if (t == 1.0) return 1.0; F32 ee = eout - ein + 1.0; // ease in section if (t <= ein) { F32 tin = t/ein; return (mSin(M_PI_F*(tin - 1.0)) + M_PI_F*tin)*ein*(1.0/M_PI_F)/ee; } // middle linear section else if (t <= eout) { return (2.0*t - ein)/ee; } // ease out section else { F32 iout = 1.0 - eout; F32 g = (t - eout)*M_PI_F/iout; return ((mSin(g) + g)*(iout)/M_PI_F + 2.0*eout - ein)*1.0/ee + 0.0; } }
void PaintMaterialAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type) { S32 mat = mTerrainEditor->getPaintMaterialIndex(); if ( !selChanged || mat < 0 ) return; const bool slopeLimit = mTerrainEditor->mSlopeMinAngle > 0.0f || mTerrainEditor->mSlopeMaxAngle < 90.0f; const F32 minSlope = mSin( mDegToRad( 90.0f - mTerrainEditor->mSlopeMinAngle ) ); const F32 maxSlope = mSin( mDegToRad( 90.0f - mTerrainEditor->mSlopeMaxAngle ) ); const TerrainBlock *terrain = mTerrainEditor->getActiveTerrain(); const F32 squareSize = terrain->getSquareSize(); Point2F p; Point3F norm; for( U32 i = 0; i < sel->size(); i++ ) { GridInfo &inf = (*sel)[i]; if ( slopeLimit ) { p.x = inf.mGridPoint.gridPos.x * squareSize; p.y = inf.mGridPoint.gridPos.y * squareSize; if ( !terrain->getNormal( p, &norm, true ) ) continue; if ( norm.z > minSlope || norm.z < maxSlope ) continue; } // If grid is already set to our material, or it is an // empty grid spot, then skip painting. if ( inf.mMaterial == mat || inf.mMaterial == U8_MAX ) continue; if ( mRandF() > mTerrainEditor->getBrushPressure() ) continue; inf.mMaterialChanged = true; mTerrainEditor->getUndoSel()->add(inf); // Painting is really simple now... set the one mat index. inf.mMaterial = mat; mTerrainEditor->setGridInfo(inf, true); } mTerrainEditor->scheduleMaterialUpdate(); }
bool AITurretShape::onNewDataBlock(GameBaseData* dptr, bool reload) { mDataBlock = dynamic_cast<AITurretShapeData*>(dptr); if (!mDataBlock || !Parent::onNewDataBlock(dptr, reload)) return false; mScanHeading = mDegToRad(mDataBlock->maxScanHeading); if (mIsZero(mScanHeading)) mScanHeading = M_PI_F; mScanPitch = mDegToRad(mDataBlock->maxScanPitch); if (mIsZero(mScanPitch)) mScanPitch = M_PI_F; mScanDistance = mDataBlock->maxScanDistance; mScanDistanceSquared = mScanDistance * mScanDistance; mWeaponRangeSquared = mDataBlock->maxWeaponRange * mDataBlock->maxWeaponRange; mWeaponLeadVelocitySquared = (mDataBlock->weaponLeadVelocity > 0) ? (mDataBlock->weaponLeadVelocity * mDataBlock->weaponLeadVelocity) : 0; // The scan box is built such that the scanning origin is at (0,0,0) and the scanning distance // is out along the y axis. When this is transformed to the turret's location is provides a // scanning volume in front of the turret. F32 scanX = mScanDistance*mSin(mScanHeading); F32 scanY = mScanDistance; F32 scanZ = mScanDistance*mSin(mScanPitch); mScanBox.set(-scanX, 0, -scanZ, scanX, scanY, scanZ); mScanTickFrequency = mDataBlock->scanTickFrequency; if (mScanTickFrequency < 1) mScanTickFrequency = 1; mScanTickFrequencyVariance = mDataBlock->scanTickFrequencyVariance; if (mScanTickFrequencyVariance < 0) mScanTickFrequencyVariance = 0; mTicksToNextScan = mScanTickFrequency; // For states mStateAnimThread = 0; if (mDataBlock->isAnimated) { mStateAnimThread = mShapeInstance->addThread(); mShapeInstance->setTimeScale(mStateAnimThread,0); } scriptOnNewDataBlock(); return true; }
QuatF & QuatF::interpolate( const QuatF & q1, const QuatF & q2, F32 t ) { //----------------------------------- // Calculate the cosine of the angle: double cosOmega = q1.dot( q2 ); //----------------------------------- // adjust signs if necessary: F32 sign2; if ( cosOmega < 0.0 ) { cosOmega = -cosOmega; sign2 = -1.0f; } else sign2 = 1.0f; //----------------------------------- // calculate interpolating coeffs: double scale1, scale2; if ( (1.0 - cosOmega) > 0.00001 ) { // standard case double omega = mAcos(cosOmega); double sinOmega = mSin(omega); scale1 = mSin((1.0 - t) * omega) / sinOmega; scale2 = sign2 * mSin(t * omega) / sinOmega; } else { // if quats are very close, just do linear interpolation scale1 = 1.0 - t; scale2 = sign2 * t; } //----------------------------------- // actually do the interpolation: x = F32(scale1 * q1.x + scale2 * q2.x); y = F32(scale1 * q1.y + scale2 * q2.y); z = F32(scale1 * q1.z + scale2 * q2.z); w = F32(scale1 * q1.w + scale2 * q2.w); return *this; }
void ScatterSky::_generateSkyPoints() { U32 rings=60, segments=20;//rings=160, segments=20; Point3F tmpPoint( 0, 0, 0 ); // Establish constants used in sphere generation. F32 deltaRingAngle = ( M_PI_F / (F32)(rings * 2) ); F32 deltaSegAngle = ( 2.0f * M_PI_F / (F32)segments ); // Generate the group of rings for the sphere. for( int ring = 0; ring < 2; ring++ ) { F32 r0 = mSin( ring * deltaRingAngle ); F32 y0 = mCos( ring * deltaRingAngle ); // Generate the group of segments for the current ring. for( int seg = 0; seg < segments + 1 ; seg++ ) { F32 x0 = r0 * sinf( seg * deltaSegAngle ); F32 z0 = r0 * cosf( seg * deltaSegAngle ); tmpPoint.set( x0, z0, y0 ); tmpPoint.normalizeSafe(); tmpPoint.x *= smEarthRadius + smAtmosphereRadius; tmpPoint.y *= smEarthRadius + smAtmosphereRadius; tmpPoint.z *= smEarthRadius + smAtmosphereRadius; tmpPoint.z -= smEarthRadius; if ( ring == 1 ) mSkyPoints.push_back( tmpPoint ); } } }
GFXTextureObject* ShadowMapManager::getTapRotationTex() { if ( mTapRotationTex.isValid() ) return mTapRotationTex; mTapRotationTex.set( 64, 64, GFXFormatR8G8B8A8, &ShadowMapTexProfile, "ShadowMapManager::getTapRotationTex" ); GFXLockedRect *rect = mTapRotationTex.lock(); U8 *f = rect->bits; F32 angle; for( U32 i = 0; i < 64*64; i++, f += 4 ) { // We only pack the rotations into the red // and green channels... the rest are empty. angle = M_2PI_F * gRandGen.randF(); f[0] = U8_MAX * ( ( 1.0f + mSin( angle ) ) * 0.5f ); f[1] = U8_MAX * ( ( 1.0f + mCos( angle ) ) * 0.5f ); f[2] = 0; f[3] = 0; } mTapRotationTex.unlock(); return mTapRotationTex; }
void EditTSCtrl::calcOrthoCamOffset(F32 mousex, F32 mousey, U8 modifier) { F32 camScale = 0.01f; switch(mDisplayType) { case DisplayTypeTop: mOrthoCamTrans.x -= mousex * mOrthoFOV * camScale; mOrthoCamTrans.y += mousey * mOrthoFOV * camScale; break; case DisplayTypeBottom: mOrthoCamTrans.x -= mousex * mOrthoFOV * camScale; mOrthoCamTrans.y -= mousey * mOrthoFOV * camScale; break; case DisplayTypeFront: mOrthoCamTrans.x += mousex * mOrthoFOV * camScale; mOrthoCamTrans.z += mousey * mOrthoFOV * camScale; break; case DisplayTypeBack: mOrthoCamTrans.x -= mousex * mOrthoFOV * camScale; mOrthoCamTrans.z += mousey * mOrthoFOV * camScale; break; case DisplayTypeLeft: mOrthoCamTrans.y += mousex * mOrthoFOV * camScale; mOrthoCamTrans.z += mousey * mOrthoFOV * camScale; break; case DisplayTypeRight: mOrthoCamTrans.y -= mousex * mOrthoFOV * camScale; mOrthoCamTrans.z += mousey * mOrthoFOV * camScale; break; case DisplayTypeIsometric: if(modifier & SI_PRIMARY_CTRL) { // NOTE: Maybe move the center of rotation code to right mouse down to avoid compound errors? F32 rot = mDegToRad(mousex); Point3F campos = (mRawCamPos + mOrthoCamTrans) - mIsoCamRotCenter; MatrixF mat(EulerF(0, 0, rot)); mat.mulP(campos); mOrthoCamTrans = (campos + mIsoCamRotCenter) - mRawCamPos; mIsoCamRot.z += rot; } else { mOrthoCamTrans.x -= mousex * mOrthoFOV * camScale * mCos(mIsoCamRot.z) - mousey * mOrthoFOV * camScale * mSin(mIsoCamRot.z); mOrthoCamTrans.y += mousex * mOrthoFOV * camScale * mSin(mIsoCamRot.z) + mousey * mOrthoFOV * camScale * mCos(mIsoCamRot.z); } break; } }
//-------------------------------------------------------------------------- // Get wave offset for texture animations using a wave transform //-------------------------------------------------------------------------- F32 ProcessedShaderMaterial::_getWaveOffset( U32 stage ) { switch( mMaterial->mWaveType[stage] ) { case Material::Sin: { return mMaterial->mWaveAmp[stage] * mSin( M_2PI * mMaterial->mWavePos[stage] ); break; } case Material::Triangle: { F32 frac = mMaterial->mWavePos[stage] - mFloor( mMaterial->mWavePos[stage] ); if( frac > 0.0 && frac <= 0.25 ) { return mMaterial->mWaveAmp[stage] * frac * 4.0; } if( frac > 0.25 && frac <= 0.5 ) { return mMaterial->mWaveAmp[stage] * ( 1.0 - ((frac-0.25)*4.0) ); } if( frac > 0.5 && frac <= 0.75 ) { return mMaterial->mWaveAmp[stage] * (frac-0.5) * -4.0; } if( frac > 0.75 && frac <= 1.0 ) { return -mMaterial->mWaveAmp[stage] * ( 1.0 - ((frac-0.75)*4.0) ); } break; } case Material::Square: { F32 frac = mMaterial->mWavePos[stage] - mFloor( mMaterial->mWavePos[stage] ); if( frac > 0.0 && frac <= 0.5 ) { return 0.0; } else { return mMaterial->mWaveAmp[stage]; } break; } } return 0.0; }
void AdvancedLightBinManager::setupSGData( SceneData &data, const SceneRenderState* state, LightInfo *light ) { PROFILE_SCOPE( AdvancedLightBinManager_setupSGData ); data.lights[0] = light; data.ambientLightColor = state->getAmbientLightColor(); data.objTrans = &MatrixF::Identity; if ( light ) { if ( light->getType() == LightInfo::Point ) { // The point light volume gets some flat spots along // the perimiter mostly visible in the constant and // quadradic falloff modes. // // To account for them slightly increase the scale // instead of greatly increasing the polycount. mLightMat = light->getTransform(); mLightMat.scale( light->getRange() * 1.01f ); data.objTrans = &mLightMat; } else if ( light->getType() == LightInfo::Spot ) { mLightMat = light->getTransform(); // Rotate it to face down the -y axis. MatrixF scaleRotateTranslate( EulerF( M_PI_F / -2.0f, 0.0f, 0.0f ) ); // Calculate the radius based on the range and angle. F32 range = light->getRange().x; F32 radius = range * mSin( mDegToRad( light->getOuterConeAngle() ) * 0.5f ); // NOTE: This fudge makes the cone a little bigger // to remove the facet egde of the cone geometry. radius *= 1.1f; // Use the scale to distort the cone to // match our radius and range. scaleRotateTranslate.scale( Point3F( radius, radius, range ) ); // Apply the transform and set the position. mLightMat *= scaleRotateTranslate; mLightMat.setPosition( light->getPosition() ); data.objTrans = &mLightMat; } } }
QuatF & QuatF::extrapolate( const QuatF & q1, const QuatF & q2, F32 t ) { // assert t >= 0 && t <= 1 // q1 is value at time = 0 // q2 is value at time = t // Computes quaternion at time = 1 F64 flip,cos = q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w; if (cos < 0.0) { cos = -cos; flip = -1.0; } else flip = 1.0; F64 s1,s2; if ((1.0 - cos) > 0.00001) { F64 om = mAcos(cos) / t; F64 sd = 1.0 / mSin(t * om); s1 = flip * mSin(om) * sd; s2 = mSin((1.0 - t) * om) * sd; } else { // If quats are very close, do linear interpolation s1 = flip / t; s2 = (1.0 - t) / t; } x = F32(s1 * q2.x - s2 * q1.x); y = F32(s1 * q2.y - s2 * q1.y); z = F32(s1 * q2.z - s2 * q1.z); w = F32(s1 * q2.w - s2 * q1.w); return *this; }
bool OculusVRDevice::process() { if(!mEnabled) return false; if(!getActive()) return false; //Build the maximum axis angle to be passed into the sensor process() F32 maxAxisRadius = mSin(mDegToRad(smMaximumAxisAngle)); // Process each sensor for(U32 i=0; i<mSensorDevices.size(); ++i) { mSensorDevices[i]->process(mDeviceType, smGenerateAngleAxisRotationEvents, smGenerateEulerRotationEvents, smGenerateRotationAsAxisEvents, maxAxisRadius); } return true; }
void Item::registerLights(LightManager * lightManager, bool lightingScene) { if(lightingScene) return; if(mDataBlock->lightOnlyStatic && !mStatic) return; F32 intensity; switch(mDataBlock->lightType) { case ConstantLight: intensity = mFadeVal; break; case PulsingLight: { S32 delta = Sim::getCurrentTime() - mDropTime; intensity = 0.5f + 0.5f * mSin(M_PI_F * F32(delta) / F32(mDataBlock->lightTime)); intensity = 0.15f + intensity * 0.85f; intensity *= mFadeVal; // fade out light on flags break; } default: return; } // Create a light if needed if (!mLight) { mLight = lightManager->createLightInfo(); } mLight->setColor( mDataBlock->lightColor * intensity ); mLight->setType( LightInfo::Point ); mLight->setRange( mDataBlock->lightRadius ); mLight->setPosition( getBoxCenter() ); lightManager->registerGlobalLight( mLight, this ); }
void ForestWindMgr::updateWind( const Point3F &camPos, const TreePlacementInfo &info, F32 timeDelta ) { PROFILE_SCOPE(ForestWindMgr_updateWind); // See if we have the blended source available. ForestWindAccumulator *blendDest = NULL; { IdToWindMap::Iterator iter = mPrevSources->find( info.itemKey ); if ( iter != mPrevSources->end() ) { blendDest = iter->value; mPrevSources->erase( iter ); } } // Get some stuff we'll need for finding the emitters. F32 treeHeight = info.scale * info.dataBlock->getObjBox().len_z(); Point3F top = info.pos; top.z += treeHeight; if ( blendDest ) top += ( 1.0f / info.scale ) * blendDest->getDirection(); // Go thru the emitters to accumulate the total wind force. VectorF windForce( 0, 0, 0 ); F32 time = Sim::getCurrentTime() / 1000.0f; ForestWindEmitterList::iterator iter = mEmitters.begin(); for ( ; iter != mEmitters.end(); iter++ ) { ForestWindEmitter *emitter = (*iter); // If disabled or no wind object... skip it. if ( !emitter->isEnabled() || !emitter->getWind() ) continue; ForestWind *wind = emitter->getWind(); F32 strength = wind->getStrength(); if ( emitter->isRadialEmitter() ) { Point3F closest = MathUtils::mClosestPointOnSegment( info.pos, top, emitter->getPosition() ); Point3F dir = closest - emitter->getPosition(); F32 lenSquared = dir.lenSquared(); if ( lenSquared > emitter->getWindRadiusSquared() ) continue; dir *= 1.0f / mSqrt( lenSquared ); F32 att = lenSquared / emitter->getWindRadiusSquared(); strength *= 1.0f - att; windForce += dir * strength; } else { F32 d = mDot( info.pos, Point3F::One ); //PlaneF( Point3F::Zero, wind->getDirection() ).distToPlane( Point3F( info.pos.x, info.pos.y, 0 ) ); //F32 d = PlaneF( Point3F::Zero, wind->getDirection() ).distToPlane( Point3F( info.pos.x, info.pos.y, 0 ) ); F32 scale = 1.0f + ( mSin( d + ( time / 10.0 ) ) * 0.5f ); windForce += wind->getDirection() * strength * scale; } } // If we need a accumulator then we also need to presimulate. if ( !blendDest ) { blendDest = new ForestWindAccumulator( info ); blendDest->presimulate( windForce, 4.0f / TickSec ); } else blendDest->updateWind( windForce, timeDelta ); mSources->insertUnique( info.itemKey, blendDest ); }
bool LeapMotionDevice::process() { if(!mEnabled) return false; if(!getActive()) return false; //Con::printf("LeapMotionDevice::process()"); //Build the maximum hand axis angle to be passed into the LeapMotionDeviceData::setData() F32 maxHandAxisRadius = mSin(mDegToRad(smMaximumHandAxisAngle)); // Get a frame of data const Leap::Frame frame = mController->frame(); //const Leap::HandList hands = frame.hands(); //Con::printf("Frame: %lld Hands: %d Fingers: %d Tools: %d", (long long)frame.id(), hands.count(), frame.fingers().count(), frame.tools().count()); // Store the current data LeapMotionDeviceData* currentBuffer = (mPrevData == mDataBuffer[0]) ? mDataBuffer[1] : mDataBuffer[0]; currentBuffer->setData(frame, mPrevData, smKeepHandIndexPersistent, smKeepPointableIndexPersistent, maxHandAxisRadius); U32 diff = mPrevData->compare(currentBuffer); U32 metaDiff = mPrevData->compareMeta(currentBuffer); // Update the previous data pointers. We do this here in case someone calls our // console functions during one of the input events below. mPrevData = currentBuffer; // Send out any meta data if(metaDiff & LeapMotionDeviceData::METADIFF_FRAME_VALID_DATA) { // Frame valid change event INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_BUTTON, LM_FRAMEVALIDDATA, currentBuffer->mHasTrackingData ? SI_MAKE : SI_BREAK, currentBuffer->mHasTrackingData ? 1.0f : 0.0f); } // Send out any valid data if(currentBuffer->mDataSet && currentBuffer->mIsValid) { // Hands and their pointables if(smGenerateIndividualEvents) { for(U32 i=0; i<LeapMotionConstants::MaxHands; ++i) { if(currentBuffer->mHandValid[i]) { // Send out position INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_POS, LM_HAND[i], SI_MOVE, currentBuffer->mHandPosPoint[i]); // Send out rotation INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_ROT, LM_HANDROT[i], SI_MOVE, currentBuffer->mHandRotQuat[i]); // Pointables for hand for(U32 j=0; j<LeapMotionConstants::MaxPointablesPerHand; ++j) { if(currentBuffer->mPointableValid[i][j]) { // Send out position INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_POS, LM_HANDPOINTABLE[i][j], SI_MOVE, currentBuffer->mPointablePosPoint[i][j]); // Send out rotation INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_ROT, LM_HANDPOINTABLEROT[i][j], SI_MOVE, currentBuffer->mPointableRotQuat[i][j]); } } } } } // Single Hand as axis rotation if(smGenerateSingleHandRotationAsAxisEvents && diff & LeapMotionDeviceData::DIFF_HANDROTAXIS) { if(diff & LeapMotionDeviceData::DIFF_HANDROTAXISX) INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_AXIS, LM_HANDAXISX, SI_MOVE, currentBuffer->mHandRotAxis[0]); if(diff & LeapMotionDeviceData::DIFF_HANDROTAXISY) INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_AXIS, LM_HANDAXISY, SI_MOVE, currentBuffer->mHandRotAxis[1]); } } // Send out whole frame event, but only if the special frame group is defined if(smGenerateWholeFrameEvents && LeapMotionFrameStore::isFrameGroupDefined()) { S32 id = LEAPMOTIONFS->generateNewFrame(frame, maxHandAxisRadius); if(id != 0) { INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_INT, LM_FRAME, SI_VALUE, id); } } return true; }
static void m_sincosD_C( F64 angle, F64 *s, F64 *c ) { *s = mSin( angle ); *c = mCos( angle ); }
//-------------------------------------- static void m_sincos_C( F32 angle, F32 *s, F32 *c ) { *s = mSin( angle ); *c = mCos( angle ); }
//----------------------------------------------------------------------------- void CameraSpline::value(F32 t, CameraSpline::Knot *result, bool skip_rotation) { // Do some easing in and out for t. if(!gBuilding) { F32 oldT = t; if(oldT < 0.5f) { t = 0.5f - (mSin( (0.5 - oldT) * M_PI ) / 2.f); } if((F32(size()) - 1.5f) > 0.f && oldT - (F32(size()) - 1.5f) > 0.f) { oldT -= (F32(size()) - 1.5f); t = (F32(size()) - 1.5f) + (mCos( (0.5f - oldT) * F32(M_PI) ) / 2.f); } } // Verify that t is in range [0 >= t > size] // AssertFatal(t >= 0.0f && t < (F32)size(), "t out of range"); Knot *p1 = getKnot((S32)mFloor(t)); Knot *p2 = next(p1); F32 i = t - mFloor(t); // adjust t to 0 to 1 on p1-p2 interval if (p1->mPath == Knot::SPLINE) { Knot *p0 = (p1->mType == Knot::KINK) ? p1 : prev(p1); Knot *p3 = (p2->mType == Knot::KINK) ? p2 : next(p2); result->mPosition.x = mCatmullrom(i, p0->mPosition.x, p1->mPosition.x, p2->mPosition.x, p3->mPosition.x); result->mPosition.y = mCatmullrom(i, p0->mPosition.y, p1->mPosition.y, p2->mPosition.y, p3->mPosition.y); result->mPosition.z = mCatmullrom(i, p0->mPosition.z, p1->mPosition.z, p2->mPosition.z, p3->mPosition.z); } else { // Linear result->mPosition.interpolate(p1->mPosition, p2->mPosition, i); } if (skip_rotation) return; buildTimeMap(); // find the two knots to interpolate rotation and velocity through since some // knots are only positional S32 start = (S32)mFloor(t); S32 end = (p2 == p1) ? start : (start + 1); while (p1->mType == Knot::POSITION_ONLY && p1 != front()) { p1 = prev(p1); start--; } while (p2->mType == Knot::POSITION_ONLY && p2 != back()) { p2 = next(p2); end++; } if (start == end) { result->mRotation = p1->mRotation; result->mSpeed = p1->mSpeed; } else { F32 c = getDistance(t); F32 d1 = getDistance((F32)start); F32 d2 = getDistance((F32)end); if (d1 == d2) { result->mRotation = p2->mRotation; result->mSpeed = p2->mSpeed; } else { i = (c-d1)/(d2-d1); if(p1->mPath == Knot::SPLINE) { Knot *p0 = (p1->mType == Knot::KINK) ? p1 : prev(p1); Knot *p3 = (p2->mType == Knot::KINK) ? p2 : next(p2); F32 q,w,e; q = mCatmullrom(i, 0, 1, 1, 1); w = mCatmullrom(i, 0, 0, 0, 1); e = mCatmullrom(i, 0, 0, 1, 1); QuatF a; a.interpolate(p0->mRotation, p1->mRotation, q); QuatF b; b.interpolate(p2->mRotation, p3->mRotation, w); result->mRotation.interpolate(a, b, e); result->mSpeed = mCatmullrom(i, p0->mSpeed, p1->mSpeed, p2->mSpeed, p3->mSpeed); } else { result->mRotation.interpolate(p1->mRotation, p2->mRotation, i); result->mSpeed = (p1->mSpeed * (1.0f-i)) + (p2->mSpeed * i); } } } }
void afxZodiacTerrainRenderer::render(SceneRenderState* state) { PROFILE_SCOPE(afxRenderZodiacTerrainMgr_render); // Early out if no terrain zodiacs to draw. if (terrain_zodes.size() == 0) return; initShader(); if (!zodiac_shader) return; bool is_reflect_pass = state->isReflectPass(); // Automagically save & restore our viewport and transforms. GFXTransformSaver saver; MatrixF proj = GFX->getProjectionMatrix(); // Set up world transform MatrixF world = GFX->getWorldMatrix(); proj.mul(world); shader_consts->set(projection_sc, proj); //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~// // RENDER EACH ZODIAC // for (S32 zz = 0; zz < terrain_zodes.size(); zz++) { TerrainZodiacElem& elem = terrain_zodes[zz]; TerrainBlock* block = (TerrainBlock*) elem.block; afxZodiacMgr::ZodiacSpec* zode = &afxZodiacMgr::terr_zodes[elem.zode_idx]; if (!zode) continue; if (is_reflect_pass) { if ((zode->zflags & afxZodiacData::SHOW_IN_REFLECTIONS) == 0) continue; } else { if ((zode->zflags & afxZodiacData::SHOW_IN_NON_REFLECTIONS) == 0) continue; } F32 fadebias = zode->calcDistanceFadeBias(elem.camDist); if (fadebias < 0.01f) continue; F32 cos_ang = mCos(elem.ang); F32 sin_ang = mSin(elem.ang); GFXStateBlock* sb = chooseStateBlock(zode->zflags & afxZodiacData::BLEND_MASK, is_reflect_pass); GFX->setShader(zodiac_shader->getShader()); GFX->setStateBlock(sb); GFX->setShaderConstBuffer(shader_consts); // set the texture GFX->setTexture(0, *zode->txr); ColorF zode_color = (ColorF)zode->color; zode_color.alpha *= fadebias; shader_consts->set(color_sc, zode_color); Point3F half_size(zode->radius_xy,zode->radius_xy,zode->radius_xy); F32 inv_radius = 1.0f/zode->radius_xy; GFXPrimitive cell_prim; GFXVertexBufferHandle<TerrVertex> cell_verts; GFXPrimitiveBufferHandle primBuff; elem.cell->getRenderPrimitive(&cell_prim, &cell_verts, &primBuff); U32 n_nonskirt_tris = TerrCellSpy::getMinCellSize()*TerrCellSpy::getMinCellSize()*2; const Point3F* verts = ((TerrCell*)elem.cell)->getZodiacVertexBuffer(); const U16 *tris = block->getZodiacPrimitiveBuffer(); if (!tris) continue; PrimBuild::begin(GFXTriangleList, 3*n_nonskirt_tris); ///////////////////////////////// U32 n_overlapping_tris = 0; U32 idx = 0; for (U32 i = 0; i < n_nonskirt_tris; i++) { Point3F tri_v[3]; tri_v[0] = verts[tris[idx++]]; tri_v[1] = verts[tris[idx++]]; tri_v[2] = verts[tris[idx++]]; elem.mRenderObjToWorld.mulP(tri_v[0]); elem.mRenderObjToWorld.mulP(tri_v[1]); elem.mRenderObjToWorld.mulP(tri_v[2]); if (!afxTriBoxOverlap2D(zode->pos, half_size, tri_v[0], tri_v[1], tri_v[2])) continue; n_overlapping_tris++; for (U32 j = 0; j < 3; j++) { // compute UV F32 u1 = (tri_v[j].x - zode->pos.x)*inv_radius; F32 v1 = (tri_v[j].y - zode->pos.y)*inv_radius; F32 ru1 = u1*cos_ang - v1*sin_ang; F32 rv1 = u1*sin_ang + v1*cos_ang; F32 uu = (ru1 + 1.0f)/2.0f; F32 vv = 1.0f - (rv1 + 1.0f)/2.0f; PrimBuild::texCoord2f(uu, vv); PrimBuild::vertex3fv(tri_v[j]); } } ///////////////////////////////// PrimBuild::end(false); } // // RENDER EACH ZODIAC //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~// }
void WaterObject::setShaderParams( SceneRenderState *state, BaseMatInstance *mat, const WaterMatParams ¶mHandles ) { MaterialParameters* matParams = mat->getMaterialParameters(); matParams->setSafe( paramHandles.mElapsedTimeSC, (F32)Sim::getCurrentTime() / 1000.0f ); // set vertex shader constants //----------------------------------- Point2F reflectTexSize( mPlaneReflector.reflectTex.getWidth(), mPlaneReflector.reflectTex.getHeight() ); matParams->setSafe( paramHandles.mReflectTexSizeSC, reflectTexSize ); static AlignedArray<Point2F> mConstArray( MAX_WAVES, sizeof( Point4F ) ); // Ripples... for ( U32 i = 0; i < MAX_WAVES; i++ ) mConstArray[i].set( -mRippleDir[i].x, -mRippleDir[i].y ); matParams->setSafe( paramHandles.mRippleDirSC, mConstArray ); Point3F rippleSpeed( mRippleSpeed[0], mRippleSpeed[1], mRippleSpeed[2] ); matParams->setSafe( paramHandles.mRippleSpeedSC, rippleSpeed ); Point4F rippleMagnitude( mRippleMagnitude[0], mRippleMagnitude[1], mRippleMagnitude[2], mOverallRippleMagnitude ); matParams->setSafe( paramHandles.mRippleMagnitudeSC, rippleMagnitude ); for ( U32 i = 0; i < MAX_WAVES; i++ ) { Point2F texScale = mRippleTexScale[i]; if ( texScale.x > 0.0 ) texScale.x = 1.0 / texScale.x; if ( texScale.y > 0.0 ) texScale.y = 1.0 / texScale.y; mConstArray[i].set( texScale.x, texScale.y ); } matParams->setSafe(paramHandles.mRippleTexScaleSC, mConstArray); static AlignedArray<Point4F> mConstArray4F( 3, sizeof( Point4F ) ); F32 angle, cosine, sine; for ( U32 i = 0; i < MAX_WAVES; i++ ) { angle = mAtan2( mRippleDir[i].x, -mRippleDir[i].y ); cosine = mCos( angle ); sine = mSin( angle ); mConstArray4F[i].set( cosine, sine, -sine, cosine ); matParams->setSafe( paramHandles.mRippleMatSC, mConstArray4F ); } // Waves... for ( U32 i = 0; i < MAX_WAVES; i++ ) mConstArray[i].set( -mWaveDir[i].x, -mWaveDir[i].y ); matParams->setSafe( paramHandles.mWaveDirSC, mConstArray ); for ( U32 i = 0; i < MAX_WAVES; i++ ) mConstArray[i].set( mWaveSpeed[i], mWaveMagnitude[i] * mOverallWaveMagnitude ); matParams->setSafe( paramHandles.mWaveDataSC, mConstArray ); // Foam... Point4F foamDir( mFoamDir[0].x, mFoamDir[0].y, mFoamDir[1].x, mFoamDir[1].y ); matParams->setSafe( paramHandles.mFoamDirSC, foamDir ); Point2F foamSpeed( mFoamSpeed[0], mFoamSpeed[1] ); matParams->setSafe( paramHandles.mFoamSpeedSC, foamSpeed ); //Point3F rippleMagnitude( mRippleMagnitude[0] * mOverallRippleMagnitude, // mRippleMagnitude[1] * mOverallRippleMagnitude, // mRippleMagnitude[2] * mOverallRippleMagnitude ); //matParams->setSafe( paramHandles.mRippleMagnitudeSC, rippleMagnitude ); Point4F foamTexScale( mFoamTexScale[0].x, mFoamTexScale[0].y, mFoamTexScale[1].x, mFoamTexScale[1].y ); for ( U32 i = 0; i < 4; i++ ) { if ( foamTexScale[i] > 0.0f ) foamTexScale[i] = 1.0 / foamTexScale[i]; } matParams->setSafe(paramHandles.mFoamTexScaleSC, foamTexScale); // Other vert params... matParams->setSafe( paramHandles.mUndulateMaxDistSC, mUndulateMaxDist ); // set pixel shader constants //----------------------------------- Point2F fogParams( mWaterFogData.density, mWaterFogData.densityOffset ); matParams->setSafe(paramHandles.mFogParamsSC, fogParams ); matParams->setSafe(paramHandles.mFarPlaneDistSC, (F32)state->getFarPlane() ); Point2F wetnessParams( mWaterFogData.wetDepth, mWaterFogData.wetDarkening ); matParams->setSafe(paramHandles.mWetnessParamsSC, wetnessParams ); Point3F distortionParams( mDistortStartDist, mDistortEndDist, mDistortFullDepth ); matParams->setSafe(paramHandles.mDistortionParamsSC, distortionParams ); LightInfo *sun = LIGHTMGR->getSpecialLight(LightManager::slSunLightType); const ColorF &sunlight = state->getAmbientLightColor(); Point3F ambientColor = mEmissive ? Point3F::One : sunlight; matParams->setSafe(paramHandles.mAmbientColorSC, ambientColor ); matParams->setSafe(paramHandles.mLightDirSC, sun->getDirection() ); Point4F foamParams( mOverallFoamOpacity, mFoamMaxDepth, mFoamAmbientLerp, mFoamRippleInfluence ); matParams->setSafe(paramHandles.mFoamParamsSC, foamParams ); Point4F miscParams( mFresnelBias, mFresnelPower, mClarity, mMiscParamW ); matParams->setSafe( paramHandles.mMiscParamsSC, miscParams ); Point4F specularParams( mSpecularColor.red, mSpecularColor.green, mSpecularColor.blue, mSpecularPower ); if ( !mEmissive ) { const ColorF &sunColor = sun->getColor(); F32 brightness = sun->getBrightness(); specularParams.x *= sunColor.red * brightness; specularParams.y *= sunColor.green * brightness; specularParams.z *= sunColor.blue * brightness; } matParams->setSafe( paramHandles.mSpecularParamsSC, specularParams ); matParams->setSafe( paramHandles.mDepthGradMaxSC, mDepthGradientMax ); matParams->setSafe( paramHandles.mReflectivitySC, mReflectivity ); }
void fxShapeReplicator::CreateShapes(void) { F32 HypX, HypY; F32 Angle; U32 RelocationRetry; Point3F ShapePosition; Point3F ShapeStart; Point3F ShapeEnd; Point3F ShapeScale; EulerF ShapeRotation; QuatF QRotation; bool CollisionResult; RayInfo RayEvent; TSShape* pShape; // Don't create shapes if we are hiding replications. if (mFieldData.mHideReplications) return; // Cannot continue without shapes! if (dStrcmp(mFieldData.mShapeFile, "") == 0) return; // Check that we can position somewhere! if (!( mFieldData.mAllowOnTerrain || mFieldData.mAllowStatics || mFieldData.mAllowOnWater)) { // Problem ... Con::warnf(ConsoleLogEntry::General, "[%s] - Could not place object, All alloweds are off!", getName()); // Return here. return; } // Check Shapes. AssertFatal(mCurrentShapeCount==0,"Shapes already present, this should not be possible!") // Check that we have a shape... if (!mFieldData.mShapeFile) return; // Set Seed. RandomGen.setSeed(mFieldData.mSeed); // Set shape vector. mReplicatedShapes.clear(); // Add shapes. for (U32 idx = 0; idx < mFieldData.mShapeCount; idx++) { fxShapeReplicatedStatic* fxStatic; // Create our static shape. fxStatic = new fxShapeReplicatedStatic(); // Set the 'shapeName' field. fxStatic->setField("shapeName", mFieldData.mShapeFile); // Is this Replicator on the Server? if (isServerObject()) // Yes, so stop it from Ghosting. (Hack, Hack, Hack!) fxStatic->touchNetFlags(Ghostable, false); else // No, so flag as ghost object. (Another damn Hack!) fxStatic->touchNetFlags(IsGhost, true); // Register the Object. if (!fxStatic->registerObject()) { // Problem ... Con::warnf(ConsoleLogEntry::General, "[%s] - Could not load shape file '%s'!", getName(), mFieldData.mShapeFile); // Destroy Shape. delete fxStatic; // Destroy existing hapes. DestroyShapes(); // Quit. return; } // Get Allocated Shape. pShape = fxStatic->getShape(); // Reset Relocation Retry. RelocationRetry = mFieldData.mShapeRetries; // Find it a home ... do { // Get the Replicator Position. ShapePosition = getPosition(); // Calculate a random offset HypX = RandomGen.randF(mFieldData.mInnerRadiusX, mFieldData.mOuterRadiusX); HypY = RandomGen.randF(mFieldData.mInnerRadiusY, mFieldData.mOuterRadiusY); Angle = RandomGen.randF(0, (F32)M_2PI); // Calcualte the new position. ShapePosition.x += HypX * mCos(Angle); ShapePosition.y += HypY * mSin(Angle); // Initialise RayCast Search Start/End Positions. ShapeStart = ShapeEnd = ShapePosition; ShapeStart.z = 2000.f; ShapeEnd.z= -2000.f; // Is this the Server? if (isServerObject()) // Perform Ray Cast Collision on Server Terrain. CollisionResult = gServerContainer.castRay(ShapeStart, ShapeEnd, FXREPLICATOR_COLLISION_MASK, &RayEvent); else // Perform Ray Cast Collision on Client Terrain. CollisionResult = gClientContainer.castRay( ShapeStart, ShapeEnd, FXREPLICATOR_COLLISION_MASK, &RayEvent); // Did we hit anything? if (CollisionResult) { // For now, let's pretend we didn't get a collision. CollisionResult = false; // Yes, so get it's type. U32 CollisionType = RayEvent.object->getTypeMask(); // Check Illegal Placements. if (((CollisionType & TerrainObjectType) && !mFieldData.mAllowOnTerrain) || ((CollisionType & StaticShapeObjectType) && !mFieldData.mAllowStatics) || ((CollisionType & WaterObjectType) && !mFieldData.mAllowOnWater) ) continue; // If we collided with water and are not allowing on the water surface then let's find the // terrain underneath and pass this on as the original collision else fail. // // NOTE:- We need to do this on the server/client as appropriate. if ((CollisionType & WaterObjectType) && !mFieldData.mAllowWaterSurface) { // Is this the Server? if (isServerObject()) { // Yes, so do it on the server container. if (!gServerContainer.castRay( ShapeStart, ShapeEnd, FXREPLICATOR_NOWATER_COLLISION_MASK, &RayEvent)) continue; } else { // No, so do it on the client container. if (!gClientContainer.castRay( ShapeStart, ShapeEnd, FXREPLICATOR_NOWATER_COLLISION_MASK, &RayEvent)) continue; } } // We passed with flying colours so carry on. CollisionResult = true; } // Invalidate if we are below Allowed Terrain Angle. if (RayEvent.normal.z < mSin(mDegToRad(90.0f-mFieldData.mAllowedTerrainSlope))) CollisionResult = false; // Wait until we get a collision. } while(!CollisionResult && --RelocationRetry); // Check for Relocation Problem. if (RelocationRetry > 0) { // Adjust Impact point. RayEvent.point.z += mFieldData.mOffsetZ; // Set New Position. ShapePosition = RayEvent.point; } else { // Warning. Con::warnf(ConsoleLogEntry::General, "[%s] - Could not find satisfactory position for shape '%s' on %s!", getName(), mFieldData.mShapeFile,isServerObject()?"Server":"Client"); // Unregister Object. fxStatic->unregisterObject(); // Destroy Shape. delete fxStatic; // Skip to next. continue; } // Get Shape Transform. MatrixF XForm = fxStatic->getTransform(); // Are we aligning to Terrain? if (mFieldData.mAlignToTerrain) { // Yes, so set rotation to Terrain Impact Normal. ShapeRotation = RayEvent.normal * mFieldData.mTerrainAlignment; } else { // No, so choose a new Rotation (in Radians). ShapeRotation.set( mDegToRad(RandomGen.randF(mFieldData.mShapeRotateMin.x, mFieldData.mShapeRotateMax.x)), mDegToRad(RandomGen.randF(mFieldData.mShapeRotateMin.y, mFieldData.mShapeRotateMax.y)), mDegToRad(RandomGen.randF(mFieldData.mShapeRotateMin.z, mFieldData.mShapeRotateMax.z))); } // Set Quaternion Roation. QRotation.set(ShapeRotation); // Set Transform Rotation. QRotation.setMatrix(&XForm); // Set Position. XForm.setColumn(3, ShapePosition); // Set Shape Position / Rotation. fxStatic->setTransform(XForm); // Choose a new Scale. ShapeScale.set( RandomGen.randF(mFieldData.mShapeScaleMin.x, mFieldData.mShapeScaleMax.x), RandomGen.randF(mFieldData.mShapeScaleMin.y, mFieldData.mShapeScaleMax.y), RandomGen.randF(mFieldData.mShapeScaleMin.z, mFieldData.mShapeScaleMax.z)); // Set Shape Scale. fxStatic->setScale(ShapeScale); // Lock it. fxStatic->setLocked(true); // Store Shape in Replicated Shapes Vector. //mReplicatedShapes[mCurrentShapeCount++] = fxStatic; mReplicatedShapes.push_back(fxStatic); } mCurrentShapeCount = mReplicatedShapes.size(); // Take first Timestamp. mLastRenderTime = Platform::getVirtualMilliseconds(); }
F32 TimeOfDay::_calcAzimuth( F32 lat, F32 dec, F32 mer ) { // Add PI to normalize this from the range of -PI/2 to PI/2 to 0 to 2 * PI; return mAtan2( mSin(mer), mCos(mer) * mSin(lat) - mTan(dec) * mCos(lat) ) + M_PI_F; }
F32 TimeOfDay::_calcElevation( F32 lat, F32 dec, F32 mer ) { return mAsin( mSin(lat) * mSin(dec) + mCos(lat) * mCos(dec) * mCos(mer) ); }
bool EditTSCtrl::processCameraQuery(CameraQuery * query) { if(mDisplayType == DisplayTypePerspective) { query->ortho = false; } else { query->ortho = true; } if (getCameraTransform(&query->cameraMatrix)) { query->farPlane = gClientSceneGraph->getVisibleDistance() * smVisibleDistanceScale; query->nearPlane = gClientSceneGraph->getNearClip(); query->fov = mDegToRad(smCamFOV); if(query->ortho) { MatrixF camRot(true); const F32 camBuffer = 1.0f; Point3F camPos = query->cameraMatrix.getPosition(); F32 isocamplanedist = 0.0f; if(mDisplayType == DisplayTypeIsometric) { const RectI& vp = GFX->getViewport(); isocamplanedist = 0.25 * vp.extent.y * mSin(mIsoCamAngle); } // Calculate the scene bounds Box3F sceneBounds; computeSceneBounds(sceneBounds); if(!sceneBounds.isValidBox()) { sceneBounds.maxExtents = camPos + smMinSceneBounds; sceneBounds.minExtents = camPos - smMinSceneBounds; } else { query->farPlane = getMax(smMinSceneBounds.x * 2.0f, (sceneBounds.maxExtents - sceneBounds.minExtents).len() + camBuffer * 2.0f + isocamplanedist); } mRawCamPos = camPos; camPos += mOrthoCamTrans; switch(mDisplayType) { case DisplayTypeTop: camRot.setColumn(0, Point3F(1.0, 0.0, 0.0)); camRot.setColumn(1, Point3F(0.0, 0.0, -1.0)); camRot.setColumn(2, Point3F(0.0, 1.0, 0.0)); camPos.z = getMax(camPos.z + smMinSceneBounds.z, sceneBounds.maxExtents.z + camBuffer); break; case DisplayTypeBottom: camRot.setColumn(0, Point3F(1.0, 0.0, 0.0)); camRot.setColumn(1, Point3F(0.0, 0.0, 1.0)); camRot.setColumn(2, Point3F(0.0, -1.0, 0.0)); camPos.z = getMin(camPos.z - smMinSceneBounds.z, sceneBounds.minExtents.z - camBuffer); break; case DisplayTypeFront: camRot.setColumn(0, Point3F(-1.0, 0.0, 0.0)); camRot.setColumn(1, Point3F( 0.0, -1.0, 0.0)); camRot.setColumn(2, Point3F( 0.0, 0.0, 1.0)); camPos.y = getMax(camPos.y + smMinSceneBounds.y, sceneBounds.maxExtents.y + camBuffer); break; case DisplayTypeBack: camRot.setColumn(0, Point3F(1.0, 0.0, 0.0)); camRot.setColumn(1, Point3F(0.0, 1.0, 0.0)); camRot.setColumn(2, Point3F(0.0, 0.0, 1.0)); camPos.y = getMin(camPos.y - smMinSceneBounds.y, sceneBounds.minExtents.y - camBuffer); break; case DisplayTypeLeft: camRot.setColumn(0, Point3F( 0.0, -1.0, 0.0)); camRot.setColumn(1, Point3F( 1.0, 0.0, 0.0)); camRot.setColumn(2, Point3F( 0.0, 0.0, 1.0)); camPos.x = getMin(camPos.x - smMinSceneBounds.x, sceneBounds.minExtents.x - camBuffer); break; case DisplayTypeRight: camRot.setColumn(0, Point3F( 0.0, 1.0, 0.0)); camRot.setColumn(1, Point3F(-1.0, 0.0, 0.0)); camRot.setColumn(2, Point3F( 0.0, 0.0, 1.0)); camPos.x = getMax(camPos.x + smMinSceneBounds.x, sceneBounds.maxExtents.x + camBuffer); break; case DisplayTypeIsometric: camPos.z = sceneBounds.maxExtents.z + camBuffer + isocamplanedist; MatrixF angle(EulerF(mIsoCamAngle, 0, 0)); MatrixF rot(mIsoCamRot); camRot.mul(rot, angle); break; } query->cameraMatrix = camRot; query->cameraMatrix.setPosition(camPos); query->fov = mOrthoFOV; } smCamMatrix = query->cameraMatrix; smCamMatrix.getColumn(3,&smCamPos); smCamOrtho = query->ortho; smCamNearPlane = query->nearPlane; return true; } return false; }