void CUmbralMap::GetMeshes(Palleon::MeshArray& meshes, const Palleon::CCamera* camera) { auto cameraFrustum = camera->GetFrustum(); for(const auto& instance : m_instances) { auto boundingSphere = instance->GetWorldBoundingSphere(); if(cameraFrustum.Intersects(boundingSphere)) { meshes.push_back(instance.get()); } } }
void CBspMapMeshProvider::GetMeshes(Palleon::MeshArray& meshes, const Palleon::CCamera* camera) { const Bsp::LeafArray& leaves(m_bspFile->GetLeaves()); const Bsp::LeafFaceArray& leafFaces(m_bspFile->GetLeafFaces()); const Bsp::FaceArray& faces(m_bspFile->GetFaces()); const Bsp::VISDATA& visData(m_bspFile->GetVisData()); CMatrix4 invViewMatrix = camera->GetViewMatrix().Inverse(); CVector3 cameraPosition = CVector3(invViewMatrix(3, 0), invViewMatrix(3, 1), invViewMatrix(3, 2)); int32 leafIndex = FindLeaf(cameraPosition); const Bsp::LEAF& leaf(leaves[leafIndex]); CFrustum cameraFrustum = camera->GetFrustum(); memset(m_faceVisibleSet, 0, m_faceVisibleSetSize); if(leaf.cluster != -1) { const uint8* visVector = &visData.vectors[leaf.cluster * visData.vectorSize]; for(uint32 i = 0; i < leaves.size(); i++) { const Bsp::LEAF& testLeaf = leaves[i]; uint32 testCluster = testLeaf.cluster; if(static_cast<int32>(testCluster) < 0) continue; uint8 visByte = visVector[testCluster / 8]; bool visible = (visByte & (1 << (testCluster & 7))) != 0; if(visible) { CVector3 leafBoxMin = Bsp::ConvertToAthenaCoord(static_cast<float>(testLeaf.mins[0]), static_cast<float>(testLeaf.mins[1]), static_cast<float>(testLeaf.mins[2])); CVector3 leafBoxMax = Bsp::ConvertToAthenaCoord(static_cast<float>(testLeaf.maxs[0]), static_cast<float>(testLeaf.maxs[1]), static_cast<float>(testLeaf.maxs[2])); if(cameraFrustum.Intersects(leafBoxMin, leafBoxMax)) { for(unsigned int i = 0; i < testLeaf.leafFaceCount; i++) { unsigned int faceIndex = leafFaces[i + testLeaf.leafFaceIndex]; unsigned int faceByte = faceIndex / 8; assert(faceByte < m_faceVisibleSetSize); m_faceVisibleSet[faceByte] |= (1 << (faceIndex & 7)); } } } } } m_visibleFaceIndices.clear(); for(unsigned int i = 0; i < faces.size(); i++) { const Bsp::FACE& currentFace = faces[i]; if(currentFace.textureIndex != -1) { BspMapMaterialPtr faceMaterial = m_bspMapResourceProvider->GetMaterial(currentFace.textureIndex); if(faceMaterial->GetIsSky()) continue; } unsigned int faceByte = i / 8; if(m_faceVisibleSet[faceByte] & (1 << (i & 7))) { m_visibleFaceIndices.push_back(i); } } if(m_visibleFaceIndices.size() == 0) return; std::sort(m_visibleFaceIndices.begin(), m_visibleFaceIndices.end(), FaceSorter(faces)); uint32 currentTextureIdx = -2; uint32 currentLightMapIdx = -2; BatchMeshPtr currentBatch; unsigned int currentBatchIndex = 0; for(unsigned int i = 0; i < m_visibleFaceIndices.size(); i++) { uint32 faceIndex = m_visibleFaceIndices[i]; const Bsp::FACE& currentFace = faces[faceIndex]; BspFaceMeshPtr faceMesh = m_faceMeshes[faceIndex]; if(!faceMesh) continue; bool needNewBatch = false; needNewBatch |= (currentFace.textureIndex != currentTextureIdx); needNewBatch |= (currentFace.lightMapIndex != currentLightMapIdx); needNewBatch |= (currentBatch && !currentBatch->CanWriteMesh(faceMesh->GetVertexCount(), faceMesh->GetIndexCount())); if(needNewBatch) { //Switch to new batch if(currentBatch) { currentBatch->EndBatch(); } currentBatch = m_batches[currentBatchIndex++]; meshes.push_back(currentBatch.get()); currentBatch->BeginBatch(); currentTextureIdx = currentFace.textureIndex; currentLightMapIdx = currentFace.lightMapIndex; //Prepare material Palleon::MaterialPtr batchMaterial = currentBatch->GetMaterial(); BspMapMaterialPtr faceMaterial = m_bspMapResourceProvider->GetMaterial(currentTextureIdx); for(unsigned int i = 0; i < Palleon::CMaterial::MAX_TEXTURE_SLOTS; i++) { batchMaterial->SetTexture(i, Palleon::TexturePtr()); } for(unsigned int i = 0; i < faceMaterial->GetPassCount(); i++) { const BspMapPassPtr& pass(faceMaterial->GetPass(i)); Palleon::TEXTURE_COMBINE_MODE combineMode = pass->GetBlendingFunction(); if(pass->GetTextureSource() == CBspMapPass::TEXTURE_SOURCE_DIFFUSE) { batchMaterial->SetTexture(i, pass->GetTexture()); batchMaterial->SetTextureMatrix(i, pass->GetUvMatrix()); batchMaterial->SetTextureCoordSource(i, Palleon::TEXTURE_COORD_UV0); batchMaterial->SetTextureCombineMode(i, combineMode); } else { batchMaterial->SetTexture(i, m_bspMapResourceProvider->GetLightMap(currentLightMapIdx)); batchMaterial->SetTextureMatrix(i, CMatrix4::MakeIdentity()); batchMaterial->SetTextureCoordSource(i, Palleon::TEXTURE_COORD_UV1); batchMaterial->SetTextureCombineMode(i, combineMode); } batchMaterial->SetTextureAddressModeU(i, Palleon::TEXTURE_ADDRESS_REPEAT); batchMaterial->SetTextureAddressModeV(i, Palleon::TEXTURE_ADDRESS_REPEAT); } } assert(currentBatch->CanWriteMesh(faceMesh->GetVertexCount(), faceMesh->GetIndexCount())); currentBatch->WriteMesh(faceMesh->GetVertices(), faceMesh->GetVertexCount(), faceMesh->GetIndices(), faceMesh->GetIndexCount()); } if(currentBatch) { currentBatch->EndBatch(); } }