#What would be the best way of doing a visualisation of a procedural mesh with Entities.Graphics ?

1 messages · Page 1 of 1 (latest)

wary smelt
#

I'm building a prototype using spline the generate a Mesh for a conveyor belt there is actually 2 spline mesh ( the frame mesh & the flat belt mesh) .
The player need to select a point, a mesh is created with a spline.
From now on, the player can move it's mouse and a system generate a preview of the mesh with a "ghost , valid or invalid" material depending of the position, the mesh regenerate each time the end point move.

My question is, after spawning the entity :

Entity mainConveyorBeltEntity = state.EntityManager.Instantiate(ConveyorBeltPrefab);
state.EntityManager.SetName(mainConveyorBeltEntity, "mainConveyorBeltEntity");
Entity mainConveyorFrameEntity = state.EntityManager.Instantiate(ConveyorFramePrefab);
state.EntityManager.SetName(mainConveyorFrameEntity, "mainConveyorFrameEntity");

To modify in real time the mesh of both is this :

RenderMeshArray ConveyorBeltArray = state.EntityManager.GetSharedComponentManaged<RenderMeshArray>(mainConveyorBeltEntity);
RenderMeshArray ConveyorFrameArray = state.EntityManager.GetSharedComponentManaged<RenderMeshArray>(mainConveyorFrameEntity);
ConveyorBeltArray.Meshes[0] = UConveyorMesh.GenerateJob(); // this return a Mesh
ConveyorFrameArray.Meshes[0] = UConveyorMesh.GenerateJob(); // this return a Mesh

And to modify the material in real time :

if(isValidPlacement)
{
  ConveyorBeltArray.Materials[0] = GhostValidMaterial; 
  ConveyorFrameArray.Materials[0] = GhostValidMaterial; 
}
else
{
  ConveyorBeltArray.Materials[0] = GhostInValidMaterial; 
  ConveyorFrameArray.Materials[0] = GhostInValidMaterial; 
}

And finally applying it to the Entity :

state.EntityManager.SetSharedComponentManaged(mainConveyorBeltEntity, ConveyorBeltArray);
state.EntityManager.SetSharedComponentManaged(mainConveyorFrameEntity, ConveyorFrameArray);

The main point being that in the end the player is going to have a crapload of belts around in the prototype. So i'm trying to do it the right way.

#

Some precisions :

The samples : MaterialMeshChange is based on a pre-existing mesh list to work. not a procedurally generate mesh.

Each belt mesh will be unique. So basically each entity will end up with it's own mesh generated.
The materials will be the same for all belt & frame. Just need to switch it to the ghose one when building the belt.
During the placement of the belt I want to avoid flooding the memory for nothing if possible.
I wish to use entities because of the scale of a factory like game so I believe on the long run that should help.
I'm looking into the sample projects on the github but it's really confusing to get started with my special case. The complexity come from the fact that i'm generating the mesh at runtime.

Am I Missing anything ? Misunderstanding how the api should be used ?
I'm in need of guidance wise comunity ! <3<3

Thanks for your time !

hasty pulsar
#

Is this currently working? My experience was updating the RenderMeshArray caused weird issues

hasty pulsar
#

Ok I dug up a project where I have procedural meshes and this is what I do:

// OnCreate
rmd = new RenderMeshDescription(ShadowCastingMode.On, true);
sharedMaterialID = entitiesGraphicsSystem.RegisterMaterial(settings.DefaultMaterial);

// to create mesh
var mesh = new Mesh();
mesh.name = $"Mesh ({coord.x}, {coord.y}, {coord.z})";
mesh.indexFormat = IndexFormat.UInt32;

var batchMeshID = entitiesGraphicsSystem.RegisterMesh(mesh);

RenderMeshUtility.AddComponents(entity, em, rmd, new RenderMeshArray(), new MaterialMeshInfo(sharedMaterialID, batchMeshID));

// LocalToWorld
var matrix = float4x4.Translate(ChunkConstants.PositionFromCoord(coord));
em.SetComponentData(entity, new LocalToWorld { Value = matrix });

// RenderBounds
em.SetComponentData(entity, new RenderBounds { Value = ChunkConstants.LocalAABB });
wary smelt
#

@hasty pulsar how mush meshes are you handling with that ?

hasty pulsar
#

if you're using a prefab I assume you can ignore RenderMeshUtility.AddComponents and just set MaterialMeshInfo though you'll probably have to update the bounds at some point too

#

this was an experimental project but probably 100s

#

I don't know if you can unregister meshes so you may have to reuse them?

#

but you definately shouldn't have a single mesh in a render mesh array

wary smelt
#

hummmm

I ended up using that technique for now , it work well

I'm just worried about the scalability

What i'm currently doing is this in the system update function :

hybridRenderer.UnregisterMesh(_temporaryBeltMeshID);
hybridRenderer.UnregisterMesh(_temporaryFrameMeshID);
        
_temporaryBeltMeshID = hybridRenderer.RegisterMesh(UConveyorMesh.GenerateJob());
_temporaryFrameMeshID = hybridRenderer.RegisterMesh(UConveyorMesh.GenerateJob());

UpdateMeshComponents(state.EntityManager, beltEntities.BeltEntity, conveyorRenderMeshArrays.renderConveyorBeltArray, _temporaryBeltMeshID);
UpdateMeshComponents(state.EntityManager, beltEntities.FrameEntity, conveyorRenderMeshArrays.renderConveyorFrameArray,_temporaryFrameMeshID);

Every frame i'm showing the visualisation BEFORE registering the last mesh for good when the belt path is defined

Notes : UConveyorMesh.GenerateJob() is not returning the same mesh I ommitted the parameters of the function for clarity

wary smelt
hasty pulsar
#

this is what I was doing

#

12500 meshes

#

with single meshes in the render mesh arrays it had terrible performance because of how unity looks them up

wary smelt
#

gotcha so it seems to be the way to go

#

thanks mate 🙂