12#include <Eigen/Geometry>
20#define TINYGLTF_IMPLEMENTATION
21#define TINYGLTF_NO_STB_IMAGE
22#define TINYGLTF_NO_STB_IMAGE_WRITE
23#define STBIWDEF static inline
40 std::vector<GHOST_XrControllerModelVertex>
vertices;
49 const tinygltf::BufferView &buffer_view,
50 const tinygltf::Buffer &buffer,
55 if (accessor.byteOffset + (accessor.count - 1) * byte_stride + element_size >
56 buffer_view.byteLength)
62 if (buffer_view.byteOffset + buffer_view.byteLength > buffer.data.size()) {
67template<
float (GHOST_XrControllerModelVertex::*field)[3]>
69 const tinygltf::BufferView &buffer_view,
70 const tinygltf::Buffer &buffer,
73 if (accessor.type != TINYGLTF_TYPE_VEC3) {
75 "glTF: Accessor for primitive attribute has incorrect type (VEC3 expected).");
78 if (accessor.componentType != TINYGLTF_COMPONENT_TYPE_FLOAT) {
80 "glTF: Accessor for primitive attribute has incorrect component type (FLOAT expected).");
84 constexpr size_t packed_size =
sizeof(
float) * 3;
85 const size_t stride = buffer_view.byteStride == 0 ? packed_size : buffer_view.byteStride;
91 primitive.
vertices.resize(accessor.count);
94 const uint8_t *buffer_ptr = buffer.data.data() + buffer_view.byteOffset + accessor.byteOffset;
95 for (
size_t i = 0; i < accessor.count; i++, buffer_ptr += stride) {
96 memcpy(primitive.
vertices[i].*field, buffer_ptr, stride);
101 const std::string &attribute_name,
105 const auto &accessor = gltf_model.accessors.at(accessor_id);
107 if (accessor.bufferView == -1) {
108 throw GHOST_XrException(
"glTF: Accessor for primitive attribute specifies no bufferview.");
111 const tinygltf::BufferView &buffer_view = gltf_model.bufferViews.at(accessor.bufferView);
112 if (buffer_view.target != TINYGLTF_TARGET_ARRAY_BUFFER && buffer_view.target != 0) {
114 "glTF: Accessor for primitive attribute uses bufferview with invalid 'target' type.");
117 const tinygltf::Buffer &buffer = gltf_model.buffers.at(buffer_view.buffer);
119 if (attribute_name.compare(
"POSITION") == 0) {
121 accessor, buffer_view, buffer, primitive);
123 else if (attribute_name.compare(
"NORMAL") == 0) {
125 accessor, buffer_view, buffer, primitive);
133template<
typename TSrcIndex>
135 const tinygltf::BufferView &buffer_view,
136 const tinygltf::Buffer &buffer,
141 if (buffer_view.target != TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER && buffer_view.target != 0) {
143 "glTF: Accessor for indices uses bufferview with invalid 'target' type.");
146 constexpr size_t component_size_bytes =
sizeof(TSrcIndex);
148 if (buffer_view.byteStride != 0 && buffer_view.byteStride != component_size_bytes) {
150 "glTF: Accessor for indices uses bufferview with invalid 'byteStride'.");
153 validate_accessor(accessor, buffer_view, buffer, component_size_bytes, component_size_bytes);
156 if ((accessor.count % 3) != 0) {
157 throw GHOST_XrException(
"glTF: Unexpected number of indices for triangle primitive");
160 const TSrcIndex *index_buffer =
reinterpret_cast<const TSrcIndex *
>(
161 buffer.data.data() + buffer_view.byteOffset + accessor.byteOffset);
162 for (
uint32_t i = 0; i < accessor.count; i++) {
163 primitive.
indices.push_back(*(index_buffer + i));
171 const tinygltf::Accessor &accessor,
174 if (accessor.type != TINYGLTF_TYPE_SCALAR) {
178 if (accessor.bufferView == -1) {
179 throw GHOST_XrException(
"glTF: Index accessor without bufferView is currently not supported.");
182 const tinygltf::BufferView &buffer_view = gltf_model.bufferViews.at(accessor.bufferView);
183 const tinygltf::Buffer &buffer = gltf_model.buffers.at(buffer_view.buffer);
185 if (accessor.componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) {
188 else if (accessor.componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT) {
191 else if (accessor.componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT) {
195 throw GHOST_XrException(
"glTF: Accessor for indices specifies invalid 'componentType'.");
200 const tinygltf::Primitive &gltf_primitive)
202 if (gltf_primitive.mode != TINYGLTF_MODE_TRIANGLES) {
204 "glTF: Unsupported primitive mode. Only TINYGLTF_MODE_TRIANGLES is supported.");
211 for (
const auto &[attr_name, accessor_idx] : gltf_primitive.attributes) {
215 if (gltf_primitive.indices != -1) {
217 load_index_accessor(gltf_model, gltf_model.accessors.at(gltf_primitive.indices), primitive);
227 const float parent_transform[4][4],
228 float r_local_transform[4][4],
229 float r_world_transform[4][4])
233 if (gltf_node.matrix.size() == 16) {
234 const std::vector<double> &dm = gltf_node.matrix;
239 memcpy(r_local_transform, m,
sizeof(
float[4][4]));
243 std::vector<double> translation = gltf_node.translation;
244 std::vector<double> rotation = gltf_node.rotation;
245 std::vector<double> scale = gltf_node.scale;
246 Eigen::Matrix4f &m = *(Eigen::Matrix4f *)r_local_transform;
247 Eigen::Quaternionf q;
248 Eigen::Matrix3f scalemat;
250 if (translation.size() != 3) {
251 translation.resize(3);
252 translation[0] = translation[1] = translation[2] = 0.0;
254 if (rotation.size() != 4) {
256 rotation[0] = rotation[1] = rotation[2] = 0.0;
259 if (scale.size() != 3) {
261 scale[0] = scale[1] = scale[2] = 1.0;
264 q.w() =
float(rotation[3]);
265 q.x() =
float(rotation[0]);
266 q.y() =
float(rotation[1]);
267 q.z() =
float(rotation[2]);
270 scalemat.setIdentity();
271 scalemat(0, 0) =
float(scale[0]);
272 scalemat(1, 1) =
float(scale[1]);
273 scalemat(2, 2) =
float(scale[2]);
276 m.block<3, 3>(0, 0) = q.toRotationMatrix() * scalemat;
277 m.block<3, 1>(0, 3) = Eigen::Vector3f(
278 float(translation[0]),
float(translation[1]),
float(translation[2]));
281 *(Eigen::Matrix4f *)r_world_transform = *(Eigen::Matrix4f *)parent_transform *
282 *(Eigen::Matrix4f *)r_local_transform;
288 const float parent_transform[4][4],
289 const std::string &parent_name,
290 const std::vector<XrControllerModelNodePropertiesMSFT> &node_properties,
291 std::vector<GHOST_XrControllerModelVertex> &vertices,
292 std::vector<uint32_t> &indices,
293 std::vector<GHOST_XrControllerModelComponent> &components,
294 std::vector<GHOST_XrControllerModelNode> &nodes,
295 std::vector<int32_t> &node_state_indices)
297 const tinygltf::Node &gltf_node = gltf_model.nodes.at(gltf_node_id);
298 float world_transform[4][4];
302 node.parent_idx = parent_idx;
305 for (
size_t i = 0; i < node_properties.size(); ++i) {
306 if ((node_state_indices[i] < 0) && (parent_name == node_properties[i].parentNodeName) &&
307 (gltf_node.name == node_properties[i].nodeName))
309 node_state_indices[i] = node_idx;
314 if (gltf_node.mesh != -1) {
315 const tinygltf::Mesh &gltf_mesh = gltf_model.meshes.at(gltf_node.mesh);
317 GHOST_XrControllerModelComponent &component = components.emplace_back();
318 node.component_idx = components.size() - 1;
319 memcpy(component.transform, world_transform,
sizeof(component.transform));
320 component.vertex_offset = vertices.size();
321 component.index_offset = indices.size();
323 for (
const tinygltf::Primitive &gltf_primitive : gltf_mesh.primitives) {
327 const size_t start_vertex = vertices.size();
328 size_t offset = start_vertex;
330 vertices.resize(offset +
count);
331 memcpy(vertices.data() + offset,
335 offset = indices.size();
337 indices.resize(offset +
count);
338 for (
size_t i = 0; i <
count; i += 3) {
339 indices[offset + i + 0] = start_vertex + primitive.
indices[i + 0];
340 indices[offset + i + 1] = start_vertex + primitive.
indices[i + 2];
341 indices[offset + i + 2] = start_vertex + primitive.
indices[i + 1];
345 component.vertex_count = vertices.size() - component.vertex_offset;
346 component.index_count = indices.size() - component.index_offset;
350 for (
const int child_node_id : gltf_node.children) {
410 const char *subaction_path_str)
414 CHECK_XR(xrStringToPath(instance, subaction_path_str, &m_subaction_path),
415 (std::string(
"Failed to get user path \"") + subaction_path_str +
"\".").
data());
420 if (m_load_task.valid()) {
427 if (m_data_loaded || m_load_task.valid()) {
432 XrControllerModelKeyStateMSFT key_state{XR_TYPE_CONTROLLER_MODEL_KEY_STATE_MSFT};
434 "Failed to get controller model key state.");
436 if (key_state.modelKey != XR_NULL_CONTROLLER_MODEL_KEY_MSFT) {
437 m_model_key = key_state.modelKey;
439 m_load_task = std::async(std::launch::async,
440 [&, session = session]() {
return loadControllerModel(session); });
444void GHOST_XrControllerModel::loadControllerModel(XrSession session)
449 "Failed to get controller model buffer size.");
451 std::vector<uint8_t> buf((
size_t(buf_size)));
453 "Failed to load controller model binary buffers.");
456 tinygltf::TinyGLTF gltf_loader;
457 tinygltf::Model gltf_model;
462 auto load_img_func = [](tinygltf::Image *img,
470 void *user_pointer) ->
bool {
482 gltf_loader.SetImageLoader(load_img_func,
nullptr);
485 if (!gltf_loader.LoadBinaryFromMemory(&gltf_model, &err_msg,
nullptr, buf.data(), buf_size)) {
486 throw GHOST_XrException((
"Failed to load glTF controller model: " + err_msg).c_str());
490 XrControllerModelPropertiesMSFT model_properties{XR_TYPE_CONTROLLER_MODEL_PROPERTIES_MSFT};
491 model_properties.nodeCapacityInput = 0;
493 "Failed to get controller model node properties count.");
495 std::vector<XrControllerModelNodePropertiesMSFT> node_properties(
496 model_properties.nodeCountOutput, {XR_TYPE_CONTROLLER_MODEL_NODE_PROPERTIES_MSFT});
497 model_properties.nodeCapacityInput =
uint32_t(node_properties.size());
498 model_properties.nodeProperties = node_properties.data();
500 "Failed to get controller model node properties.");
502 m_node_state_indices.resize(node_properties.size(), -1);
505 const tinygltf::Scene &default_scene = gltf_model.scenes.at(
506 (gltf_model.defaultScene == -1) ? 0 : gltf_model.defaultScene);
508 const std::string root_name =
"";
509 float root_transform[4][4] = {{0}};
510 root_transform[0][0] = root_transform[1][1] = root_transform[2][2] = root_transform[3][3] = 1.0f;
512 for (
const int node_id : default_scene.nodes) {
523 m_node_state_indices);
526 m_data_loaded =
true;
531 if (!m_data_loaded) {
536 XrControllerModelStateMSFT model_state{XR_TYPE_CONTROLLER_MODEL_STATE_MSFT};
537 model_state.nodeCapacityInput = 0;
539 "Failed to get controller model node state count.");
542 std::vector<XrControllerModelNodeStateMSFT> node_states(
543 count, {XR_TYPE_CONTROLLER_MODEL_NODE_STATE_MSFT});
544 model_state.nodeCapacityInput =
count;
545 model_state.nodeStates = node_states.data();
547 "Failed to get controller model node states.");
550 assert(m_node_state_indices.size() ==
count);
552 for (
uint32_t state_idx = 0; state_idx <
count; ++state_idx) {
553 const int32_t &node_idx = m_node_state_indices[state_idx];
555 const XrPosef &pose = node_states[state_idx].nodePose;
556 Eigen::Matrix4f &m = *(Eigen::Matrix4f *)m_nodes[node_idx].local_transform;
557 Eigen::Quaternionf q(
558 pose.orientation.w, pose.orientation.x, pose.orientation.y, pose.orientation.z);
560 m.block<3, 3>(0, 0) = q.toRotationMatrix();
561 m.block<3, 1>(0, 3) = Eigen::Vector3f(pose.position.x, pose.position.y, pose.position.z);
566 std::vector<Eigen::Matrix4f> world_transforms(m_nodes.size());
569 world_transforms[i] = (node.parent_idx >= 0) ? world_transforms[node.parent_idx] *
570 *(Eigen::Matrix4f *)node.local_transform :
571 *(Eigen::Matrix4f *)node.local_transform;
572 if (node.component_idx >= 0) {
573 memcpy(m_components[node.component_idx].transform,
574 world_transforms[i].data(),
575 sizeof(m_components[node.component_idx].transform));
584 r_data.count_vertices =
uint32_t(m_vertices.size());
585 r_data.vertices = m_vertices.data();
586 r_data.count_indices =
uint32_t(m_indices.size());
587 r_data.indices = m_indices.data();
588 r_data.count_components =
uint32_t(m_components.size());
589 r_data.components = m_components.data();
592 r_data.count_vertices = 0;
593 r_data.vertices =
nullptr;
594 r_data.count_indices = 0;
595 r_data.indices =
nullptr;
596 r_data.count_components = 0;
597 r_data.components =
nullptr;
static void init_controller_model_extension_functions(XrInstance instance)
static void load_node(const tinygltf::Model &gltf_model, int gltf_node_id, int32_t parent_idx, const float parent_transform[4][4], const std::string &parent_name, const std::vector< XrControllerModelNodePropertiesMSFT > &node_properties, std::vector< GHOST_XrControllerModelVertex > &vertices, std::vector< uint32_t > &indices, std::vector< GHOST_XrControllerModelComponent > &components, std::vector< GHOST_XrControllerModelNode > &nodes, std::vector< int32_t > &node_state_indices)
static void read_vertices(const tinygltf::Accessor &accessor, const tinygltf::BufferView &buffer_view, const tinygltf::Buffer &buffer, GHOST_XrPrimitive &primitive)
static XrInstance g_instance
static void validate_accessor(const tinygltf::Accessor &accessor, const tinygltf::BufferView &buffer_view, const tinygltf::Buffer &buffer, size_t byte_stride, size_t element_size)
static PFN_xrLoadControllerModelMSFT g_xrLoadControllerModelMSFT
static void read_indices(const tinygltf::Accessor &accessor, const tinygltf::BufferView &buffer_view, const tinygltf::Buffer &buffer, GHOST_XrPrimitive &primitive)
static PFN_xrGetControllerModelPropertiesMSFT g_xrGetControllerModelPropertiesMSFT
static void load_index_accessor(const tinygltf::Model &gltf_model, const tinygltf::Accessor &accessor, GHOST_XrPrimitive &primitive)
static PFN_xrGetControllerModelStateMSFT g_xrGetControllerModelStateMSFT
static PFN_xrGetControllerModelKeyMSFT g_xrGetControllerModelKeyMSFT
static GHOST_XrPrimitive read_primitive(const tinygltf::Model &gltf_model, const tinygltf::Primitive &gltf_primitive)
static void calc_node_transforms(const tinygltf::Node &gltf_node, const float parent_transform[4][4], float r_local_transform[4][4], float r_world_transform[4][4])
static void load_attribute_accessor(const tinygltf::Model &gltf_model, const std::string &attribute_name, int accessor_id, GHOST_XrPrimitive &primitive)
#define INIT_EXTENSION_FUNCTION(name)
#define CHECK_XR(call, error_msg)
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object instance
void updateComponents(XrSession session)
GHOST_XrControllerModel(XrInstance instance, const char *subaction_path)
void getData(GHOST_XrControllerModelData &r_data)
~GHOST_XrControllerModel()
void load(XrSession session)
draw_view in_light_buf[] float
float local_transform[4][4]
std::vector< GHOST_XrControllerModelVertex > vertices
std::vector< uint32_t > indices