From: Mikko Rasa Date: Thu, 6 Oct 2016 17:15:19 +0000 (+0300) Subject: Provide objects for visualizing controllers X-Git-Url: http://git.tdb.fi/?p=libs%2Fvr.git;a=commitdiff_plain;h=8b0577558582dd34362219e498f688d9416f0ca1 Provide objects for visualizing controllers --- diff --git a/source/motioncontroller.h b/source/motioncontroller.h index 959e056..0dbee9c 100644 --- a/source/motioncontroller.h +++ b/source/motioncontroller.h @@ -2,6 +2,7 @@ #define MSP_VR_MOTIONCONTROLLER_H_ #include +#include #include namespace Msp { @@ -29,6 +30,9 @@ public: virtual void update() = 0; protected: void update_from_matrix(const Msp::GL::Matrix &); + +public: + virtual const GL::Object *get_object() const { return 0; } }; } // namespace VR diff --git a/source/openvr/openvrcontroller.cpp b/source/openvr/openvrcontroller.cpp index 016405b..e757221 100644 --- a/source/openvr/openvrcontroller.cpp +++ b/source/openvr/openvrcontroller.cpp @@ -101,5 +101,15 @@ void OpenVRController::update_input_state() } } +const GL::Object *OpenVRController::get_object() const +{ + char buf[1024]; + unsigned len = vr::VRSystem()->GetStringTrackedDeviceProperty(index, vr::Prop_RenderModelName_String, buf, sizeof(buf)); + if(len>1) + return system.get_render_model(string(buf, len-1)); + + return 0; +} + } // namespace VR } // namespace Msp diff --git a/source/openvr/openvrcontroller.h b/source/openvr/openvrcontroller.h index 00ae1c0..79924f3 100644 --- a/source/openvr/openvrcontroller.h +++ b/source/openvr/openvrcontroller.h @@ -31,6 +31,8 @@ public: void event(const Event &); virtual void update(); void update_input_state(); + + virtual const GL::Object *get_object() const; }; } // namespace VR diff --git a/source/openvr/openvrsystem.cpp b/source/openvr/openvrsystem.cpp index e847b20..5b08ba7 100644 --- a/source/openvr/openvrsystem.cpp +++ b/source/openvr/openvrsystem.cpp @@ -1,4 +1,7 @@ #include +#include +#include +#include #include #include "openvrcontroller_private.h" #include "openvrsystem.h" @@ -16,12 +19,30 @@ Msp::GL::Matrix convert_matrix(const vr::HmdMatrix34_t &m) return result; } +void set_texture_image(Msp::GL::Texture2D &texture, const vr::RenderModel_TextureMap_t &openvr_tex) +{ + texture.storage(Msp::GL::SRGB8_ALPHA8, openvr_tex.unWidth, openvr_tex.unHeight); + texture.image(0, Msp::GL::RGBA, Msp::GL::UNSIGNED_BYTE, openvr_tex.rubTextureMapData); +} + } namespace Msp { namespace VR { +struct OpenVRSystem::RenderModel +{ + GL::Mesh mesh; + GL::Technique tech; + GL::Object object; + + RenderModel(); + + void convert(const vr::RenderModel_t &, OpenVRSystem &); +}; + + unsigned OpenVRSystem::n_instances = 0; OpenVRSystem::OpenVRSystem(): @@ -52,6 +73,19 @@ OpenVRSystem::OpenVRSystem(): } tracking_matrices.resize(n_tracked_devices); + + GL::ProgramBuilder::StandardFeatures features; + features.lighting = true; + features.material = true; + GL::ProgramBuilder(features).add_shaders(render_shprog); + render_shprog.link(); + + features.texture = true; + GL::ProgramBuilder(features).add_shaders(render_shprog_textured); + render_shprog_textured.link(); + + render_material.set_diffuse(GL::Color(1.0f)); + render_material.set_ambient(GL::Color(1.0f)); } OpenVRSystem::~OpenVRSystem() @@ -159,6 +193,22 @@ void OpenVRSystem::tick() for(vector::iterator i=controllers.begin(); i!=controllers.end(); ++i) (*i)->update_input_state(); + + for(list::iterator i=loading_render_models.begin(); i!=loading_render_models.end(); ) + { + if(check_loading_render_model(*i)) + loading_render_models.erase(i++); + else + ++i; + } + + for(list::iterator i=loading_textures.begin(); i!=loading_textures.end(); ) + { + if(check_loading_texture(*i)) + loading_textures.erase(i++); + else + ++i; + } } void OpenVRSystem::update_pose_matrices() @@ -216,5 +266,121 @@ void OpenVRSystem::remove_controller(OpenVRController &controller) controllers.erase(i); } +const GL::Object *OpenVRSystem::get_render_model(const string &name) +{ + map::const_iterator i = render_models.find(name); + if(i!=render_models.end()) + return &i->second->object; + + vr::IVRRenderModels *service = vr::VRRenderModels(); + vr::RenderModel_t *openvr_model = 0; + vr::EVRRenderModelError err = service->LoadRenderModel_Async(name.c_str(), &openvr_model); + if(err!=vr::VRRenderModelError_None && err!=vr::VRRenderModelError_Loading) + throw runtime_error(service->GetRenderModelErrorNameFromEnum(err)); + + if(err==vr::VRRenderModelError_None && !openvr_model) + return 0; + + RenderModel *model = new RenderModel; + render_models[name] = model; + if(err==vr::VRRenderModelError_Loading) + loading_render_models.push_back(name); + else + model->convert(*openvr_model, *this); + + return &model->object; +} + +bool OpenVRSystem::check_loading_render_model(const string &name) +{ + RenderModel &model = *get_item(render_models, name); + + vr::IVRRenderModels *service = vr::VRRenderModels(); + vr::RenderModel_t *openvr_model = 0; + vr::EVRRenderModelError err = service->LoadRenderModel_Async(name.c_str(), &openvr_model); + if(err==vr::VRRenderModelError_Loading) + return false; + else if(err!=vr::VRRenderModelError_None) + throw runtime_error(service->GetRenderModelErrorNameFromEnum(err)); + + model.convert(*openvr_model, *this); + return true; +} + +const GL::Texture2D *OpenVRSystem::get_texture(unsigned id) +{ + map::const_iterator i = render_textures.find(id); + if(i!=render_textures.end()) + return i->second; + + vr::IVRRenderModels *service = vr::VRRenderModels(); + vr::RenderModel_TextureMap_t *openvr_texture = 0; + vr::EVRRenderModelError err = service->LoadTexture_Async(id, &openvr_texture); + if(err!=vr::VRRenderModelError_None && err!=vr::VRRenderModelError_Loading) + throw runtime_error(service->GetRenderModelErrorNameFromEnum(err)); + + GL::Texture2D *texture = new GL::Texture2D; + render_textures[id] = texture; + texture->set_min_filter(GL::LINEAR_MIPMAP_LINEAR); + texture->set_generate_mipmap(true); + if(err==vr::VRRenderModelError_Loading) + loading_textures.push_back(id); + else + set_texture_image(*texture, *openvr_texture); + + return texture; +} + +bool OpenVRSystem::check_loading_texture(unsigned id) +{ + GL::Texture2D &texture = *get_item(render_textures, id); + + vr::IVRRenderModels *service = vr::VRRenderModels(); + vr::RenderModel_TextureMap_t *openvr_texture = 0; + vr::EVRRenderModelError err = service->LoadTexture_Async(id, &openvr_texture); + if(err==vr::VRRenderModelError_Loading) + return false; + else if(err!=vr::VRRenderModelError_None) + throw runtime_error(service->GetRenderModelErrorNameFromEnum(err)); + + set_texture_image(texture, *openvr_texture); + return true; +} + + +OpenVRSystem::RenderModel::RenderModel(): + mesh((GL::NORMAL3, GL::TEXCOORD2, GL::VERTEX3)), + object(&mesh, &tech) +{ } + +void OpenVRSystem::RenderModel::convert(const vr::RenderModel_t &model, OpenVRSystem &system) +{ + GL::RenderPass &pass = tech.add_pass(0); + pass.set_material(&system.render_material); + if(model.diffuseTextureId>=0) + { + pass.set_shader_program(&system.render_shprog_textured, 0); + pass.set_texture(0, system.get_texture(model.diffuseTextureId)); + } + else + pass.set_shader_program(&system.render_shprog, 0); + + mesh.clear(); + Msp::GL::MeshBuilder bld(mesh); + for(unsigned i=0; i #include +#include +#include #include #include "openvrcamera.h" #include "openvrcombiner.h" @@ -13,11 +16,21 @@ namespace VR { class OpenVRSystem: public System { private: + struct RenderModel; + unsigned n_tracked_devices; std::vector tracking_matrices; std::vector controllers; std::vector unclaimed_controllers; + GL::Program render_shprog; + GL::Program render_shprog_textured; + GL::Material render_material; + std::map render_models; + std::map render_textures; + std::list loading_render_models; + std::list loading_textures; + static unsigned n_instances; public: @@ -42,6 +55,12 @@ public: const GL::Matrix &get_hmd_matrix() const; void add_controller(OpenVRController &); void remove_controller(OpenVRController &); + + const GL::Object *get_render_model(const std::string &); +private: + bool check_loading_render_model(const std::string &); + const GL::Texture2D *get_texture(unsigned); + bool check_loading_texture(unsigned); }; } // namespace VR