// Fill out your copyright notice in the Description page of Project Settings. #include "PlotCanvas.h" #include "PawnBase.h" #include "Plot3D.h" #include "Runtime/Engine/Classes/Kismet/GameplayStatics.h" void UPlotCanvas::InitializeCanvas(const int32 pixelsH, const int32 pixelsV) { //dynamic texture initialization canvasWidth = pixelsH; canvasHeight = pixelsV; dynamicCanvas = UTexture2D::CreateTransient(canvasWidth, canvasHeight); #if WITH_EDITORONLY_DATA dynamicCanvas->MipGenSettings = TextureMipGenSettings::TMGS_NoMipmaps; #endif dynamicCanvas->CompressionSettings = TextureCompressionSettings::TC_VectorDisplacementmap; dynamicCanvas->SRGB = 1; dynamicCanvas->AddToRoot(); dynamicCanvas->Filter = TextureFilter::TF_Nearest; dynamicCanvas->UpdateResource(); echoUpdateTextureRegion = std::unique_ptr(new FUpdateTextureRegion2D(0, 0, 0, 0, canvasWidth, canvasHeight)); // buffers initialization bytesPerPixel = 4; // r g b a bufferPitch = canvasWidth * bytesPerPixel; bufferSize = canvasWidth * canvasHeight * bytesPerPixel; canvasPixelData = std::unique_ptr(new uint8[bufferSize]); ClearCanvas(); } void UPlotCanvas::InitializeDrawingTools(const int32 brushRadius, uint8 r, uint8 g, uint8 b) { radius = brushRadius; brushBufferSize = radius * radius * 4 * bytesPerPixel; //2r*2r * bpp canvasBrushMask = std::unique_ptr(new uint8[brushBufferSize]); uint8* canvasBrushPixelPtr = canvasBrushMask.get(); for (int px = -radius; px < radius; ++px) { for (int py = -radius; py < radius; ++py) { int32 tx = px + radius; int32 ty = py + radius; canvasBrushPixelPtr = canvasBrushMask.get() + (tx + +ty * 2 * radius) * bytesPerPixel; if (px*px + py * py < radius*radius) { setPixelColor(canvasBrushPixelPtr, r,g,b, 255); //black alpha 255 - bgra } else { setPixelColor(canvasBrushPixelPtr, 0, 0, 0, 0); // alpha 0 } } } } void UPlotCanvas::DrawFromData() { APawn* Pawn = UGameplayStatics::GetPlayerPawn(this, 0); APawnBase* PawnBase = Cast(Pawn); for (int i = 0; i < PawnBase->Plot3D->Points.Num(); ++i) { InitializeDrawingTools(1, PawnBase->Plot3D->Points[i].Color.R, PawnBase->Plot3D->Points[i].Color.G, PawnBase->Plot3D->Points[i].Color.B); DrawDot((PawnBase->Plot3D->Points[i].Location.X - PawnBase->Plot3D->MinX) / (PawnBase->Plot3D->MaxX - PawnBase->Plot3D->MinX) * canvasWidth, (PawnBase->Plot3D->U[i] - PawnBase->Plot3D->MinU) / (PawnBase->Plot3D->MaxU - PawnBase->Plot3D->MinU) * canvasHeight); } UpdateCanvas(); } void UPlotCanvas::DrawDot(const int32 pixelCoordX, const int32 pixelCoordY) { uint8* canvasPixelPtr = canvasPixelData.get(); const uint8* canvasBrushPixelPtr = canvasBrushMask.get(); for (int px = -radius; px < radius; ++px) { for (int py = -radius; py < radius; ++py) { int32 tbx = px + radius; int32 tby = py + radius; canvasBrushPixelPtr = canvasBrushMask.get() + (tbx + tby * 2 * radius) * bytesPerPixel; if (*(canvasBrushPixelPtr + 3) == 255) // check the alpha value of the pixel of the brush mask { int32 tx = pixelCoordX + px; int32 ty = pixelCoordY + py; if (tx >= 0 && tx < canvasWidth && ty >= 0 && ty < canvasHeight) { canvasPixelPtr = canvasPixelData.get() + (tx + ty * canvasWidth) * bytesPerPixel; setPixelColor(canvasPixelPtr, *(canvasBrushPixelPtr + 2), *(canvasBrushPixelPtr + 1), *(canvasBrushPixelPtr), *(canvasBrushPixelPtr + 3)); } } } } } void UPlotCanvas::ClearCanvas() { uint8* canvasPixelPtr = canvasPixelData.get(); for (int i = 0; i < canvasWidth * canvasHeight; ++i) { setPixelColor(canvasPixelPtr, 128, 128, 128, 0); canvasPixelPtr += bytesPerPixel; } UpdateCanvas(); } void UPlotCanvas::UpdateCanvas() { if (echoUpdateTextureRegion) { dynamicCanvas->UpdateTextureRegions((int32)0, (uint32)1, echoUpdateTextureRegion.get(), (uint32)bufferPitch, (uint32)bytesPerPixel, canvasPixelData.get()); } } void UPlotCanvas::setPixelColor(uint8*& pointer, uint8 red, uint8 green, uint8 blue, uint8 alpha) { *pointer = blue; //b *(pointer + 1) = green; //g *(pointer + 2) = red; //r *(pointer + 3) = alpha; //a }