Result::Name RegisterAsPlanarMirror( CCopyEntity& entity, BasicMesh& mesh, int subset_index )
{
	const AABB3& aabb = mesh.GetAABB(subset_index);

	EntityRenderManager& entity_render_mgr
		= *(entity.GetStage()->GetEntitySet()->GetRenderManager());

	// >>> TODO: support planes that are not axis-aligned or facing along the negative half-space
	SPlane plane;
	int plane_axis = 1;
	if(      aabb.vMax.x - aabb.vMin.x < 0.001f ) plane_axis = 0;
	else if( aabb.vMax.y - aabb.vMin.y < 0.001f ) plane_axis = 1;
	else if( aabb.vMax.z - aabb.vMin.z < 0.001f ) plane_axis = 2;
	else plane_axis = 1;

	plane.normal = Vector3(0,0,0);
	plane.normal[plane_axis] = 1;
	plane.dist = aabb.vMax[plane_axis];

	Result::Name res = entity_render_mgr.AddPlanarReflector( EntityHandle<>( entity.Self() ), plane );

	if( res != Result::SUCCESS )
		return Result::UNKNOWN_ERROR;

	entity.RaiseEntityFlags( BETYPE_PLANAR_REFLECTOR );

	// Create shader variable loader for mirror 

	if( !entity.m_pMeshRenderMethod )
	{
		if( entity.pBaseEntity->MeshProperty().m_pMeshRenderMethod )
		{
			entity.m_pMeshRenderMethod
				= entity.pBaseEntity->MeshProperty().m_pMeshRenderMethod->CreateCopy();

			if( !entity.m_pMeshRenderMethod )
				return Result::UNKNOWN_ERROR;
		}
		else
			return Result::UNKNOWN_ERROR;
	}

	// create a planar reflection entity
//	shared_ptr<MeshContainerRenderMethod> pMeshRenderMethodCopy
//		= entity.m_pMeshRenderMethod->CreateCopy();

	shared_ptr<MirroredSceneTextureParam> pTexParam;
	pTexParam.reset( new MirroredSceneTextureParam( EntityHandle<>( entity.Self() ) ) );
	pTexParam->m_fReflection = mesh.GetMaterial(subset_index).m_Mat.fReflection;
//	pMeshRenderMethodCopy->SetShaderParamsLoaderToAllMeshRenderMethods( pTexParam );

	// test - we assume that the entity's mesh is composed of polygons that belong to a single plane.
	entity.m_pMeshRenderMethod->SetShaderParamsLoaderToAllMeshRenderMethods( pTexParam );

	// Move the indices of the planar reflection subset(s)
	// to the render method of the planar reflection entity

	return Result::SUCCESS;
}
/// 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 );
}
Exemple #3
0
EntityHandle<> CStage::LoadStaticGeometryFromFile( const std::string filename )
{
	SafeDelete( m_pStaticGeometry );
	m_pStaticGeometry = CreateStaticGeometry( this, filename );

	if( !m_pStaticGeometry )
		return EntityHandle<>();

	// register the static geometry as an entity
	// - the entity is used to render the static geometry

	BaseEntityHandle baseentity_handle;
	baseentity_handle.SetBaseEntityName( "StaticGeometry" );
	CCopyEntityDesc desc;
	desc.strName = filename;
	desc.pBaseEntityHandle = &baseentity_handle;
	desc.pUserData = m_pStaticGeometry;

	CCopyEntity *pStaticGeometryEntity = CreateEntity( desc );

	if( !pStaticGeometryEntity )
		return EntityHandle<>();

//	shared_ptr<CStaticGeometryEntity> pEntity( new CStaticGeometryEntity );
//	pEntity->SetStaticGeometry( m_pStaticGeometry );
//	EntityHandle<CStaticGeometryEntity> entity
//		= CreateEntity( pEntity, baseentity_handle );

	m_pEntitySet->WriteEntityTreeToFile( "debug/entity_tree - loaded static geometry.txt" );

	// load the static geometry from file
	this->PauseTimer();
	bool loaded = m_pStaticGeometry->LoadFromFile( filename );
	this->ResumeTimer();

	return EntityHandle<>( pStaticGeometryEntity->Self() );
//	return 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 );
	}
}
// Initializes CCopyEntity::m_pMeshRenderMethod
// - Initialize the mesh render method
// - Initialize shader parameter loaders
// - Create alpha entities
// - Creates a shader
void BaseEntity::InitEntityGraphics( CCopyEntity &entity,
                                      ShaderHandle& shader,
                                      ShaderTechniqueHandle& tech )
{
	if( shader.IsLoaded()
	 && tech.GetTechniqueName()
	 && 0 < strlen(tech.GetTechniqueName()) )
	{
		CreateMeshRenderMethod( EntityHandle<>( entity.Self() ), shader, tech );
	}
	else
	{
		InitMeshRenderMethod( entity );
	}

	// create transparent parts of the model as separate entities
	if( m_EntityFlag & BETYPE_SUPPORT_TRANSPARENT_PARTS )
	{
		// Remove any previous alpha entities
		int next_child_index = 0;
		while( next_child_index < entity.GetNumChildren() )
//		for( int i=0; i<entity.GetNumChildren(); i++ )
		{
			shared_ptr<CCopyEntity> pChild = entity.m_aChild[next_child_index].Get();
			if( IsValidEntity(pChild.get())
			 && pChild->GetEntityTypeID() == CCopyEntityTypeID::ALPHA_ENTITY )
			{
				CCopyEntity *pChildRawPtr = pChild.get();
				m_pStage->TerminateEntity( pChildRawPtr );
			}
			else
				next_child_index += 1;
		}

		CreateAlphaEntities( &entity );
	}

	shared_ptr<BasicMesh> pMesh = entity.m_MeshHandle.GetMesh();
	if( !pMesh )
		return;

	BasicMesh& mesh = *pMesh;
	const int num_mesh_materials = mesh.GetNumMaterials();

	std::vector<GenericShaderDesc> shader_descs;
	shader_descs.resize( num_mesh_materials );

	std::vector<int> mirror_subsets_indices;
//	std::vector<int> non_mirror_subsets_indices;

	if( m_MeshProperty.m_MeshDesc.IsValid() )
//	if( true )
	{
		// The mesh is specified in the base entity
	}
	else
	{
		// base entity has no mesh
		// - entity's mesh is individual
		shader_descs.resize( num_mesh_materials );
		for( int i=0; i<num_mesh_materials; i++ )
		{
			// Fill out the shader desc based on the parameter values of the material

			// reflection
			bool registered_as_mirror = RegisterAsMirrorIfReflective( entity, mesh, i, shader_descs[i] );
			if( registered_as_mirror )
				mirror_subsets_indices.push_back( i );

			// specularity
			if( 0.001f < mesh.GetMaterial(i).m_Mat.fSpecularity )
				shader_descs[i].Specular = SpecularSource::UNIFORM;
			else
				shader_descs[i].Specular = SpecularSource::NONE;
		}

		vector< pair< GenericShaderDesc, vector<unsigned int> > > grouped_descs;
		group_elements( shader_descs, grouped_descs );

		// Do a NULL check just in case
		// The mesh render method is initialized by InitMeshRenderMethod() above.
		if( !entity.m_pMeshRenderMethod )
			entity.m_pMeshRenderMethod.reset( new MeshContainerRenderMethod );

		bool shader_loaded = false;
		if( grouped_descs.size() == 1 )
		{
			SubsetRenderMethod& render_method = entity.m_pMeshRenderMethod->PrimaryMeshRenderMethod();

			render_method.m_Technique.SetTechniqueName( "Default" );
			render_method.m_ShaderDesc.pShaderGenerator.reset( new GenericShaderGenerator( grouped_descs[0].first ) );

//			shader_loaded = render_method.Load();
			shader_loaded = render_method.m_Shader.Load( render_method.m_ShaderDesc );
		}
		else
		{
			LOG_PRINT_WARNING( "Mesh materials need different shaders. This situation is not supported yet (the total number of materials: " + to_string(num_mesh_materials) + ")." );
		}
	}
}