// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Async/ParallelFor.h" #include "MuR/ImagePrivate.h" #include "MuR/Platform.h" #include "MuR/MeshPrivate.h" #include "MuR/Raster.h" #include "MuR/ConvertData.h" namespace mu { class WhitePixelProcessor { public: inline void ProcessPixel(uint8* pBufferPos, float[1]) const { pBufferPos[0] = 255; } inline void operator()(uint8* BufferPos, float Interpolators[1]) const { ProcessPixel(BufferPos, Interpolators); } }; inline void ImageRasterMesh( const FMesh* pMesh, FImage* pImage, int32 LayoutIndex, uint64 BlockId, UE::Math::TIntVector2 CropMin, UE::Math::TIntVector2 UncroppedSize ) { MUTABLE_CPUPROFILER_SCOPE(ImageRasterMesh); if (pMesh->GetVertexCount() == 0) { return; } check( pImage->GetFormat()== EImageFormat::L_UByte ); int32 sizeX = pImage->GetSizeX(); int32 sizeY = pImage->GetSizeY(); // Get the vertices int32 vertexCount = pMesh->GetVertexCount(); TArray< RasterVertex<1> > vertices; vertices.SetNumZeroed(vertexCount); UntypedMeshBufferIteratorConst texIt( pMesh->GetVertexBuffers(), EMeshBufferSemantic::TexCoords, 0 ); if (!texIt.ptr()) { ensure(false); return; } for ( int32 v=0; v 0; if (bUseCropping) { vertices[v].x = uv[0] * UncroppedSize[0] - CropMin[0]; vertices[v].y = uv[1] * UncroppedSize[1] - CropMin[1]; } else { vertices[v].x = uv[0] * sizeX; vertices[v].y = uv[1] * sizeY; } ++texIt; } // Get the indices int32 faceCount = pMesh->GetFaceCount(); TArray indices; indices.SetNumZeroed(faceCount * 3); UntypedMeshBufferIteratorConst indIt( pMesh->GetIndexBuffers(), EMeshBufferSemantic::VertexIndex, 0 ); for ( int32 i=0; iGetVertexBuffers(), EMeshBufferSemantic::LayoutBlock, LayoutIndex ); if (BlockId== FLayoutBlock::InvalidBlockId || bloIt.GetElementSize()==0 ) { // Raster all the faces WhitePixelProcessor pixelProc; const TArrayView ImageData = pImage->DataStorage.GetLOD(0); //for ( int f=0; f(ImageData.GetData(), ImageData.Num(), sizeX, sizeY, 1, vertices[indices[f * 3 + 0]], vertices[indices[f * 3 + 1]], vertices[indices[f * 3 + 2]], pixelProc, false); }; ParallelFor(faceCount, ProcessFace); } else { // Raster only the faces in the selected block check(bloIt.GetComponents() == 1); // Get the block per vertex TArray VertexBlockIds; VertexBlockIds.SetNumZeroed(vertexCount); if (bloIt.GetFormat() == EMeshBufferFormat::UInt16) { // Relative blocks. const uint16* SourceIds = reinterpret_cast(bloIt.ptr()); for (int32 i = 0; i < vertexCount; ++i) { uint64 Id = SourceIds[i]; Id = Id | (uint64(pMesh->MeshIDPrefix)<<32); VertexBlockIds[i] = Id; } } else if (bloIt.GetFormat() == EMeshBufferFormat::UInt64) { // Absolute blocks. const uint64* SourceIds = reinterpret_cast(bloIt.ptr()); for (int32 i = 0; i < vertexCount; ++i) { uint64 Id = SourceIds[i]; VertexBlockIds[i] = Id; } } else { // Format not supported check(false); } WhitePixelProcessor pixelProc; const TArrayView ImageData = pImage->DataStorage.GetLOD(0); const auto& ProcessFace = [ vertices, indices, VertexBlockIds, BlockId, ImageData, sizeX, sizeY, pixelProc ] (int32 f) { // TODO: Select faces outside for loop? if (VertexBlockIds[indices[f * 3 + 0]] == BlockId) { constexpr int32 NumInterpolators = 1; Triangle(ImageData.GetData(), ImageData.Num(), sizeX, sizeY, 1, vertices[indices[f * 3 + 0]], vertices[indices[f * 3 + 1]], vertices[indices[f * 3 + 2]], pixelProc, false); } }; ParallelFor(faceCount, ProcessFace); } } }