Hi fellow game developers!
I have been working on a c++ class that would draw 2D graph on a 3D object from discrete data. Since Material Editor has no loops or arrays, I see no other choice. I have been mostly following this tutorial:
A new, community-hosted Unreal Engine Wiki - Announcements - Unreal Engine Forums,
but I have left out some “lava specific” stuff and used AActor class instead of StaticMesh actor.
What I have been trying to do so far:
-create an actor,
-create a cube and set it as root component (so far it works),
-create a dynamic texture, apply it to a dynamic material and the material to the cube.
My problem:
When I set the material to my cube, nothing happens. I have tried many different things from many tutorials and no matter what I do, my cube looks the same.
Here is what I have so far:
Header file:
UCLASS()
class REACTIVITYGAME_API AScrollingGraph : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AScrollingGraph(const FObjectInitializer& ObjectInitializer);
// Called when the game starts or when spawned
virtual void BeginPlay() override;
// Called every frame
virtual void Tick( float DeltaSeconds ) override;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Graph)
UTexture2D* DynTexture;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Graph)
UMaterialInstanceDynamic* DynMaterial;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Graph)
class UStaticMeshComponent* CanvasBG;
virtual void PostInitializeComponents() override;
protected:
void UpdateTextureRegions(UTexture2D* Texture, int32 MipIndex, uint32 NumRegions, FUpdateTextureRegion2D* Regions, uint32 SrcPitch, uint32 SrcBpp, uint8* SrcData, bool bFreeData);
UFUNCTION(BlueprintCallable, Category = Graph)
void CreateBgTexture();
void CreateBgMaterial();
UFUNCTION(BlueprintCallable, Category = Graph)
void UpdateBgTexture();
private:
UPROPERTY()
TArray<FColor> data;
FUpdateTextureRegion2D *bgUpdateTextureRegion;
//Assets
UStaticMesh * AssetSM_CanvasBG;
UMaterial * AssetMat_CanvasBG;
};
C++ file:
AScrollingGraph::AScrollingGraph(const FObjectInitializer &ObjectInitializer) :Super(ObjectInitializer)
{
//Find static mesh asset
static ConstructorHelpers::FObjectFinder<UStaticMesh> StaticMeshOb_CU1(TEXT("StaticMesh'/Engine/BasicShapes/Cube.Cube'"));
if (StaticMeshOb_CU1.Succeeded()) AssetSM_CanvasBG = StaticMeshOb_CU1.Object;
//Find a Material asset
//static ConstructorHelpers::FObjectFinder<UMaterial> MaterialOb_CU1(TEXT("Material'/Engine/EngineMaterials/DefaultMaterial.DefaultMaterial'"));
//if (MaterialOb_CU1.Succeeded()) AssetMat_CanvasBG = MaterialOb_CU1.Object;
//Create Object and set a static mesh
CanvasBG = ObjectInitializer.CreateDefaultSubobject < UStaticMeshComponent >(this, TEXT("Cube_BG"));
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
}
// Called when the game starts or when spawned
void AScrollingGraph::BeginPlay()
{
Super::BeginPlay();
UWorld* world = GetWorld();
//if (world)
if (true)//should be word, true is for debugging
{
//Create a texture
CreateBgTexture();
DynMaterial = CanvasBG->CreateAndSetMaterialInstanceDynamic(0);
CanvasBG->SetStaticMesh(AssetSM_CanvasBG);
RootComponent = CanvasBG;
//DynMaterial = UMaterialInstanceDynamic::Create(AssetMat_CanvasBG, NULL);
//CanvasBG->SetMaterial(0, DynMaterial);
//Also tried using this to create and assing material, same result
}
}
// Called every frame
void AScrollingGraph::Tick( float DeltaTime )
{
Super::Tick( DeltaTime );
UpdateBgTexture();
}
void AScrollingGraph::CreateBgTexture() {
// Create echo texture
DynTexture = UTexture2D::CreateTransient(BG_TEXTURE_SIZEX, BG_TEXTURE_SIZEY);
DynTexture->SRGB = 0;
DynTexture->CompressionSettings = TextureCompressionSettings::TC_VectorDisplacementmap;
DynTexture->AddToRoot();
DynTexture->UpdateResource();
bgUpdateTextureRegion = new FUpdateTextureRegion2D(0, 0, 0, 0, BG_TEXTURE_SIZEX, BG_TEXTURE_SIZEY); // Note: This never gets freed
// Initialize data
data.Init(FColor(0, 20, 255, 255), BG_TEXTURE_DATA_LENGHT);
}
void AScrollingGraph::UpdateBgTexture() {
UpdateTextureRegions(DynTexture, (int32)0, (uint32)1, bgUpdateTextureRegion, (uint32)(4 * BG_TEXTURE_SIZEX), (uint32)4, (uint8*)data.GetData(), false);
DynMaterial->SetTextureParameterValue(FName(TEXT("DynamicTexture")), DynTexture);
}
void AScrollingGraph::PostInitializeComponents() {
Super::PostInitializeComponents();
CreateBgTexture();
DynMaterial = CanvasBG->CreateAndSetMaterialInstanceDynamic(0);
CanvasBG->SetStaticMesh(AssetSM_CanvasBG);
RootComponent = CanvasBG;
}
My problem: Nothing I try has any effect whatsoever. Even If I try to load a material that already exists and assing it using
static ConstructorHelpers::FObjectFinder<UMaterial> MaterialOb_CU1(TEXT("Material'/Engine/EngineMaterials/DefaultMaterial.DefaultMaterial'"));
if (MaterialOb_CU1.Succeeded()) AssetMat_CanvasBG = MaterialOb_CU1.Object;
DynMaterial = UMaterialInstanceDynamic::Create(AssetMat_CanvasBG, NULL);
CanvasBG->SetMaterial(0, DynMaterial);
Nothing happens. I must be missing something really obvious. I don’t want to admit how much time I have already spent on this material assigning from c++ thing, but way too much.
Thanks in advance guys!