29

There are some hand wavey answers for this on answers.unrealengine.com, but they seem to lack any detail or examples.

Specifically, and in detail, if you wanted to implement a set of dynamic textured quads which rendered in the 3d game world, how would you do it?

For use case, consider a 2dish side scroller that uses Spriter animations. The 2D animations are loaded from XML easily enough, but how do you then render this 2D set of textured, rotated and scaled quads dynamically on the scene?

Doug
  • 26,182
  • 26
  • 140
  • 197
  • I think you need to look into procedural static mesh and material creation. It doesn't seem to be very well catered to in UE4 APIs, but you can start with https://docs.unrealengine.com/latest/INT/API/Plugins/ProceduralMeshComponent/index.html and https://wiki.unrealengine.com/Procedural_Materials – vipw Apr 24 '16 at 17:47
  • @vipw Oh, I've read them... I just can't actually make them work. If you have an *example* of them *actually working* you're welcome to the expired 200 point bonus on this question. – Doug Apr 25 '16 at 06:32
  • I've got something working based on this code: https://wiki.unrealengine.com/Procedural_Mesh_Component_in_C%2B%2B:Getting_Started Another, more complex example: https://github.com/LaP0573/ue4-fbx-importer/blob/master/ProceduralEntity.cpp – vipw May 12 '16 at 11:30

1 Answers1

4

Is the problem you are facing concern spawning the mesh or with obtaining the right orientation? (i.e. orthographic projection, facing the camera)

Spawning the mesh is easy enough, can be done either through Blueprints or in code.

In Blueprints, you would set up certain preconditions and then choose to spawn actors based on the conditions. The actual coding solution would look much the same.

If it is regarding orientation, then this answer will be of help to you, found on the UnrealEngine forums:

https://answers.unrealengine.com/questions/62126/how-do-i-render-a-dynamic-mesh-with-orthographic-p.html

EDIT:

After much hair pulling and documentation surfing, here's the code that made things work.

ADynamicMeshSpawner::ADynamicMeshSpawner()
{
     // 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;

    // Using a SphereComponent is not particularly necessary or relevant, but the cube refused to spawn without a root component to attach to, or so I surmise. Yay Unreal. =/
    USphereComponent* CubeComponent = CreateDefaultSubobject<USphereComponent>(TEXT("RootComponent"));
    RootComponent = CubeComponent;
    CubeComponent->InitSphereRadius(40.0f);
    CubeComponent->SetCollisionProfileName(TEXT("Pawn"));

    // Create and position a mesh component so we can see where our cube is
    UStaticMeshComponent* CubeVisual = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("VisualRepresentation"));
    CubeVisual->AttachTo(RootComponent);
    static ConstructorHelpers::FObjectFinder<UStaticMesh> SphereVisualAsset(TEXT("StaticMesh'/Game/StarterContent/Shapes/Shape_Cube.Shape_Cube'"));
    if (SphereVisualAsset.Succeeded())
    {
        CubeVisual->SetStaticMesh(SphereVisualAsset.Object);
        CubeVisual->SetRelativeLocation(FVector(-200.0f, 0.0f, 100.0f));
        CubeVisual->SetWorldScale3D(FVector(2.0f));
    }
    // Create a material to be applied on the StaticMeshComponent
    static ConstructorHelpers::FObjectFinder<UMaterial> Material(TEXT("Material'/Game/StarterContent/Materials/M_Tech_Hex_Tile_Pulse.M_Tech_Hex_Tile_Pulse'"));

    if (Material.Object != NULL)
    {
        TheMaterial = (UMaterial*)Material.Object;
    }

    CubeVisual->SetMaterial(0, TheMaterial);
}

The headerfile looks like this:

UCLASS()
class MYPROJECT_API ADynamicMeshSpawner : public AActor
{
    GENERATED_BODY()

public: 
    // Sets default values for this actor's properties
    ADynamicMeshSpawner();

    // Called when the game starts or when spawned
    virtual void BeginPlay() override;

    // Called every frame
    virtual void Tick( float DeltaSeconds ) override;
    // Pointer to the material that needs to be used
    UMaterial* TheMaterial;
};

The final output looked like this in the editor:

A glorious cube spawned from code!

I set it up so that an instance of my class 'DynamicMeshSpawner' would be spawned everytime I hit 'P' on the keyboard. When the instance of this class is created, it calls the constructor, which spawns the cube with the material applied. I did the class instance spawning stuff in BluePrints using the SpawnActor node.

Implemented in the level blueprint

The conditions that you require for spawning stuff would obviously depend on the application.

This method works for normal Materials but NOT Material Instances. I believe you would have to make changes to the type of TheMaterial, the ConstructorHelper call, and the cast from the material reference into TheMaterial in order to make it function.

I'm confident that this would work with Animated materials as well, meaning that the 2D animations would need to be converted into a Material of some sort.

Perhaps the link below would help.

https://forums.unrealengine.com/showthread.php?6744-Flipbook-material-to-recreate-an-animated-gif

EDIT 2:

Below are a very good set of examples on how to procedurally create objects in Unreal. Leaving it here for posterity and in case anyone comes looking.

https://github.com/SiggiG/ProceduralMeshes/

Sai Narayan
  • 302
  • 3
  • 13
  • Like I said in the question: 'There are some hand wavey answers for this on answers.unrealengine.com, but they seem to lack any detail or examples.'. What I want is very very simple: procedurally create a quad (at runtime) and render a texture (selected at runtime) on it. That's it. It's not a vague question; and unfortunately the link you've linked to is exactly the kind of 'vague handwaving' I'm talking about. I'll happily accept any answer that *actually shows the code* of how to do this. – Doug Dec 30 '15 at 12:07
  • Fair point Doug. Apologies for contributing to the vagueness. I'm fairly piqued myself by the lack of documentation or examples for something that should be quite easy to implement. Give me a bit, I'm taking a crack at implementing this myself, and will get back to you soon. – Sai Narayan Dec 30 '15 at 12:23
  • Posted the implementation that worked for me. I noticed that you asked for selection of a texture at runtime. I'm fairly sure that such a feature would not be straightforward to implement. It would require having all the textures converted into Materials beforehand (before runtime), and stored in a data structure of some sort. An array would be the easiest. This array (for instance) would then need to be available for indexing at runtime. Preconditions would trigger the spawning of different quads with different Materials (textures) rendered on them. Not impossible, but not too easy either. – Sai Narayan Dec 30 '15 at 15:47
  • This is a great attempt at answering the question, and by far the closest I've ever seen to doing it successfully; but notice that you neither procedurally create the geometry (you're just using a cube component), nor the material (you're just loading an existing material). That's the issue here; spriter geometry is not fixed; every animation in it has a different set of quads, and the geometry active in a particular animation can actually change over the course of the animation as you hit keyframes; so ultimately, I'm not really any closer to a solution unfortunately. – Doug Dec 31 '15 at 03:03
  • 2
    Well shit. =/ I believe you are right on the nail there. But with a little persistence and some work, I believe I can make it happen! It's become something of an obsession now I'll admit. I need to solve this issue! Doug, I'll either solve this or die trying. Wish me luck. – Sai Narayan Dec 31 '15 at 08:28