-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
internal_render_engine_gltf_client.h
173 lines (148 loc) · 6.98 KB
/
internal_render_engine_gltf_client.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#pragma once
#include <filesystem>
#include <map>
#include <memory>
#include <string>
#include <nlohmann/json.hpp>
#include "drake/common/drake_export.h"
#include "drake/geometry/render/render_camera.h"
#include "drake/geometry/render_gltf_client/internal_merge_gltf.h"
#include "drake/geometry/render_gltf_client/internal_render_client.h"
#include "drake/geometry/render_vtk/internal_render_engine_vtk.h"
#include "drake/systems/sensors/image.h"
namespace drake {
namespace geometry {
namespace render_gltf_client {
namespace internal {
/* A RenderEngine that exports
<a href="https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html">glTF
</a> scenes, uploads to a render server, and retrieves the renderings back. */
class DRAKE_NO_EXPORT RenderEngineGltfClient
: public render_vtk::internal::RenderEngineVtk {
public:
/* @name Does not allow copy, move, or assignment */
//@{
// Note: the copy constructor operator is actually protected to serve as the
// basis for implementing the DoClone() method.
RenderEngineGltfClient& operator=(const RenderEngineGltfClient&) = delete;
RenderEngineGltfClient(RenderEngineGltfClient&&) = delete;
RenderEngineGltfClient& operator=(RenderEngineGltfClient&&) = delete;
//@}}
/* Constructs the render engine from the given `parameters`. By default,
RenderEngineGltfClient will communicate with a local server.
@sa RenderEngineGltfClientParams */
RenderEngineGltfClient(const RenderEngineGltfClientParams& parameters =
RenderEngineGltfClientParams());
const RenderEngineGltfClientParams& get_params() const {
return render_client_->get_params();
}
const std::string& temp_directory() const {
return render_client_->temp_directory();
}
/* (For unit testing only) Helper function to alter the behavior of
`DoPostForm()` during unit testing. */
void SetHttpService(std::unique_ptr<HttpService> service);
/* (For unit testing only) Helper function for testing UpdateViewpoint matrix
inversion for the specified image_type.
TODO(zachfang): Remove this after VTK is updated. */
Eigen::Matrix4d CameraModelViewTransformMatrix(
render_vtk::internal::ImageType image_type) const;
protected:
/* Copy constructor for the purpose of cloning. */
RenderEngineGltfClient(const RenderEngineGltfClient& other);
private:
friend class RenderEngineGltfClientTester;
// @see RenderEngine::DoClone().
std::unique_ptr<render::RenderEngine> DoClone() const override;
// @see RenderEngine::DoRenderColorImage().
void DoRenderColorImage(
const render::ColorRenderCamera& camera,
systems::sensors::ImageRgba8U* color_image_out) const override;
// @see RenderEngine::DoRenderDepthImage().
void DoRenderDepthImage(
const render::DepthRenderCamera& render_camera,
systems::sensors::ImageDepth32F* depth_image_out) const override;
// @see RenderEngine::DoRenderLabelImage().
void DoRenderLabelImage(
const render::ColorRenderCamera& camera,
systems::sensors::ImageLabel16I* label_image_out) const override;
/* Exports the `RenderEngineVtk::pipelines_[image_type]` VTK scene to a
glTF file given `export_path`. */
void ExportScene(const std::string& export_path,
render_vtk::internal::ImageType image_type) const;
/* Overrides RenderEngineVtk's default handling of the mesh types. We want to
detect .gltf meshes and handle them in a special way. */
void DoUpdateVisualPose(GeometryId id,
const math::RigidTransformd& X_WG) override;
bool DoRemoveGeometry(GeometryId id) override;
using RenderEngineVtk::ImplementGeometry;
void ImplementGeometry(const Convex& convex, void* user_data) override;
void ImplementGeometry(const Mesh& mesh, void* user_data) override;
void ImplementMesh(const std::filesystem::path& mesh_path, double scale,
void* user_data);
/* Adds a .gltf to the scene for the id currently being reified (data->id).
Returns true if added, false if ignored (for whatever reason).
Note: Even though RenderEngineVtk supports consuming and rendering glTF
files, GltfClient handles glTF files in its own way because vtkGLTFImporter
and vtkGLTFExporter have limited support for glTF extensions -- useful,
common extensions. So, by injecting the files directly into the exported glTF
file, we maintain whatever declarations the source glTF had without the lossy
filter provided by VTK. */
bool ImplementGltf(const std::filesystem::path& gltf_path, double scale,
const RenderEngineVtk::RegistrationData& data);
std::unique_ptr<RenderClient> render_client_;
struct GltfRecord {
// The path for the .gltf file.
std::filesystem::path path;
// The contents of a glTF file registered as Mesh or Convex.
nlohmann::json contents;
// The root nodes of the gltf file represented as a mapping from the node's
// *local* index in the gltf to the pose of that node relative to the
// file's frame F. Note this "pose" is not necessarily a RigidTransform. It
// can include scale. It is the node matrix stored in the gltf.
std::map<int, Matrix4<double>> root_nodes;
// The isotropic scale of the mesh.
double scale{};
// The render label associated with the geometry.
render::RenderLabel label;
};
// TODO(SeanCurtis-TRI) Based on the file path, I should load a gltf *one
// time*. Each instance of it should be re-used. Assuming that all instances
// of a gltf always use the *same* materials, all I would have to worry about
// is the transforms applied to the root nodes. That means a GltfRecord
// should contain a reference to the canonical mesh, and a transform instead
// of the `contents` it has now.
//
// Exporting the scene:
// - Export the *mesh* once (this includes the material).
// - Export each instance as a (gltf node) that has the "mesh":id member
// (where id is the new, merged mesh id).
//
// Registering logic:
// - Check absolute path (resolving symlinks) to file.
// - Load it if it isn't already loaded.
// - Create a GltfRecord for an instance.
// - Increment the counter for the content.
//
// Merging logic:
// - For each canonical gltf with non-zero reference count
// - Merge everything except its root nodes.
// - store the mapping between canonical indices and merged indices.
// - For each GltfRecord
// - Create one node per root node.
// - Map to the merged mesh id.
// - If it has children, map canonical indices into merged indices.
//
// Removing logic:
// - Simply remove the gltf record.
// - Decrement the counter with the associated json structure.
// - Maybe delete the canonical json.
//
// Note: if we allowed materials to vary between instances, we'd have to
// distinguish at the mesh level instead of only at the node level.
std::map<GeometryId, GltfRecord> gltfs_;
};
} // namespace internal
} // namespace render_gltf_client
} // namespace geometry
} // namespace drake