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; }
bool RegisterAsMirrorIfReflective( CCopyEntity& entity, BasicMesh& mesh, int subset_index, GenericShaderDesc& shader_desc ) { if( mesh.GetMaterial(subset_index).m_Mat.fReflection < 0.001f ) return false; const MeshMaterial& mat = mesh.GetMaterial(subset_index); const AABB3& aabb = mesh.GetAABB(subset_index); bool subset_triangles_on_plane = false; if( aabb.vMax.x - aabb.vMin.x < 0.001f || aabb.vMax.y - aabb.vMin.y < 0.001f || aabb.vMax.z - aabb.vMin.z < 0.001f ) { // The triangles of the i-th subset is on an axis-aligned plane. subset_triangles_on_plane = true; } // else if( IsSubsetTrianglesOnSinglePlane(pMesh,i) ) // { // subset_triangles_on_plane = true; // } if( subset_triangles_on_plane ) { RegisterAsPlanarMirror( entity, mesh, subset_index ); shader_desc.PlanarReflection = PlanarReflectionOption::FLAT; return true; } else { // TODO: Register as an envmap target? // entity.RaiseEntityFlags( BETYPE_ENVMAPTARGET ); // shader_desc.EnvMap = EnvMapOption::ENABLED; return false; } return false; }
// - Set the world transform 'world_transform' to shader // - Update shader params // - Set technique void MeshContainerRenderMethod::RenderMesh( BasicMesh &mesh, const Matrix34& world_transform ) { if( !m_RenderMethodsAndSubsetIndices.empty() ) { if( m_RenderMethodsAndSubsetIndices.size() == 1 && m_RenderMethodsAndSubsetIndices[0].second.empty() ) { // render all the subsets at once RenderMeshOrMeshSubsets( mesh, m_RenderMethodsAndSubsetIndices[0].second, m_RenderMethodsAndSubsetIndices[0].first, world_transform ); } else { for( int i=0; i<(int)m_RenderMethodsAndSubsetIndices.size(); i++ ) { SubsetRenderMethod& render_method = m_RenderMethodsAndSubsetIndices[i].first; const vector<int>& subset_indices = m_RenderMethodsAndSubsetIndices[i].second; for( int j=0; j<(int)subset_indices.size(); j++ ) { RenderMeshOrMeshSubsets( mesh, subset_indices, render_method, world_transform ); } } } } else if( 0 < m_vecSubsetNameToRenderMethod.size() ) { // render subsets one by one // set different shaders / techniques for each subset const int num_subsets = mesh.GetNumMaterials(); std::vector<int> *pvecIndicesOfSubsetsToRender = NULL; if( m_vecIndicesOfSubsetsToRender.size() == 0 ) { // render all the subsets // - create the full indices list // - For the same mesh, this is done only once. for( int j=(int)m_vecFullIndicesOfSubsets.size(); j<num_subsets; j++ ) m_vecFullIndicesOfSubsets.push_back( j ); pvecIndicesOfSubsetsToRender = &m_vecFullIndicesOfSubsets; } else { pvecIndicesOfSubsetsToRender = &m_vecIndicesOfSubsetsToRender; } int lod_index = 0; // for( i=0; i<num_subsets; i++ ) for( size_t i=0; i<pvecIndicesOfSubsetsToRender->size(); i++ ) { int index = (*pvecIndicesOfSubsetsToRender)[i]; map< string, SubsetRenderMethod >::iterator itr = m_vecSubsetNameToRenderMethod[lod_index].find( mesh.GetMaterial(index).Name ); if( itr == m_vecSubsetNameToRenderMethod[lod_index].end() ) continue; SubsetRenderMethod& subset_render_method = (*itr).second; ShaderManager *pShaderMgr = subset_render_method.m_Shader.GetShaderManager(); if( !pShaderMgr ) continue; pShaderMgr->SetWorldTransform( world_transform ); pShaderMgr->SetTechnique( subset_render_method.m_Technique ); for( size_t j=0; j<subset_render_method.m_vecpShaderParamsLoader.size(); j++ ) { subset_render_method.m_vecpShaderParamsLoader[j]->UpdateShaderParams( *pShaderMgr ); } mesh.RenderSubset( *pShaderMgr, index ); for( size_t j=0; j<subset_render_method.m_vecpShaderParamsLoader.size(); j++ ) { subset_render_method.m_vecpShaderParamsLoader[j]->ResetShaderParams( *pShaderMgr ); } } } }