/// Update shader params loaders for the entity. /// Shader params loaders are shared by entities, and need to be updated every time an entity is rendered. void UpdateEntityForRendering( CCopyEntity& entity ) { BaseEntity& base_entity = *(entity.pBaseEntity); // light params writer if( entity.GetEntityFlags() & BETYPE_LIGHTING ) { UpdateLightInfo( entity ); if( base_entity.MeshProperty().m_pShaderLightParamsLoader ) { // Set the entity to the light params loader, because a single light params loader // is shared by all the entities of this base entity. base_entity.MeshProperty().m_pShaderLightParamsLoader->SetEntity( entity.Self().lock() ); } } const float offset_world_transform_threshold = 150000.0f; if( square(offset_world_transform_threshold) < Vec3LengthSq(entity.GetWorldPose().vPosition) ) { Camera* pCam = entity.GetStage()->GetCurrentCamera(); if( pCam ) { sg_pWorldTransLoader->SetActive( true ); sg_pWorldTransLoader->SetCameraPosition( pCam->GetPosition() ); } else sg_pWorldTransLoader->SetActive( false ); } else sg_pWorldTransLoader->SetActive( false ); }
/// Perhaps this should be a member of CCopyEntity, not BaseEntity /// - m_pStage is the only member of the base entity /// - CCopyEnttiy has m_pStage void BaseEntity::SetAsEnvMapTarget( CCopyEntity& entity ) { if( entity.GetEntityFlags() & BETYPE_ENVMAPTARGET ) { // shared_ptr<CubeTextureParamsLoader> pCubeTexLoader( new CCubeTextureParamsLoader() ); // pCubeTexLoader->SetCubeTexture( 0, m_pStage->GetEntitySet()->GetRenderManager()->GetEnvMapTexture(entity.GetID()) ); // entity.m_pMeshRenderMethod->AddShaderParamsLoaderToAllRenderMethods( pCubeTexLoader ); /* if( 0 < entity.m_pMeshRenderMethod->MeshRenderMethod().size() ) { // shader LOD: fixed to 0 entity.m_pMeshRenderMethod->MeshRenderMethod(0).m_vecpShaderParamsLoader.push_back( pCubeTexLoader ); } else { // alpha entity? }*/ } }
// sets the following shader params loaders to the render method of an entity // - CEntityShaderLightParamsLoader // - Set if the BETYPE_LIGHTING flag is on // - BlendTransformsLoader // - Set if pEntity->m_MeshHandle is a skeletal mesh void InitMeshRenderMethod( CCopyEntity &entity, shared_ptr<BlendTransformsLoader> pBlendTransformsLoader ) { if( !entity.m_pMeshRenderMethod ) { entity.m_pMeshRenderMethod.reset( new MeshContainerRenderMethod ); // entity.m_pMeshRenderMethod->MeshRenderMethod().resize( 1 ); } if( entity.GetEntityFlags() & BETYPE_LIGHTING ) { shared_ptr<CEntityShaderLightParamsLoader> pLightParamsLoader( new CEntityShaderLightParamsLoader() ); pLightParamsLoader->SetEntity( entity.Self() ); entity.m_pMeshRenderMethod->SetShaderParamsLoaderToAllMeshRenderMethods( pLightParamsLoader ); } // Not used now. // Item entities set this in its own member function ItemEntity::InitMesh(). // Does any entity other than item entty need this? if( pBlendTransformsLoader ) entity.m_pMeshRenderMethod->SetShaderParamsLoaderToAllMeshRenderMethods( pBlendTransformsLoader ); /* shared_ptr<BasicMesh> pMesh = entity.m_MeshHandle.GetMesh(); if( pMesh && pMesh->GetMeshType() == MeshType::SKELETAL ) { // shared_ptr<SkeletalMesh> pSkeletalMesh // = boost::dynamic_pointer_cast<SkeletalMesh,BasicMesh>(pMesh); if( !pBlendTransformsLoader ) pBlendTransformsLoader.reset( new BlendTransformsLoader() ); entity.m_pMeshRenderMethod->SetShaderParamsLoaderToAllMeshRenderMethods( pBlendTransformsLoader ); }*/ if( true /* world position of entity has large values */ ) { entity.m_pMeshRenderMethod->SetShaderParamsLoaderToAllMeshRenderMethods( sg_pWorldTransLoader ); } }
void EntityManager::UpdatePhysics( float frametime ) { PROFILE_FUNCTION(); // frametime *= 0.5f; Scalar total_time = frametime + m_PhysOverlapTime; if (total_time > 0.1f) total_time = 0.1f; // split the timestep into fixed size chunks int num_loops = (int) (total_time / m_PhysTimestep); Scalar timestep = m_PhysTimestep; if ( false /*m_allow_smaller_timesteps*/ ) { if (num_loops == 0) num_loops = 1; timestep = total_time / num_loops; } m_PhysOverlapTime = total_time - num_loops * timestep; // TCPreAllocDynamicLinkList<CJL_PhysicsActor>& rActorList = m_pStage->m_pPhysicsManager->GetActorList(); // TCPreAllocDynamicLinkList<CJL_PhysicsActor>::LinkListIterator itrActor; int i; for (i=0 ; i<num_loops ; ++i) { // m_physics_time += timestep; // apply gravity /* for( itrActor = rActorList.Begin(); itrActor != rActorList.End(); itrActor++ ) { if( !(itrActor->GetActorFlag() & JL_ACTOR_STATIC) ) itrActor->AddWorldForce( itrActor->GetMass() * Vector3(0,-9.8f,0) ); } */ ProfileBegin( "Entity Update (Physics)" ); // update physics properties that are specific to each entity // DO NOT CONFUSE THIS WITH CCopyEntity::UpdatePhysics() CCopyEntity *pEntity; for( pEntity = m_pEntityInUse.get(); pEntity != NULL; pEntity = pEntity->m_pNextRawPtr ) { if( pEntity->GetEntityFlags() & BETYPE_COPY_PARENT_POSE ) pEntity->CopyParentPose(); // if( pEntity->inuse && pEntity->pPhysicsActor ) if( pEntity->inuse && 0 < pEntity->m_vecpPhysicsActor.size() ) pEntity->pBaseEntity->UpdatePhysics( pEntity, timestep ); UpdateEntityAfterMoving( pEntity ); } ProfileEnd( "Entity Update (Physics)" ); { PROFILE_SCOPE( "Physics Simulation" ); // handle the motions and collisions of rigid body entities // m_pStage->m_pPhysicsManager->Integrate( timestep ); m_pStage->GetPhysicsScene()->Simulate( timestep ); while( !m_pStage->GetPhysicsScene()->FetchResults( physics::SimulationStatus::RigidBodyFinished ) ) {} } // clear forces on actors /* for( itrActor = rActorList.Begin(); itrActor != rActorList.End(); itrActor++ ) { itrActor->ClearForces(); } */ } }
void EntityManager::InitEntity( boost::shared_ptr<CCopyEntity> pNewCopyEntPtr, CCopyEntity *pParent, BaseEntity *pBaseEntity, CActorDesc* pPhysActorDesc ) { CCopyEntity* pNewCopyEnt = pNewCopyEntPtr.get(); // Mark the entity as in use pNewCopyEnt->inuse = true; pNewCopyEnt->m_pSelf = pNewCopyEntPtr; pNewCopyEnt->pBaseEntity = pBaseEntity; BaseEntity& rBaseEntity = (*pBaseEntity); pNewCopyEnt->m_pStage = m_pStage; // set id and increment the counter pNewCopyEnt->m_ID = m_EntityIDConter++; // z-sort is disabled by default initialization // Entities that have translucent polygons have to turn on their copy entities' // 'BETYPE_USE_ZSORT' in InitCopyEntity() if( pNewCopyEnt->m_TypeID == CCopyEntityTypeID::ALPHA_ENTITY ) { // For alpha entity, always use the z-sorting pNewCopyEnt->RaiseEntityFlags( BETYPE_USE_ZSORT ); } else { // Otherwise, disable z-sorting by default pNewCopyEnt->ClearEntityFlags( BETYPE_USE_ZSORT ); } // set the glare type if( rBaseEntity.m_EntityFlag & BETYPE_GLARESOURCE ) { pNewCopyEnt->RaiseEntityFlags( BETYPE_GLARESOURCE ); } else if( rBaseEntity.m_EntityFlag & BETYPE_GLAREHINDER ) { pNewCopyEnt->RaiseEntityFlags( BETYPE_GLAREHINDER ); } // update world aabb pNewCopyEnt->world_aabb.TransformCoord( pNewCopyEnt->local_aabb, pNewCopyEnt->GetWorldPosition() ); // link the new copy-entity to the top of 'm_pEntityInUse' if( m_pEntityInUse ) pNewCopyEnt->SetNext( m_pEntityInUse ); else pNewCopyEnt->SetNextToNull(); // first entity in the link list m_pEntityInUse = pNewCopyEntPtr; // set the created time of the entity pNewCopyEnt->m_CreatedTime = m_pStage->GetElapsedTime(); // set parent entity pNewCopyEnt->m_pParent = pParent; if( pNewCopyEnt->m_pParent ) { // 'pNewCopyEnt' is being created as a child of another copy entity pNewCopyEnt->m_pParent->AddChild( pNewCopyEnt->m_pSelf ); // establish link from the parent to this entity } // LOG_PRINT( "linking a copy entity of " + rBaseEntity.GetNameString() + " to the tree" ); // link the new copy-entity to the entity-tree Link( pNewCopyEnt ); // update light information if( pNewCopyEnt->Lighting() ) { pNewCopyEnt->ClearLights(); // UpdateLightInfo( pNewCopyEnt ); pNewCopyEnt->sState |= CESTATE_LIGHT_INFORMATION_INVALID; } // create object for physics simulation if( pNewCopyEnt->GetEntityFlags() & BETYPE_RIGIDBODY ) { CActor *pPhysActor = NULL; if( pPhysActorDesc ) { pPhysActorDesc->WorldPose = pNewCopyEnt->GetWorldPose();// * pNewCopyEnt->GetActorLocalPose(); pPhysActorDesc->BodyDesc.LinearVelocity = pNewCopyEnt->Velocity(); // each entity has its own actor desc pPhysActor = m_pStage->GetPhysicsScene()->CreateActor( *pPhysActorDesc ); } else if( pBaseEntity->GetPhysicsActorDesc().IsValid() ) { // actor desc is defined by entity attributes CActorDesc actor_desc = pBaseEntity->GetPhysicsActorDesc(); actor_desc.WorldPose = pNewCopyEnt->GetWorldPose(); actor_desc.BodyDesc.LinearVelocity = pNewCopyEnt->Velocity(); // pNewCopyEnt->pPhysicsActor = m_pStage->GetPhysicsScene()->CreateActor( actor_desc ); pPhysActor = m_pStage->GetPhysicsScene()->CreateActor( actor_desc ); } if( pPhysActor ) { pNewCopyEnt->m_vecpPhysicsActor.resize( 1 ); pNewCopyEnt->m_vecpPhysicsActor[0] = pPhysActor; pPhysActor->m_pFrameworkData = pNewCopyEnt; } } // When all the basic properties are copied, InitCopyEntity() is called to // do additional initialization specific to each base entity. rBaseEntity.InitCopyEntity( pNewCopyEnt ); }
/** Update all the entities cerrently existing in the stage. This function must be called once per frame. - Basic steps - 1. Call BaseEntity::UpdateBaseEntity( dt ) for each base entity - 2. Save positions of copy entities - 3. Run physics simulator - 4. Remove terminated entities from the active list - 5. Call CCopyEntity::Act() for each copy entity except for child entities - 6. Update link to the entity tree node if an entity has changed its position in Act() TODO: Do 5 & 6 in a single loop to update link for each entity right after is Act(). Current code does this in separate loops. */ void EntityManager::UpdateAllEntities( float dt ) { CCopyEntity *pEntity = NULL; CCopyEntity *pPrevEntity = NULL; CCopyEntity *pTouchedEnt = NULL; ONCE( LOG_PRINT( " - updating base entities" ) ); size_t i, num_base_entities = m_vecpBaseEntity.size(); for( i=0; i<num_base_entities; i++ ) { m_vecpBaseEntity[i]->UpdateBaseEntity( dt ); } // save the current entity positions for( pEntity = m_pEntityInUse.get(); pEntity != NULL; pEntity = pEntity->m_pNextRawPtr ) { pEntity->PrevPosition() = pEntity->GetWorldPosition(); } // run physics simulator // entity position may be modified in this call UpdatePhysics( dt ); ONCE( LOG_PRINT( " - updated physics" ) ); // remove terminated entities from the active entity list ReleaseTerminatedEntities(); ONCE( LOG_PRINT( " - removed terminated entities from the active entity list" ) ); // update active entities for( pEntity = this->m_pEntityInUse.get(), pPrevEntity = NULL; pEntity != NULL; pPrevEntity = pEntity, pEntity = pEntity->m_pNextRawPtr ) { // before updating pEntity, check if it has been terminated. if( !pEntity->inuse ) continue; // set the results of physics simulation to // pose, velocity and angular velocity of the entity // if( pEntity->pPhysicsActor && pEntity->GetEntityFlags() & BETYPE_USE_PHYSSIM_RESULTS ) if( 0 < pEntity->m_vecpPhysicsActor.size() && pEntity->GetEntityFlags() & BETYPE_USE_PHYSSIM_RESULTS ) pEntity->UpdatePhysics(); if( pEntity->sState & CESTATE_ATREST ) continue; if( !pEntity->m_pParent || !pEntity->m_pParent->inuse ) { // 'pEntity' has no parent or its parent is already terminated pEntity->pBaseEntity->Act( pEntity ); } if( !pEntity->inuse ) continue; // terminated in its own update routine UpdateEntityAfterMoving( pEntity ); // deal with entities touched during this frame for(int i=0; i<pEntity->vecpTouchedEntity.size(); i++) { pTouchedEnt = pEntity->vecpTouchedEntity[i]; pEntity->pBaseEntity->Touch( pEntity, pTouchedEnt ); if( pTouchedEnt ) pTouchedEnt->pBaseEntity->Touch( pTouchedEnt, pEntity ); } // clear touched entities for the next frame pEntity->vecpTouchedEntity.clear(); } ONCE( LOG_PRINT( " - updated active entities" ) ); // unlink and link the entity in the entity tree if it changed its position /* for( pEntity = m_pEntityInUse.get(); pEntity != NULL; pPrevEntity = pEntity, pEntity = pEntity->m_pNextRawPtr ) { if( !pEntity->inuse ) continue; UpdateEntityAfterMoving(); } */ }