Problem solved from Unreal Engine
We found the solution to paint the polygons from Unreal Engine and post it in case someone is with the same problem. The idea of the solution is to assign a dynamic instance of the material to each polygon of the model, starting from a base material with a parameter in the base color. For each dynamic instance of the material, the base color must be assigned to color the polygons. The assignment of colors must be done in the PostInitializeComponents. In this example case, only a lot of polygons are assigned a new color, but you could set one color per face in the same way, making this assignment within the loop.
Definition of the material (created in the editor):
Model.h:
UCLASS()
class BOTONLUZ_API AModelo : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AModelo();
// Called when the game starts or when spawned
virtual void BeginPlay() override;
// Called every frame
virtual void Tick( float DeltaSeconds ) override;
virtual void PostInitializeComponents() override;
UPROPERTY(Category = StaticMeshActor, VisibleAnywhere, BlueprintReadOnly,
Meta = (ExposeFunctionCategories = "Mesh,Rendering,Physics,Components|StaticMesh", AllowPrivateAccess = "true"))
UStaticMeshComponent * modeloActor;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Materials)
UMaterial* BaseMat;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Materials)
UMaterialInstanceDynamic* MaterialInst;
bool errorCargaModelo;
};
Model.cpp:
AModelo::AModelo()
{
PrimaryActorTick.bCanEverTick = true;
errorCargaModelo = false;
// Carga del material
static ConstructorHelpers::FObjectFinder<UMaterial> MatObj(TEXT("Material'/Game/Materiales/MaterialEjemplo.MaterialEjemplo'"));
if (MatObj.Succeeded()){
BaseMat = MatObj.Object;
}
static ConstructorHelpers::FObjectFinder<UStaticMesh> cargadorModelo(TEXT("/Game/Modelos/basico_mm"));
UStaticMesh* modelo;
if (cargadorModelo.Succeeded()){
modelo = cargadorModelo.Object;
}
else {
errorCargaModelo = true;
return;
}
if (!modelo->IsValidLowLevel()){
errorCargaModelo = true;
return;
}
if (&modelo->SourceModels[0] == nullptr){
errorCargaModelo = true;
return;
}
FStaticMeshSourceModel* sourceModel = &modelo->SourceModels[0];
FRawMesh rawMesh;
sourceModel->RawMeshBulkData->LoadRawMesh(rawMesh);
for (int32 i = 0; i < rawMesh.FaceMaterialIndices.Num(); i++){
rawMesh.FaceMaterialIndices[i] = i;
}
// Creo nuevo modelo
UStaticMesh* modeloNuevo = NewObject<UStaticMesh>();
new(modeloNuevo->SourceModels) FStaticMeshSourceModel();
modeloNuevo->SourceModels[0].RawMeshBulkData->SaveRawMesh(rawMesh);
for (int32 i = 0; i < rawMesh.FaceMaterialIndices.Num(); i++){
modeloNuevo->Materials.Add(BaseMat);
}
TArray<FText> BuildErrorsNuevo;
modeloNuevo->Build(true, &BuildErrorsNuevo);
modeloNuevo->MarkPackageDirty();
// Asigno nuevo modelo
modeloActor = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ModeloActor"));
modeloActor->SetStaticMesh(modeloNuevo);
}
void AModelo::PostInitializeComponents()
{
Super::PostInitializeComponents();
if (!errorCargaModelo){
if (BaseMat)
{
// Creo y agrego materiales a la lista del modelo
MaterialInst = UMaterialInstanceDynamic::Create(BaseMat, this);
modeloActor->SetMaterial(0, MaterialInst);
FLinearColor color1 = FLinearColor::Yellow;
MaterialInst->SetVectorParameterValue("baseColor", color1);
for (int32 i = 0; i < 100; i++){
modeloActor->SetMaterial(i, MaterialInst);
}
}
}
}
After spawning the actor from a blueprint, the model is painted:
I hope it serves you.
Greetings