void afxZodiacData::convertGradientRangeFromDegrees(Point2F& gradrange, const Point2F& gradrange_deg) { F32 x = mCos(mDegToRad(gradrange_deg.x)); F32 y = mCos(mDegToRad(gradrange_deg.y)); if (y > x) gradrange.set(x, y); else gradrange.set(y, x); }
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 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 ); } } }
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; } }
EulerF MatrixF::toEuler() const { const F32 * mat = m; EulerF r; r.x = mAsin(mat[MatrixF::idx(2,1)]); if(mCos(r.x) != 0.f) { r.y = mAtan2(-mat[MatrixF::idx(2,0)], mat[MatrixF::idx(2,2)]); r.z = mAtan2(-mat[MatrixF::idx(0,1)], mat[MatrixF::idx(1,1)]); } else { r.y = 0.f; r.z = mAtan2(mat[MatrixF::idx(1,0)], mat[MatrixF::idx(0,0)]); } return r; }
//----------------------------------------------------------------------------- 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); } } } }
//-------------------------------------- static void m_sincos_C( F32 angle, F32 *s, F32 *c ) { *s = mSin( angle ); *c = mCos( angle ); }
void ScatterSky::_initVBIB() { // Vertex Buffer... U32 vertStride = 50; U32 strideMinusOne = vertStride - 1; mVertCount = vertStride * vertStride; mPrimCount = strideMinusOne * strideMinusOne * 2; Point3F vertScale( 16.0f, 16.0f, 4.0f ); F32 zOffset = -( mCos( mSqrt( 1.0f ) ) + 0.01f ); mVB.set( GFX, mVertCount, GFXBufferTypeStatic ); ScatterSkyVertex *pVert = mVB.lock(); for ( U32 y = 0; y < vertStride; y++ ) { F32 v = ( (F32)y / (F32)strideMinusOne - 0.5f ) * 2.0f; for ( U32 x = 0; x < vertStride; x++ ) { F32 u = ( (F32)x / (F32)strideMinusOne - 0.5f ) * 2.0f; F32 sx = u; F32 sy = v; F32 sz = (mCos( mSqrt( sx*sx + sy*sy ) ) * 1.0f) + zOffset; //F32 sz = 1.0f; pVert->point.set( sx, sy, sz ); pVert->point *= vertScale; pVert->point.normalize(); pVert->point *= 200000.0f; pVert++; } } mVB.unlock(); // Primitive Buffer... mPrimBuffer.set( GFX, mPrimCount * 3, mPrimCount, GFXBufferTypeStatic ); U16 *pIdx = NULL; mPrimBuffer.lock(&pIdx); U32 curIdx = 0; for ( U32 y = 0; y < strideMinusOne; y++ ) { for ( U32 x = 0; x < strideMinusOne; x++ ) { U32 offset = x + y * vertStride; pIdx[curIdx] = offset; curIdx++; pIdx[curIdx] = offset + 1; curIdx++; pIdx[curIdx] = offset + vertStride + 1; curIdx++; pIdx[curIdx] = offset; curIdx++; pIdx[curIdx] = offset + vertStride + 1; curIdx++; pIdx[curIdx] = offset + vertStride; curIdx++; } } mPrimBuffer.unlock(); }
void LightManager::_update4LightConsts( const SceneData &sgData, GFXShaderConstHandle *lightPositionSC, GFXShaderConstHandle *lightDiffuseSC, GFXShaderConstHandle *lightAmbientSC, GFXShaderConstHandle *lightInvRadiusSqSC, GFXShaderConstHandle *lightSpotDirSC, GFXShaderConstHandle *lightSpotAngleSC, GFXShaderConstHandle *lightSpotFalloffSC, GFXShaderConstBuffer *shaderConsts ) { PROFILE_SCOPE( LightManager_Update4LightConsts ); // Skip over gathering lights if we don't have to! if ( lightPositionSC->isValid() || lightDiffuseSC->isValid() || lightInvRadiusSqSC->isValid() || lightSpotDirSC->isValid() || lightSpotAngleSC->isValid() || lightSpotFalloffSC->isValid() ) { PROFILE_SCOPE( LightManager_Update4LightConsts_setLights ); static AlignedArray<Point4F> lightPositions( 3, sizeof( Point4F ) ); static AlignedArray<Point4F> lightSpotDirs( 3, sizeof( Point4F ) ); static AlignedArray<Point4F> lightColors( 4, sizeof( Point4F ) ); static Point4F lightInvRadiusSq; static Point4F lightSpotAngle; static Point4F lightSpotFalloff; F32 range; // Need to clear the buffers so that we don't leak // lights from previous passes or have NaNs. dMemset( lightPositions.getBuffer(), 0, lightPositions.getBufferSize() ); dMemset( lightSpotDirs.getBuffer(), 0, lightSpotDirs.getBufferSize() ); dMemset( lightColors.getBuffer(), 0, lightColors.getBufferSize() ); lightInvRadiusSq = Point4F::Zero; lightSpotAngle.set( -1.0f, -1.0f, -1.0f, -1.0f ); lightSpotFalloff.set( F32_MAX, F32_MAX, F32_MAX, F32_MAX ); // Gather the data for the first 4 lights. const LightInfo *light; for ( U32 i=0; i < 4; i++ ) { light = sgData.lights[i]; if ( !light ) break; // The light positions and spot directions are // in SoA order to make optimal use of the GPU. const Point3F &lightPos = light->getPosition(); lightPositions[0][i] = lightPos.x; lightPositions[1][i] = lightPos.y; lightPositions[2][i] = lightPos.z; const VectorF &lightDir = light->getDirection(); lightSpotDirs[0][i] = lightDir.x; lightSpotDirs[1][i] = lightDir.y; lightSpotDirs[2][i] = lightDir.z; if ( light->getType() == LightInfo::Spot ) { lightSpotAngle[i] = mCos( mDegToRad( light->getOuterConeAngle() / 2.0f ) ); lightSpotFalloff[i] = 1.0f / getMax( F32_MIN, mCos( mDegToRad( light->getInnerConeAngle() / 2.0f ) ) - lightSpotAngle[i] ); } // Prescale the light color by the brightness to // avoid doing this in the shader. lightColors[i] = Point4F(light->getColor()) * light->getBrightness(); // We need 1 over range^2 here. range = light->getRange().x; lightInvRadiusSq[i] = 1.0f / ( range * range ); } shaderConsts->setSafe( lightPositionSC, lightPositions ); shaderConsts->setSafe( lightDiffuseSC, lightColors ); shaderConsts->setSafe( lightInvRadiusSqSC, lightInvRadiusSq ); shaderConsts->setSafe( lightSpotDirSC, lightSpotDirs ); shaderConsts->setSafe( lightSpotAngleSC, lightSpotAngle ); shaderConsts->setSafe( lightSpotFalloffSC, lightSpotFalloff ); } // Setup the ambient lighting from the first // light which is the directional light if // one exists at all in the scene. if ( lightAmbientSC->isValid() ) shaderConsts->set( lightAmbientSC, sgData.ambientLightColor ); }
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; }
//-------------------------------------------------------------------------- // from Graphics Gems I: pp 738-742 U32 mSolveCubic_c(F32 a, F32 b, F32 c, F32 d, F32 * x) { if(mIsZero(a)) return(mSolveQuadratic(b, c, d, x)); // normal form: x^3 + Ax^2 + BX + C = 0 F32 A = b / a; F32 B = c / a; F32 C = d / a; // substitute x = y - A/3 to eliminate quadric term and depress // the cubic equation to (x^3 + px + q = 0) F32 A2 = A * A; F32 A3 = A2 * A; F32 p = (1.f/3.f) * (((-1.f/3.f) * A2) + B); F32 q = (1.f/2.f) * (((2.f/27.f) * A3) - ((1.f/3.f) * A * B) + C); // use Cardano's fomula to solve the depressed cubic F32 p3 = p * p * p; F32 q2 = q * q; F32 D = q2 + p3; U32 num = 0; if(mIsZero(D)) // 1 or 2 solutions { if(mIsZero(q)) // 1 triple solution { x[0] = 0.f; num = 1; } else // 1 single and 1 double { F32 u = mCbrt(-q); x[0] = 2.f * u; x[1] = -u; num = 2; } } else if(D < 0.f) // 3 solutions: casus irreducibilis { F32 phi = (1.f/3.f) * mAcos(-q / mSqrt(-p3)); F32 t = 2.f * mSqrt(-p); x[0] = t * mCos(phi); x[1] = -t * mCos(phi + (M_PI / 3.f)); x[2] = -t * mCos(phi - (M_PI / 3.f)); num = 3; } else // 1 solution { F32 sqrtD = mSqrt(D); F32 u = mCbrt(sqrtD - q); F32 v = -mCbrt(sqrtD + q); x[0] = u + v; num = 1; } // resubstitute F32 sub = (1.f/3.f) * A; for(U32 i = 0; i < num; i++) x[i] -= sub; // sort the roots for(S32 j = 0; j < (num - 1); j++) for(S32 k = j + 1; k < num; k++) if(x[k] < x[j]) swap(x[k], x[j]); return(num); }
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 //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~// }
F32 TimeOfDay::_calcElevation( F32 lat, F32 dec, F32 mer ) { return mAsin( mSin(lat) * mSin(dec) + mCos(lat) * mCos(dec) * mCos(mer) ); }
static void m_sincosD_C( F64 angle, F64 *s, F64 *c ) { *s = mSin( angle ); *c = mCos( angle ); }
void CloudLayer::_initBuffers() { // Vertex Buffer... Point3F vertScale( 16.0f, 16.0f, mHeight ); F32 zOffset = -( mCos( mSqrt( 1.0f ) ) + 0.01f ); mVB.set( GFX, smVertCount, GFXBufferTypeStatic ); GFXCloudVertex *pVert = mVB.lock(); if(!pVert) return; for ( U32 y = 0; y < smVertStride; y++ ) { F32 v = ( (F32)y / (F32)smStrideMinusOne - 0.5f ) * 2.0f; for ( U32 x = 0; x < smVertStride; x++ ) { F32 u = ( (F32)x / (F32)smStrideMinusOne - 0.5f ) * 2.0f; F32 sx = u; F32 sy = v; F32 sz = mCos( mSqrt( sx*sx + sy*sy ) ) + zOffset; //F32 sz = 1.0f; pVert->point.set( sx, sy, sz ); pVert->point *= vertScale; // The vert to our right. Point3F rpnt; F32 ru = ( (F32)( x + 1 ) / (F32)smStrideMinusOne - 0.5f ) * 2.0f; F32 rv = v; rpnt.x = ru; rpnt.y = rv; rpnt.z = mCos( mSqrt( rpnt.x*rpnt.x + rpnt.y*rpnt.y ) ) + zOffset; rpnt *= vertScale; // The vert to our front. Point3F fpnt; F32 fu = u; F32 fv = ( (F32)( y + 1 ) / (F32)smStrideMinusOne - 0.5f ) * 2.0f; fpnt.x = fu; fpnt.y = fv; fpnt.z = mCos( mSqrt( fpnt.x*fpnt.x + fpnt.y*fpnt.y ) ) + zOffset; fpnt *= vertScale; Point3F fvec = fpnt - pVert->point; fvec.normalize(); Point3F rvec = rpnt - pVert->point; rvec.normalize(); pVert->normal = mCross( fvec, rvec ); pVert->normal.normalize(); pVert->binormal = fvec; pVert->tangent = rvec; pVert->texCoord.set( u, v ); pVert++; } } mVB.unlock(); // Primitive Buffer... mPB.set( GFX, smTriangleCount * 3, smTriangleCount, GFXBufferTypeStatic ); U16 *pIdx = NULL; mPB.lock(&pIdx); U32 curIdx = 0; for ( U32 y = 0; y < smStrideMinusOne; y++ ) { for ( U32 x = 0; x < smStrideMinusOne; x++ ) { U32 offset = x + y * smVertStride; pIdx[curIdx] = offset; curIdx++; pIdx[curIdx] = offset + 1; curIdx++; pIdx[curIdx] = offset + smVertStride + 1; curIdx++; pIdx[curIdx] = offset; curIdx++; pIdx[curIdx] = offset + smVertStride + 1; curIdx++; pIdx[curIdx] = offset + smVertStride; curIdx++; } } mPB.unlock(); }
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(); }
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 BasicClouds::_initBuffers() { // Primitive Buffer... Is shared for all Layers. mPB.set( GFX, smTriangleCount * 3, smTriangleCount, GFXBufferTypeStatic ); U16 *pIdx = NULL; mPB.lock(&pIdx); U32 curIdx = 0; for ( U32 y = 0; y < smStrideMinusOne; y++ ) { for ( U32 x = 0; x < smStrideMinusOne; x++ ) { U32 offset = x + y * smVertStride; pIdx[curIdx] = offset; curIdx++; pIdx[curIdx] = offset + 1; curIdx++; pIdx[curIdx] = offset + smVertStride + 1; curIdx++; pIdx[curIdx] = offset; curIdx++; pIdx[curIdx] = offset + smVertStride + 1; curIdx++; pIdx[curIdx] = offset + smVertStride; curIdx++; } } mPB.unlock(); // Vertex Buffer... // Each layer has their own so they can be at different heights. for ( U32 i = 0; i < TEX_COUNT; i++ ) { Point3F vertScale( 16.0f, 16.0f, mHeight[i] ); F32 zOffset = -( mCos( mSqrt( 1.0f ) ) + 0.01f ); mVB[i].set( GFX, smVertCount, GFXBufferTypeStatic ); GFXVertexPT *pVert = mVB[i].lock(); for ( U32 y = 0; y < smVertStride; y++ ) { F32 v = ( (F32)y / (F32)smStrideMinusOne - 0.5f ) * 2.0f; for ( U32 x = 0; x < smVertStride; x++ ) { F32 u = ( (F32)x / (F32)smStrideMinusOne - 0.5f ) * 2.0f; F32 sx = u; F32 sy = v; F32 sz = mCos( mSqrt( sx*sx + sy*sy ) ) + zOffset; pVert->point.set( sx, sy, sz ); pVert->point *= vertScale; pVert->texCoord.set( u, v ); pVert++; } } mVB[i].unlock(); } }
void AdvancedLightBinManager::LightMaterialInfo::setLightParameters( const LightInfo *lightInfo, const SceneRenderState* renderState, const MatrixF &worldViewOnly ) { MaterialParameters *matParams = matInstance->getMaterialParameters(); // Set color in the right format, set alpha to the luminance value for the color. ColorF col = lightInfo->getColor(); // TODO: The specularity control of the light // is being scaled by the overall lumiance. // // Not sure if this may be the source of our // bad specularity results maybe? // const Point3F colorToLumiance( 0.3576f, 0.7152f, 0.1192f ); F32 lumiance = mDot(*((const Point3F *)&lightInfo->getColor()), colorToLumiance ); col.alpha *= lumiance; matParams->setSafe( lightColor, col ); matParams->setSafe( lightBrightness, lightInfo->getBrightness() ); switch( lightInfo->getType() ) { case LightInfo::Vector: { VectorF lightDir = lightInfo->getDirection(); worldViewOnly.mulV(lightDir); lightDir.normalize(); matParams->setSafe( lightDirection, lightDir ); // Set small number for alpha since it represents existing specular in // the vector light. This prevents a divide by zero. ColorF ambientColor = renderState->getAmbientLightColor(); ambientColor.alpha = 0.00001f; matParams->setSafe( lightAmbient, ambientColor ); // If no alt color is specified, set it to the average of // the ambient and main color to avoid artifacts. // // TODO: Trilight disabled until we properly implement it // in the light info! // //ColorF lightAlt = lightInfo->getAltColor(); ColorF lightAlt( ColorF::BLACK ); // = lightInfo->getAltColor(); if ( lightAlt.red == 0.0f && lightAlt.green == 0.0f && lightAlt.blue == 0.0f ) lightAlt = (lightInfo->getColor() + renderState->getAmbientLightColor()) / 2.0f; ColorF trilightColor = lightAlt; matParams->setSafe(lightTrilight, trilightColor); } break; case LightInfo::Spot: { const F32 outerCone = lightInfo->getOuterConeAngle(); const F32 innerCone = getMin( lightInfo->getInnerConeAngle(), outerCone ); const F32 outerCos = mCos( mDegToRad( outerCone / 2.0f ) ); const F32 innerCos = mCos( mDegToRad( innerCone / 2.0f ) ); Point4F spotParams( outerCos, innerCos - outerCos, mCos( mDegToRad( outerCone ) ), 0.0f ); matParams->setSafe( lightSpotParams, spotParams ); VectorF lightDir = lightInfo->getDirection(); worldViewOnly.mulV(lightDir); lightDir.normalize(); matParams->setSafe( lightDirection, lightDir ); } // Fall through case LightInfo::Point: { const F32 radius = lightInfo->getRange().x; matParams->setSafe( lightRange, radius ); Point3F lightPos; worldViewOnly.mulP(lightInfo->getPosition(), &lightPos); matParams->setSafe( lightPosition, lightPos ); // Get the attenuation falloff ratio and normalize it. Point3F attenRatio = lightInfo->getExtended<ShadowMapParams>()->attenuationRatio; F32 total = attenRatio.x + attenRatio.y + attenRatio.z; if ( total > 0.0f ) attenRatio /= total; Point2F attenParams( ( 1.0f / radius ) * attenRatio.y, ( 1.0f / ( radius * radius ) ) * attenRatio.z ); matParams->setSafe( lightAttenuation, attenParams ); break; } default: AssertFatal( false, "Bad light type!" ); break; } }
//---------------------------------------------------------------------------- /// Core rendering method for this control. /// /// This method scans through all the current client ShapeBase objects. /// If one is named, it displays the name and damage information for it. /// /// Information is offset from the center of the object's bounding box, /// unless the object is a PlayerObjectType, in which case the eye point /// is used. /// /// @param updateRect Extents of control. void afxGuiTextHud::onRender( Point2I, const RectI &updateRect) { // Background fill first if (mShowFill) GFX->getDrawUtil()->drawRectFill(updateRect, mFillColor.toColorI()); // Must be in a TS Control GuiTSCtrl *parent = dynamic_cast<GuiTSCtrl*>(getParent()); if (!parent) return; // Must have a connection and control object GameConnection* conn = GameConnection::getConnectionToServer(); if (!conn) return; GameBase * control = dynamic_cast<GameBase*>(conn->getControlObject()); if (!control) return; // Get control camera info MatrixF cam; Point3F camPos; VectorF camDir; conn->getControlCameraTransform(0,&cam); cam.getColumn(3, &camPos); cam.getColumn(1, &camDir); F32 camFovCos; conn->getControlCameraFov(&camFovCos); camFovCos = mCos(mDegToRad(camFovCos) / 2); // Visible distance info & name fading F32 visDistance = gClientSceneGraph->getVisibleDistance(); F32 visDistanceSqr = visDistance * visDistance; F32 fadeDistance = visDistance * mDistanceFade; // Collision info. We're going to be running LOS tests and we // don't want to collide with the control object. static U32 losMask = TerrainObjectType | TerrainLikeObjectType | ShapeBaseObjectType; if (!mEnableControlObjectOcclusion) control->disableCollision(); if (mLabelAllShapes) { // This section works just like GuiShapeNameHud and renders labels for // all the shapes. // All ghosted objects are added to the server connection group, // so we can find all the shape base objects by iterating through // our current connection. for (SimSetIterator itr(conn); *itr; ++itr) { ///if ((*itr)->getTypeMask() & ShapeBaseObjectType) ///{ ShapeBase* shape = dynamic_cast<ShapeBase*>(*itr); if ( shape ) { if (shape != control && shape->getShapeName()) { // Target pos to test, if it's a player run the LOS to his eye // point, otherwise we'll grab the generic box center. Point3F shapePos; if (shape->getTypeMask() & PlayerObjectType) { MatrixF eye; // Use the render eye transform, otherwise we'll see jittering shape->getRenderEyeTransform(&eye); eye.getColumn(3, &shapePos); } else { // Use the render transform instead of the box center // otherwise it'll jitter. MatrixF srtMat = shape->getRenderTransform(); srtMat.getColumn(3, &shapePos); } VectorF shapeDir = shapePos - camPos; // Test to see if it's in range F32 shapeDist = shapeDir.lenSquared(); if (shapeDist == 0 || shapeDist > visDistanceSqr) continue; shapeDist = mSqrt(shapeDist); // Test to see if it's within our viewcone, this test doesn't // actually match the viewport very well, should consider // projection and box test. shapeDir.normalize(); F32 dot = mDot(shapeDir, camDir); if (dot < camFovCos) continue; // Test to see if it's behind something, and we want to // ignore anything it's mounted on when we run the LOS. RayInfo info; shape->disableCollision(); SceneObject *mount = shape->getObjectMount(); if (mount) mount->disableCollision(); bool los = !gClientContainer.castRay(camPos, shapePos,losMask, &info); shape->enableCollision(); if (mount) mount->enableCollision(); if (!los) continue; // Project the shape pos into screen space and calculate // the distance opacity used to fade the labels into the // distance. Point3F projPnt; shapePos.z += mVerticalOffset; if (!parent->project(shapePos, &projPnt)) continue; F32 opacity = (shapeDist < fadeDistance)? 1.0: 1.0 - (shapeDist - fadeDistance) / (visDistance - fadeDistance); // Render the shape's name drawName(Point2I((S32)projPnt.x, (S32)projPnt.y),shape->getShapeName(),opacity); } } } } // This section renders all text added by afxGuiText effects. for (S32 i = 0; i < text_items.size(); i++) { HudTextSpec* spec = &text_items[i]; if (spec->text && spec->text[0] != '\0') { VectorF shapeDir = spec->pos - camPos; // do range test F32 shapeDist = shapeDir.lenSquared(); if (shapeDist == 0 || shapeDist > visDistanceSqr) continue; shapeDist = mSqrt(shapeDist); // Test to see if it's within our viewcone, this test doesn't // actually match the viewport very well, should consider // projection and box test. shapeDir.normalize(); F32 dot = mDot(shapeDir, camDir); if (dot < camFovCos) continue; // Test to see if it's behind something, and we want to // ignore anything it's mounted on when we run the LOS. RayInfo info; if (spec->obj) spec->obj->disableCollision(); bool los = !gClientContainer.castRay(camPos, spec->pos, losMask, &info); if (spec->obj) spec->obj->enableCollision(); if (!los) continue; // Project the shape pos into screen space. Point3F projPnt; if (!parent->project(spec->pos, &projPnt)) continue; // Calculate the distance opacity used to fade text into the distance. F32 opacity = (shapeDist < fadeDistance)? 1.0 : 1.0 - (shapeDist - fadeDistance) / (25.0f); if (opacity > 0.01f) drawName(Point2I((S32)projPnt.x, (S32)projPnt.y), spec->text, opacity, &spec->text_clr); } } // Restore control object collision if (!mEnableControlObjectOcclusion) control->enableCollision(); // Border last if (mShowFrame) GFX->getDrawUtil()->drawRect(updateRect, mFrameColor.toColorI()); reset(); }