diff --git a/library/phx/vr_system.cpp b/library/phx/vr_system.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..566524b9d3dbefd7bf0e93896d0ca2f4ff2f8f04
--- /dev/null
+++ b/library/phx/vr_system.cpp
@@ -0,0 +1,102 @@
+//------------------------------------------------------------------------------
+// Project Phoenix
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualization Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// Licensed under the 3-Clause BSD License (the "License");
+// you may not use this file except in compliance with the License.
+// See the file LICENSE for the full text.
+// You may obtain a copy of the License at
+//
+//     https://opensource.org/licenses/BSD-3-Clause
+//
+// 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 "vr_system.hpp"
+
+namespace phx {
+namespace detail {
+  template <di::tracking_device_type type>
+Transform* create_tracking_device_entity(di::tracking_device<type>* tracking_device, Model* model, Scene* scene)
+{
+  const auto openvr_model   = tracking_device->model();
+  if (!openvr_model) 
+    return nullptr;
+
+  const auto openvr_texture = openvr_model->texture();
+  if (!openvr_texture) 
+    return nullptr;
+
+  model->meshes   .push_back(std::make_unique<mak::mesh>                     ());
+  model->materials.push_back(std::make_unique<mak::physically_based_material>()); // TODO: Add support for other type of materials.
+  auto mesh     = model->meshes.back().get();
+  auto material = dynamic_cast<mak::physically_based_material*>(model->materials.back().get());
+  mesh->vertices           .reserve(openvr_model->vertices           .size());
+  mesh->normals            .reserve(openvr_model->normals            .size());
+  mesh->texture_coordinates.reserve(openvr_model->texture_coordinates.size());
+  mesh->indices            .reserve(openvr_model->indices            .size());
+
+  for (auto& vertex : openvr_model->vertices)
+    mesh  ->vertices           .push_back({vertex[0], vertex[1], -vertex[2]});
+  for (auto& normal : openvr_model->normals )
+    mesh  ->normals            .push_back({normal[0], normal[1], -normal[2]});
+  for (auto& texture_coordinate : openvr_model->texture_coordinates)
+    mesh  ->texture_coordinates.push_back({texture_coordinate[0], texture_coordinate[1], 0.0f});
+  for (auto i = 0; i < openvr_model->indices.size(); i+=3)
+    mesh  ->indices            .insert(mesh->indices.end(), {openvr_model->indices[i + 0], openvr_model->indices[i + 2], openvr_model->indices[i + 1]});
+
+  material->albedo_image = std::make_unique<mak::image>(openvr_texture->data.data(), openvr_texture->size, fi::type::bitmap, 32, std::array<fi::color_mask, 3>{fi::color_mask::red, fi::color_mask::green, fi::color_mask::blue});
+  material->albedo_image->to_32_bits();
+
+  auto entity           = scene->add_entity();
+  auto transform        = entity->add_component<mak::transform>  ();
+  auto mesh_render      = entity->add_component<mak::mesh_render>();
+  mesh_render->mesh     = mesh;
+  mesh_render->material = material;
+
+  if(type == di::tracking_device_type::hmd)
+  {
+    const auto hmd = dynamic_cast<di::hmd*>(tracking_device);
+    {
+      auto eye            = scene ->add_entity();
+      auto eye_metadata   = eye   ->add_component<mak::metadata>  ();
+      auto eye_transform  = eye   ->add_component<mak::transform> ();
+      auto eye_projection = eye   ->add_component<mak::projection>();
+      eye_metadata  ->tags.push_back("hmd_left_camera" );
+      eye_transform ->set_parent(transform);
+      eye_transform ->set_matrix(convert_to_glm_matrix(hmd->eye_to_head_transform(di::eye::left )));
+      eye_projection->set_matrix(convert_to_glm_matrix(hmd->projection_matrix    (di::eye::left , 0.1f, 10000.0f)));
+    }
+    {
+      auto eye            = scene ->add_entity();
+      auto eye_metadata   = eye   ->add_component<mak::metadata>  ();
+      auto eye_transform  = eye   ->add_component<mak::transform> ();
+      auto eye_projection = eye   ->add_component<mak::projection>();
+      eye_metadata  ->tags.push_back("hmd_right_camera");
+      eye_transform ->set_parent(transform);
+      eye_transform ->set_matrix(convert_to_glm_matrix(hmd->eye_to_head_transform(di::eye::right)));
+      eye_projection->set_matrix(convert_to_glm_matrix(hmd->projection_matrix    (di::eye::right, 0.1f, 10000.0f)));
+    }
+  }
+  
+  return transform;
+}
+}
+
+VRSystem::VRSystem(di::tracking_mode tracking_mode) {
+
+}
+
+void VRSystem::Update(const FrameTimer::TimeInfo&) {
+  tick();
+
+}
+}  // namespace phx
diff --git a/library/phx/vr_system.hpp b/library/phx/vr_system.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..4724c14d87428578df6d49063366101a1fd00918
--- /dev/null
+++ b/library/phx/vr_system.hpp
@@ -0,0 +1,59 @@
+//------------------------------------------------------------------------------
+// Project Phoenix
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualization Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// Licensed under the 3-Clause BSD License (the "License");
+// you may not use this file except in compliance with the License.
+// See the file LICENSE for the full text.
+// You may obtain a copy of the License at
+//
+//     https://opensource.org/licenses/BSD-3-Clause
+//
+// 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 LIBRARY_PHX_VR_SYSTEM_HPP_
+#define LIBRARY_PHX_VR_SYSTEM_HPP_
+
+#include <di/systems/vr/vr_system.hpp>
+
+#include <map>
+
+#include "phx/engine.hpp"
+#include "phx/export.hpp"
+#include "phx/system.hpp"
+#include "phx/transform.hpp"
+
+namespace phx {
+class PHOENIX_EXPORT VRSystem : public System, public di::vr_system {
+ public:
+  explicit VRSystem(
+      di::tracking_mode tracking_mode = di::tracking_mode::seated);
+  VRSystem(const VRSystem&) = delete;
+  VRSystem(VRSystem&&) = delete;
+  virtual ~VRSystem() = default;
+  VRSystem& operator=(const VRSystem&) = delete;
+  VRSystem& operator=(VRSystem&&) = delete;
+
+  void Update(const FrameTimer::TimeInfo&) override;
+
+ protected:
+  std::map<di::hmd*, Transform*> hmd_transform_map_;
+  std::map<di::vr_controller*, Transform*> controller_transform_map_;
+  std::map<di::tracking_reference*, Transform*>
+      tracking_reference_transform_map_;
+  std::map<di::display_redirect*, Transform*> display_redirect_transform_map_;
+  std::map<di::generic_tracking_device*, Transform*>
+      generic_tracking_device_transform_map_;
+};
+}  // namespace phx
+
+#endif  // LIBRARY_PHX_VR_SYSTEM_HPP_