void FMesh::Init(const FMeshData& MeshData, const FImageCache& ImageCache) { // #FIXME: This function could be more maintainable than it currently is. // Specifically: VertexAttribPointer and EnableVertexAttribArray. F_Assert(MeshData.Positions.size(), "Position data is missing."); F_Assert(MeshData.Normals.size(), "Normal data is missing."); F_Assert(MeshData.UVCoords.size(), "UVCoords data is missing."); F_Assert(MeshData.Indices.size(), "Index data is missing."); F_GLDisplayErrors(); DeInit(); F_GL(GL::GenVertexArrays(1, &VertexArray)); F_GL(GL::GenBuffers(1, &VertexBuffer)); F_GL(GL::GenBuffers(1, &ElementBuffer)); F_GL(GL::BindVertexArray(VertexArray)); { const GLsizeiptr PositionsSize = MeshData.Positions.size() * sizeof(FMeshData::PositionT); const GLsizeiptr NormalsSize = MeshData.Normals.size() * sizeof(FMeshData::NormalT); const GLsizeiptr UVCoordsSize = MeshData.UVCoords.size() * sizeof(FMeshData::UVCoordT); const GLsizeiptr TotalSize = PositionsSize + NormalsSize + UVCoordsSize; const GLsizeiptr NormalsStart = PositionsSize; const GLsizeiptr UVCoordsStart = NormalsStart + NormalsSize; const GLvoid* const NormalsStartPtr = reinterpret_cast<GLvoid*>(NormalsStart); const GLvoid* const UVCoordsStartPtr = reinterpret_cast<GLvoid*>(UVCoordsStart); F_GL(GL::BindBuffer(GL::EBuffer::Array, VertexArray)); F_GL(GL::BufferData(GL::EBuffer::Array, TotalSize, nullptr, GL::EUsage::StaticDraw)); F_GL(GL::BufferSubData(GL::EBuffer::Array, 0, PositionsSize, &MeshData.Positions[0])); F_GL(GL::BufferSubData(GL::EBuffer::Array, NormalsStart, NormalsSize, &MeshData.Normals[0])); F_GL(GL::BufferSubData(GL::EBuffer::Array, UVCoordsStart, UVCoordsSize, &MeshData.UVCoords[0])); F_GL(GL::EnableVertexAttribArray(0)); F_GL(GL::EnableVertexAttribArray(1)); F_GL(GL::EnableVertexAttribArray(2)); F_GL(GL::VertexAttribPointer(0, 3, GL::EType::Float, GL::EBool::False, 3 * sizeof(GLfloat), nullptr)); F_GL(GL::VertexAttribPointer(1, 3, GL::EType::Float, GL::EBool::False, 3 * sizeof(GLfloat), NormalsStartPtr)); F_GL(GL::VertexAttribPointer(2, 2, GL::EType::Float, GL::EBool::False, 2 * sizeof(GLfloat), UVCoordsStartPtr)); } { const GLsizeiptr Size = MeshData.Indices.size() * sizeof(FMeshData::IndexT); F_GL(GL::BindBuffer(GL::EBuffer::ElementArray, ElementBuffer)); F_GL(GL::BufferData(GL::EBuffer::ElementArray, Size, &MeshData.Indices[0], GL::EUsage::StaticDraw)); IndexCount = Size / MeshData.IndexTSize; IndexTSize = MeshData.IndexTSize; VertexCount = MeshData.VertexCount; F_GL(GL::BindVertexArray(0)); } { if (MeshData.HasTextureName(EMeshDataIndex::Diffuse)) { const FChar* const DiffuseName = MeshData.GetTextureName(EMeshDataIndex::Diffuse); DiffuseImage = ImageCache.GetItem(DiffuseName, DiffuseImage); } } }
void FMesh::Init(const FMeshData& MeshData, const FImageCache& ImageCache) { F_Assert(MeshData.Positions.size(), "Position data is missing."); const bool bNormalsProvided = !MeshData.Normals.empty(); const bool bUVCoordsProvided = !MeshData.UVCoords.empty(); const bool bIndicesProvided = !MeshData.Indices.empty(); DeInit(); F_GL(GL::GenVertexArrays(1, &VertexArray)); F_GL(GL::GenBuffers(1, &VertexBuffer)); F_GL(GL::BindVertexArray(VertexArray)); { const GLsizeiptr PositionsSize = MeshData.Positions.size() * sizeof(FMeshData::PositionT); const GLsizeiptr NormalsSize = MeshData.Normals.size() * sizeof(FMeshData::NormalT); const GLsizeiptr UVCoordsSize = MeshData.UVCoords.size() * sizeof(FMeshData::UVCoordT); const GLsizeiptr TotalSize = PositionsSize + NormalsSize + UVCoordsSize; const GLsizeiptr NormalsStart = PositionsSize; const GLsizeiptr UVCoordsStart = NormalsStart + NormalsSize; const GLvoid* const NormalsStartPtr = reinterpret_cast<GLvoid*>(NormalsStart); const GLvoid* const UVCoordsStartPtr = reinterpret_cast<GLvoid*>(UVCoordsStart); F_GL(GL::BindBuffer(EBuffer::Array, VertexArray)); F_GL(GL::BufferData(EBuffer::Array, TotalSize, nullptr, EUsage::StaticDraw)); GLuint CurrentIndex = 0; const EMeshPositionType::SizeType Size = EMeshPositionType::GetSize(MeshData.PositionType); F_GL(GL::BufferSubData(EBuffer::Array, 0, PositionsSize, &MeshData.Positions[0])); F_GL(GL::EnableVertexAttribArray(CurrentIndex)); F_GL(GL::VertexAttribPointer(CurrentIndex, Size, EType::Float, EBool::False, Size * sizeof(GLfloat), nullptr)); if (bNormalsProvided) { ++CurrentIndex; F_GL(GL::BufferSubData(EBuffer::Array, NormalsStart, NormalsSize, &MeshData.Normals[0])); F_GL(GL::EnableVertexAttribArray(CurrentIndex)); F_GL(GL::VertexAttribPointer(CurrentIndex, 3, EType::Float, EBool::False, 3 * sizeof(GLfloat), NormalsStartPtr)); } if (bUVCoordsProvided) { ++CurrentIndex; F_GL(GL::BufferSubData(EBuffer::Array, UVCoordsStart, UVCoordsSize, &MeshData.UVCoords[0])); F_GL(GL::EnableVertexAttribArray(CurrentIndex)); F_GL(GL::VertexAttribPointer(CurrentIndex, 2, EType::Float, EBool::False, 2 * sizeof(GLfloat), UVCoordsStartPtr)); } } if (bIndicesProvided) { const GLsizeiptr Size = MeshData.Indices.size() * sizeof(FMeshData::IndexT); F_GL(GL::GenBuffers(1, &ElementBuffer)); F_GL(GL::BindBuffer(EBuffer::ElementArray, ElementBuffer)); F_GL(GL::BufferData(EBuffer::ElementArray, Size, &MeshData.Indices[0], EUsage::StaticDraw)); IndexCount = Size / MeshData.IndexTSize; IndexTSize = MeshData.IndexTSize; } VertexCount = MeshData.VertexCount; F_GL(GL::BindVertexArray(0)); if (MeshData.HasTextureName(EMeshDataIndex::Diffuse)) { const FChar* const DiffuseName = MeshData.GetTextureName(EMeshDataIndex::Diffuse); DiffuseImage = ImageCache.GetItem(DiffuseName, DiffuseImage); } F_GFXLog("Mesh VAO Created: " << VertexArray << " " << VertexBuffer << " " << ElementBuffer); }