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 {
|
Renderable::~Renderable() noexcept {
|
||||||
while (!entities_.empty()) {
|
while (!entities_.empty()) {
|
||||||
RemoveLast();
|
RemoveLastEntity();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderable::RemoveLast() {
|
void Renderable::RemoveLastEntity() {
|
||||||
if (entities_.empty()) {
|
if (entities_.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -53,37 +53,32 @@ void Renderable::RemoveLast() {
|
|||||||
meshes_.pop_back();
|
meshes_.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderable::Update(int index, const Mesh* mesh) {
|
void Renderable::UpdateMesh(int index, const Mesh* mesh, int elem_offset,
|
||||||
if (index < 0 || index >= entities_.size()) {
|
int elem_count) {
|
||||||
mju_error("Invalid index %d for renderable.", index);
|
MeshInfo& mesh_info = SetMesh(index, mesh, nullptr, elem_offset, elem_count);
|
||||||
}
|
UpdateEntity(index, mesh_info);
|
||||||
utils::Entity& entity = entities_[index];
|
|
||||||
UpdateEntity(entity, mesh);
|
|
||||||
UpdateMeshes(index, mesh);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderable::Update(int index, MeshPtr mesh) {
|
void Renderable::UpdateMesh(int index, MeshPtr mesh, int elem_offset,
|
||||||
if (index < 0 || index >= entities_.size()) {
|
int elem_count) {
|
||||||
mju_error("Invalid index %d for renderable.", index);
|
MeshInfo& mesh_info =
|
||||||
}
|
SetMesh(index, mesh.get(), std::move(mesh), elem_offset, elem_count);
|
||||||
utils::Entity& entity = entities_[index];
|
UpdateEntity(index, mesh_info);
|
||||||
UpdateEntity(entity, mesh.get());
|
|
||||||
UpdateMeshes(index, mesh.get(), std::move(mesh));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderable::Append(const Mesh* mesh) {
|
void Renderable::AppendMesh(const Mesh* mesh, int elem_offset, int elem_count) {
|
||||||
utils::Entity entity = CreateEntity(mesh);
|
MeshInfo& mesh_info = SetMesh(-1, mesh, nullptr, elem_offset, elem_count);
|
||||||
entities_.push_back(entity);
|
AppendEntity(mesh_info);
|
||||||
meshes_.push_back({nullptr, mesh});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderable::Append(MeshPtr mesh) {
|
void Renderable::AppendMesh(MeshPtr mesh, int elem_offset, int elem_count) {
|
||||||
utils::Entity entity = CreateEntity(mesh.get());
|
MeshInfo& mesh_info =
|
||||||
entities_.push_back(entity);
|
SetMesh(-1, mesh.get(), std::move(mesh), elem_offset, elem_count);
|
||||||
meshes_.push_back({std::move(mesh), mesh.get()});
|
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();
|
filament::VertexBuffer* vertex_buffer = mesh->GetFilamentVertexBuffer();
|
||||||
if (vertex_buffer == nullptr) {
|
if (vertex_buffer == nullptr) {
|
||||||
mju_error("Invalid (null) vertex buffer.");
|
mju_error("Invalid (null) vertex buffer.");
|
||||||
@@ -100,7 +95,8 @@ utils::Entity Renderable::CreateEntity(const Mesh* mesh) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
filament::RenderableManager::Builder builder(1);
|
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()) {
|
if (mesh->HasBounds()) {
|
||||||
builder.boundingBox(mesh->GetBounds());
|
builder.boundingBox(mesh->GetBounds());
|
||||||
} else {
|
} else {
|
||||||
@@ -113,17 +109,23 @@ utils::Entity Renderable::CreateEntity(const Mesh* mesh) {
|
|||||||
builder.receiveShadows(receive_shadows_);
|
builder.receiveShadows(receive_shadows_);
|
||||||
builder.layerMask(0xff, layer_mask_);
|
builder.layerMask(0xff, layer_mask_);
|
||||||
builder.priority(priority_);
|
builder.priority(priority_);
|
||||||
|
builder.blendOrder(0, blend_order_);
|
||||||
builder.screenSpaceContactShadows(true);
|
builder.screenSpaceContactShadows(true);
|
||||||
;
|
|
||||||
|
|
||||||
builder.build(*GetEngine(), entity);
|
builder.build(*GetEngine(), entity);
|
||||||
if (assigned_scene_) {
|
if (assigned_scene_) {
|
||||||
assigned_scene_->addEntity(entity);
|
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();
|
filament::VertexBuffer* vertex_buffer = mesh->GetFilamentVertexBuffer();
|
||||||
if (vertex_buffer == nullptr) {
|
if (vertex_buffer == nullptr) {
|
||||||
mju_error("Invalid (null) vertex buffer.");
|
mju_error("Invalid (null) vertex buffer.");
|
||||||
@@ -136,16 +138,32 @@ void Renderable::UpdateEntity(utils::Entity entity, const Mesh* mesh) {
|
|||||||
|
|
||||||
filament::RenderableManager& rm = GetEngine()->getRenderableManager();
|
filament::RenderableManager& rm = GetEngine()->getRenderableManager();
|
||||||
rm.setGeometryAt(rm.getInstance(entity), 0, mesh->GetPrimitiveType(),
|
rm.setGeometryAt(rm.getInstance(entity), 0, mesh->GetPrimitiveType(),
|
||||||
vertex_buffer, index_buffer, 0,
|
vertex_buffer, index_buffer, mesh_info.elem_offset,
|
||||||
index_buffer->getIndexCount());
|
mesh_info.elem_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderable::UpdateMeshes(int index, const Mesh* mesh, MeshPtr owned_mesh) {
|
Renderable::MeshInfo& Renderable::SetMesh(int index, const Mesh* mesh,
|
||||||
if (index < 0 || index >= meshes_.size()) {
|
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);
|
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) {
|
void Renderable::AddToScene(filament::Scene* scene) {
|
||||||
@@ -209,6 +227,19 @@ std::uint8_t Renderable::SetPriority(std::uint8_t priority) {
|
|||||||
return prev;
|
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) {
|
void Renderable::SetCastShadows(bool cast_shadows) {
|
||||||
if (cast_shadows_ != cast_shadows) {
|
if (cast_shadows_ != cast_shadows) {
|
||||||
cast_shadows_ = cast_shadows;
|
cast_shadows_ = cast_shadows;
|
||||||
@@ -246,8 +277,8 @@ void Renderable::SetWireframe(bool wireframe) {
|
|||||||
filament::IndexBuffer* index_buffer = mesh->GetFilamentIndexBuffer();
|
filament::IndexBuffer* index_buffer = mesh->GetFilamentIndexBuffer();
|
||||||
rm.setGeometryAt(rm.getInstance(entity), 0,
|
rm.setGeometryAt(rm.getInstance(entity), 0,
|
||||||
wireframe_ ? kWireframeType : mesh->GetPrimitiveType(),
|
wireframe_ ? kWireframeType : mesh->GetPrimitiveType(),
|
||||||
vertex_buffer, index_buffer, 0,
|
vertex_buffer, index_buffer, meshes_[i].elem_offset,
|
||||||
index_buffer->getIndexCount());
|
meshes_[i].elem_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,14 @@
|
|||||||
|
|
||||||
namespace mujoco {
|
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 {
|
class Renderable {
|
||||||
public:
|
public:
|
||||||
// Default filament values for priority and layer mask.
|
// Default filament values for priority and layer mask.
|
||||||
@@ -39,42 +46,51 @@ class Renderable {
|
|||||||
Renderable(const Renderable&) = delete;
|
Renderable(const Renderable&) = delete;
|
||||||
Renderable& operator=(const Renderable&) = delete;
|
Renderable& operator=(const Renderable&) = delete;
|
||||||
|
|
||||||
// Appends a new renderable entity built from the given mesh.
|
// Appends a mesh to the renderable. The elem_offset and elem_count parameters
|
||||||
void Append(const Mesh* mesh);
|
// can be used to specify a submesh to append. If elem_count is 0, assumes
|
||||||
void Append(MeshPtr mesh);
|
// 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.
|
// Replaces the mesh at the index with a new mesh. The elem_offset and
|
||||||
void Update(int index, const Mesh* mesh);
|
// elem_count parameters can be used to specify a submesh to append. If
|
||||||
void Update(int index, MeshPtr mesh);
|
// 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.
|
// Returns the number of meshes that define the renderable.
|
||||||
void RemoveLast();
|
int GetNumMeshes() const { return meshes_.size(); }
|
||||||
|
|
||||||
// Returns the entity at the given index.
|
// Sets the layer mask for the managed filament Entities. Layer masks can be
|
||||||
utils::Entity operator[](int index) { return entities_[index]; }
|
// used to show/hide the renderable in different views. Returns the previous
|
||||||
|
// layer mask.
|
||||||
// Returns the number of Entities that make up this renderable.
|
|
||||||
int GetNumEntities() const { return entities_.size(); }
|
|
||||||
|
|
||||||
// Hides all managed entities.
|
|
||||||
std::uint8_t SetLayerMask(std::uint8_t 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);
|
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);
|
void SetCastShadows(bool cast_shadows);
|
||||||
|
|
||||||
// Disables the renderables from receiving shadows.
|
// Disables the renderable from receiving shadows.
|
||||||
void SetReceiveShadows(bool receive_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);
|
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);
|
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);
|
void RemoveFromScene(filament::Scene* scene);
|
||||||
|
|
||||||
// Sets the material instance for all managed entities.
|
// Sets the material instance for all managed entities.
|
||||||
@@ -86,23 +102,40 @@ class Renderable {
|
|||||||
// Returns the filament Engine managing the renderables.
|
// Returns the filament Engine managing the renderables.
|
||||||
filament::Engine* GetEngine();
|
filament::Engine* GetEngine();
|
||||||
|
|
||||||
private:
|
// Returns the underlying filament::entity for the given mesh.
|
||||||
utils::Entity CreateEntity(const Mesh* mesh);
|
utils::Entity operator[](int index) { return entities_[index]; }
|
||||||
void UpdateEntity(utils::Entity entity, const Mesh* mesh);
|
|
||||||
void UpdateMeshes(int index, const Mesh* mesh, MeshPtr owned_mesh = nullptr);
|
|
||||||
|
|
||||||
struct MeshWrapper {
|
private:
|
||||||
|
struct MeshInfo {
|
||||||
MeshPtr owned_mesh;
|
MeshPtr owned_mesh;
|
||||||
const Mesh* mesh = nullptr;
|
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_;
|
Material material_;
|
||||||
filament::Scene* assigned_scene_ = nullptr;
|
filament::Scene* assigned_scene_ = nullptr;
|
||||||
filament::MaterialInstance* material_instance_ = nullptr;
|
filament::MaterialInstance* material_instance_ = nullptr;
|
||||||
std::vector<utils::Entity> entities_;
|
std::vector<utils::Entity> entities_;
|
||||||
std::vector<MeshWrapper> meshes_;
|
std::vector<MeshInfo> meshes_;
|
||||||
std::uint8_t priority_ = kDefaultPriority;
|
std::uint8_t priority_ = kDefaultPriority;
|
||||||
std::uint8_t layer_mask_ = kDefaultLayerMask;
|
std::uint8_t layer_mask_ = kDefaultLayerMask;
|
||||||
|
std::uint16_t blend_order_ = 0;
|
||||||
bool wireframe_ = false;
|
bool wireframe_ = false;
|
||||||
bool cast_shadows_ = true;
|
bool cast_shadows_ = true;
|
||||||
bool receive_shadows_ = true;
|
bool receive_shadows_ = true;
|
||||||
|
|||||||
@@ -93,15 +93,15 @@ static void AddMesh(Renderable& renderable, ModelObjects* model_objs,
|
|||||||
if (mesh == nullptr) {
|
if (mesh == nullptr) {
|
||||||
mju_error("Unknown mesh %d", data_id);
|
mju_error("Unknown mesh %d", data_id);
|
||||||
}
|
}
|
||||||
renderable.Append(mesh);
|
renderable.AppendMesh(mesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AddGeom(Renderable& renderable, ModelObjects* model_objs,
|
static void AddGeom(Renderable& renderable, ModelObjects* model_objs,
|
||||||
const mjvScene* scene, const mjvGeom& geom) {
|
const mjvScene* scene, const mjvGeom& geom) {
|
||||||
if (geom.type == mjGEOM_FLEX) {
|
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) {
|
} 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) {
|
if (mesh == nullptr) {
|
||||||
mju_error("Unknown height field %d", hfield_id);
|
mju_error("Unknown height field %d", hfield_id);
|
||||||
}
|
}
|
||||||
renderable.Append(mesh);
|
renderable.AppendMesh(mesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AddShape(Renderable& renderable, ModelObjects* model_objs,
|
static void AddShape(Renderable& renderable, ModelObjects* model_objs,
|
||||||
@@ -120,7 +120,7 @@ static void AddShape(Renderable& renderable, ModelObjects* model_objs,
|
|||||||
if (mesh == nullptr) {
|
if (mesh == nullptr) {
|
||||||
mju_error("Unknown shape %d", shape_type);
|
mju_error("Unknown shape %d", shape_type);
|
||||||
}
|
}
|
||||||
renderable.Append(mesh);
|
renderable.AppendMesh(mesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrepareGeomMeshes(Renderable& renderable, const mjvGeom& geom,
|
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);
|
float3 size = ReadFloat3(geom.size);
|
||||||
filament::TransformManager& tm =
|
filament::TransformManager& tm =
|
||||||
renderable.GetEngine()->getTransformManager();
|
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];
|
const utils::Entity& entity = renderable[j];
|
||||||
|
|
||||||
// Update object transform.
|
// Update object transform.
|
||||||
|
|||||||
Reference in New Issue
Block a user