C ++ API for editing three-dimensional models

3

I tell you that we are developing an architectural visualization project using the Unreal Engine video game engine. We have a requirement that is very complicated to complete from the tools provided by Unreal Engine, and is to change the colors of each polygon of the model individually, receiving the list of colors per parameter.

As this engine supports programming with C ++ (complementing its own graphic language called Blueprints), I would like to know if there are any APIs that can be integrated into the C ++ project and that allow the edition of models, particularly with .obj and / or formats. .fbx, in which you can access the low level of the model and edit the color individually to each polygon.

Edit: It would be good if this API allows generating a new file for the model with the changes made, so that we can separate what is this edition at a low level of the model and the rest of the processing in the Unreal Engine.

Thank you very much.

    
asked by ggimenez 11.03.2016 в 19:25
source

3 answers

3

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

    
answered by 11.04.2016 / 06:19
source
0

I have not used so much Unreal Engine to have to use HLSL, but if I touch it a bit in XNA

See if you can do it

answered by 11.03.2016 в 20:09
0

For CAD development you can try OpenCascade . It is a pretty good engine and is specialized in CAD design and 3D modeling, which I think is quite suitable for your needs.

    
answered by 11.03.2016 в 20:40