SceneObject::SceneObject() { mContainer = 0; mTypeMask = DefaultObjectType; mCollisionMask = 0xFF; mCollisionCount = 0; mGlobalBounds = false; mObjScale.set(1,1,1); mObjToWorld.identity(); mWorldToObj.identity(); mObjBox = Box3F(Point3F(0, 0, 0), Point3F(0, 0, 0)); mWorldBox = Box3F(Point3F(0, 0, 0), Point3F(0, 0, 0)); mWorldSphere = SphereF(Point3F(0, 0, 0), 0); mRenderObjToWorld.identity(); mRenderWorldToObj.identity(); mRenderWorldBox = Box3F(Point3F(0, 0, 0), Point3F(0, 0, 0)); mRenderWorldSphere = SphereF(Point3F(0, 0, 0), 0); mContainerSeqKey = 0; mBinRefHead = NULL; mSceneManager = NULL; mNumCurrZones = 0; mZoneRefHead = NULL; mZoneRefDirty = false; mBinMinX = 0xFFFFFFFF; mBinMaxX = 0xFFFFFFFF; mBinMinY = 0xFFFFFFFF; mBinMaxY = 0xFFFFFFFF; mLightPlugin = NULL; mMount.object = NULL; mMount.link = NULL; mMount.list = NULL; mMount.node = -1; mMount.xfm = MatrixF::Identity; mMountPID = NULL; mSceneObjectLinks = NULL; for(U32 i = 0; i < Palette::NumSlots; i++) mPalette.colors[i] = Palette::defaultColor; mFlickerTime = 0; mObjectFlags.set( RenderEnabledFlag | SelectionEnabledFlag ); mIsScopeAlways = false; }
SceneObject::SceneObject() { mContainer = 0; mTypeMask = DefaultObjectType; mCollisionCount = 0; mGlobalBounds = false; mObjScale.set(1,1,1); mObjToWorld.identity(); mWorldToObj.identity(); mObjBox = Box3F(Point3F(0, 0, 0), Point3F(0, 0, 0)); mWorldBox = Box3F(Point3F(0, 0, 0), Point3F(0, 0, 0)); mWorldSphere = SphereF(Point3F(0, 0, 0), 0); mRenderObjToWorld.identity(); mRenderWorldToObj.identity(); mRenderWorldBox = Box3F(Point3F(0, 0, 0), Point3F(0, 0, 0)); mRenderWorldSphere = SphereF(Point3F(0, 0, 0), 0); mContainerSeqKey = 0; mBinRefHead = NULL; mSceneManager = NULL; mNumCurrZones = 0; mZoneRefHead = NULL; mZoneRefDirty = false; mBinMinX = 0xFFFFFFFF; mBinMaxX = 0xFFFFFFFF; mBinMinY = 0xFFFFFFFF; mBinMaxY = 0xFFFFFFFF; mLightPlugin = NULL; mMount.object = NULL; mMount.link = NULL; mMount.list = NULL; mMount.node = -1; mMount.xfm = MatrixF::Identity; mMountPID = NULL; mSceneObjectLinks = NULL; mObjectFlags.set( RenderEnabledFlag | SelectionEnabledFlag ); mIsScopeAlways = false; //.logicking guidebot >> m_worldObject = NULL; //.logicking guidebot << }
void GuiObjectView::renderWorld( const RectI& updateRect ) { if( !mModel ) return; GFXTransformSaver _saveTransforms; // Determine the camera position, and store off render state. MatrixF modelview; MatrixF mv; Point3F cp; modelview = GFX->getWorldMatrix(); mv = modelview; mv.inverse(); mv.getColumn( 3, &cp ); RenderPassManager* renderPass = gClientSceneGraph->getDefaultRenderPass(); S32 time = Platform::getVirtualMilliseconds(); S32 dt = time - mLastRenderTime; mLastRenderTime = time; LIGHTMGR->unregisterAllLights(); LIGHTMGR->setSpecialLight( LightManager::slSunLightType, mLight ); GFX->setStateBlock( mDefaultGuiSB ); F32 left, right, top, bottom, nearPlane, farPlane; bool isOrtho; GFX->getFrustum( &left, &right, &bottom, &top, &nearPlane, &farPlane, &isOrtho ); Frustum frust( false, left, right, top, bottom, nearPlane, farPlane, MatrixF::Identity ); SceneRenderState state ( gClientSceneGraph, SPT_Diffuse, SceneCameraState( GFX->getViewport(), frust, GFX->getWorldMatrix(), GFX->getProjectionMatrix() ), renderPass, false ); // Set up our TS render state here. TSRenderState rdata; rdata.setSceneState( &state ); // We might have some forward lit materials // so pass down a query to gather lights. LightQuery query; query.init( SphereF( Point3F::Zero, 1.0f ) ); rdata.setLightQuery( &query ); // Render primary model. if( mModel ) { if( mRunThread ) { mModel->advanceTime( dt / 1000.f, mRunThread ); mModel->animate(); } mModel->render( rdata ); } // Render mounted model. if( mMountedModel && mMountNode != -1 ) { GFX->pushWorldMatrix(); GFX->multWorld( mModel->mNodeTransforms[ mMountNode ] ); GFX->multWorld( mMountTransform ); mMountedModel->render( rdata ); GFX->popWorldMatrix(); } renderPass->renderPass( &state ); // Make sure to remove our fake sun. LIGHTMGR->unregisterAllLights(); }
void BaseShadowRenderImage::preRenderShadow(TSRenderContext & rc, float curTime) { if (!castShadow) return; // do visibility check for shadow Point3F center; m_mul(shape->getShape().fCenter,transform,¢er); SphereF shadowSphere = SphereF(center,shape->getShape().fRadius); int shadowVis = rc.getCamera()->testVisibility(shadowSphere); if ( shadowVis==TS::ClipNoneVis ) { shadowSettings.shadowDetail = -1; return; } // shape detail to use for shadows if (!shadowOwnDetail) { projSize = rc.getCamera()->transformProjectRadius( center, shape->getShape().fRadius ); float adjustedSize = shadowDetailScale * projSize; shadowSettings.shadowDetail = shape->getShape().selectDetail( adjustedSize ); if (shadowSettings.shadowDetail==-1) return; } // first pass at shadow details setShadowDetailsA(rc); // set shadow details may veto shadow if (shadowSettings.shadowDetail==-1) return; // set light direction, but only if different than before Point3F * pLight = &lightDirection; Point3F tempDirection; if (swingDown != 0.0f) { tempDirection = (lightDirection * (1.0f - swingDown)) + (Point3F(0, 0, -1) * swingDown); tempDirection.normalize(); pLight = &tempDirection; } if (m_dot(*pLight,lastLight) < 0.999) { shadow.setLight( *pLight, shape); lastLight = *pLight; nextShadowUpdateTime = -1; } // set position of shadow shadow.setPosition(transform.p); if (shadowSettings.cacheProjection) { if (shadowSettings.recacheProjection) { shadow.calcSourceWindow(shape,transform); getPolys(); shadow.cachePolys(); shadowSettings.recacheProjection = false; } } else { shadow.calcSourceWindow(shape,transform); getPolys(); Point3F cc = rc.getCamera()->getTCW().p; Point3F camY = transform.p-cc; camY.normalize(); shadow.getPlanes(cc,camY); } setShadowDetails(rc); // set shadow details may veto shadow if (shadowSettings.shadowDetail==-1) return; if (shadowSettings.shadowDetail < shadowSettings.hiShadowDetail) shadowSettings.shadowDetail = shadowSettings.hiShadowDetail; // adjust next update time... nextShadowUpdateTime += shadowSettings.updateDelta - prevShadowUpdateDelta; prevShadowUpdateDelta = shadowSettings.updateDelta; // adjust bmp dim... int newBmpDim = shadowSettings.bmpDim; if (newBmpDim != prevBmpDim) { prevBmpDim = newBmpDim; shadow.setBitmapSize(deviceManager.getGFXDeviceManager(),newBmpDim,rc.getSurface()); nextShadowUpdateTime = -1; } shadow.setAlphaLevel(alphaLevel); // create the shadow bitmap if needed if (curTime > nextShadowUpdateTime) { if (shadowSettings.useFloor) { SimContainerQuery query; Box3F & box = query.box; box.fMin = box.fMax = center; box.fMin.z += shape->getShape().fRadius; box.fMax.z -= shape->getShape().fRadius * 1.5f; query.id = -1; query.type = -1; query.mask = shadowSettings.projectTerrainOnly ? SimTerrainObjectType : projectionMask; SimCollisionInfo collision; if (root->findLOS(query,&collision)) { Point3F n,p; m_mul(collision.surfaces[0].position,collision.surfaces.tWorld,&p); m_mul(collision.surfaces[0].normal,(RMat3F&)collision.surfaces.tWorld,&n); p -= transform.p; Point3F lift = n; lift *= shadowSettings.liftFloor; p += lift; shadow.setFloor(p,n); } else shadow.clearFloor(); } else shadow.clearFloor(); shape->setDetailLevel(shadowSettings.shadowDetail); shape->animate(); GFXPalette * pal = SimGame::get()->getWorld(SimGame::CLIENT)->getPalette(); AssertFatal(pal, "invalid palette"); // getShadowBitmap assumes calcSourceWindow already called... // ...but that's ok because we called it above shadow.getShadowBitmap(shape,pal,transform,shadowSettings.blurMethod); nextShadowUpdateTime = curTime + shadowSettings.updateDelta; } AssertFatal(root, "shadowRenderImage::preRenderShadow: cannot cast shadow before \'root\' container set"); // this'll keep track of how many shadows are out there if (shadowNum < 0) shadowNum=1; // first preRender this render cycle else shadowNum++; }
SphereF Box3F::getBoundingSphere() const { return SphereF( getCenter(), getGreatestDiagonalLength() / 2.f ); }
void GuiMaterialPreview::renderWorld(const RectI &updateRect) { // nothing to render, punt if ( !mModel && !mMountedModel ) return; S32 time = Platform::getVirtualMilliseconds(); //S32 dt = time - lastRenderTime; lastRenderTime = time; F32 left, right, top, bottom, nearPlane, farPlane; bool isOrtho; GFX->getFrustum( &left, &right, &bottom, &top, &nearPlane, &farPlane, &isOrtho); Frustum frust( isOrtho, left, right, bottom, top, nearPlane, farPlane, MatrixF::Identity ); FogData savedFogData = gClientSceneGraph->getFogData(); gClientSceneGraph->setFogData( FogData() ); // no fog in preview window RenderPassManager* renderPass = gClientSceneGraph->getDefaultRenderPass(); SceneRenderState state ( gClientSceneGraph, SPT_Diffuse, SceneCameraState( GFX->getViewport(), frust, GFX->getWorldMatrix(), GFX->getProjectionMatrix() ), renderPass, true ); // Set up our TS render state here. TSRenderState rdata; rdata.setSceneState( &state ); // We might have some forward lit materials // so pass down a query to gather lights. LightQuery query; query.init( SphereF( Point3F::Zero, 1.0f ) ); rdata.setLightQuery( &query ); // Set up pass transforms renderPass->assignSharedXform(RenderPassManager::View, MatrixF::Identity); renderPass->assignSharedXform(RenderPassManager::Projection, GFX->getProjectionMatrix()); LIGHTMGR->unregisterAllLights(); LIGHTMGR->setSpecialLight( LightManager::slSunLightType, mFakeSun ); if ( mModel ) mModel->render( rdata ); if ( mMountedModel ) { // render a weapon /* MatrixF mat; GFX->pushWorldMatrix(); GFX->multWorld( mat ); GFX->popWorldMatrix(); */ } renderPass->renderPass( &state ); gClientSceneGraph->setFogData( savedFogData ); // restore fog setting // Make sure to remove our fake sun LIGHTMGR->unregisterAllLights(); }
bool ProjectedShadow::_updateDecal( const SceneRenderState *state ) { PROFILE_SCOPE( ProjectedShadow_UpdateDecal ); if ( !LIGHTMGR ) return false; // Get the position of the decal first. const Box3F &objBox = mParentObject->getObjBox(); const Point3F boxCenter = objBox.getCenter(); Point3F decalPos = boxCenter; const MatrixF &renderTransform = mParentObject->getRenderTransform(); { // Set up the decal position. // We use the object space box center // multiplied by the render transform // of the object to ensure we benefit // from interpolation. MatrixF t( renderTransform ); t.setColumn(2,Point3F::UnitZ); t.mulP( decalPos ); } if ( mDecalInstance ) { mDecalInstance->mPosition = decalPos; if ( !shouldRender( state ) ) return false; } // Get the sunlight for the shadow projection. // We want the LightManager to return NULL if it can't // get the "real" sun, so we specify false for the useDefault parameter. LightInfo *lights[4] = {0}; LightQuery query; query.init( mParentObject->getWorldSphere() ); query.getLights( lights, 4 ); Point3F pos = renderTransform.getPosition(); Point3F lightDir( 0, 0, 0 ); Point3F tmp( 0, 0, 0 ); F32 weight = 0; F32 range = 0; U32 lightCount = 0; F32 dist = 0; F32 fade = 0; for ( U32 i = 0; i < 4; i++ ) { // If we got a NULL light, // we're at the end of the list. if ( !lights[i] ) break; if ( !lights[i]->getCastShadows() ) continue; if ( lights[i]->getType() != LightInfo::Point ) tmp = lights[i]->getDirection(); else tmp = pos - lights[i]->getPosition(); range = lights[i]->getRange().x; dist = ( (tmp.lenSquared()) / ((range * range) * 0.5f)); weight = mClampF( 1.0f - ( tmp.lenSquared() / (range * range)), 0.00001f, 1.0f ); if ( lights[i]->getType() == LightInfo::Vector ) fade = getMax( fade, 1.0f ); else fade = getMax( fade, mClampF( 1.0f - dist, 0.00001f, 1.0f ) ); lightDir += tmp * weight; lightCount++; } lightDir.normalize(); // No light... no shadow. if ( !lights[0] ) return false; // Has the light direction // changed since last update? bool lightDirChanged = !mLastLightDir.equal( lightDir ); // Has the parent object moved // or scaled since the last update? bool hasMoved = !mLastObjectPosition.equal( mParentObject->getRenderPosition() ); bool hasScaled = !mLastObjectScale.equal( mParentObject->getScale() ); // Set the last light direction // to the current light direction. mLastLightDir = lightDir; mLastObjectPosition = mParentObject->getRenderPosition(); mLastObjectScale = mParentObject->getScale(); // Temps used to generate // tangent vector for DecalInstance below. VectorF right( 0, 0, 0 ); VectorF fwd( 0, 0, 0 ); VectorF tmpFwd( 0, 0, 0 ); U32 idx = lightDir.getLeastComponentIndex(); tmpFwd[idx] = 1.0f; right = mCross( tmpFwd, lightDir ); fwd = mCross( lightDir, right ); right = mCross( fwd, lightDir ); right.normalize(); // Set up the world to light space // matrix, along with proper position // and rotation to be used as the world // matrix for the render to texture later on. static MatrixF sRotMat(EulerF( 0.0f, -(M_PI_F/2.0f), 0.0f)); mWorldToLight.identity(); MathUtils::getMatrixFromForwardVector( lightDir, &mWorldToLight ); mWorldToLight.setPosition( ( pos + boxCenter ) - ( ( (mRadius * smDepthAdjust) + 0.001f ) * lightDir ) ); mWorldToLight.mul( sRotMat ); mWorldToLight.inverse(); // Get the shapebase datablock if we have one. ShapeBaseData *data = NULL; if ( mShapeBase ) data = static_cast<ShapeBaseData*>( mShapeBase->getDataBlock() ); // We use the object box's extents multiplied // by the object's scale divided by 2 for the radius // because the object's worldsphere radius is not // rotationally invariant. mRadius = (objBox.getExtents() * mParentObject->getScale()).len() * 0.5f; if ( data ) mRadius *= data->shadowSphereAdjust; // Create the decal if we don't have one yet. if ( !mDecalInstance ) mDecalInstance = gDecalManager->addDecal( decalPos, lightDir, right, mDecalData, 1.0f, 0, PermanentDecal | ClipDecal | CustomDecal ); if ( !mDecalInstance ) return false; mDecalInstance->mVisibility = fade; // Setup decal parameters. mDecalInstance->mSize = mRadius * 2.0f; mDecalInstance->mNormal = -lightDir; mDecalInstance->mTangent = -right; mDecalInstance->mRotAroundNormal = 0; mDecalInstance->mPosition = decalPos; mDecalInstance->mDataBlock = mDecalData; // If the position of the world // space box center is the same // as the decal's position, and // the light direction has not // changed, we don't need to clip. bool shouldClip = lightDirChanged || hasMoved || hasScaled; // Now, check and see if the object is visible. const Frustum &frust = state->getCullingFrustum(); if ( frust.isCulled( SphereF( mDecalInstance->mPosition, mDecalInstance->mSize * mDecalInstance->mSize ) ) && !shouldClip ) return false; F32 shadowLen = 10.0f; if ( data ) shadowLen = data->shadowProjectionDistance; const Point3F &boxExtents = objBox.getExtents(); mShadowLength = shadowLen * mParentObject->getScale().z; // Set up clip depth, and box half // offset for decal clipping. Point2F clipParams( mShadowLength, (boxExtents.x + boxExtents.y) * 0.25f ); bool render = false; bool clipSucceeded = true; // Clip! if ( shouldClip ) { clipSucceeded = gDecalManager->clipDecal( mDecalInstance, NULL, &clipParams ); } // If the clip failed, // we'll return false in // order to keep from // unnecessarily rendering // into the texture. If // there was no reason to clip // on this update, we'll assume we // should update the texture. render = clipSucceeded; // Tell the DecalManager we've changed this decal. gDecalManager->notifyDecalModified( mDecalInstance ); return render; }