Move flex/skin Mesh creation into ModelObjects.
PiperOrigin-RevId: 896419032 Change-Id: Ib0f0cd0c80c9f630127f2f72dbaed7c644046663
This commit is contained in:
committed by
Copybara-Service
parent
87b0ea785e
commit
c6a434a408
@@ -33,8 +33,6 @@ target_sources(${MUJOCO_FILAMENT_TARGET_NAME}
|
||||
filament/filament_context.h
|
||||
filament/filament_platform_factory.cc
|
||||
filament/filament_platform_factory.h
|
||||
filament/geom_util.cc
|
||||
filament/geom_util.h
|
||||
filament/gui_view.cc
|
||||
filament/gui_view.h
|
||||
filament/imgui_editor.cc
|
||||
|
||||
@@ -16,9 +16,7 @@
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <numbers>
|
||||
#include <utility>
|
||||
|
||||
#include <filament/Material.h>
|
||||
#include <filament/RenderableManager.h>
|
||||
@@ -32,7 +30,6 @@
|
||||
#include <utils/Entity.h>
|
||||
#include <mujoco/mjvisualize.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
#include "experimental/filament/filament/geom_util.h"
|
||||
#include "experimental/filament/filament/material.h"
|
||||
#include "experimental/filament/filament/math_util.h"
|
||||
#include "experimental/filament/filament/mesh.h"
|
||||
@@ -171,15 +168,18 @@ Drawable::Drawable(ObjectManager* object_mgr, ModelObjects* model_objects,
|
||||
|
||||
void Drawable::Update(const mjModel* model, const mjvScene* scene,
|
||||
const mjvGeom& geom) {
|
||||
if (geom.type == mjGEOM_FLEX || geom.type == mjGEOM_SKIN) {
|
||||
// Flex geometry is updated every frame with new vertex data.
|
||||
filament::Engine* engine = renderables_.GetEngine();
|
||||
std::unique_ptr<Mesh> mesh = CreateGeomBuffers(engine, model, scene, geom);
|
||||
|
||||
// Flex and skin geometries are recreated every frame from the scene data.
|
||||
if (geom.type == mjGEOM_FLEX) {
|
||||
if (renderables_.GetNumEntities() == 0) {
|
||||
renderables_.Append(std::move(mesh));
|
||||
renderables_.Append(model_objs_->CreateFlexMesh(scene, geom));
|
||||
} else {
|
||||
renderables_.Update(0, std::move(mesh));
|
||||
renderables_.Update(0, model_objs_->CreateFlexMesh(scene, geom));
|
||||
}
|
||||
} else if (geom.type == mjGEOM_SKIN) {
|
||||
if (renderables_.GetNumEntities() == 0) {
|
||||
renderables_.Append(model_objs_->CreateSkinMesh(scene, geom));
|
||||
} else {
|
||||
renderables_.Update(0, model_objs_->CreateSkinMesh(scene, geom));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
// Copyright 2025 DeepMind Technologies Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "experimental/filament/filament/geom_util.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <span>
|
||||
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/IndexBuffer.h>
|
||||
#include <filament/VertexBuffer.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
#include "experimental/filament/filament/mesh.h"
|
||||
|
||||
namespace mujoco {
|
||||
|
||||
static std::span<const float> GetPositions(const mjModel* model,
|
||||
const mjvScene* scene,
|
||||
const mjvGeom& geom) {
|
||||
if (geom.type == mjGEOM_FLEX) {
|
||||
const int num = 9 * scene->flexfaceused[geom.objid];
|
||||
const int addr = scene->flexfaceadr[geom.objid];
|
||||
const float* ptr = scene->flexface + (9 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
} else {
|
||||
const int num = 3 * scene->skinvertnum[geom.objid];
|
||||
const int addr = scene->skinvertadr[geom.objid];
|
||||
const float* ptr = scene->skinvert + (3 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
}
|
||||
}
|
||||
|
||||
static std::span<const float> GetNormals(const mjModel* model,
|
||||
const mjvScene* scene,
|
||||
const mjvGeom& geom) {
|
||||
if (geom.type == mjGEOM_FLEX) {
|
||||
const int num = 9 * scene->flexfaceused[geom.objid];
|
||||
const int addr = scene->flexfaceadr[geom.objid];
|
||||
const float* ptr = scene->flexnormal + (9 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
} else {
|
||||
const int num = 3 * scene->skinvertnum[geom.objid];
|
||||
const int addr = scene->skinvertadr[geom.objid];
|
||||
const float* ptr = scene->skinnormal + (3 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
}
|
||||
}
|
||||
|
||||
static std::span<const float> GetUvs(const mjModel* model,
|
||||
const mjvScene* scene,
|
||||
const mjvGeom& geom) {
|
||||
if (geom.type == mjGEOM_FLEX) {
|
||||
if (geom.texcoord && geom.matid >= 0) {
|
||||
const int num = 6 * scene->flexfaceused[geom.objid];
|
||||
const int addr = scene->flexfaceadr[geom.objid];
|
||||
const float* ptr = scene->flextexcoord + (6 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
} else {
|
||||
const float* ptr = nullptr;
|
||||
return {ptr, 0};
|
||||
}
|
||||
} else {
|
||||
if (model->skin_texcoordadr[geom.objid] >= 0) {
|
||||
const int num = 3 * scene->skinvertnum[geom.objid];
|
||||
const int addr = model->skin_texcoordadr[geom.objid];
|
||||
const float* ptr = model->skin_texcoord + (2 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
} else {
|
||||
const float* ptr = nullptr;
|
||||
return {ptr, 0};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::span<const int> GetIndices(const mjModel* model,
|
||||
const mjvScene* scene,
|
||||
const mjvGeom& geom) {
|
||||
if (geom.type == mjGEOM_FLEX) {
|
||||
const int* ptr = nullptr;
|
||||
return {ptr, 0};
|
||||
} else {
|
||||
const int num = 3 * model->skin_facenum[geom.objid];
|
||||
const int* ptr = model->skin_face + 3 * model->skin_faceadr[geom.objid];
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
auto indices = GetIndices(model, scene, geom);
|
||||
|
||||
int num_indices = indices.size();
|
||||
if (num_indices == 0 && geom.type == mjGEOM_FLEX) {
|
||||
num_indices = 3 * scene->flexfaceused[geom.objid];
|
||||
}
|
||||
|
||||
MeshData data;
|
||||
DefaultMeshData(&data);
|
||||
|
||||
data.nattributes = uvs.data() ? 3 : 2;
|
||||
data.attributes[0].usage = mjVERTEX_ATTRIBUTE_POSITION;
|
||||
data.attributes[0].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT3;
|
||||
data.attributes[0].bytes = positions.data();
|
||||
data.attributes[1].usage = mjVERTEX_ATTRIBUTE_NORMAL;
|
||||
data.attributes[1].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT3;
|
||||
data.attributes[1].bytes = normals.data();
|
||||
data.attributes[2].usage = mjVERTEX_ATTRIBUTE_UV;
|
||||
data.attributes[2].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT2;
|
||||
data.attributes[2].bytes = uvs.data();
|
||||
data.nvertices = positions.size() / 3;
|
||||
data.nindices = num_indices;
|
||||
data.indices = indices.data();
|
||||
data.index_type = mjINDEX_TYPE_UINT;
|
||||
data.primitive_type = mjPRIM_TYPE_TRIANGLES;
|
||||
data.compute_bounds = true;
|
||||
data.release_callback = nullptr;
|
||||
data.user_data = nullptr;
|
||||
return std::make_unique<Mesh>(engine, data);
|
||||
}
|
||||
|
||||
} // namespace mujoco
|
||||
@@ -1,30 +0,0 @@
|
||||
// Copyright 2025 DeepMind Technologies Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_GEOM_UTIL_H_
|
||||
#define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_GEOM_UTIL_H_
|
||||
|
||||
#include <filament/Engine.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
#include "experimental/filament/filament/mesh.h"
|
||||
|
||||
namespace mujoco {
|
||||
|
||||
// Populates the FilamentBuffers for a flex geometry.
|
||||
MeshPtr CreateGeomBuffers(filament::Engine* engine, const mjModel* model,
|
||||
const mjvScene* scene, const mjvGeom& geom);
|
||||
|
||||
} // namespace mujoco
|
||||
|
||||
#endif // MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_GEOM_UTIL_H_
|
||||
@@ -17,9 +17,11 @@
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#include <cfloat>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <span>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -339,6 +341,77 @@ static int GetNumVertices(const mjModel* model, int id, MeshType mesh_type) {
|
||||
}
|
||||
}
|
||||
|
||||
static std::span<const float> GetPositions(const mjModel* model,
|
||||
const mjvScene* scene,
|
||||
const mjvGeom& geom) {
|
||||
if (geom.type == mjGEOM_FLEX) {
|
||||
const int num = 9 * scene->flexfaceused[geom.objid];
|
||||
const int addr = scene->flexfaceadr[geom.objid];
|
||||
const float* ptr = scene->flexface + (9 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
} else {
|
||||
const int num = 3 * scene->skinvertnum[geom.objid];
|
||||
const int addr = scene->skinvertadr[geom.objid];
|
||||
const float* ptr = scene->skinvert + (3 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
}
|
||||
}
|
||||
|
||||
static std::span<const float> GetNormals(const mjModel* model,
|
||||
const mjvScene* scene,
|
||||
const mjvGeom& geom) {
|
||||
if (geom.type == mjGEOM_FLEX) {
|
||||
const int num = 9 * scene->flexfaceused[geom.objid];
|
||||
const int addr = scene->flexfaceadr[geom.objid];
|
||||
const float* ptr = scene->flexnormal + (9 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
} else {
|
||||
const int num = 3 * scene->skinvertnum[geom.objid];
|
||||
const int addr = scene->skinvertadr[geom.objid];
|
||||
const float* ptr = scene->skinnormal + (3 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
}
|
||||
}
|
||||
|
||||
static std::span<const float> GetUvs(const mjModel* model,
|
||||
const mjvScene* scene,
|
||||
const mjvGeom& geom) {
|
||||
if (geom.type == mjGEOM_FLEX) {
|
||||
if (geom.texcoord && geom.matid >= 0) {
|
||||
const int num = 6 * scene->flexfaceused[geom.objid];
|
||||
const int addr = scene->flexfaceadr[geom.objid];
|
||||
const float* ptr = scene->flextexcoord + (6 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
} else {
|
||||
const float* ptr = nullptr;
|
||||
return {ptr, 0};
|
||||
}
|
||||
} else {
|
||||
if (model->skin_texcoordadr[geom.objid] >= 0) {
|
||||
const int num = 3 * scene->skinvertnum[geom.objid];
|
||||
const int addr = model->skin_texcoordadr[geom.objid];
|
||||
const float* ptr = model->skin_texcoord + (2 * addr);
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
} else {
|
||||
const float* ptr = nullptr;
|
||||
return {ptr, 0};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::span<const int> GetIndices(const mjModel* model,
|
||||
const mjvScene* scene,
|
||||
const mjvGeom& geom) {
|
||||
if (geom.type == mjGEOM_FLEX) {
|
||||
const int* ptr = nullptr;
|
||||
return {ptr, 0};
|
||||
} else {
|
||||
const int num = 3 * model->skin_facenum[geom.objid];
|
||||
const int* ptr = model->skin_face + 3 * model->skin_faceadr[geom.objid];
|
||||
return {ptr, static_cast<size_t>(num)};
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateMeshData(MeshData* data, const mjModel* model, int id,
|
||||
MeshType mesh_type) {
|
||||
if (!IsValidIndex(model, id, mesh_type)) {
|
||||
@@ -394,6 +467,38 @@ static void UpdateMeshData(MeshData* data, const mjModel* model, int id,
|
||||
data->bounds_max[2] = builder->bounds_max.z;
|
||||
}
|
||||
|
||||
void UpdateSkinFlexMeshData(MeshData* data, 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);
|
||||
auto indices = GetIndices(model, scene, geom);
|
||||
|
||||
int num_indices = indices.size();
|
||||
if (num_indices == 0 && geom.type == mjGEOM_FLEX) {
|
||||
num_indices = 3 * scene->flexfaceused[geom.objid];
|
||||
}
|
||||
|
||||
data->nattributes = uvs.data() ? 3 : 2;
|
||||
data->attributes[0].usage = mjVERTEX_ATTRIBUTE_POSITION;
|
||||
data->attributes[0].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT3;
|
||||
data->attributes[0].bytes = positions.data();
|
||||
data->attributes[1].usage = mjVERTEX_ATTRIBUTE_NORMAL;
|
||||
data->attributes[1].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT3;
|
||||
data->attributes[1].bytes = normals.data();
|
||||
data->attributes[2].usage = mjVERTEX_ATTRIBUTE_UV;
|
||||
data->attributes[2].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT2;
|
||||
data->attributes[2].bytes = uvs.data();
|
||||
data->nvertices = positions.size() / 3;
|
||||
data->nindices = num_indices;
|
||||
data->indices = indices.data();
|
||||
data->index_type = mjINDEX_TYPE_UINT;
|
||||
data->primitive_type = mjPRIM_TYPE_TRIANGLES;
|
||||
data->compute_bounds = true;
|
||||
data->release_callback = nullptr;
|
||||
data->user_data = nullptr;
|
||||
}
|
||||
|
||||
ModelObjects::ModelObjects(const mjModel* model, filament::Engine* engine)
|
||||
: model_(model), engine_(engine) {
|
||||
const int nstack = model->vis.quality.numstacks;
|
||||
@@ -525,6 +630,22 @@ void ModelObjects::UploadHeightField(const mjModel* model, int id) {
|
||||
height_fields_[id] = std::make_unique<Mesh>(engine_, data);
|
||||
}
|
||||
|
||||
MeshPtr ModelObjects::CreateFlexMesh(const mjvScene* scene,
|
||||
const mjvGeom& geom) {
|
||||
MeshData data;
|
||||
DefaultMeshData(&data);
|
||||
UpdateSkinFlexMeshData(&data, model_, scene, geom);
|
||||
return std::make_unique<Mesh>(engine_, data);
|
||||
}
|
||||
|
||||
MeshPtr ModelObjects::CreateSkinMesh(const mjvScene* scene,
|
||||
const mjvGeom& geom) {
|
||||
MeshData data;
|
||||
DefaultMeshData(&data);
|
||||
UpdateSkinFlexMeshData(&data, model_, scene, geom);
|
||||
return std::make_unique<Mesh>(engine_, data);
|
||||
}
|
||||
|
||||
const Mesh* ModelObjects::GetMeshBuffer(int data_id) const {
|
||||
// As defined by mjv_updateScene:
|
||||
// original mesh: mesh_id * 2
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#ifndef MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_MODEL_OBJECTS_H_
|
||||
#define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_MODEL_OBJECTS_H_
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
@@ -24,6 +23,7 @@
|
||||
#include <filament/IndirectLight.h>
|
||||
#include <filament/Skybox.h>
|
||||
#include <mujoco/mjmodel.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
#include "experimental/filament/filament/mesh.h"
|
||||
#include "experimental/filament/filament/texture.h"
|
||||
|
||||
@@ -66,6 +66,9 @@ class ModelObjects {
|
||||
const Texture* GetTexture(int tex_id) const;
|
||||
const Texture* GetTexture(int mat_id, int role) const;
|
||||
|
||||
MeshPtr CreateFlexMesh(const mjvScene* scene, const mjvGeom& geom);
|
||||
MeshPtr CreateSkinMesh(const mjvScene* scene, const mjvGeom& geom);
|
||||
|
||||
filament::Skybox* CreateSkybox();
|
||||
filament::IndirectLight* CreateIndirectLight(int tex_id, float intensity);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user