Commit cb558583 authored by Jan Kremer's avatar Jan Kremer

Working on 2D plotting (added vispy and own C++ implementations)

parent 63905fe4
# pylint: disable=invalid-name, no-member, unused-argument
import numpy as np
import datetime
import unreal_engine as ue
from unreal_engine.enums import EPixelFormat
from vispy import app, gloo
class Plot:
def begin_play(self):
self.uobject.get_owner().bind_event('OnRedraw', self.redraw)
def redraw(self, x, y, r, g, b):
width=1024
height=1024
canvas = app.Canvas(size=(width, height))
vertex = """
#version 150 compatibility
attribute vec2 a_position;
attribute vec3 a_color;
out vec4 color;
void main(void)
{
gl_Position = vec4(a_position, 0.0, 1.0);
color = vec4(a_color, 1.0);
}
"""
fragment = """
#version 150 compatibility
in vec4 color;
void main()
{
gl_FragColor = color;
}
"""
program = gloo.Program(vert=vertex, frag=fragment)
N = 4000000
data = np.c_[x,y]
data2 = np.c_[r,g,b]
program['a_color'] = data2.astype('float32')
program['a_position'] = data.astype('float32')
@canvas.connect
def on_draw(event):
gloo.set_clear_color((1.0, 1.0, 1.0, 1.0))
gloo.clear()
program.draw(mode='points')
array = canvas.render().tobytes()
self.texture = ue.create_transient_texture(width, height, EPixelFormat.PF_R8G8B8A8)
self.texture.texture_set_data(array)
self.uobject.get_owner().StaticMeshComponent.OverrideMaterials[0].set_material_texture_parameter('Graph', self.texture)
\ No newline at end of file
......@@ -5,7 +5,7 @@ matplotlib.use('Agg')
import matplotlib.pyplot as plt
import numpy as np
class Hero:
class Plot:
# this is called on game start
def begin_play(self):
......@@ -29,6 +29,11 @@ class Hero:
self.uobject.get_owner().bind_event('OnRedraw', self.redraw)
self.uobject.get_owner().bind_event('OnDrawPoint', self.draw_point)
self.fig.canvas.draw()
array=self.fig.canvas.buffer_rgba()
print(type(array))
self.texture.texture_set_data(array)
def redraw(self, x, y, c):
# clear the current plot data
plt.clf()
......@@ -42,11 +47,15 @@ class Hero:
self.uobject.get_owner().call_function('UpdatePlotBounds', x0, y0, x1, y1, xmin, xmax, ymin, ymax)
self.fig.canvas.draw()
self.texture.texture_set_data(self.fig.canvas.buffer_rgba())
array=self.fig.canvas.buffer_rgba()
print(type(array))
self.texture.texture_set_data(array)
def draw_point(self, x, y):
ue.log('plotter draw point')
#plt.clf()
plt.plot(x, y, 'bo')
self.fig.canvas.draw()
self.texture.texture_set_data(self.fig.canvas.buffer_rgba())
\ No newline at end of file
array=self.fig.canvas.buffer_rgba()
print(type(array))
self.texture.texture_set_data(array)
\ No newline at end of file
# pylint: disable=invalid-name, no-member, unused-argument
import platform
class Plot:
def begin_play(self):
python_version=platform.python_version()
print(python_version)
print(platform.architecture()[0])
No preview for this file type
......@@ -50,12 +50,4 @@ bHQBuffer=False
bHQDistortion=False
bUpdateOnRT=True
[WindowsApplication.Accessibility]
StickyKeysHotkey=True
ToggleKeysHotkey=True
FilterKeysHotkey=True
StickyKeysConfirmation=True
ToggleKeysConfirmation=True
FilterKeysConfirmation=True
[/Script/Engine.Console]
HistoryBuffer=unlit
HistoryBuffer=mode unlit
// 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<FUpdateTextureRegion2D>(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<uint8[]>(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<uint8[]>(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<APawnBase>(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 * 10000 + canvasWidth / 2, PawnBase->Plot3D->U[i] * 5 + canvasHeight / 2);
}
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
}
\ No newline at end of file
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "Engine/Texture2D.h"
#include <memory>
#include "PlotCanvas.generated.h"
/**
*
*/
UCLASS(Blueprintable, BlueprintType)
class IMMERSIVEANALYTICS_API UPlotCanvas : public UObject
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Variables)
UTexture2D* dynamicCanvas;
UFUNCTION(BlueprintCallable, Category = DrawingTools)
void InitializeCanvas(const int32 pixelsH, const int32 pixelsV);
UFUNCTION(BlueprintCallable, Category = DrawingTools)
void UpdateCanvas();
UFUNCTION(BlueprintCallable, Category = DrawingTools)
void ClearCanvas();
UFUNCTION(BlueprintCallable, Category = DrawingTools)
void InitializeDrawingTools(const int32 brushRadius, uint8 r, uint8 g, uint8 b);
UFUNCTION(BlueprintCallable, Category = DrawingTools)
void DrawFromData();
UFUNCTION(BlueprintCallable, Category = DrawingTools)
void DrawDot(const int32 pixelCoordX, const int32 pixelCoordY);
private:
// canvas
std::unique_ptr<uint8[]> canvasPixelData;
int canvasWidth;
int canvasHeight;
int bytesPerPixel;
int bufferPitch;
int bufferSize;
// draw brush tool
std::unique_ptr<uint8[]> canvasBrushMask;
int radius;
int brushBufferSize;
std::unique_ptr<FUpdateTextureRegion2D> echoUpdateTextureRegion;
void setPixelColor(uint8*& pointer, uint8 red, uint8 green, uint8 blue, uint8 alpha);
};
......@@ -26,10 +26,18 @@ void UPlotRenderTarget::OnUpdate(UCanvas * Canvas, int32 Width, int32 Height)
for (int i = 0; i < PawnBase->Plot3D->Points.Num(); ++i)
{
FVector2D Location = FVector2D(PawnBase->Plot3D->Points[i].Location.X * 10000 + Width / 2, PawnBase->Plot3D->U[i] * 5 + Height / 2);
FVector2D LocationB = Location + FVector2D(0, 100);
/*
* Still not fast enough. Using other way to draw the graph.
*/
FCanvasLineItem LineItem(Location, LocationB);
LineItem.LineThickness = 2;
LineItem.SetColor(FLinearColor(1, 1, 1));
LineItem.Draw(Canvas->Canvas);
//Canvas->K2_DrawBox(Location, FVector2D(10, 10), 5);
Canvas->K2_DrawLine(Location, Location + FVector2D(0, 100), 2);
//Canvas->K2_DrawMaterial(MaterialDot, Location, FVector2D(10, 10), FVector2D(0, 0), FVector2D(1, 1), 0, FVector2D(0.5, 0.5));
//Canvas->K2_DrawLine(Location, LocationB, 2);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment