Allow submeshes to be set when adding meshes to a Renderable.
Also add support for blend order. PiperOrigin-RevId: 900061778 Change-Id: I601757a8672fed23e45defd4cdbe4e9526ea3b70
This commit is contained in:
committed by
Copybara-Service
parent
9289905c9a
commit
f24f9ef44d
@@ -31,11 +31,11 @@ Renderable::Renderable(filament::Engine* engine) : material_(engine) {}
|
||||
|
||||
Renderable::~Renderable() noexcept {
|
||||
while (!entities_.empty()) {
|
||||
RemoveLast();
|
||||
RemoveLastEntity();
|
||||
}
|
||||
}
|
||||
|
||||
void Renderable::RemoveLast() {
|
||||
void Renderable::RemoveLastEntity() {
|
||||
if (entities_.empty()) {
|
||||
return;
|
||||
}
|
||||
@@ -53,37 +53,32 @@ void Renderable::RemoveLast() {
|
||||
meshes_.pop_back();
|
||||
}
|
||||
|
||||
void Renderable::Update(int index, const Mesh* mesh) {
|
||||
if (index < 0 || index >= entities_.size()) {
|
||||
mju_error("Invalid index %d for renderable.", index);
|
||||
}
|
||||
utils::Entity& entity = entities_[index];
|
||||
UpdateEntity(entity, mesh);
|
||||
UpdateMeshes(index, mesh);
|
||||
void Renderable::UpdateMesh(int index, const Mesh* mesh, int elem_offset,
|
||||
int elem_count) {
|
||||
MeshInfo& mesh_info = SetMesh(index, mesh, nullptr, elem_offset, elem_count);
|
||||
UpdateEntity(index, mesh_info);
|
||||
}
|
||||
|
||||
void Renderable::Update(int index, MeshPtr mesh) {
|
||||
if (index < 0 || index >= entities_.size()) {
|
||||
mju_error("Invalid index %d for renderable.", index);
|
||||
}
|
||||
utils::Entity& entity = entities_[index];
|
||||
UpdateEntity(entity, mesh.get());
|
||||
UpdateMeshes(index, mesh.get(), std::move(mesh));
|
||||
void Renderable::UpdateMesh(int index, MeshPtr mesh, int elem_offset,
|
||||
int elem_count) {
|
||||
MeshInfo& mesh_info =
|
||||
SetMesh(index, mesh.get(), std::move(mesh), elem_offset, elem_count);
|
||||
UpdateEntity(index, mesh_info);
|
||||
}
|
||||
|
||||
void Renderable::Append(const Mesh* mesh) {
|
||||
utils::Entity entity = CreateEntity(mesh);
|
||||
entities_.push_back(entity);
|
||||
meshes_.push_back({nullptr, mesh});
|
||||
void Renderable::AppendMesh(const Mesh* mesh, int elem_offset, int elem_count) {
|
||||
MeshInfo& mesh_info = SetMesh(-1, mesh, nullptr, elem_offset, elem_count);
|
||||
AppendEntity(mesh_info);
|
||||
}
|
||||
|
||||
void Renderable::Append(MeshPtr mesh) {
|
||||
utils::Entity entity = CreateEntity(mesh.get());
|
||||
entities_.push_back(entity);
|
||||
meshes_.push_back({std::move(mesh), mesh.get()});
|
||||
void Renderable::AppendMesh(MeshPtr mesh, int elem_offset, int elem_count) {
|
||||
MeshInfo& mesh_info =
|
||||
SetMesh(-1, mesh.get(), std::move(mesh), elem_offset, elem_count);
|
||||
AppendEntity(mesh_info);
|
||||
}
|
||||
|
||||
utils::Entity Renderable::CreateEntity(const Mesh* mesh) {
|
||||
void Renderable::AppendEntity(const MeshInfo& mesh_info) {
|
||||
const Mesh* mesh = mesh_info.mesh;
|
||||
filament::VertexBuffer* vertex_buffer = mesh->GetFilamentVertexBuffer();
|
||||
if (vertex_buffer == nullptr) {
|
||||
mju_error("Invalid (null) vertex buffer.");
|
||||
@@ -100,7 +95,8 @@ utils::Entity Renderable::CreateEntity(const Mesh* mesh) {
|
||||
}
|
||||
|
||||
filament::RenderableManager::Builder builder(1);
|
||||
builder.geometry(0, mesh->GetPrimitiveType(), vertex_buffer, index_buffer);
|
||||
builder.geometry(0, mesh->GetPrimitiveType(), vertex_buffer, index_buffer,
|
||||
mesh_info.elem_offset, mesh_info.elem_count);
|
||||
if (mesh->HasBounds()) {
|
||||
builder.boundingBox(mesh->GetBounds());
|
||||
} else {
|
||||
@@ -113,17 +109,23 @@ utils::Entity Renderable::CreateEntity(const Mesh* mesh) {
|
||||
builder.receiveShadows(receive_shadows_);
|
||||
builder.layerMask(0xff, layer_mask_);
|
||||
builder.priority(priority_);
|
||||
builder.blendOrder(0, blend_order_);
|
||||
builder.screenSpaceContactShadows(true);
|
||||
;
|
||||
|
||||
builder.build(*GetEngine(), entity);
|
||||
if (assigned_scene_) {
|
||||
assigned_scene_->addEntity(entity);
|
||||
}
|
||||
return entity;
|
||||
entities_.push_back(entity);
|
||||
}
|
||||
|
||||
void Renderable::UpdateEntity(utils::Entity entity, const Mesh* mesh) {
|
||||
void Renderable::UpdateEntity(int index, const MeshInfo& mesh_info) {
|
||||
if (index < 0 || index >= entities_.size()) {
|
||||
mju_error("Invalid index %d for renderable.", index);
|
||||
}
|
||||
utils::Entity entity = entities_[index];
|
||||
|
||||
const Mesh* mesh = mesh_info.mesh;
|
||||
filament::VertexBuffer* vertex_buffer = mesh->GetFilamentVertexBuffer();
|
||||
if (vertex_buffer == nullptr) {
|
||||
mju_error("Invalid (null) vertex buffer.");
|
||||
@@ -136,16 +138,32 @@ void Renderable::UpdateEntity(utils::Entity entity, const Mesh* mesh) {
|
||||
|
||||
filament::RenderableManager& rm = GetEngine()->getRenderableManager();
|
||||
rm.setGeometryAt(rm.getInstance(entity), 0, mesh->GetPrimitiveType(),
|
||||
vertex_buffer, index_buffer, 0,
|
||||
index_buffer->getIndexCount());
|
||||
vertex_buffer, index_buffer, mesh_info.elem_offset,
|
||||
mesh_info.elem_count);
|
||||
}
|
||||
|
||||
void Renderable::UpdateMeshes(int index, const Mesh* mesh, MeshPtr owned_mesh) {
|
||||
if (index < 0 || index >= meshes_.size()) {
|
||||
Renderable::MeshInfo& Renderable::SetMesh(int index, const Mesh* mesh,
|
||||
MeshPtr owned_mesh, int elem_offset,
|
||||
int elem_count) {
|
||||
if (index == -1) {
|
||||
index = meshes_.size();
|
||||
meshes_.emplace_back();
|
||||
}
|
||||
if (index < 0 || index >= static_cast<int>(meshes_.size())) {
|
||||
mju_error("Invalid index %d for renderable.", index);
|
||||
}
|
||||
meshes_[index].owned_mesh = std::move(owned_mesh);
|
||||
meshes_[index].mesh = mesh;
|
||||
|
||||
MeshInfo* mesh_info = &meshes_[index];
|
||||
mesh_info->owned_mesh = std::move(owned_mesh);
|
||||
mesh_info->mesh = mesh;
|
||||
mesh_info->elem_offset = elem_offset;
|
||||
mesh_info->elem_count = elem_count;
|
||||
if (mesh_info->elem_count == 0) {
|
||||
const int total =
|
||||
mesh_info->mesh->GetFilamentIndexBuffer()->getIndexCount();
|
||||
mesh_info->elem_count = total - mesh_info->elem_offset;
|
||||
}
|
||||
return *mesh_info;
|
||||
}
|
||||
|
||||
void Renderable::AddToScene(filament::Scene* scene) {
|
||||
@@ -209,6 +227,19 @@ std::uint8_t Renderable::SetPriority(std::uint8_t priority) {
|
||||
return prev;
|
||||
}
|
||||
|
||||
std::uint16_t Renderable::SetBlendOrder(std::uint16_t blend_order) {
|
||||
std::uint16_t prev = blend_order_;
|
||||
if (blend_order != blend_order_) {
|
||||
blend_order_ = blend_order;
|
||||
|
||||
filament::RenderableManager& rm = GetEngine()->getRenderableManager();
|
||||
for (utils::Entity& entity : entities_) {
|
||||
rm.setBlendOrderAt(rm.getInstance(entity), 0, blend_order_);
|
||||
}
|
||||
}
|
||||
return prev;
|
||||
}
|
||||
|
||||
void Renderable::SetCastShadows(bool cast_shadows) {
|
||||
if (cast_shadows_ != cast_shadows) {
|
||||
cast_shadows_ = cast_shadows;
|
||||
@@ -246,8 +277,8 @@ void Renderable::SetWireframe(bool wireframe) {
|
||||
filament::IndexBuffer* index_buffer = mesh->GetFilamentIndexBuffer();
|
||||
rm.setGeometryAt(rm.getInstance(entity), 0,
|
||||
wireframe_ ? kWireframeType : mesh->GetPrimitiveType(),
|
||||
vertex_buffer, index_buffer, 0,
|
||||
index_buffer->getIndexCount());
|
||||
vertex_buffer, index_buffer, meshes_[i].elem_offset,
|
||||
meshes_[i].elem_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,14 @@
|
||||
|
||||
namespace mujoco {
|
||||
|
||||
// Manages a collection of related filament Renderable Entities.
|
||||
// A collection of meshes and a material that, together, define an object that
|
||||
// can be rendered in a scene.
|
||||
//
|
||||
// Meshes can be added to the Renderable either by unique_ptr or raw pointer.
|
||||
// This determines whether or not the Renderable takes ownership of the mesh.
|
||||
//
|
||||
// Internally, the Renderable creates a filament::Entity for each mesh and
|
||||
// assigns the same material instance to all of them.
|
||||
class Renderable {
|
||||
public:
|
||||
// Default filament values for priority and layer mask.
|
||||
@@ -39,42 +46,51 @@ class Renderable {
|
||||
Renderable(const Renderable&) = delete;
|
||||
Renderable& operator=(const Renderable&) = delete;
|
||||
|
||||
// Appends a new renderable entity built from the given mesh.
|
||||
void Append(const Mesh* mesh);
|
||||
void Append(MeshPtr mesh);
|
||||
// Appends a mesh to the renderable. The elem_offset and elem_count parameters
|
||||
// can be used to specify a submesh to append. If elem_count is 0, assumes
|
||||
// the entire mesh should be appended.
|
||||
void AppendMesh(const Mesh* mesh, int elem_offset = 0, int elem_count = 0);
|
||||
void AppendMesh(MeshPtr mesh, int elem_offset = 0, int elem_count = 0);
|
||||
|
||||
// Updates the entity at the index with new mesh.
|
||||
void Update(int index, const Mesh* mesh);
|
||||
void Update(int index, MeshPtr mesh);
|
||||
// Replaces the mesh at the index with a new mesh. The elem_offset and
|
||||
// elem_count parameters can be used to specify a submesh to append. If
|
||||
// elem_count is 0, assumes the entire mesh should be appended.
|
||||
void UpdateMesh(int index, const Mesh* mesh, int elem_offset = 0,
|
||||
int elem_count = 0);
|
||||
void UpdateMesh(int index, MeshPtr mesh, int elem_offset = 0,
|
||||
int elem_count = 0);
|
||||
|
||||
// Removes the last entity.
|
||||
void RemoveLast();
|
||||
// Returns the number of meshes that define the renderable.
|
||||
int GetNumMeshes() const { return meshes_.size(); }
|
||||
|
||||
// Returns the entity at the given index.
|
||||
utils::Entity operator[](int index) { return entities_[index]; }
|
||||
|
||||
// Returns the number of Entities that make up this renderable.
|
||||
int GetNumEntities() const { return entities_.size(); }
|
||||
|
||||
// Hides all managed entities.
|
||||
// Sets the layer mask for the managed filament Entities. Layer masks can be
|
||||
// used to show/hide the renderable in different views. Returns the previous
|
||||
// layer mask.
|
||||
std::uint8_t SetLayerMask(std::uint8_t mask);
|
||||
|
||||
// Sets the priority of all managed entities.
|
||||
// Sets the priority for the managed filament Entities. The priority
|
||||
// determines the order in which renderables are rendered. Returns the
|
||||
// previous priority.
|
||||
std::uint8_t SetPriority(std::uint8_t priority);
|
||||
|
||||
// Disables the renderables from casting shadows.
|
||||
// Sets the blend order of the managed filament entities. This determines the
|
||||
// order in which renderables are blended together. Returns the previous blend
|
||||
// order.
|
||||
std::uint16_t SetBlendOrder(std::uint16_t blend_order);
|
||||
|
||||
// Disables the renderable from casting shadows.
|
||||
void SetCastShadows(bool cast_shadows);
|
||||
|
||||
// Disables the renderables from receiving shadows.
|
||||
// Disables the renderable from receiving shadows.
|
||||
void SetReceiveShadows(bool receive_shadows);
|
||||
|
||||
// If true, forces all entities to be rendered as lines.
|
||||
// If true, forces all meshes to be rendered using Lines primitives.
|
||||
void SetWireframe(bool wireframe);
|
||||
|
||||
// Adds all managed entities to the given filament Scene.
|
||||
// Adds the renderable to the given filament Scene.
|
||||
void AddToScene(filament::Scene* scene);
|
||||
|
||||
// Removes all managed entities from the given filament Scene.
|
||||
// Removes the renderable from the given filament Scene.
|
||||
void RemoveFromScene(filament::Scene* scene);
|
||||
|
||||
// Sets the material instance for all managed entities.
|
||||
@@ -86,23 +102,40 @@ class Renderable {
|
||||
// Returns the filament Engine managing the renderables.
|
||||
filament::Engine* GetEngine();
|
||||
|
||||
private:
|
||||
utils::Entity CreateEntity(const Mesh* mesh);
|
||||
void UpdateEntity(utils::Entity entity, const Mesh* mesh);
|
||||
void UpdateMeshes(int index, const Mesh* mesh, MeshPtr owned_mesh = nullptr);
|
||||
// Returns the underlying filament::entity for the given mesh.
|
||||
utils::Entity operator[](int index) { return entities_[index]; }
|
||||
|
||||
struct MeshWrapper {
|
||||
private:
|
||||
struct MeshInfo {
|
||||
MeshPtr owned_mesh;
|
||||
const Mesh* mesh = nullptr;
|
||||
int elem_offset = 0;
|
||||
int elem_count = 0;
|
||||
};
|
||||
|
||||
// Sets the mesh information for the mesh at the given index. If index is -1,
|
||||
// a new mesh will be appended to the renderable.
|
||||
MeshInfo& SetMesh(int index, const Mesh* mesh, MeshPtr owned_mesh,
|
||||
int elem_offset, int elem_count);
|
||||
|
||||
// Appends a new filament::Entity to the renderable, configured to use the
|
||||
// given mesh.
|
||||
void AppendEntity(const MeshInfo& mesh_info);
|
||||
|
||||
// Updates the filament::Entity at the given index to use the given mesh.
|
||||
void UpdateEntity(int index, const MeshInfo& mesh_info);
|
||||
|
||||
// Removes the last filament::Entity from the renderable.
|
||||
void RemoveLastEntity();
|
||||
|
||||
Material material_;
|
||||
filament::Scene* assigned_scene_ = nullptr;
|
||||
filament::MaterialInstance* material_instance_ = nullptr;
|
||||
std::vector<utils::Entity> entities_;
|
||||
std::vector<MeshWrapper> meshes_;
|
||||
std::vector<MeshInfo> meshes_;
|
||||
std::uint8_t priority_ = kDefaultPriority;
|
||||
std::uint8_t layer_mask_ = kDefaultLayerMask;
|
||||
std::uint16_t blend_order_ = 0;
|
||||
bool wireframe_ = false;
|
||||
bool cast_shadows_ = true;
|
||||
bool receive_shadows_ = true;
|
||||
|
||||
@@ -93,15 +93,15 @@ static void AddMesh(Renderable& renderable, ModelObjects* model_objs,
|
||||
if (mesh == nullptr) {
|
||||
mju_error("Unknown mesh %d", data_id);
|
||||
}
|
||||
renderable.Append(mesh);
|
||||
renderable.AppendMesh(mesh);
|
||||
}
|
||||
|
||||
static void AddGeom(Renderable& renderable, ModelObjects* model_objs,
|
||||
const mjvScene* scene, const mjvGeom& geom) {
|
||||
if (geom.type == mjGEOM_FLEX) {
|
||||
renderable.Append(model_objs->CreateFlexMesh(scene, geom));
|
||||
renderable.AppendMesh(model_objs->CreateFlexMesh(scene, geom));
|
||||
} else if (geom.type == mjGEOM_SKIN) {
|
||||
renderable.Append(model_objs->CreateSkinMesh(scene, geom));
|
||||
renderable.AppendMesh(model_objs->CreateSkinMesh(scene, geom));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ static void AddHeightField(Renderable& renderable, ModelObjects* model_objs,
|
||||
if (mesh == nullptr) {
|
||||
mju_error("Unknown height field %d", hfield_id);
|
||||
}
|
||||
renderable.Append(mesh);
|
||||
renderable.AppendMesh(mesh);
|
||||
}
|
||||
|
||||
static void AddShape(Renderable& renderable, ModelObjects* model_objs,
|
||||
@@ -120,7 +120,7 @@ static void AddShape(Renderable& renderable, ModelObjects* model_objs,
|
||||
if (mesh == nullptr) {
|
||||
mju_error("Unknown shape %d", shape_type);
|
||||
}
|
||||
renderable.Append(mesh);
|
||||
renderable.AppendMesh(mesh);
|
||||
}
|
||||
|
||||
static void PrepareGeomMeshes(Renderable& renderable, const mjvGeom& geom,
|
||||
@@ -211,7 +211,7 @@ static void SetGeomTransform(Renderable& renderable, const mjvGeom& geom) {
|
||||
float3 size = ReadFloat3(geom.size);
|
||||
filament::TransformManager& tm =
|
||||
renderable.GetEngine()->getTransformManager();
|
||||
for (int j = 0; j < renderable.GetNumEntities(); ++j) {
|
||||
for (int j = 0; j < renderable.GetNumMeshes(); ++j) {
|
||||
const utils::Entity& entity = renderable[j];
|
||||
|
||||
// Update object transform.
|
||||
|
||||
Reference in New Issue
Block a user