void Trigger::renderObject( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat ) { if(overrideMat) return; GFXStateBlockDesc desc; desc.setZReadWrite( true, false ); desc.setBlend( true ); // Trigger polyhedrons are set up with outward facing normals and CCW ordering // so can't enable backface culling. desc.setCullMode( GFXCullNone ); GFXTransformSaver saver; MatrixF mat = getRenderTransform(); mat.scale( getScale() ); GFX->multWorld( mat ); GFXDrawUtil *drawer = GFX->getDrawUtil(); drawer->drawPolyhedron( desc, mTriggerPolyhedron, ColorI( 255, 192, 0, 45 ) ); // Render wireframe. desc.setFillModeWireframe(); drawer->drawPolyhedron( desc, mTriggerPolyhedron, ColorI::BLACK ); }
void LightBase::prepRenderImage( SceneRenderState *state ) { if ( mIsEnabled && mFlareData ) { mFlareState.fullBrightness = mBrightness; mFlareState.scale = mFlareScale; mFlareState.lightInfo = mLight; mFlareState.lightMat = getRenderTransform(); mFlareData->prepRender( state, &mFlareState ); } if ( !state->isDiffusePass() ) return; const bool isSelectedInEditor = ( gEditingMission && isSelected() ); // If the light is selected or light visualization // is enabled then register the callback. if ( smRenderViz || isSelectedInEditor ) { ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>(); ri->renderDelegate.bind( this, &LightBase::_onRenderViz ); ri->type = RenderPassManager::RIT_Editor; state->getRenderPass()->addInst( ri ); } }
void Projectile::submitLights( LightManager *lm, bool staticLighting ) { if ( staticLighting || mHasExploded || !mDataBlock->lightDesc ) return; mDataBlock->lightDesc->submitLight( &mLightState, getRenderTransform(), lm, this ); }
void SceneSpace::_renderObject( ObjectRenderInst* ri, SceneRenderState* state, BaseMatInstance* overrideMat ) { if( overrideMat ) return; if( !mEditorRenderMaterial ) { // We have no material for rendering so just render // a plain box. GFXTransformSaver saver; MatrixF mat = getRenderTransform(); mat.scale( getScale() ); GFX->multWorld( mat ); GFXStateBlockDesc desc; desc.setZReadWrite( true, false ); desc.setBlend( true ); desc.setCullMode( GFXCullNone ); GFXDrawUtil *drawer = GFX->getDrawUtil(); drawer->drawCube( desc, mObjBox, _getDefaultEditorSolidColor() ); // Render black wireframe. desc.setFillModeWireframe(); drawer->drawCube( desc, mObjBox, _getDefaultEditorWireframeColor() ); } else { //RDTODO } }
void FlyingVehicle::updateEmitter(bool active,F32 dt,ParticleEmitterData *emitter,S32 idx,S32 count) { if (!emitter) return; for (S32 j = idx; j < idx + count; j++) if (active) { if (mDataBlock->jetNode[j] != -1) { if (!bool(mJetEmitter[j])) { mJetEmitter[j] = new ParticleEmitter; mJetEmitter[j]->onNewDataBlock(emitter,false); mJetEmitter[j]->registerObject(); } MatrixF mat; Point3F pos,axis; mat.mul(getRenderTransform(), mShapeInstance->mNodeTransforms[mDataBlock->jetNode[j]]); mat.getColumn(1,&axis); mat.getColumn(3,&pos); mJetEmitter[j]->emitParticles(pos,true,axis,getVelocity(),(U32)(dt * 1000)); } } else { for (S32 j = idx; j < idx + count; j++) if (bool(mJetEmitter[j])) { mJetEmitter[j]->deleteWhenEmpty(); mJetEmitter[j] = 0; } } }
void TurretShape::getRenderWeaponMountTransform( F32 delta, S32 mountPoint, const MatrixF &xfm, MatrixF *outMat ) { // Returns mount point to world space transform if ( mountPoint >= 0 && mountPoint < SceneObject::NumMountPoints) { S32 ni = mDataBlock->weaponMountNode[mountPoint]; if (ni != -1) { MatrixF mountTransform = mShapeInstance->mNodeTransforms[ni]; mountTransform.mul( xfm ); const Point3F& scale = getScale(); // The position of the mount point needs to be scaled. Point3F position = mountTransform.getPosition(); position.convolve( scale ); mountTransform.setPosition( position ); // Also we would like the object to be scaled to the model. mountTransform.scale( scale ); outMat->mul(getRenderTransform(), mountTransform); return; } } // Then let SceneObject handle it. GrandParent::getRenderMountTransform( delta, mountPoint, xfm, outMat ); }
void Projectile::prepBatchRender( SceneRenderState *state ) { if ( !mProjectileShape ) return; GFXTransformSaver saver; // Set up our TS render state. TSRenderState rdata; rdata.setSceneState( state ); // We might have some forward lit materials // so pass down a query to gather lights. LightQuery query; query.init( getWorldSphere() ); rdata.setLightQuery( &query ); MatrixF mat = getRenderTransform(); mat.scale( mObjScale ); mat.scale( mDataBlock->scale ); GFX->setWorldMatrix( mat ); mProjectileShape->setDetailFromPosAndScale( state, mat.getPosition(), mObjScale ); mProjectileShape->animate(); mProjectileShape->render( rdata ); }
void Shape3DOverlay::render(RenderArgs* args) { if (!_renderVisible) { return; // do nothing if we're not visible } float alpha = getAlpha(); xColor color = getColor(); const float MAX_COLOR = 255.0f; glm::vec4 cubeColor(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha); auto batch = args->_batch; if (batch) { auto geometryCache = DependencyManager::get<GeometryCache>(); auto shapePipeline = args->_shapePipeline; if (!shapePipeline) { shapePipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline(); } batch->setModelTransform(getRenderTransform()); if (_isSolid) { geometryCache->renderSolidShapeInstance(args, *batch, _shape, cubeColor, shapePipeline); } else { geometryCache->renderWireShapeInstance(args, *batch, _shape, cubeColor, shapePipeline); } } }
void TerrainBlock::_renderDebug( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat ) { GFXTransformSaver saver; GFX->multWorld( getRenderTransform() ); for ( U32 i=0; i < mDebugCells.size(); i++ ) mDebugCells[i]->renderBounds(); mDebugCells.clear(); }
void TSStatic::_renderNormals( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat ) { PROFILE_SCOPE( TSStatic_RenderNormals ); GFXTransformSaver saver; MatrixF mat = getRenderTransform(); mat.scale( mObjScale ); GFX->multWorld( mat ); S32 dl = mShapeInstance->getCurrentDetail(); mShapeInstance->renderDebugNormals( mRenderNormalScalar, dl ); }
void WaterPlane::setShaderParams( SceneRenderState *state, BaseMatInstance* mat, const WaterMatParams& paramHandles) { // Set variables that will be assigned to shader consts within WaterCommon // before calling Parent::setShaderParams mUndulateMaxDist = mGridElementSize * mGridSizeMinusOne * 0.5f; Parent::setShaderParams( state, mat, paramHandles ); // Now set the rest of the shader consts that are either unique to this // class or that WaterObject leaves to us to handle... MaterialParameters* matParams = mat->getMaterialParameters(); // set vertex shader constants //----------------------------------- matParams->setSafe(paramHandles.mGridElementSizeSC, (F32)mGridElementSize); //matParams->setSafe( paramHandles.mReflectTexSizeSC, mReflectTexSize ); if ( paramHandles.mModelMatSC->isValid() ) matParams->set(paramHandles.mModelMatSC, getRenderTransform(), GFXSCT_Float4x4); // set pixel shader constants //----------------------------------- ColorF c( mWaterFogData.color ); matParams->setSafe( paramHandles.mBaseColorSC, c ); // By default we need to show a true reflection is fullReflect is enabled and // we are above water. F32 reflect = mPlaneReflector.isEnabled() && !isUnderwater( state->getCameraPosition() ); // If we were occluded the last frame a query was fetched ( not necessarily last frame ) // and we weren't updated last frame... we don't have a valid texture to show // so use the cubemap / fake reflection color this frame. if ( mPlaneReflector.lastUpdateMs != REFLECTMGR->getLastUpdateMs() && mPlaneReflector.isOccluded() ) reflect = false; //Point4F reflectParams( getRenderPosition().z, mReflectMinDist, mReflectMaxDist, reflect ); Point4F reflectParams( getRenderPosition().z, 0.0f, 1000.0f, !reflect ); // TODO: This is a hack... why is this broken... check after // we merge advanced lighting with trunk! // reflectParams.z = 0.0f; matParams->setSafe( paramHandles.mReflectParamsSC, reflectParams ); VectorF reflectNorm( 0, 0, 1 ); matParams->setSafe(paramHandles.mReflectNormalSC, reflectNorm ); }
void TurretShape::getRenderImageTransform(U32 imageSlot,S32 node,MatrixF* mat) { // Same as ShapeBase::getRenderImageTransform() other than getRenderWeaponMountTransform() below // Image transform in world space MountedImage& image = mMountedImageList[imageSlot]; if (image.dataBlock) { if (node != -1) { ShapeBaseImageData& data = *image.dataBlock; U32 shapeIndex = getImageShapeIndex(image); MatrixF nmat = image.shapeInstance[shapeIndex]->mNodeTransforms[node]; MatrixF mmat; if ( data.useEyeNode && isFirstPerson() && data.eyeMountNode[shapeIndex] != -1 ) { MatrixF emat; getRenderEyeBaseTransform(&emat, mDataBlock->mountedImagesBank); MatrixF mountTransform = image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeMountNode[shapeIndex]]; mountTransform.affineInverse(); mmat.mul(emat, mountTransform); } else if ( data.useEyeOffset && isFirstPerson() ) { MatrixF emat; getRenderEyeTransform(&emat); mmat.mul(emat,data.eyeOffset); } else { MatrixF emat; getRenderWeaponMountTransform( 0.0f, imageSlot, MatrixF::Identity, &emat ); mmat.mul(emat,data.mountTransform[shapeIndex]); } mat->mul(mmat, nmat); } else getRenderImageTransform(imageSlot,mat); } else *mat = getRenderTransform(); }
void Projectile::updateSound() { if (!mDataBlock->sound) return; if ( mHidden && mSound ) mSound->stop(); else if ( !mHidden && mSound ) { if ( !mSound->isPlaying() ) mSound->play(); mSound->setVelocity( getVelocity() ); mSound->setTransform( getRenderTransform() ); } }
void MetaShapeRenderer::render( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat ) { if ( overrideMat ) return; PROFILE_SCOPE(MetaShapeRenderer_Render); mPolyList.render(); if ( mVertexBuffer.isNull() ) return; // Set up a GFX debug event (this helps with debugging rendering events in external tools) GFXDEBUGEVENT_SCOPE( MetaShapeRenderer_Render, ColorI::RED ); // GFXTransformSaver is a handy helper class that restores // the current GFX matrices to their original values when // it goes out of scope at the end of the function GFXTransformSaver saver; // Calculate our object to world transform matrix MatrixF objectToWorld = getRenderTransform(); objectToWorld.scale( getScale() ); // Apply our object transform GFX->multWorld( objectToWorld ); // Deal with reflect pass otherwise // set the normal StateBlock if ( state->isReflectPass() ) GFX->setStateBlock( mReflectSB ); else GFX->setStateBlock( mNormalSB ); // Set up the "generic" shaders // These handle rendering on GFX layers that don't support // fixed function. Otherwise they disable shaders. GFX->setupGenericShaders( GFXDevice::GSModColorTexture ); // Set the vertex buffer GFX->setVertexBuffer( mVertexBuffer ); // Draw our triangles GFX->drawPrimitive( GFXTriangleList, 0, 12 ); }
void LightBase::submitLights( LightManager *lm, bool staticLighting ) { if ( !mIsEnabled || staticLighting ) return; if ( mAnimState.active && mAnimState.animationPeriod > 0.0f && mAnimationData ) { mAnimState.brightness = mBrightness; mAnimState.transform = getRenderTransform(); mAnimState.color = mColor; mAnimationData->animate( mLight, &mAnimState ); } lm->registerGlobalLight( mLight, this ); }
SceneData WaterPlane::setupSceneGraphInfo( SceneRenderState *state ) { SceneData sgData; sgData.lights[0] = LIGHTMGR->getSpecialLight( LightManager::slSunLightType ); // fill in water's transform sgData.objTrans = &getRenderTransform(); // fog sgData.setFogParams( state->getSceneManager()->getFogData() ); // misc sgData.backBuffTex = REFLECTMGR->getRefractTex(); sgData.reflectTex = mPlaneReflector.reflectTex; sgData.wireframe = GFXDevice::getWireframe() || smWireframe; return sgData; }
void Text3DOverlay::render(RenderArgs* args) { if (!_renderVisible || !getParentVisible()) { return; // do nothing if we're not visible } Q_ASSERT(args->_batch); auto& batch = *args->_batch; auto transform = getRenderTransform(); batch.setModelTransform(transform); glm::u8vec3 backgroundColor = getBackgroundColor(); glm::vec4 quadColor(toGlm(backgroundColor), getBackgroundAlpha()); glm::vec2 dimensions = getDimensions(); glm::vec2 halfDimensions = dimensions * 0.5f; const float SLIGHTLY_BEHIND = -0.001f; glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND); glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND); DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, quadColor.a < 1.0f, false, false, false); DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, quadColor, _geometryId); // Same font properties as textSize() float maxHeight = (float)_textRenderer->computeExtent("Xy").y * LINE_SCALE_RATIO; float scaleFactor = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight; glm::vec2 clipDimensions((dimensions.x - (_leftMargin + _rightMargin)) / scaleFactor, (dimensions.y - (_topMargin + _bottomMargin)) / scaleFactor); transform.postTranslate(glm::vec3(-(halfDimensions.x - _leftMargin), halfDimensions.y - _topMargin, 0.001f)); transform.setScale(scaleFactor); batch.setModelTransform(transform); glm::vec4 textColor = { toGlm(_color), getTextAlpha() }; // FIXME: Factor out textRenderer so that Text3DOverlay overlay parts can be grouped by pipeline for a gpu performance increase. _textRenderer->draw(batch, 0, 0, getText(), textColor, glm::vec2(-1.0f), true); }
void TurretShape::getRenderImageTransform( U32 imageSlot, MatrixF* mat, bool noEyeOffset ) { // Image transform in world space MountedImage& image = mMountedImageList[imageSlot]; if (image.dataBlock) { ShapeBaseImageData& data = *image.dataBlock; MatrixF nmat; if ( !noEyeOffset && data.useEyeOffset && isFirstPerson() ) { getRenderEyeTransform(&nmat); mat->mul(nmat,data.eyeOffset); } else { getRenderWeaponMountTransform( 0.0f, imageSlot, MatrixF::Identity, &nmat ); mat->mul(nmat,data.mountTransform[getImageShapeIndex(image)]); } } else *mat = getRenderTransform(); }
void Projectile::prepBatchRender( SceneState *state ) { GFXTransformSaver saver; // Set up our TS render state. TSRenderState rdata; rdata.setSceneState( state ); MatrixF mat = getRenderTransform(); mat.scale( mObjScale ); mat.scale( mDataBlock->scale ); GFX->setWorldMatrix( mat ); if(mProjectileShape) { AssertFatal(mProjectileShape != NULL, "Projectile::renderObject: Error, projectile shape should always be present in renderObject"); mProjectileShape->setDetailFromPosAndScale( state, mat.getPosition(), mObjScale ); mProjectileShape->animate(); mProjectileShape->render( rdata ); } }
//-------------------------------------------------------------------------- bool Projectile::prepRenderImage(SceneState* state, const U32 stateKey, const U32 /*startZone*/, const bool /*modifyBaseState*/) { if (isLastState(state, stateKey)) return false; setLastState(state, stateKey); if (mHidden == true || mFadeValue <= (1.0/255.0)) return false; // This should be sufficient for most objects that don't manage zones, and // don't need to return a specialized RenderImage... if (state->isObjectRendered(this)) { if ( mDataBlock->lightDesc ) { mDataBlock->lightDesc->prepRender( state, &mLightState, getRenderTransform() ); } /* if ( mFlareData ) { mFlareState.fullBrightness = mDataBlock->lightDesc->mBrightness; mFlareState.scale = mFlareScale; mFlareState.lightInfo = mLight; mFlareState.lightMat = getTransform(); mFlareData->prepRender( state, &mFlareState ); } */ prepBatchRender( state ); } return false; }
//-------------------------------------------------------------------------- void Projectile::prepRenderImage( SceneRenderState* state ) { if (mHasExploded || mFadeValue <= (1.0/255.0)) return; if ( mDataBlock->lightDesc ) { mDataBlock->lightDesc->prepRender( state, &mLightState, getRenderTransform() ); } /* if ( mFlareData ) { mFlareState.fullBrightness = mDataBlock->lightDesc->mBrightness; mFlareState.scale = mFlareScale; mFlareState.lightInfo = mLight; mFlareState.lightMat = getTransform(); mFlareData->prepRender( state, &mFlareState ); } */ prepBatchRender( state ); }
void WaterPlane::innerRender( SceneRenderState *state ) { GFXDEBUGEVENT_SCOPE( WaterPlane_innerRender, ColorI( 255, 0, 0 ) ); const Point3F &camPosition = state->getCameraPosition(); Point3F rvec, fvec, uvec, pos; const MatrixF &objMat = getTransform(); //getRenderTransform(); const MatrixF &camMat = state->getCameraTransform(); MatrixF renderMat( true ); camMat.getColumn( 1, &fvec ); uvec.set( 0, 0, 1 ); rvec = mCross( fvec, uvec ); rvec.normalize(); fvec = mCross( uvec, rvec ); pos = camPosition; pos.z = objMat.getPosition().z; renderMat.setColumn( 0, rvec ); renderMat.setColumn( 1, fvec ); renderMat.setColumn( 2, uvec ); renderMat.setColumn( 3, pos ); setRenderTransform( renderMat ); // Setup SceneData SceneData sgData = setupSceneGraphInfo( state ); // set the material S32 matIdx = getMaterialIndex( camPosition ); if ( !initMaterial( matIdx ) ) return; BaseMatInstance *mat = mMatInstances[matIdx]; WaterMatParams matParams = mMatParamHandles[matIdx]; // render the geometry if ( mat ) { // setup proj/world transform mMatrixSet->restoreSceneViewProjection(); mMatrixSet->setWorld(getRenderTransform()); setShaderParams( state, mat, matParams ); while( mat->setupPass( state, sgData ) ) { mat->setSceneInfo(state, sgData); mat->setTransforms(*mMatrixSet, state, sgData); setCustomTextures( matIdx, mat->getCurPass(), matParams ); // set vert/prim buffer GFX->setVertexBuffer( mVertBuff ); GFX->setPrimitiveBuffer( mPrimBuff ); GFX->drawIndexedPrimitive( GFXTriangleList, 0, 0, mVertCount, 0, mPrimCount ); } } }
void TurretShape::getCameraTransform(F32* pos,MatrixF* mat) { // Returns camera to world space transform // Handles first person / third person camera position if (isServerObject() && mShapeInstance) mShapeInstance->animateNodeSubtrees(true); if (*pos == 0) { getRenderEyeTransform(mat); return; } // Get the shape's camera parameters. F32 min,max; MatrixF rot; Point3F offset; getCameraParameters(&min,&max,&offset,&rot); // Start with the current eye position MatrixF eye; getRenderEyeTransform(&eye); // Build a transform that points along the eye axis // but where the Z axis is always up. { MatrixF cam(1); VectorF x,y,z(0,0,1); eye.getColumn(1, &y); mCross(y, z, &x); x.normalize(); mCross(x, y, &z); z.normalize(); cam.setColumn(0,x); cam.setColumn(1,y); cam.setColumn(2,z); mat->mul(cam,rot); } // Camera is positioned straight back along the eye's -Y axis. // A ray is cast to make sure the camera doesn't go through // anything solid. VectorF vp,vec; vp.x = vp.z = 0; vp.y = -(max - min) * *pos; eye.mulV(vp,&vec); // Use the camera node as the starting position if it exists. Point3F osp,sp; if (mDataBlock->cameraNode != -1) { mShapeInstance->mNodeTransforms[mDataBlock->cameraNode].getColumn(3,&osp); getRenderTransform().mulP(osp,&sp); } else eye.getColumn(3,&sp); // Make sure we don't hit ourself... disableCollision(); if (isMounted()) getObjectMount()->disableCollision(); // Cast the ray into the container database to see if we're going // to hit anything. RayInfo collision; Point3F ep = sp + vec + offset; if (mContainer->castRay(sp, ep, ~(WaterObjectType | GameBaseObjectType | DefaultObjectType | sTriggerMask), &collision) == true) { // Shift the collision point back a little to try and // avoid clipping against the front camera plane. F32 t = collision.t - (-mDot(vec, collision.normal) / vec.len()) * 0.1; if (t > 0.0f) ep = sp + offset + (vec * t); else eye.getColumn(3,&ep); } mat->setColumn(3,ep); // Re-enable our collision. if (isMounted()) getObjectMount()->enableCollision(); enableCollision(); // Apply Camera FX. mat->mul( gCamFXMgr.getTrans() ); }
void TSStatic::prepRenderImage( SceneRenderState* state ) { if( !mShapeInstance ) return; Point3F cameraOffset; getRenderTransform().getColumn(3,&cameraOffset); cameraOffset -= state->getDiffuseCameraPosition(); F32 dist = cameraOffset.len(); if (dist < 0.01f) dist = 0.01f; F32 invScale = (1.0f/getMax(getMax(mObjScale.x,mObjScale.y),mObjScale.z)); if ( mForceDetail == -1 ) mShapeInstance->setDetailFromDistance( state, dist * invScale ); else mShapeInstance->setCurrentDetail( mForceDetail ); if ( mShapeInstance->getCurrentDetail() < 0 ) return; GFXTransformSaver saver; // Set up our TS render state. TSRenderState rdata; rdata.setSceneState( state ); rdata.setFadeOverride( 1.0f ); rdata.setOriginSort( mUseOriginSort ); // If we have submesh culling enabled then prepare // the object space frustum to pass to the shape. Frustum culler; if ( mMeshCulling ) { culler = state->getFrustum(); MatrixF xfm( true ); xfm.scale( Point3F::One / getScale() ); xfm.mul( getRenderWorldTransform() ); xfm.mul( culler.getTransform() ); culler.setTransform( xfm ); rdata.setCuller( &culler ); } // We might have some forward lit materials // so pass down a query to gather lights. LightQuery query; query.init( getWorldSphere() ); rdata.setLightQuery( &query ); MatrixF mat = getRenderTransform(); mat.scale( mObjScale ); GFX->setWorldMatrix( mat ); mShapeInstance->animate(); mShapeInstance->render( rdata ); if ( mRenderNormalScalar > 0 ) { ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>(); ri->renderDelegate.bind( this, &TSStatic::_renderNormals ); ri->type = RenderPassManager::RIT_Editor; state->getRenderPass()->addInst( ri ); } }
void ProximityMine::processTick( const Move* move ) { Parent::processTick( move ); // Process state machine mStateTimeout -= TickSec; State lastState = NumStates;; while ( mState != lastState ) { lastState = mState; switch ( mState ) { case Thrown: if ( mAtRest ) { mState = Deployed; mStateTimeout = mDataBlock->armingDelay; // Get deployed position if mine was not stuck to another surface if ( mStickyCollisionPos.isZero() ) { mObjToWorld.getColumn( 2, &mStickyCollisionNormal ); mObjToWorld.getColumn( 3, &mStickyCollisionPos ); } setDeployedPos( mStickyCollisionPos, mStickyCollisionNormal ); if ( mDataBlock->armingSequence != -1 ) { mAnimThread = mShapeInstance->addThread(); mShapeInstance->setSequence( mAnimThread, mDataBlock->armingSequence, 0.0f ); } if ( mDataBlock->armingSound ) SFX->playOnce( mDataBlock->armingSound, &getRenderTransform() ); } break; case Deployed: // Timeout into Armed state if ( mStateTimeout <= 0 ) { mState = Armed; mStateTimeout = mDataBlock->autoTriggerDelay ? mDataBlock->autoTriggerDelay : F32_MAX; } break; case Armed: { // Check for objects within the trigger area Box3F triggerBox( mDataBlock->triggerRadius * 2 ); triggerBox.setCenter( getTransform().getPosition() ); SimpleQueryList sql; getContainer()->findObjects( triggerBox, sTriggerCollisionMask, SimpleQueryList::insertionCallback, &sql ); for ( int i = 0; i < sql.mList.size(); i++ ) { // Detect movement in the trigger area if ( ( sql.mList[i] == mOwner && !mDataBlock->triggerOnOwner ) || sql.mList[i]->getVelocity().len() < mDataBlock->triggerSpeed ) continue; // Mine has been triggered mShapeInstance->destroyThread( mAnimThread ); mAnimThread = NULL; mState = Triggered; mStateTimeout = mDataBlock->triggerDelay; if ( mDataBlock->triggerSequence != -1 ) { mAnimThread = mShapeInstance->addThread(); mShapeInstance->setSequence( mAnimThread, mDataBlock->triggerSequence, 0.0f ); } if ( mDataBlock->triggerSound ) SFX->playOnce( mDataBlock->triggerSound, &getRenderTransform() ); if ( isServerObject() ) mDataBlock->onTriggered_callback( this, sql.mList[0] ); } break; } case Triggered: // Timeout into exploded state if ( mStateTimeout <= 0 ) { explode(); } break; case Exploded: // Mine's delete themselves on the server after exploding if ( isServerObject() && ( mStateTimeout <= 0 ) ) { deleteObject(); return; } break; } } }
void RenderMeshExample::prepRenderImage( SceneRenderState *state ) { // Do a little prep work if needed if ( mVertexBuffer.isNull() ) createGeometry(); // If we have no material then skip out. if ( !mMaterialInst ) return; // If we don't have a material instance after the override then // we can skip rendering all together. BaseMatInstance *matInst = state->getOverrideMaterial( mMaterialInst ); if ( !matInst ) return; // Get a handy pointer to our RenderPassmanager RenderPassManager *renderPass = state->getRenderPass(); // Allocate an MeshRenderInst so that we can submit it to the RenderPassManager MeshRenderInst *ri = renderPass->allocInst<MeshRenderInst>(); // Set our RenderInst as a standard mesh render ri->type = RenderPassManager::RIT_Mesh; // Calculate our sorting point if ( state ) { // Calculate our sort point manually. const Box3F& rBox = getRenderWorldBox(); ri->sortDistSq = rBox.getSqDistanceToPoint( state->getCameraPosition() ); } else ri->sortDistSq = 0.0f; // Set up our transforms MatrixF objectToWorld = getRenderTransform(); objectToWorld.scale( getScale() ); ri->objectToWorld = renderPass->allocUniqueXform( objectToWorld ); ri->worldToCamera = renderPass->allocSharedXform(RenderPassManager::View); ri->projection = renderPass->allocSharedXform(RenderPassManager::Projection); // If our material needs lights then fill the RIs // light vector with the best lights. if ( matInst->isForwardLit() ) { LightQuery query; query.init( getWorldSphere() ); query.getLights( ri->lights, 8 ); } // Make sure we have an up-to-date backbuffer in case // our Material would like to make use of it // NOTICE: SFXBB is removed and refraction is disabled! //ri->backBuffTex = GFX->getSfxBackBuffer(); // Set our Material ri->matInst = matInst; // Set up our vertex buffer and primitive buffer ri->vertBuff = &mVertexBuffer; ri->primBuff = &mPrimitiveBuffer; ri->prim = renderPass->allocPrim(); ri->prim->type = GFXTriangleList; ri->prim->minIndex = 0; ri->prim->startIndex = 0; ri->prim->numPrimitives = 12; ri->prim->startVertex = 0; ri->prim->numVertices = 36; // We sort by the material then vertex buffer ri->defaultKey = matInst->getStateHint(); ri->defaultKey2 = (U32)ri->vertBuff; // Not 64bit safe! // Submit our RenderInst to the RenderPassManager state->getRenderPass()->addInst( ri ); }
void TerrainBlock::_renderBlock( SceneRenderState *state ) { PROFILE_SCOPE( TerrainBlock_RenderBlock ); // Prevent rendering shadows if feature is disabled if ( !mCastShadows && state->isShadowPass() ) return; MatrixF worldViewXfm = state->getWorldViewMatrix(); worldViewXfm.mul( getRenderTransform() ); MatrixF worldViewProjXfm = state->getProjectionMatrix(); worldViewProjXfm.mul( worldViewXfm ); const MatrixF &objectXfm = getRenderWorldTransform(); Point3F objCamPos = state->getDiffuseCameraPosition(); objectXfm.mulP( objCamPos ); // Get the shadow material. if ( !mDefaultMatInst ) mDefaultMatInst = TerrainCellMaterial::getShadowMat(); // Make sure we have a base material. if ( !mBaseMaterial ) { mBaseMaterial = new TerrainCellMaterial(); mBaseMaterial->init( this, 0, false, false, true ); } // Did the detail layers change? if ( mDetailsDirty ) { _updateMaterials(); mDetailsDirty = false; } // If the layer texture has been cleared or is // dirty then update it. if ( mLayerTex.isNull() || mLayerTexDirty ) _updateLayerTexture(); // If the layer texture is dirty or we lost the base // texture then regenerate it. if ( mLayerTexDirty || mBaseTex.isNull() ) { _updateBaseTexture( false ); mLayerTexDirty = false; } static Vector<TerrCell*> renderCells; renderCells.clear(); mCell->cullCells( state, objCamPos, &renderCells ); RenderPassManager *renderPass = state->getRenderPass(); MatrixF *riObjectToWorldXfm = renderPass->allocUniqueXform( getRenderTransform() ); const bool isColorDrawPass = state->isDiffusePass() || state->isReflectPass(); // This is here for shadows mostly... it allows the // proper shadow material to be generated. BaseMatInstance *defaultMatInst = state->getOverrideMaterial( mDefaultMatInst ); // Only pass and use the light manager if this is not a shadow pass. LightManager *lm = NULL; if ( isColorDrawPass ) lm = LIGHTMGR; for ( U32 i=0; i < renderCells.size(); i++ ) { TerrCell *cell = renderCells[i]; // Ok this cell is fit to render. TerrainRenderInst *inst = renderPass->allocInst<TerrainRenderInst>(); // Setup lights for this cell. if ( lm ) { SphereF bounds = cell->getSphereBounds(); getRenderTransform().mulP( bounds.center ); LightQuery query; query.init( bounds ); query.getLights( inst->lights, 8 ); } GFXVertexBufferHandleBase vertBuff; GFXPrimitiveBufferHandle primBuff; cell->getRenderPrimitive( &inst->prim, &vertBuff, &primBuff ); inst->mat = defaultMatInst; inst->vertBuff = vertBuff.getPointer(); if ( primBuff.isValid() ) { // Use the cell's custom primitive buffer inst->primBuff = primBuff.getPointer(); } else { // Use the standard primitive buffer for this cell inst->primBuff = mPrimBuffer.getPointer(); } inst->objectToWorldXfm = riObjectToWorldXfm; // If we're not drawing to the shadow map then we need // to include the normal rendering materials. if ( isColorDrawPass ) { const SphereF &bounds = cell->getSphereBounds(); F32 sqDist = ( bounds.center - objCamPos ).lenSquared(); F32 radiusSq = mSquared( ( mMaxDetailDistance + bounds.radius ) * smDetailScale ); // If this cell is near enough to get detail textures then // use the full detail mapping material. Else we use the // simple base only material. if ( !state->isReflectPass() && sqDist < radiusSq ) inst->cellMat = cell->getMaterial(); else if ( state->isReflectPass() ) inst->cellMat = mBaseMaterial->getReflectMat(); else inst->cellMat = mBaseMaterial; } inst->defaultKey = (U32)cell->getMaterials(); // Submit it for rendering. renderPass->addInst( inst ); } // Trigger the debug rendering. if ( state->isDiffusePass() && !renderCells.empty() && smDebugRender ) { // Store the render cells for later. mDebugCells = renderCells; ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>(); ri->renderDelegate.bind( this, &TerrainBlock::_renderDebug ); ri->type = RenderPassManager::RIT_Editor; state->getRenderPass()->addInst( ri ); } }
void ConvexShape::prepRenderImage( SceneRenderState *state ) { /* if ( state->isDiffusePass() ) { ObjectRenderInst *ri2 = state->getRenderPass()->allocInst<ObjectRenderInst>(); ri2->renderDelegate.bind( this, &ConvexShape::_renderDebug ); ri2->type = RenderPassManager::RIT_Editor; state->getRenderPass()->addInst( ri2 ); } */ if ( mVertexBuffer.isNull() ) return; // If we don't have a material instance after the override then // we can skip rendering all together. BaseMatInstance *matInst = state->getOverrideMaterial( mMaterialInst ? mMaterialInst : MATMGR->getWarningMatInstance() ); if ( !matInst ) return; // Get a handy pointer to our RenderPassmanager RenderPassManager *renderPass = state->getRenderPass(); // Allocate an MeshRenderInst so that we can submit it to the RenderPassManager MeshRenderInst *ri = renderPass->allocInst<MeshRenderInst>(); // Set our RenderInst as a standard mesh render ri->type = RenderPassManager::RIT_Mesh; // Calculate our sorting point if ( state ) { // Calculate our sort point manually. const Box3F& rBox = getRenderWorldBox(); ri->sortDistSq = rBox.getSqDistanceToPoint( state->getCameraPosition() ); } else ri->sortDistSq = 0.0f; // Set up our transforms MatrixF objectToWorld = getRenderTransform(); objectToWorld.scale( getScale() ); ri->objectToWorld = renderPass->allocUniqueXform( objectToWorld ); ri->worldToCamera = renderPass->allocSharedXform(RenderPassManager::View); ri->projection = renderPass->allocSharedXform(RenderPassManager::Projection); // If we need lights then set them up. if ( matInst->isForwardLit() ) { LightQuery query; query.init( getWorldSphere() ); query.getLights( ri->lights, 8 ); } // Make sure we have an up-to-date backbuffer in case // our Material would like to make use of it // NOTICE: SFXBB is removed and refraction is disabled! //ri->backBuffTex = GFX->getSfxBackBuffer(); // Set our Material ri->matInst = matInst; if ( matInst->getMaterial()->isTranslucent() ) { ri->translucentSort = true; ri->type = RenderPassManager::RIT_Translucent; } // Set up our vertex buffer and primitive buffer ri->vertBuff = &mVertexBuffer; ri->primBuff = &mPrimitiveBuffer; ri->prim = renderPass->allocPrim(); ri->prim->type = GFXTriangleList; ri->prim->minIndex = 0; ri->prim->startIndex = 0; ri->prim->numPrimitives = mPrimCount; ri->prim->startVertex = 0; ri->prim->numVertices = mVertCount; // We sort by the material then vertex buffer. ri->defaultKey = matInst->getStateHint(); ri->defaultKey2 = (U32)ri->vertBuff; // Not 64bit safe! // Submit our RenderInst to the RenderPassManager state->getRenderPass()->addInst( ri ); }
void ConvexShape::_renderDebug( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *mat ) { GFXDrawUtil *drawer = GFX->getDrawUtil(); GFX->setTexture( 0, NULL ); // Render world box. if ( false ) { Box3F wbox( mWorldBox ); //if ( getServerObject() ) // Box3F wbox = static_cast<ConvexShape*>( getServerObject() )->mWorldBox; GFXStateBlockDesc desc; desc.setCullMode( GFXCullNone ); desc.setFillModeWireframe(); drawer->drawCube( desc, wbox, ColorI::RED ); } const Vector< Point3F > &pointList = mGeometry.points; const Vector< ConvexShape::Face > &faceList = mGeometry.faces; // Render Edges. if ( false ) { GFXTransformSaver saver; //GFXFrustumSaver fsaver; MatrixF xfm( getRenderTransform() ); xfm.scale( getScale() ); GFX->multWorld( xfm ); GFXStateBlockDesc desc; desc.setZReadWrite( true, false ); desc.setBlend( true ); GFX->setStateBlockByDesc( desc ); //MathUtils::getZBiasProjectionMatrix( 0.01f, state->getFrustum(), ) const Point3F &camFvec = state->getCameraTransform().getForwardVector(); for ( S32 i = 0; i < faceList.size(); i++ ) { const ConvexShape::Face &face = faceList[i]; const Vector< ConvexShape::Edge > &edgeList = face.edges; const Vector< U32 > &facePntList = face.points; PrimBuild::begin( GFXLineList, edgeList.size() * 2 ); PrimBuild::color( ColorI::WHITE * 0.8f ); for ( S32 j = 0; j < edgeList.size(); j++ ) { PrimBuild::vertex3fv( pointList[ facePntList[ edgeList[j].p0 ] ] - camFvec * 0.001f ); PrimBuild::vertex3fv( pointList[ facePntList[ edgeList[j].p1 ] ] - camFvec * 0.001f ); } PrimBuild::end(); } } ColorI faceColorsx[4] = { ColorI( 255, 0, 0 ), ColorI( 0, 255, 0 ), ColorI( 0, 0, 255 ), ColorI( 255, 0, 255 ) }; MatrixF objToWorld( mObjToWorld ); objToWorld.scale( mObjScale ); // Render faces centers/colors. if ( false ) { GFXStateBlockDesc desc; desc.setCullMode( GFXCullNone ); Point3F size( 0.1f ); for ( S32 i = 0; i < faceList.size(); i++ ) { ColorI color = faceColorsx[ i % 4 ]; S32 div = ( i / 4 ) * 4; if ( div > 0 ) color /= div; color.alpha = 255; Point3F pnt; objToWorld.mulP( faceList[i].centroid, &pnt ); drawer->drawCube( desc, size, pnt, color, NULL ); } } // Render winding order. if ( false ) { GFXStateBlockDesc desc; desc.setCullMode( GFXCullNone ); desc.setZReadWrite( true, false ); GFX->setStateBlockByDesc( desc ); U32 pointCount = 0; for ( S32 i = 0; i < faceList.size(); i++ ) pointCount += faceList[i].winding.size(); PrimBuild::begin( GFXLineList, pointCount * 2 ); for ( S32 i = 0; i < faceList.size(); i++ ) { for ( S32 j = 0; j < faceList[i].winding.size(); j++ ) { Point3F p0 = pointList[ faceList[i].points[ faceList[i].winding[j] ] ]; Point3F p1 = p0 + mSurfaces[ faceList[i].id ].getUpVector() * 0.75f * ( Point3F::One / mObjScale ); objToWorld.mulP( p0 ); objToWorld.mulP( p1 ); ColorI color = faceColorsx[ j % 4 ]; S32 div = ( j / 4 ) * 4; if ( div > 0 ) color /= div; color.alpha = 255; PrimBuild::color( color ); PrimBuild::vertex3fv( p0 ); PrimBuild::color( color ); PrimBuild::vertex3fv( p1 ); } } PrimBuild::end(); } // Render Points. if ( false ) { /* GFXTransformSaver saver; MatrixF xfm( getRenderTransform() ); xfm.scale( getScale() ); GFX->multWorld( xfm ); GFXStateBlockDesc desc; Point3F size( 0.05f ); */ } // Render surface transforms. if ( false ) { GFXStateBlockDesc desc; desc.setBlend( false ); desc.setZReadWrite( true, true ); Point3F scale(mNormalLength); for ( S32 i = 0; i < mSurfaces.size(); i++ ) { MatrixF objToWorld( mObjToWorld ); objToWorld.scale( mObjScale ); MatrixF renderMat; renderMat.mul( objToWorld, mSurfaces[i] ); renderMat.setPosition( renderMat.getPosition() + renderMat.getUpVector() * 0.001f ); drawer->drawTransform( desc, renderMat, &scale, NULL ); } } }
void Image3DOverlay::render(RenderArgs* args) { if (!_renderVisible || !getParentVisible() || !_texture || !_texture->isLoaded()) { return; } // Once the texture has loaded, check if we need to update the render item because of transparency if (!_textureIsLoaded && _texture && _texture->getGPUTexture()) { _textureIsLoaded = true; bool prevAlphaTexture = _alphaTexture; _alphaTexture = _texture->getGPUTexture()->getUsage().isAlpha(); if (_alphaTexture != prevAlphaTexture) { auto itemID = getRenderItemID(); if (render::Item::isValidID(itemID)) { render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); render::Transaction transaction; transaction.updateItem(itemID); scene->enqueueTransaction(transaction); } } } Q_ASSERT(args->_batch); gpu::Batch* batch = args->_batch; float imageWidth = _texture->getWidth(); float imageHeight = _texture->getHeight(); QRect fromImage; if (_fromImage.isNull()) { fromImage.setX(0); fromImage.setY(0); fromImage.setWidth(imageWidth); fromImage.setHeight(imageHeight); } else { float scaleX = imageWidth / _texture->getOriginalWidth(); float scaleY = imageHeight / _texture->getOriginalHeight(); fromImage.setX(scaleX * _fromImage.x()); fromImage.setY(scaleY * _fromImage.y()); fromImage.setWidth(scaleX * _fromImage.width()); fromImage.setHeight(scaleY * _fromImage.height()); } float maxSize = glm::max(fromImage.width(), fromImage.height()); float x = _keepAspectRatio ? fromImage.width() / (2.0f * maxSize) : 0.5f; float y = _keepAspectRatio ? -fromImage.height() / (2.0f * maxSize) : -0.5f; glm::vec2 topLeft(-x, -y); glm::vec2 bottomRight(x, y); glm::vec2 texCoordTopLeft((fromImage.x() + 0.5f) / imageWidth, (fromImage.y() + 0.5f) / imageHeight); glm::vec2 texCoordBottomRight((fromImage.x() + fromImage.width() - 0.5f) / imageWidth, (fromImage.y() + fromImage.height() - 0.5f) / imageHeight); float alpha = getAlpha(); glm::u8vec3 color = getColor(); glm::vec4 imageColor(toGlm(color), alpha); batch->setModelTransform(getRenderTransform()); batch->setResourceTexture(0, _texture->getGPUTexture()); DependencyManager::get<GeometryCache>()->renderQuad( *batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, imageColor, _geometryId ); batch->setResourceTexture(0, nullptr); // restore default white color after me }