Improve wireframe rendering support in Filament renderer and Studio.
- Draw complete wireframes in the Filament renderer. - Bind the 'W' key to toggle the wireframe render flag in Studio. PiperOrigin-RevId: 957230911 Change-Id: Ib583c81ddcfa834686c7cf01d2b12842479993ea
This commit is contained in:
committed by
Copybara-Service
parent
6c78c98418
commit
e295b31c60
@@ -811,6 +811,8 @@ void App::HandleKeyboardEvents() {
|
||||
ToggleFlag(vis_options_.flags[mjVIS_COM]);
|
||||
} else if (!is_freecam_wasd && ImGui_IsChordJustPressed(ImGuiKey_D)) {
|
||||
ToggleFlag(vis_options_.flags[mjVIS_STATIC]);
|
||||
} else if (!is_freecam_wasd && ImGui_IsChordJustPressed(ImGuiKey_W)) {
|
||||
ToggleFlag(renderer_->GetRenderFlags()[mjRND_WIREFRAME]);
|
||||
} else if (ImGui_IsChordJustPressed(ImGuiKey_Semicolon)) {
|
||||
ToggleFlag(vis_options_.flags[mjVIS_SKIN]);
|
||||
} else if (ImGui_IsChordJustPressed(ImGuiKey_GraveAccent)) {
|
||||
@@ -2152,6 +2154,7 @@ void App::HelpGui() {
|
||||
ImGui::Text("Tendon");
|
||||
ImGui::Text("Texture");
|
||||
ImGui::Text("Transparent");
|
||||
ImGui::Text("Wireframe");
|
||||
|
||||
ImGui::NextColumn();
|
||||
ImGui::Indent(indent);
|
||||
@@ -2181,6 +2184,7 @@ void App::HelpGui() {
|
||||
ImGui::Text("V");
|
||||
ImGui::Text("X");
|
||||
ImGui::Text("T");
|
||||
ImGui::Text("W");
|
||||
|
||||
ImGui::Columns();
|
||||
}
|
||||
|
||||
@@ -146,6 +146,9 @@ Mesh::~Mesh() {
|
||||
if (index_buffer_) {
|
||||
engine_->destroy(index_buffer_);
|
||||
}
|
||||
if (wireframe_index_buffer_) {
|
||||
engine_->destroy(wireframe_index_buffer_);
|
||||
}
|
||||
if (vertex_buffer_) {
|
||||
engine_->destroy(vertex_buffer_);
|
||||
}
|
||||
@@ -308,6 +311,55 @@ void Mesh::UpdateIndexBuffer(const mjrfMeshData& data) {
|
||||
// callback for the vertex buffer will call release_callbacks_.
|
||||
filament::backend::BufferDescriptor desc(indices, num_bytes);
|
||||
index_buffer_->setBuffer(*engine_, std::move(desc));
|
||||
|
||||
UpdateWireframeIndexBuffer(indices);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void FillWireframeIndices(const void* src, int num_indices, T* out) {
|
||||
const T* in = static_cast<const T*>(src);
|
||||
for (int i = 0; i < num_indices - 2; i += 3) {
|
||||
*out++ = in[i + 0];
|
||||
*out++ = in[i + 1];
|
||||
*out++ = in[i + 1];
|
||||
*out++ = in[i + 2];
|
||||
*out++ = in[i + 2];
|
||||
*out++ = in[i + 0];
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::UpdateWireframeIndexBuffer(const void* src_indices) {
|
||||
// Line meshes are their own wireframe. Interior edges shared between two
|
||||
// triangles are deliberately not deduplicated so that triangle index ranges
|
||||
// map to line index ranges by doubling; see GetWireframeIndexBuffer().
|
||||
if (config_.primitive_type != mjMESH_PRIMITIVE_TYPE_TRIANGLES) {
|
||||
return;
|
||||
}
|
||||
const int num_line_indices = 2 * config_.max_indices;
|
||||
if (wireframe_index_buffer_ == nullptr) {
|
||||
filament::IndexBuffer::Builder ib_builder;
|
||||
ib_builder.indexCount(num_line_indices);
|
||||
ib_builder.bufferType(config_.index_type == mjINDEX_TYPE_U16
|
||||
? filament::IndexBuffer::IndexType::USHORT
|
||||
: filament::IndexBuffer::IndexType::UINT);
|
||||
wireframe_index_buffer_ = ib_builder.build(*engine_);
|
||||
}
|
||||
|
||||
const int element_size = config_.index_type == mjINDEX_TYPE_U16
|
||||
? sizeof(uint16_t)
|
||||
: sizeof(uint32_t);
|
||||
const int num_bytes = num_line_indices * element_size;
|
||||
std::byte* lines = new std::byte[num_bytes];
|
||||
shared_state_->callbacks.push_back([=]() { delete[] lines; });
|
||||
if (config_.index_type == mjINDEX_TYPE_U16) {
|
||||
FillWireframeIndices(src_indices, config_.max_indices,
|
||||
reinterpret_cast<uint16_t*>(lines));
|
||||
} else {
|
||||
FillWireframeIndices(src_indices, config_.max_indices,
|
||||
reinterpret_cast<uint32_t*>(lines));
|
||||
}
|
||||
filament::backend::BufferDescriptor desc(lines, num_bytes);
|
||||
wireframe_index_buffer_->setBuffer(*engine_, std::move(desc));
|
||||
}
|
||||
|
||||
void Mesh::UpdateBounds(const mjrfMeshData& data) {
|
||||
@@ -361,6 +413,10 @@ filament::IndexBuffer* Mesh::GetFilamentIndexBuffer() const {
|
||||
return index_buffer_;
|
||||
}
|
||||
|
||||
filament::IndexBuffer* Mesh::GetWireframeIndexBuffer() const {
|
||||
return wireframe_index_buffer_;
|
||||
}
|
||||
|
||||
filament::VertexBuffer* Mesh::GetFilamentVertexBuffer() const {
|
||||
return vertex_buffer_;
|
||||
}
|
||||
|
||||
@@ -49,6 +49,12 @@ class Mesh : public mjrfMesh {
|
||||
// Returns the filament IndexBuffer for the mesh.
|
||||
filament::IndexBuffer* GetFilamentIndexBuffer() const;
|
||||
|
||||
// Returns the filament IndexBuffer of line indices for wireframe rendering,
|
||||
// or nullptr for non-triangle meshes. Each triangle contributes its three
|
||||
// edges, so a triangle index range [offset, count) maps to the line index
|
||||
// range [2*offset, 2*count).
|
||||
filament::IndexBuffer* GetWireframeIndexBuffer() const;
|
||||
|
||||
// Returns the filament VertexBuffer for the mesh.
|
||||
filament::VertexBuffer* GetFilamentVertexBuffer() const;
|
||||
|
||||
@@ -75,6 +81,7 @@ class Mesh : public mjrfMesh {
|
||||
|
||||
void UpdateVertexBuffer(const mjrfMeshData& data);
|
||||
void UpdateIndexBuffer(const mjrfMeshData& data);
|
||||
void UpdateWireframeIndexBuffer(const void* indices);
|
||||
void UpdateBounds(const mjrfMeshData& data);
|
||||
|
||||
filament::math::float4* BuildOrientationsFromNormals(int num_vertices,
|
||||
@@ -86,6 +93,7 @@ class Mesh : public mjrfMesh {
|
||||
mjrfMeshConfig config_;
|
||||
|
||||
filament::IndexBuffer* index_buffer_ = nullptr;
|
||||
filament::IndexBuffer* wireframe_index_buffer_ = nullptr;
|
||||
filament::VertexBuffer* vertex_buffer_ = nullptr;
|
||||
std::optional<filament::Box> bounds_;
|
||||
|
||||
|
||||
@@ -461,11 +461,22 @@ void Renderable::SetWireframe(bool wireframe) {
|
||||
for (Part& part : parts_) {
|
||||
filament::VertexBuffer* vertex_buffer =
|
||||
part.mesh->GetFilamentVertexBuffer();
|
||||
filament::IndexBuffer* index_buffer = part.mesh->GetFilamentIndexBuffer();
|
||||
rm.setGeometryAt(
|
||||
rm.getInstance(part.entity), 0,
|
||||
wireframe ? kWireframeType : part.mesh->GetPrimitiveType(),
|
||||
vertex_buffer, index_buffer, part.elem_offset, part.elem_count);
|
||||
filament::IndexBuffer* wireframe_index_buffer =
|
||||
part.mesh->GetWireframeIndexBuffer();
|
||||
if (wireframe && wireframe_index_buffer) {
|
||||
// Triangle meshes have a dedicated line index buffer enumerating the
|
||||
// three edges of each triangle, addressed by doubling the range.
|
||||
rm.setGeometryAt(rm.getInstance(part.entity), 0, kWireframeType,
|
||||
vertex_buffer, wireframe_index_buffer,
|
||||
2 * part.elem_offset, 2 * part.elem_count);
|
||||
} else {
|
||||
// Line meshes are drawn as-is in both modes.
|
||||
rm.setGeometryAt(rm.getInstance(part.entity), 0,
|
||||
wireframe ? kWireframeType
|
||||
: part.mesh->GetPrimitiveType(),
|
||||
vertex_buffer, part.mesh->GetFilamentIndexBuffer(),
|
||||
part.elem_offset, part.elem_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user