/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. // Description : Manages static meshes for geometry caches #include "StdAfx.h" #if defined(USE_GEOM_CACHES) #include "GeomCacheMeshManager.h" #include "GeomCacheDecoder.h" void CGeomCacheMeshManager::Reset() { stl::free_container(m_meshMap); } bool CGeomCacheMeshManager::ReadMeshStaticData(CGeomCacheStreamReader& reader, const GeomCacheFile::SMeshInfo& meshInfo, SGeomCacheStaticMeshData& staticMeshData) const { LOADING_TIME_PROFILE_SECTION; if (staticMeshData.m_constantStreams & GeomCacheFile::eStream_Indices) { if (!ReadMeshIndices(reader, meshInfo, staticMeshData, staticMeshData.m_indices)) { return false; } } if ((staticMeshData.m_constantStreams & GeomCacheFile::eStream_Positions) != 0) { staticMeshData.m_positions.resize(staticMeshData.m_numVertices); strided_pointer positions(&staticMeshData.m_positions[0], sizeof(Vec3)); if (!ReadMeshPositions(reader, meshInfo, positions)) { return false; } } if ((staticMeshData.m_constantStreams & GeomCacheFile::eStream_Texcoords) != 0) { staticMeshData.m_texcoords.resize(staticMeshData.m_numVertices); strided_pointer texcoords(&staticMeshData.m_texcoords[0], sizeof(Vec2)); if (!ReadMeshTexcoords(reader, meshInfo, texcoords)) { return false; } } if ((staticMeshData.m_constantStreams & GeomCacheFile::eStream_QTangents) != 0) { staticMeshData.m_tangents.resize(staticMeshData.m_numVertices); strided_pointer tangents(&staticMeshData.m_tangents[0], sizeof(SPipTangents)); if (!ReadMeshQTangents(reader, meshInfo, tangents)) { return false; } } if ((staticMeshData.m_constantStreams & GeomCacheFile::eStream_Colors) != 0) { UCol defaultColor; defaultColor.dcolor = 0xFFFFFFFF; staticMeshData.m_colors.resize(staticMeshData.m_numVertices, defaultColor); strided_pointer colors(&staticMeshData.m_colors[0], sizeof(UCol)); if (!ReadMeshColors(reader, meshInfo, colors)) { return false; } } if (staticMeshData.m_bUsePredictor) { uint32 predictorDataSize; if (!reader.Read(&predictorDataSize)) { return false; } staticMeshData.m_predictorData.resize(predictorDataSize); if (!reader.Read(&staticMeshData.m_predictorData[0], predictorDataSize)) { return false; } } return true; } _smart_ptr CGeomCacheMeshManager::ConstructStaticRenderMesh(CGeomCacheStreamReader& reader, const GeomCacheFile::SMeshInfo& meshInfo, SGeomCacheStaticMeshData& staticMeshData, const char* pFileName) { LOADING_TIME_PROFILE_SECTION; std::vector vertexData(staticMeshData.m_numVertices * sizeof(SVF_P3F_C4B_T2F), 0); std::vector tangentData(staticMeshData.m_numVertices); std::vector indices; strided_pointer positions((Vec3*)(&vertexData[0] + offsetof(SVF_P3F_C4B_T2F, xyz)), sizeof(SVF_P3F_C4B_T2F)); strided_pointer colors((UCol*)(&vertexData[0] + offsetof(SVF_P3F_C4B_T2F, color)), sizeof(SVF_P3F_C4B_T2F)); strided_pointer texcoords((Vec2*)(&vertexData[0] + offsetof(SVF_P3F_C4B_T2F, st)), sizeof(SVF_P3F_C4B_T2F)); strided_pointer tangents((SPipTangents*)((char*)(&tangentData[0])), sizeof(SPipTangents)); if (!ReadMeshIndices(reader, meshInfo, staticMeshData, indices) || !ReadMeshPositions(reader, meshInfo, positions) || !ReadMeshTexcoords(reader, meshInfo, texcoords) || !ReadMeshQTangents(reader, meshInfo, tangents)) { return NULL; } if (meshInfo.m_constantStreams & GeomCacheFile::eStream_Colors) { if (!ReadMeshColors(reader, meshInfo, colors)) { return NULL; } } else { UCol defaultColor; defaultColor.dcolor = 0xFFFFFFFF; const uint numVertices = meshInfo.m_numVertices; for (uint i = 0; i < numVertices; ++i) { colors[i] = defaultColor; } } TMeshMap::iterator findIter = m_meshMap.find(staticMeshData.m_hash); if (findIter != m_meshMap.end()) { ++findIter->second.m_refCount; return findIter->second.m_pRenderMesh; } _smart_ptr pRenderMesh = gEnv->pRenderer->CreateRenderMeshInitialized(&vertexData[0], meshInfo.m_numVertices, eVF_P3F_C4B_T2F, &indices[0], indices.size(), prtTriangleList, "GeomCacheConstantMesh", pFileName, eRMT_Static, 1, 0, NULL, NULL, false, false, &tangentData[0]); CRenderChunk chunk; chunk.nNumVerts = meshInfo.m_numVertices; uint32 currentIndexOffset = 0; for (unsigned int i = 0; i < meshInfo.m_numMaterials; ++i) { chunk.nFirstIndexId = currentIndexOffset; chunk.nNumIndices = staticMeshData.m_numIndices[i]; chunk.m_nMatID = staticMeshData.m_materialIds[i]; chunk.m_vertexFormat = eVF_P3F_C4B_T2F; pRenderMesh->SetChunk(i, chunk); currentIndexOffset += chunk.nNumIndices; } SMeshMapInfo meshMapInfo; meshMapInfo.m_refCount = 1; meshMapInfo.m_pRenderMesh = pRenderMesh; m_meshMap[staticMeshData.m_hash] = meshMapInfo; return pRenderMesh; } _smart_ptr CGeomCacheMeshManager::GetStaticRenderMesh(const uint64 hash) const { TMeshMap::const_iterator findIter = m_meshMap.find(hash); if (findIter != m_meshMap.end()) { return findIter->second.m_pRenderMesh; } return NULL; } void CGeomCacheMeshManager::RemoveReference(SGeomCacheStaticMeshData& staticMeshData) { TMeshMap::iterator findIter = m_meshMap.find(staticMeshData.m_hash); if (findIter != m_meshMap.end()) { uint& refCount = findIter->second.m_refCount; --refCount; if (refCount == 0) { m_meshMap.erase(findIter); } } } bool CGeomCacheMeshManager::ReadMeshIndices(CGeomCacheStreamReader& reader, const GeomCacheFile::SMeshInfo& meshInfo, SGeomCacheStaticMeshData& staticMeshData, std::vector& indices) const { const uint16 numMaterials = meshInfo.m_numMaterials; staticMeshData.m_numIndices.reserve(numMaterials); for (unsigned int i = 0; i < numMaterials; ++i) { uint32 numIndices; if (!reader.Read(&numIndices)) { return false; } staticMeshData.m_numIndices.push_back(numIndices); const uint indicesStart = indices.size(); indices.resize(indicesStart + numIndices); if (!reader.Read(&indices[indicesStart], numIndices)) { return false; } } return true; } bool CGeomCacheMeshManager::ReadMeshPositions(CGeomCacheStreamReader& reader, const GeomCacheFile::SMeshInfo& meshInfo, strided_pointer positions) const { const Vec3 aabbMin = Vec3(meshInfo.m_aabbMin[0], meshInfo.m_aabbMin[1], meshInfo.m_aabbMin[2]); const Vec3 aabbMax = Vec3(meshInfo.m_aabbMax[0], meshInfo.m_aabbMax[1], meshInfo.m_aabbMax[2]); const AABB meshAABB(aabbMin, aabbMax); const Vec3 aabbSize = meshAABB.GetSize(); const Vec3 posConvertFactor = Vec3(1.0f / float((2 << (meshInfo.m_positionPrecision[0] - 1)) - 1), 1.0f / float((2 << (meshInfo.m_positionPrecision[1] - 1)) - 1), 1.0f / float((2 << (meshInfo.m_positionPrecision[2] - 1)) - 1)); const uint numVertices = meshInfo.m_numVertices; for (uint i = 0; i < numVertices; ++i) { GeomCacheFile::Position position; if (!reader.Read(&position)) { return false; } positions[i] = GeomCacheDecoder::DecodePosition(aabbMin, aabbSize, position, posConvertFactor); } return true; } bool CGeomCacheMeshManager::ReadMeshTexcoords(CGeomCacheStreamReader& reader, const GeomCacheFile::SMeshInfo& meshInfo, strided_pointer texcoords) const { const uint numVertices = meshInfo.m_numVertices; for (uint i = 0; i < numVertices; ++i) { GeomCacheFile::Texcoords texcoord; if (!reader.Read(&texcoord)) { return false; } texcoords[i] = GeomCacheDecoder::DecodeTexcoord(texcoord, meshInfo.m_uvMax); } return true; } bool CGeomCacheMeshManager::ReadMeshQTangents(CGeomCacheStreamReader& reader, const GeomCacheFile::SMeshInfo& meshInfo, strided_pointer tangents) const { const uint numVertices = meshInfo.m_numVertices; for (uint i = 0; i < numVertices; ++i) { GeomCacheFile::QTangent qTangent; if (!reader.Read(&qTangent)) { return false; } Quat qDecodedTangent = GeomCacheDecoder::DecodeQTangent(qTangent); GeomCacheDecoder::ConvertToTangentAndBitangent(qDecodedTangent, tangents[i]); } return true; } bool CGeomCacheMeshManager::ReadMeshColors(CGeomCacheStreamReader& reader, const GeomCacheFile::SMeshInfo& meshInfo, strided_pointer colors) const { const uint numVertices = meshInfo.m_numVertices; for (int colorIndex = 2; colorIndex >= 0; --colorIndex) { for (uint i = 0; i < numVertices; ++i) { GeomCacheFile::Color color; if (!reader.Read(&color)) { return false; } colors[i].bcolor[colorIndex] = color; } } for (uint i = 0; i < numVertices; ++i) { GeomCacheFile::Color color; if (!reader.Read(&color)) { return false; } colors[i].bcolor[3] = color; } return true; } #endif