--- /dev/null
+#ifndef MSP_GAME_TRACKINGANCHOR_H_
+#define MSP_GAME_TRACKINGANCHOR_H_
+
+#include "component.h"
+
+namespace Msp::Game {
+
+class TrackingAnchor: public Component
+{
+public:
+ TrackingAnchor(Handle<Entity> p): Component(p) { }
+};
+
+} // namespace Msp::Game
+
+#endif
#include "motiontracker.h"
#include <msp/game/root.h>
#include <msp/game/transform.h>
+#include <msp/vr/trackingarea.h>
using namespace std;
namespace Msp::GameView {
-MotionTracker::MotionTracker(Game::Stage &s):
+MotionTracker::MotionTracker(Game::Stage &s, const VR::TrackingArea &area):
System(s)
{
declare_dependency<Game::Transform>(WRITE);
-}
-
-void MotionTracker::track(const VR::HeadTrackingCamera &cam)
-{
- Part &part = get_or_create_part(TrackedElement::HEAD);
- part.head = &cam;
-}
-void MotionTracker::track(const VR::MotionController &ctrl)
-{
- TrackedElement::Role role;
- switch(ctrl.get_role())
+ if(const GL::Camera *head = area.get_head())
{
- case VR::LEFT_HAND: role = TrackedElement::LEFT_HAND; break;
- case VR::RIGHT_HAND: role = TrackedElement::RIGHT_HAND; break;
- default: throw invalid_argument("MotionTracker::track");
+ Part &part = get_or_create_part(TrackedElement::HEAD);
+ part.head = head;
}
- Part &part = get_or_create_part(role);
- part.controller = &ctrl;
+ for(const VR::MotionController *c: area.get_controllers())
+ {
+ TrackedElement::Role role;
+ switch(c->get_role())
+ {
+ case VR::LEFT_HAND: role = TrackedElement::LEFT_HAND; break;
+ case VR::RIGHT_HAND: role = TrackedElement::RIGHT_HAND; break;
+ default: continue;
+ }
+
+ Part &part = get_or_create_part(role);
+ part.controller = c;
+ }
}
auto MotionTracker::get_or_create_part(TrackedElement::Role role) -> Part &
#include <msp/game/owned.h>
#include <msp/game/system.h>
-#include <msp/vr/headtrackingcamera.h>
+#include <msp/gl/camera.h>
#include <msp/vr/motioncontroller.h>
#include "trackedelement.h"
private:
struct Part
{
- const VR::HeadTrackingCamera *head = nullptr;
+ const GL::Camera *head = nullptr;
const VR::MotionController *controller = nullptr;
Game::Owned<Game::Entity> entity;
Game::Owned<TrackedElement> element;
std::vector<Part> parts;
public:
- MotionTracker(Game::Stage &);
+ MotionTracker(Game::Stage &, const VR::TrackingArea &);
- void track(const VR::HeadTrackingCamera &);
- void track(const VR::MotionController &);
private:
Part &get_or_create_part(TrackedElement::Role);
resources(director.get_resources()),
event_observer(director.get_event_bus())
{
- event_observer.observe<Events::LocalPlayerArrived>([this](auto &e){ player_arrived(e); });
event_observer.observe<Game::Events::StageActivated>([this](auto &e){ stage_activated(e); });
if(Game::Stage *active_stage = director.get_active_stage())
void Presenter::enable_vr(VR::System &vr_sys)
{
vr_system = &vr_sys;
+ vr_view = vr_sys.create_view(gl_view);
+ vr_tracking = vr_sys.create_tracking_area(VR::FIXED_ORIGIN);
if(active_renderer)
stage_activated({ active_renderer->get_stage() });
}
-void Presenter::player_arrived(const Events::LocalPlayerArrived &event)
-{
- Input::DeviceType VR_CONTROLLER = VR::MotionController::get_class_type();
- for(unsigned i=0;; ++i)
- {
- Input::Device *dev = event.device.find_subdevice(VR_CONTROLLER, i);
- if(!dev)
- break;
-
- VR::MotionController *vr_ctrl = dynamic_cast<VR::MotionController *>(dev);
- if(vr_ctrl)
- vr_controllers.push_back(vr_ctrl);
- }
-}
-
void Presenter::stage_activated(const Game::Events::StageActivated &event)
{
if(active_renderer)
active_renderer = event.stage.get_system<Renderer>();
if(!active_renderer)
systems.push_back(active_renderer = &event.stage.add_system<Renderer>());
- MotionTracker *tracker = nullptr;
- if(vr_system)
- {
- tracker = event.stage.get_system<MotionTracker>();
- if(!tracker)
- {
- systems.push_back(tracker = &event.stage.add_system<MotionTracker>());
- for(VR::MotionController *c: vr_controllers)
- tracker->track(*c);
- }
- }
+ if(vr_system && !event.stage.get_system<MotionTracker>())
+ systems.push_back(&event.stage.add_system<MotionTracker>(*vr_tracking));
if(event.stage.get_system<Game::Landscape>() && !event.stage.get_system<TerrainMeshCreator>())
systems.push_back(&event.stage.add_system<TerrainMeshCreator>());
if(active_renderer)
{
- if(vr_system)
- {
- VR::StereoView *view = active_renderer->output_to_vr(*vr_system, gl_view);
- vr_system->set_tracking_view(view);
- if(const VR::HeadTrackingCamera *head = view->get_head_camera())
- tracker->track(*head);
- }
+ if(vr_view)
+ active_renderer->output_to_vr(*vr_view, vr_tracking.get());
else
active_renderer->output_to_view(gl_view);
}
Game::EventObserver event_observer;
std::vector<Game::System *> systems;
Renderer *active_renderer = nullptr;
- std::vector<VR::MotionController *> vr_controllers;
+ std::unique_ptr<VR::StereoView> vr_view;
+ std::unique_ptr<VR::TrackingArea> vr_tracking;
public:
Presenter(Game::Director &, GL::View &);
void enable_vr(VR::System &);
private:
- void player_arrived(const Events::LocalPlayerArrived &);
void stage_activated(const Game::Events::StageActivated &);
};
create_sequence();
}
-VR::StereoView *Renderer::output_to_vr(VR::System &vr_sys, GL::View &view)
+void Renderer::output_to_vr(VR::StereoView &v, VR::TrackingArea *t)
{
cancel_output();
- vr_view = vr_sys.create_view(view, gl_camera);
+ vr_view = &v;
+ vr_view->set_camera(&gl_camera);
+ vr_tracking = t;
+ if(vr_tracking)
+ vr_tracking->set_head(&gl_camera);
if(active_camera)
- create_sequence();
- return vr_view.get();
+ camera_changed({ active_camera });
}
void Renderer::cancel_output()
{
+ if(vr_view)
+ {
+ vr_view->set_content(nullptr);
+ vr_view->set_camera(nullptr);
+ }
if(gl_view)
{
gl_view->set_content(nullptr);
gl_view->set_camera(nullptr);
}
vr_view = nullptr;
+ vr_tracking = nullptr;
+ tracking_anchor = nullptr;
sequence = nullptr;
}
shadows_changed = true;
}
}
+
+ if(event.component==tracking_anchor)
+ tracking_anchor = nullptr;
}
void Renderer::camera_changed(const Game::Events::CameraChanged &event)
{
active_camera = event.camera;
- if(active_camera && (gl_view || vr_view))
- create_sequence();
+ if(active_camera)
+ {
+ tracking_anchor = nullptr;
+ for(Game::Handle<Game::Entity> e=active_camera->get_entity(); (e && !tracking_anchor); e=e->get_parent())
+ tracking_anchor = e->get_component<Game::TrackingAnchor>();
+ if(gl_view || vr_view)
+ create_sequence();
+ }
+ else
+ tracking_anchor = nullptr;
}
void Renderer::tick(Time::TimeDelta)
if(active_camera)
{
- Game::Handle<Game::Transform> transform = active_camera->get_entity()->get_transform();
- if(transform)
- gl_camera.set_object_matrix(transform->get_world_matrix());
- else
- gl_camera.set_object_matrix(GL::Matrix());
+ if(!vr_tracking)
+ {
+ Game::Handle<Game::Transform> transform = active_camera->get_entity()->get_transform();
+ if(transform)
+ gl_camera.set_object_matrix(transform->get_world_matrix());
+ else
+ gl_camera.set_object_matrix(GL::Matrix());
+ }
if(active_camera->is_orthographic())
{
const LinAl::Vector<float, 2> &size = active_camera->get_size();
stage.iterate_objects<LightEmitter>([](LightEmitter &e){ e.update_matrix(); });
if(vr_view)
+ {
+ if(vr_tracking)
+ {
+ if(tracking_anchor)
+ {
+ const GL::Matrix &anchor_matrix = tracking_anchor->get_entity()->get_transform()->get_world_matrix();
+ vr_tracking->set_position(anchor_matrix*GL::Vector3(0.0f, 0.0f, 0.0f));
+ vr_tracking->set_up_direction((anchor_matrix*GL::Vector4(0.0f, 0.0f, 1.0f, 0.0f)).slice<3>(0));
+ vr_tracking->set_forward_direction((anchor_matrix*GL::Vector4(1.0f, 0.0f, 0.0f, 0.0f)).slice<3>(0));
+ }
+ vr_tracking->update_for_render();
+ }
vr_view->render();
+ }
else if(gl_view)
gl_view->render();
}
#include <msp/game/events.h>
#include <msp/game/owned.h>
#include <msp/game/system.h>
+#include <msp/game/trackinganchor.h>
#include <msp/gl/camera.h>
#include <msp/gl/light.h>
#include <msp/gl/lighting.h>
unsigned shadow_base_size = 4096;
bool shadows_changed = false;
GL::View *gl_view = nullptr;
- std::unique_ptr<VR::StereoView> vr_view;
+ VR::StereoView *vr_view = nullptr;
+ VR::TrackingArea *vr_tracking = nullptr;
+ Game::Handle<Game::TrackingAnchor> tracking_anchor;
public:
Renderer(Game::Stage &);
~Renderer();
void output_to_view(GL::View &);
- VR::StereoView *output_to_vr(VR::System &, GL::View &);
+ void output_to_vr(VR::StereoView &, VR::TrackingArea *);
void cancel_output();
private:
void create_sequence();