Rename FilamentBuffers class to Mesh.
Update the Mesh class so that it manages the lifetime of the vertex and index buffers. PiperOrigin-RevId: 895794022 Change-Id: I5eda578b8b7ed7f918e792f6181ec724729b5215
This commit is contained in:
committed by
Copybara-Service
parent
6de35648d1
commit
28d8ddcbeb
@@ -18,6 +18,7 @@
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
#include <backend/BufferDescriptor.h>
|
||||
@@ -30,15 +31,59 @@
|
||||
// Functions for creating filament vertex and index buffers.
|
||||
namespace mujoco {
|
||||
|
||||
// Simple tuple-type of a IndexBuffer+VertexBuffer.
|
||||
struct FilamentBuffers {
|
||||
filament::IndexBuffer* index_buffer = nullptr;
|
||||
filament::VertexBuffer* vertex_buffer = nullptr;
|
||||
std::optional<filament::Box> bounds = std::nullopt;
|
||||
filament::RenderableManager::PrimitiveType type =
|
||||
// Owns a Vertex and Index buffer representing a geometry mesh.
|
||||
class Mesh {
|
||||
public:
|
||||
Mesh(filament::Engine* engine, filament::IndexBuffer* index_buffer,
|
||||
filament::VertexBuffer* vertex_buffer,
|
||||
std::optional<filament::Box> bounds = std::nullopt,
|
||||
filament::RenderableManager::PrimitiveType type =
|
||||
filament::RenderableManager::PrimitiveType::TRIANGLES)
|
||||
: engine_(engine),
|
||||
index_buffer_(index_buffer),
|
||||
vertex_buffer_(vertex_buffer),
|
||||
type_(type),
|
||||
bounds_(bounds) {}
|
||||
|
||||
~Mesh() {
|
||||
if (index_buffer_) {
|
||||
engine_->destroy(index_buffer_);
|
||||
}
|
||||
if (vertex_buffer_) {
|
||||
engine_->destroy(vertex_buffer_);
|
||||
}
|
||||
}
|
||||
|
||||
filament::IndexBuffer* GetFilamentIndexBuffer() const {
|
||||
return index_buffer_;
|
||||
}
|
||||
filament::VertexBuffer* GetFilamentVertexBuffer() const {
|
||||
return vertex_buffer_;
|
||||
}
|
||||
filament::RenderableManager::PrimitiveType GetPrimitiveType() const {
|
||||
return type_;
|
||||
}
|
||||
bool HasBounds() const {
|
||||
return bounds_.has_value();
|
||||
}
|
||||
filament::Box GetBounds() const {
|
||||
return bounds_.value();
|
||||
}
|
||||
|
||||
Mesh(const Mesh&) = delete;
|
||||
Mesh& operator=(const Mesh&) = delete;
|
||||
|
||||
private:
|
||||
filament::Engine* engine_ = nullptr;
|
||||
filament::IndexBuffer* index_buffer_ = nullptr;
|
||||
filament::VertexBuffer* vertex_buffer_ = nullptr;
|
||||
filament::RenderableManager::PrimitiveType type_ =
|
||||
filament::RenderableManager::PrimitiveType::TRIANGLES;
|
||||
std::optional<filament::Box> bounds_;
|
||||
};
|
||||
|
||||
using MeshPtr = std::unique_ptr<Mesh>;
|
||||
|
||||
// Function that fills in the given buffer with actual data.
|
||||
using FillBufferFn = std::function<void(std::byte*, std::size_t)>;
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <numbers>
|
||||
|
||||
#include <filament/Box.h>
|
||||
@@ -422,8 +423,8 @@ class ConeBuilder {
|
||||
|
||||
int idx = 0;
|
||||
for (int j = 0; j < num_slices_; ++j) {
|
||||
const float angle1 = (j+0) * delta_angle;
|
||||
const float angle2 = (j+1) * delta_angle;
|
||||
const float angle1 = (j + 0) * delta_angle;
|
||||
const float angle2 = (j + 1) * delta_angle;
|
||||
|
||||
ptr[idx++] = MakeVert(angle1, delta_radius);
|
||||
ptr[idx++] = MakeVert(angle2, delta_radius);
|
||||
@@ -436,12 +437,12 @@ class ConeBuilder {
|
||||
|
||||
// the rest: use quads
|
||||
for (int i = 1; i < num_stacks_; ++i) {
|
||||
const float radius1 = delta_radius * (i+0);
|
||||
const float radius2 = delta_radius * (i+1);
|
||||
const float radius1 = delta_radius * (i + 0);
|
||||
const float radius2 = delta_radius * (i + 1);
|
||||
|
||||
for (int j = 0; j < num_slices_; ++j) {
|
||||
const float angle1 = (j+0) * delta_angle;
|
||||
const float angle2 = (j+1) * delta_angle;
|
||||
const float angle1 = (j + 0) * delta_angle;
|
||||
const float angle2 = (j + 1) * delta_angle;
|
||||
|
||||
ptr[idx++] = MakeVert(angle1, radius2);
|
||||
ptr[idx++] = MakeVert(angle2, radius2);
|
||||
@@ -676,34 +677,34 @@ class DomeBuilder {
|
||||
(num_quads_body * kNumIndicesPerQuad);
|
||||
}
|
||||
|
||||
void GenerateVertices(VertexType* ptr, size_t num) const {
|
||||
const float lat_angle_delta =
|
||||
0.5 * std::numbers::pi / static_cast<float>(num_stacks_);
|
||||
const float lon_angle_delta =
|
||||
2.0 * std::numbers::pi / static_cast<float>(num_slices_);
|
||||
void GenerateVertices(VertexType* ptr, size_t num) const {
|
||||
const float lat_angle_delta =
|
||||
0.5 * std::numbers::pi / static_cast<float>(num_stacks_);
|
||||
const float lon_angle_delta =
|
||||
2.0 * std::numbers::pi / static_cast<float>(num_slices_);
|
||||
|
||||
// Add the pole.
|
||||
int idx = 0;
|
||||
ptr[idx++] = MakeVert(0, 0, 1);
|
||||
// Add the pole.
|
||||
int idx = 0;
|
||||
ptr[idx++] = MakeVert(0, 0, 1);
|
||||
|
||||
// Vertices by latitude.
|
||||
for (int lat = 0; lat < num_stacks_; ++lat) {
|
||||
// +1 because we handle the north pole (which would be at a lat angle of
|
||||
// 0-degrees) explicitly.
|
||||
const float lat_angle = static_cast<float>(lat + 1) * lat_angle_delta;
|
||||
const float cos_lat_angle = std::cos(lat_angle);
|
||||
const float sin_lat_angle = std::sin(lat_angle);
|
||||
const float z = cos_lat_angle;
|
||||
// Vertices by latitude.
|
||||
for (int lat = 0; lat < num_stacks_; ++lat) {
|
||||
// +1 because we handle the north pole (which would be at a lat angle of
|
||||
// 0-degrees) explicitly.
|
||||
const float lat_angle = static_cast<float>(lat + 1) * lat_angle_delta;
|
||||
const float cos_lat_angle = std::cos(lat_angle);
|
||||
const float sin_lat_angle = std::sin(lat_angle);
|
||||
const float z = cos_lat_angle;
|
||||
|
||||
for (int lon = 0; lon < num_slices_; ++lon) {
|
||||
const float lon_angle = static_cast<float>(lon) * lon_angle_delta;
|
||||
const float cos_lon_angle = std::cos(lon_angle);
|
||||
const float sin_lon_angle = std::sin(lon_angle);
|
||||
for (int lon = 0; lon < num_slices_; ++lon) {
|
||||
const float lon_angle = static_cast<float>(lon) * lon_angle_delta;
|
||||
const float cos_lon_angle = std::cos(lon_angle);
|
||||
const float sin_lon_angle = std::sin(lon_angle);
|
||||
|
||||
const float x = sin_lat_angle * cos_lon_angle;
|
||||
const float y = sin_lat_angle * sin_lon_angle;
|
||||
ptr[idx++] = MakeVert(x, y, z);
|
||||
}
|
||||
const float x = sin_lat_angle * cos_lon_angle;
|
||||
const float y = sin_lat_angle * sin_lon_angle;
|
||||
ptr[idx++] = MakeVert(x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -756,9 +757,8 @@ class DomeBuilder {
|
||||
int num_slices_;
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
FilamentBuffers CreateFromBuilder(filament::Engine* engine, const T& builder) {
|
||||
MeshPtr CreateFromBuilder(filament::Engine* engine, const T& builder) {
|
||||
using VertexType = typename T::VertexType;
|
||||
using IndexType = typename T::IndexType;
|
||||
|
||||
@@ -786,46 +786,47 @@ FilamentBuffers CreateFromBuilder(filament::Engine* engine, const T& builder) {
|
||||
|
||||
auto vb = CreateVertexBuffer<VertexType>(engine, num_vertices, vertices);
|
||||
auto ib = CreateIndexBuffer<IndexType>(engine, num_indices, indices);
|
||||
return {ib, vb, builder.GetBounds(), T::kPrimitiveType};
|
||||
return std::make_unique<Mesh>(engine, ib, vb, builder.GetBounds(),
|
||||
T::kPrimitiveType);
|
||||
}
|
||||
|
||||
FilamentBuffers CreateLine(filament::Engine* engine) {
|
||||
MeshPtr CreateLine(filament::Engine* engine) {
|
||||
return CreateFromBuilder(engine, LineBuilder());
|
||||
}
|
||||
|
||||
FilamentBuffers CreatePlane(filament::Engine* engine, int nquad) {
|
||||
MeshPtr CreatePlane(filament::Engine* engine, int nquad) {
|
||||
return CreateFromBuilder(engine, PlaneBuilder(nquad));
|
||||
}
|
||||
|
||||
FilamentBuffers CreateTriangle(filament::Engine* engine) {
|
||||
MeshPtr CreateTriangle(filament::Engine* engine) {
|
||||
return CreateFromBuilder(engine, TriangleBuilder());
|
||||
}
|
||||
|
||||
FilamentBuffers CreateBox(filament::Engine* engine, int nquad) {
|
||||
MeshPtr CreateBox(filament::Engine* engine, int nquad) {
|
||||
return CreateFromBuilder(engine, BoxBuilder(nquad));
|
||||
}
|
||||
|
||||
FilamentBuffers CreateLineBox(filament::Engine* engine) {
|
||||
MeshPtr CreateLineBox(filament::Engine* engine) {
|
||||
return CreateFromBuilder(engine, LineBoxBuilder());
|
||||
}
|
||||
|
||||
FilamentBuffers CreateSphere(filament::Engine* engine, int nstack, int nslice) {
|
||||
MeshPtr CreateSphere(filament::Engine* engine, int nstack, int nslice) {
|
||||
return CreateFromBuilder(engine, SphereBuilder(nstack, nslice));
|
||||
}
|
||||
|
||||
FilamentBuffers CreateTube(filament::Engine* engine, int nstack, int nslice) {
|
||||
MeshPtr CreateTube(filament::Engine* engine, int nstack, int nslice) {
|
||||
return CreateFromBuilder(engine, TubeBuilder(nstack, nslice));
|
||||
}
|
||||
|
||||
FilamentBuffers CreateDisk(filament::Engine* engine, int nslice) {
|
||||
MeshPtr CreateDisk(filament::Engine* engine, int nslice) {
|
||||
return CreateFromBuilder(engine, DiskBuilder(nslice));
|
||||
}
|
||||
|
||||
FilamentBuffers CreateDome(filament::Engine* engine, int nstack, int nslice) {
|
||||
MeshPtr CreateDome(filament::Engine* engine, int nstack, int nslice) {
|
||||
return CreateFromBuilder(engine, DomeBuilder(nstack, nslice));
|
||||
}
|
||||
|
||||
FilamentBuffers CreateCone(filament::Engine* engine, int nstack, int nslice) {
|
||||
MeshPtr CreateCone(filament::Engine* engine, int nstack, int nslice) {
|
||||
return CreateFromBuilder(engine, ConeBuilder(nstack, nslice));
|
||||
}
|
||||
|
||||
|
||||
@@ -21,16 +21,16 @@
|
||||
// Generates buffers for built-in shapes.
|
||||
namespace mujoco {
|
||||
|
||||
FilamentBuffers CreateLine(filament::Engine* engine);
|
||||
FilamentBuffers CreatePlane(filament::Engine* engine, int nquad);
|
||||
FilamentBuffers CreateTriangle(filament::Engine* engine);
|
||||
FilamentBuffers CreateBox(filament::Engine* engine, int nquad);
|
||||
FilamentBuffers CreateLineBox(filament::Engine* engine);
|
||||
FilamentBuffers CreateSphere(filament::Engine* engine, int nstack, int nslice);
|
||||
FilamentBuffers CreateTube(filament::Engine* engine, int nstack, int nslice);
|
||||
FilamentBuffers CreateDisk(filament::Engine* engine, int nslice);
|
||||
FilamentBuffers CreateDome(filament::Engine* engine, int nstack, int nslice);
|
||||
FilamentBuffers CreateCone(filament::Engine* engine, int nstack, int nslice);
|
||||
MeshPtr CreateLine(filament::Engine* engine);
|
||||
MeshPtr CreatePlane(filament::Engine* engine, int nquad);
|
||||
MeshPtr CreateTriangle(filament::Engine* engine);
|
||||
MeshPtr CreateBox(filament::Engine* engine, int nquad);
|
||||
MeshPtr CreateLineBox(filament::Engine* engine);
|
||||
MeshPtr CreateSphere(filament::Engine* engine, int nstack, int nslice);
|
||||
MeshPtr CreateTube(filament::Engine* engine, int nstack, int nslice);
|
||||
MeshPtr CreateDisk(filament::Engine* engine, int nslice);
|
||||
MeshPtr CreateDome(filament::Engine* engine, int nstack, int nslice);
|
||||
MeshPtr CreateCone(filament::Engine* engine, int nstack, int nslice);
|
||||
|
||||
} // namespace mujoco
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <numbers>
|
||||
#include <utility>
|
||||
|
||||
@@ -173,12 +174,12 @@ void Drawable::Update(const mjModel* model, const mjvScene* scene,
|
||||
if (geom.type == mjGEOM_FLEX || geom.type == mjGEOM_SKIN) {
|
||||
// Flex geometry is updated every frame with new vertex data.
|
||||
filament::Engine* engine = renderables_.GetEngine();
|
||||
FilamentBuffers buffers = CreateGeomBuffers(engine, model, scene, geom);
|
||||
std::unique_ptr<Mesh> mesh = CreateGeomBuffers(engine, model, scene, geom);
|
||||
|
||||
if (renderables_.GetNumEntities() == 0) {
|
||||
renderables_.Append(std::move(buffers));
|
||||
renderables_.Append(std::move(mesh));
|
||||
} else {
|
||||
renderables_.Update(0, std::move(buffers));
|
||||
renderables_.Update(0, std::move(mesh));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,27 +193,27 @@ void Drawable::Update(const mjModel* model, const mjvScene* scene,
|
||||
}
|
||||
|
||||
void Drawable::AddMesh(int data_id) {
|
||||
const FilamentBuffers* buffers = model_objs_->GetMeshBuffer(data_id);
|
||||
const Mesh* buffers = model_objs_->GetMeshBuffer(data_id);
|
||||
if (buffers == nullptr) {
|
||||
mju_error("Unknown mesh %d", data_id);
|
||||
}
|
||||
renderables_.Append(*buffers);
|
||||
renderables_.Append(buffers);
|
||||
}
|
||||
|
||||
void Drawable::AddHeightField(int hfield_id) {
|
||||
const FilamentBuffers* buffers = model_objs_->GetHeightFieldBuffer(hfield_id);
|
||||
const Mesh* buffers = model_objs_->GetHeightFieldBuffer(hfield_id);
|
||||
if (buffers == nullptr) {
|
||||
mju_error("Unknown height field %d", hfield_id);
|
||||
}
|
||||
renderables_.Append(*buffers);
|
||||
renderables_.Append(buffers);
|
||||
}
|
||||
|
||||
void Drawable::AddShape(ModelObjects::ShapeType shape_type) {
|
||||
const FilamentBuffers* buffers = model_objs_->GetShapeBuffer(shape_type);
|
||||
const Mesh* buffers = model_objs_->GetShapeBuffer(shape_type);
|
||||
if (buffers == nullptr) {
|
||||
mju_error("Unknown shape %d", shape_type);
|
||||
}
|
||||
renderables_.Append(*buffers);
|
||||
renderables_.Append(buffers);
|
||||
}
|
||||
|
||||
void Drawable::AddToScene(filament::Scene* scene) {
|
||||
|
||||
@@ -18,8 +18,10 @@
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <span>
|
||||
|
||||
#include <filament/Box.h>
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/IndexBuffer.h>
|
||||
#include <filament/VertexBuffer.h>
|
||||
@@ -162,9 +164,8 @@ static filament::IndexBuffer* BuildIndexBuffer(filament::Engine* engine,
|
||||
}
|
||||
}
|
||||
|
||||
FilamentBuffers CreateGeomBuffers(filament::Engine* engine,
|
||||
const mjModel* model, const mjvScene* scene,
|
||||
const mjvGeom& geom) {
|
||||
MeshPtr CreateGeomBuffers(filament::Engine* engine, const mjModel* model,
|
||||
const mjvScene* scene, const mjvGeom& geom) {
|
||||
auto positions = GetPositions(model, scene, geom);
|
||||
auto normals = GetNormals(model, scene, geom);
|
||||
auto uvs = GetUvs(model, scene, geom);
|
||||
@@ -175,14 +176,13 @@ FilamentBuffers CreateGeomBuffers(filament::Engine* engine,
|
||||
num_indices = 3 * scene->flexfaceused[geom.objid];
|
||||
}
|
||||
|
||||
FilamentBuffers buffers;
|
||||
float3 vmin = {FLT_MAX, FLT_MAX, FLT_MAX};
|
||||
float3 vmax = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
|
||||
buffers.vertex_buffer =
|
||||
BuildVertexBuffer(engine, positions, normals, uvs, &vmin, &vmax);
|
||||
buffers.index_buffer = BuildIndexBuffer(engine, indices, num_indices);
|
||||
buffers.bounds.emplace().set(vmin, vmax);
|
||||
return buffers;
|
||||
auto vertex_buffer = BuildVertexBuffer(engine, positions, normals, uvs, &vmin, &vmax);
|
||||
auto index_buffer = BuildIndexBuffer(engine, indices, num_indices);
|
||||
filament::Box bounds;
|
||||
bounds.set(vmin, vmax);
|
||||
return std::make_unique<Mesh>(engine, index_buffer, vertex_buffer, bounds);
|
||||
}
|
||||
|
||||
} // namespace mujoco
|
||||
|
||||
@@ -22,9 +22,8 @@
|
||||
namespace mujoco {
|
||||
|
||||
// Populates the FilamentBuffers for a flex geometry.
|
||||
FilamentBuffers CreateGeomBuffers(filament::Engine* engine,
|
||||
const mjModel* model, const mjvScene* scene,
|
||||
const mjvGeom& geom);
|
||||
MeshPtr CreateGeomBuffers(filament::Engine* engine, const mjModel* model,
|
||||
const mjvScene* scene, const mjvGeom& geom);
|
||||
|
||||
} // namespace mujoco
|
||||
|
||||
|
||||
@@ -62,10 +62,7 @@ GuiView::~GuiView() {
|
||||
}
|
||||
auto& em = utils::EntityManager::get();
|
||||
em.destroy(renderable_);
|
||||
for (auto& buffer : buffers_) {
|
||||
engine_->destroy(buffer.vertex_buffer);
|
||||
engine_->destroy(buffer.index_buffer);
|
||||
}
|
||||
meshes_.clear();
|
||||
for (auto& instance : instances_) {
|
||||
engine_->destroy(instance);
|
||||
}
|
||||
@@ -84,12 +81,7 @@ void GuiView::ResetRenderable() {
|
||||
em.destroy(renderable_);
|
||||
renderable_ = utils::Entity();
|
||||
}
|
||||
|
||||
for (auto& buffer : buffers_) {
|
||||
engine_->destroy(buffer.vertex_buffer);
|
||||
engine_->destroy(buffer.index_buffer);
|
||||
}
|
||||
buffers_.clear();
|
||||
meshes_.clear();
|
||||
}
|
||||
|
||||
uintptr_t GuiView::UploadImage(uintptr_t tex_id, const uint8_t* pixels,
|
||||
@@ -275,12 +267,7 @@ void GuiView::UpdateRenderable() {
|
||||
builder.build(*engine_, renderable_);
|
||||
scene_->addEntity(renderable_);
|
||||
}
|
||||
|
||||
for (auto& buffer : buffers_) {
|
||||
engine_->destroy(buffer.vertex_buffer);
|
||||
engine_->destroy(buffer.index_buffer);
|
||||
}
|
||||
buffers_.clear();
|
||||
meshes_.clear();
|
||||
|
||||
auto ri = rm.getInstance(renderable_);
|
||||
|
||||
@@ -299,10 +286,13 @@ void GuiView::UpdateRenderable() {
|
||||
}
|
||||
std::memcpy(dst, cmds->IdxBuffer.Data, size);
|
||||
};
|
||||
buffers_.push_back(
|
||||
{CreateIndexBuffer<uint16_t>(engine_, cmds->IdxBuffer.Size, ifill),
|
||||
CreateVertexBuffer<GuiVertex>(engine_, cmds->VtxBuffer.Size, vfill)});
|
||||
const mujoco::FilamentBuffers& buffer = buffers_.back();
|
||||
filament::IndexBuffer* index_buffer =
|
||||
CreateIndexBuffer<uint16_t>(engine_, cmds->IdxBuffer.Size, ifill);
|
||||
filament::VertexBuffer* vertex_buffer =
|
||||
CreateVertexBuffer<GuiVertex>(engine_, cmds->VtxBuffer.Size, vfill);
|
||||
|
||||
meshes_.push_back(std::make_unique<Mesh>(engine_, index_buffer, vertex_buffer));
|
||||
const auto& mesh = meshes_.back();
|
||||
|
||||
int index_offset = 0;
|
||||
for (const ImDrawCmd& command : cmds->CmdBuffer) {
|
||||
@@ -327,8 +317,9 @@ void GuiView::UpdateRenderable() {
|
||||
rm.setMaterialInstanceAt(
|
||||
ri, drawable_index,
|
||||
GetMaterialInstance(drawable_index, clip_rect, command.GetTexID()));
|
||||
rm.setGeometryAt(ri, drawable_index, kTriangles, buffer.vertex_buffer,
|
||||
buffer.index_buffer, index_offset, command.ElemCount);
|
||||
rm.setGeometryAt(
|
||||
ri, drawable_index, kTriangles, mesh->GetFilamentVertexBuffer(),
|
||||
mesh->GetFilamentIndexBuffer(), index_offset, command.ElemCount);
|
||||
rm.setBlendOrderAt(ri, drawable_index, drawable_index);
|
||||
|
||||
index_offset += command.ElemCount;
|
||||
|
||||
@@ -71,7 +71,7 @@ class GuiView {
|
||||
filament::View* view_ = nullptr;
|
||||
filament::Material* material_ = nullptr;
|
||||
utils::Entity renderable_;
|
||||
std::vector<FilamentBuffers> buffers_;
|
||||
std::vector<MeshPtr> meshes_;
|
||||
std::vector<filament::MaterialInstance*> instances_;
|
||||
std::unordered_map<uintptr_t, std::unique_ptr<Texture>> textures_;
|
||||
int num_elements_ = 0;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <filament/Box.h>
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/IndirectLight.h>
|
||||
#include <filament/Material.h>
|
||||
@@ -29,7 +30,6 @@
|
||||
#include "experimental/filament/filament/model_util.h"
|
||||
#include "experimental/filament/filament/texture.h"
|
||||
|
||||
|
||||
namespace mujoco {
|
||||
|
||||
ModelObjects::ModelObjects(const mjModel* model, filament::Engine* engine)
|
||||
@@ -73,14 +73,7 @@ ModelObjects::~ModelObjects() {
|
||||
for (auto& iter : indirect_lights_) {
|
||||
engine_->destroy(iter);
|
||||
}
|
||||
for (auto& iter : meshes_) {
|
||||
engine_->destroy(iter.second.vertex_buffer);
|
||||
engine_->destroy(iter.second.index_buffer);
|
||||
}
|
||||
for (auto& iter : shapes_) {
|
||||
engine_->destroy(iter.vertex_buffer);
|
||||
engine_->destroy(iter.index_buffer);
|
||||
}
|
||||
meshes_.clear();
|
||||
textures_.clear();
|
||||
}
|
||||
|
||||
@@ -88,32 +81,25 @@ void ModelObjects::UploadMesh(const mjModel* model, int id) {
|
||||
if (model != model_) {
|
||||
mju_error("Model mismatch.");
|
||||
}
|
||||
if (id < 0 || id >= model->nmesh) {
|
||||
if (id < 0 || id >= model->nmesh) {
|
||||
mju_error("Invalid mesh index %d", id);
|
||||
}
|
||||
meshes_.erase(id);
|
||||
convex_hulls_.erase(id);
|
||||
|
||||
if (auto iter = meshes_.find(id); iter != meshes_.end()) {
|
||||
engine_->destroy(iter->second.vertex_buffer);
|
||||
engine_->destroy(iter->second.index_buffer);
|
||||
}
|
||||
if (auto iter = convex_hulls_.find(id); iter != convex_hulls_.end()) {
|
||||
engine_->destroy(iter->second.vertex_buffer);
|
||||
engine_->destroy(iter->second.index_buffer);
|
||||
}
|
||||
|
||||
FilamentBuffers& buffers = meshes_[id];
|
||||
buffers.vertex_buffer = CreateVertexBuffer(
|
||||
engine_, model, id, MeshType::kNormal, &buffers.bounds.emplace());
|
||||
buffers.index_buffer =
|
||||
CreateIndexBuffer(engine_, model, id, MeshType::kNormal);
|
||||
filament::Box bounds;
|
||||
auto vertex_buffer =
|
||||
CreateVertexBuffer(engine_, model, id, MeshType::kNormal, &bounds);
|
||||
auto index_buffer = CreateIndexBuffer(engine_, model, id, MeshType::kNormal);
|
||||
meshes_[id] =
|
||||
std::make_unique<Mesh>(engine_, index_buffer, vertex_buffer, bounds);
|
||||
|
||||
if (model->mesh_graphadr[id] >= 0) {
|
||||
FilamentBuffers& hull_buffers = convex_hulls_[id];
|
||||
hull_buffers.vertex_buffer =
|
||||
CreateVertexBuffer(engine_, model, id, MeshType::kConvexHull,
|
||||
&hull_buffers.bounds.emplace());
|
||||
hull_buffers.index_buffer =
|
||||
CreateIndexBuffer(engine_, model, id, MeshType::kConvexHull);
|
||||
vertex_buffer =
|
||||
CreateVertexBuffer(engine_, model, id, MeshType::kConvexHull, &bounds);
|
||||
index_buffer = CreateIndexBuffer(engine_, model, id, MeshType::kConvexHull);
|
||||
convex_hulls_[id] =
|
||||
std::make_unique<Mesh>(engine_, index_buffer, vertex_buffer, bounds);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,43 +158,41 @@ void ModelObjects::UploadHeightField(const mjModel* model, int id) {
|
||||
mju_error("Invalid height field index %d", id);
|
||||
}
|
||||
|
||||
if (auto iter = height_fields_.find(id); iter != height_fields_.end()) {
|
||||
engine_->destroy(iter->second.vertex_buffer);
|
||||
engine_->destroy(iter->second.index_buffer);
|
||||
}
|
||||
height_fields_.erase(id);
|
||||
|
||||
FilamentBuffers& buffers = height_fields_[id];
|
||||
buffers.vertex_buffer = CreateVertexBuffer(
|
||||
engine_, model, id, MeshType::kHeightField, &buffers.bounds.emplace());
|
||||
buffers.index_buffer =
|
||||
filament::Box bounds;
|
||||
auto vertex_buffer =
|
||||
CreateVertexBuffer(engine_, model, id, MeshType::kHeightField, &bounds);
|
||||
auto index_buffer =
|
||||
CreateIndexBuffer(engine_, model, id, MeshType::kHeightField);
|
||||
height_fields_[id] =
|
||||
std::make_unique<Mesh>(engine_, index_buffer, vertex_buffer, bounds);
|
||||
}
|
||||
|
||||
const FilamentBuffers* ModelObjects::GetMeshBuffer(int data_id) const {
|
||||
const Mesh* ModelObjects::GetMeshBuffer(int data_id) const {
|
||||
// As defined by mjv_updateScene:
|
||||
// original mesh: mesh_id * 2
|
||||
// convex hull: (mesh_id * 2) + 1
|
||||
const int mesh_id = data_id / 2;
|
||||
if (data_id % 2 == 0) {
|
||||
auto it = meshes_.find(mesh_id);
|
||||
return it != meshes_.end() ? &it->second : nullptr;
|
||||
return it != meshes_.end() ? it->second.get() : nullptr;
|
||||
} else {
|
||||
auto it = convex_hulls_.find(mesh_id);
|
||||
return it != convex_hulls_.end() ? &it->second : nullptr;
|
||||
return it != convex_hulls_.end() ? it->second.get() : nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
const FilamentBuffers* ModelObjects::GetHeightFieldBuffer(
|
||||
int hfield_id) const {
|
||||
const Mesh* ModelObjects::GetHeightFieldBuffer(int hfield_id) const {
|
||||
auto it = height_fields_.find(hfield_id);
|
||||
return it != height_fields_.end() ? &it->second : nullptr;
|
||||
return it != height_fields_.end() ? it->second.get() : nullptr;
|
||||
}
|
||||
|
||||
const FilamentBuffers* ModelObjects::GetShapeBuffer(ShapeType shape) const {
|
||||
const Mesh* ModelObjects::GetShapeBuffer(ShapeType shape) const {
|
||||
if (shape < 0 || shape >= kNumShapes) {
|
||||
mju_error("Invalid shape type: %d", shape);
|
||||
}
|
||||
return &shapes_[shape];
|
||||
return shapes_[shape].get();
|
||||
}
|
||||
|
||||
const Texture* ModelObjects::GetTexture(int tex_id) const {
|
||||
|
||||
@@ -61,9 +61,9 @@ class ModelObjects {
|
||||
filament::Engine* GetEngine() const { return engine_; }
|
||||
|
||||
// Returns the cached instance of a filament object created from the mjModel.
|
||||
const FilamentBuffers* GetShapeBuffer(ShapeType shape) const;
|
||||
const FilamentBuffers* GetMeshBuffer(int data_id) const;
|
||||
const FilamentBuffers* GetHeightFieldBuffer(int hfield_id) const;
|
||||
const Mesh* GetShapeBuffer(ShapeType shape) const;
|
||||
const Mesh* GetMeshBuffer(int data_id) const;
|
||||
const Mesh* GetHeightFieldBuffer(int hfield_id) const;
|
||||
const Texture* GetTexture(int tex_id) const;
|
||||
const Texture* GetTexture(int mat_id, int role) const;
|
||||
|
||||
@@ -84,10 +84,10 @@ class ModelObjects {
|
||||
filament::Engine* engine_ = nullptr;
|
||||
std::vector<filament::Skybox*> skyboxes_;
|
||||
std::vector<filament::IndirectLight*> indirect_lights_;
|
||||
std::array<FilamentBuffers, kNumShapes> shapes_;
|
||||
std::unordered_map<int, FilamentBuffers> meshes_;
|
||||
std::unordered_map<int, FilamentBuffers> convex_hulls_;
|
||||
std::unordered_map<int, FilamentBuffers> height_fields_;
|
||||
std::array<MeshPtr, kNumShapes> shapes_;
|
||||
std::unordered_map<int, MeshPtr> meshes_;
|
||||
std::unordered_map<int, MeshPtr> convex_hulls_;
|
||||
std::unordered_map<int, MeshPtr> height_fields_;
|
||||
std::unordered_map<int, std::unique_ptr<Texture>> textures_;
|
||||
float specular_multiplier_ = 0.2f;
|
||||
float shininess_multiplier_ = 0.1f;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "experimental/filament/filament/renderables.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/RenderableManager.h>
|
||||
@@ -49,67 +49,65 @@ void Renderables::RemoveLast() {
|
||||
engine_->destroy(entity);
|
||||
em.destroy(entity);
|
||||
entities_.pop_back();
|
||||
|
||||
if (owned_buffers_.back().owned) {
|
||||
engine_->destroy(owned_buffers_.back().buffers.vertex_buffer);
|
||||
engine_->destroy(owned_buffers_.back().buffers.index_buffer);
|
||||
}
|
||||
owned_buffers_.pop_back();
|
||||
meshes_.pop_back();
|
||||
}
|
||||
|
||||
void Renderables::Update(int index, const FilamentBuffers& buffers) {
|
||||
void Renderables::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, buffers);
|
||||
UpdateBuffers(index, buffers, false);
|
||||
UpdateEntity(entity, mesh);
|
||||
UpdateMeshes(index, mesh);
|
||||
}
|
||||
|
||||
void Renderables::Update(int index, FilamentBuffers&& buffers) {
|
||||
void Renderables::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, buffers);
|
||||
UpdateBuffers(index, buffers, true);
|
||||
UpdateEntity(entity, mesh.get());
|
||||
UpdateMeshes(index, mesh.get(), std::move(mesh));
|
||||
}
|
||||
|
||||
void Renderables::Append(const FilamentBuffers& buffers) {
|
||||
utils::Entity entity = CreateEntity(buffers);
|
||||
void Renderables::Append(const Mesh* mesh) {
|
||||
utils::Entity entity = CreateEntity(mesh);
|
||||
entities_.push_back(entity);
|
||||
owned_buffers_.push_back({.owned = false, .buffers = buffers});
|
||||
meshes_.emplace_back(nullptr, mesh);
|
||||
}
|
||||
|
||||
void Renderables::Append(FilamentBuffers&& buffers) {
|
||||
utils::Entity entity = CreateEntity(buffers);
|
||||
void Renderables::Append(MeshPtr mesh) {
|
||||
utils::Entity entity = CreateEntity(mesh.get());
|
||||
entities_.push_back(entity);
|
||||
owned_buffers_.push_back({.owned = true, .buffers = buffers});
|
||||
meshes_.emplace_back(std::move(mesh), mesh.get());
|
||||
}
|
||||
|
||||
utils::Entity Renderables::CreateEntity(const FilamentBuffers& buffers) {
|
||||
if (buffers.vertex_buffer == nullptr) {
|
||||
utils::Entity Renderables::CreateEntity(const Mesh* mesh) {
|
||||
filament::VertexBuffer* vertex_buffer = mesh->GetFilamentVertexBuffer();
|
||||
if (vertex_buffer == nullptr) {
|
||||
mju_error("Invalid (null) vertex buffer.");
|
||||
}
|
||||
if (buffers.index_buffer == nullptr) {
|
||||
|
||||
filament::IndexBuffer* index_buffer = mesh->GetFilamentIndexBuffer();
|
||||
if (index_buffer == nullptr) {
|
||||
mju_error("Invalid (null) index buffer.");
|
||||
}
|
||||
|
||||
utils::Entity entity = utils::EntityManager::get().create();
|
||||
if (entity.isNull()) {
|
||||
mju_error("Failed to create entity.");
|
||||
}
|
||||
|
||||
filament::RenderableManager::Builder builder(1);
|
||||
builder.geometry(0, buffers.type, buffers.vertex_buffer,
|
||||
buffers.index_buffer);
|
||||
if (material_instance_) {
|
||||
builder.material(0, material_instance_);
|
||||
}
|
||||
if (buffers.bounds.has_value()) {
|
||||
builder.boundingBox(buffers.bounds.value());
|
||||
builder.geometry(0, mesh->GetPrimitiveType(), vertex_buffer, index_buffer);
|
||||
if (mesh->HasBounds()) {
|
||||
builder.boundingBox(mesh->GetBounds());
|
||||
} else {
|
||||
builder.culling(false);
|
||||
}
|
||||
if (material_instance_) {
|
||||
builder.material(0, material_instance_);
|
||||
}
|
||||
builder.castShadows(cast_shadows_);
|
||||
builder.receiveShadows(receive_shadows_);
|
||||
builder.layerMask(0xff, layer_mask_);
|
||||
@@ -123,30 +121,29 @@ utils::Entity Renderables::CreateEntity(const FilamentBuffers& buffers) {
|
||||
return entity;
|
||||
}
|
||||
|
||||
void Renderables::UpdateEntity(utils::Entity entity,
|
||||
const FilamentBuffers& buffers) {
|
||||
if (buffers.vertex_buffer == nullptr) {
|
||||
void Renderables::UpdateEntity(utils::Entity entity, const Mesh* mesh) {
|
||||
filament::VertexBuffer* vertex_buffer = mesh->GetFilamentVertexBuffer();
|
||||
if (vertex_buffer == nullptr) {
|
||||
mju_error("Invalid (null) vertex buffer.");
|
||||
}
|
||||
if (buffers.index_buffer == nullptr) {
|
||||
|
||||
filament::IndexBuffer* index_buffer = mesh->GetFilamentIndexBuffer();
|
||||
if (index_buffer == nullptr) {
|
||||
mju_error("Invalid (null) index buffer.");
|
||||
}
|
||||
|
||||
filament::RenderableManager& rm = engine_->getRenderableManager();
|
||||
rm.setGeometryAt(rm.getInstance(entity), 0, buffers.type,
|
||||
buffers.vertex_buffer, buffers.index_buffer, 0,
|
||||
buffers.index_buffer->getIndexCount());
|
||||
rm.setGeometryAt(rm.getInstance(entity), 0, mesh->GetPrimitiveType(),
|
||||
vertex_buffer, index_buffer, 0,
|
||||
index_buffer->getIndexCount());
|
||||
}
|
||||
|
||||
void Renderables::UpdateBuffers(int index, FilamentBuffers buffers, bool owned) {
|
||||
if (index < 0 || index >= owned_buffers_.size()) {
|
||||
void Renderables::UpdateMeshes(int index, const Mesh* mesh, MeshPtr owned_mesh) {
|
||||
if (index < 0 || index >= meshes_.size()) {
|
||||
mju_error("Invalid index %d for renderable.", index);
|
||||
}
|
||||
if (owned_buffers_[index].owned) {
|
||||
engine_->destroy(owned_buffers_[index].buffers.vertex_buffer);
|
||||
engine_->destroy(owned_buffers_[index].buffers.index_buffer);
|
||||
}
|
||||
owned_buffers_[index].buffers = buffers;
|
||||
owned_buffers_[index].owned = owned;
|
||||
meshes_[index].owned_mesh = std::move(owned_mesh);
|
||||
meshes_[index].mesh = mesh;
|
||||
}
|
||||
|
||||
void Renderables::AddToScene(filament::Scene* scene) {
|
||||
@@ -239,11 +236,13 @@ void Renderables::SetWireframe(bool wireframe) {
|
||||
filament::RenderableManager& rm = engine_->getRenderableManager();
|
||||
for (int i = 0; i < entities_.size(); ++i) {
|
||||
utils::Entity& entity = entities_[i];
|
||||
FilamentBuffers& buffers = owned_buffers_[i].buffers;
|
||||
const Mesh* mesh = meshes_[i].mesh;
|
||||
filament::VertexBuffer* vertex_buffer = mesh->GetFilamentVertexBuffer();
|
||||
filament::IndexBuffer* index_buffer = mesh->GetFilamentIndexBuffer();
|
||||
rm.setGeometryAt(rm.getInstance(entity), 0,
|
||||
wireframe_ ? kWireframeType : buffers.type,
|
||||
buffers.vertex_buffer, buffers.index_buffer, 0,
|
||||
buffers.index_buffer->getIndexCount());
|
||||
wireframe_ ? kWireframeType : mesh->GetPrimitiveType(),
|
||||
vertex_buffer, index_buffer, 0,
|
||||
index_buffer->getIndexCount());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_RENDERABLES_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include <filament/Engine.h>
|
||||
@@ -39,13 +38,13 @@ class Renderables {
|
||||
Renderables(const Renderables&) = delete;
|
||||
Renderables& operator=(const Renderables&) = delete;
|
||||
|
||||
// Appends a new renderable entity built from the given buffers.
|
||||
void Append(const FilamentBuffers& buffers);
|
||||
void Append(FilamentBuffers&& buffers);
|
||||
// Appends a new renderable entity built from the given mesh.
|
||||
void Append(const Mesh* mesh);
|
||||
void Append(MeshPtr mesh);
|
||||
|
||||
// Updates the entity at the index with new buffers.
|
||||
void Update(int index, const FilamentBuffers& buffers);
|
||||
void Update(int index, FilamentBuffers&& buffers);
|
||||
// Updates the entity at the index with new mesh.
|
||||
void Update(int index, const Mesh* mesh);
|
||||
void Update(int index, MeshPtr mesh);
|
||||
|
||||
// Removes the last entity.
|
||||
void RemoveLast();
|
||||
@@ -53,7 +52,7 @@ class Renderables {
|
||||
// Returns the entity at the given index.
|
||||
utils::Entity operator[](int index) { return entities_[index]; }
|
||||
|
||||
// Returns the owned buffers at the given index.
|
||||
// Returns the number of Entities that make up this renderable.
|
||||
int GetNumEntities() const { return entities_.size(); }
|
||||
|
||||
// Hides all managed entities.
|
||||
@@ -84,22 +83,20 @@ class Renderables {
|
||||
filament::Engine* GetEngine() { return engine_; }
|
||||
|
||||
private:
|
||||
utils::Entity CreateEntity(const FilamentBuffers& buffers);
|
||||
void UpdateEntity(utils::Entity entity, const FilamentBuffers& buffers);
|
||||
void UpdateBuffers(int index, FilamentBuffers buffers, bool owned);
|
||||
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);
|
||||
|
||||
// Tracks whether of not the filament buffers should be destroyed by this
|
||||
// class.
|
||||
struct OwnedBuffers {
|
||||
bool owned = false;
|
||||
FilamentBuffers buffers;
|
||||
struct MeshWrapper {
|
||||
MeshPtr owned_mesh;
|
||||
const Mesh* mesh = nullptr;
|
||||
};
|
||||
|
||||
filament::Engine* engine_ = nullptr;
|
||||
filament::Scene* assigned_scene_ = nullptr;
|
||||
filament::MaterialInstance* material_instance_ = nullptr;
|
||||
std::vector<utils::Entity> entities_;
|
||||
std::vector<OwnedBuffers> owned_buffers_;
|
||||
std::vector<MeshWrapper> meshes_;
|
||||
std::uint8_t priority_ = kDefaultPriority;
|
||||
std::uint8_t layer_mask_ = kDefaultLayerMask;
|
||||
bool wireframe_ = false;
|
||||
|
||||
Reference in New Issue
Block a user