mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-17 23:39:18 +02:00
openvr WIP
This commit is contained in:
@@ -27,6 +27,7 @@ file(GLOB HEADERS "*.h"
|
|||||||
"McZapkie/*.h"
|
"McZapkie/*.h"
|
||||||
"gl/*.h"
|
"gl/*.h"
|
||||||
"network/*.h"
|
"network/*.h"
|
||||||
|
"vr/*.h"
|
||||||
"network/backend/*.h"
|
"network/backend/*.h"
|
||||||
"widgets/*.h"
|
"widgets/*.h"
|
||||||
"launcher/*.h"
|
"launcher/*.h"
|
||||||
@@ -38,6 +39,7 @@ endif()
|
|||||||
|
|
||||||
option(USE_IMGUI_GL3 "Use OpenGL3+ imgui implementation" ON)
|
option(USE_IMGUI_GL3 "Use OpenGL3+ imgui implementation" ON)
|
||||||
option(WITH_UART "Compile with libserialport" ON)
|
option(WITH_UART "Compile with libserialport" ON)
|
||||||
|
option(WITH_OPENVR "Compile with OpenVR" ON)
|
||||||
option(WITH_ZMQ "Compile with cppzmq" ON)
|
option(WITH_ZMQ "Compile with cppzmq" ON)
|
||||||
option(USE_VSDEV_CAMERA "Use VS_Dev camera preview implementation" OFF)
|
option(USE_VSDEV_CAMERA "Use VS_Dev camera preview implementation" OFF)
|
||||||
|
|
||||||
@@ -195,6 +197,12 @@ if (WITH_ZMQ)
|
|||||||
set(SOURCES ${SOURCES} "zmq_input.cpp")
|
set(SOURCES ${SOURCES} "zmq_input.cpp")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (WITH_OPENVR)
|
||||||
|
add_definitions(-DWITH_OPENVR)
|
||||||
|
set(SOURCES ${SOURCES} "vr/openvr_imp.cpp" "vr/vr_interface.cpp")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
if (USE_VSDEV_CAMERA)
|
if (USE_VSDEV_CAMERA)
|
||||||
add_definitions(-DUSE_VSDEV_CAMERA)
|
add_definitions(-DUSE_VSDEV_CAMERA)
|
||||||
set(SOURCES ${SOURCES} "extras/VS_Dev.cpp" "widgets/cameraview_vsdev.cpp")
|
set(SOURCES ${SOURCES} "extras/VS_Dev.cpp" "widgets/cameraview_vsdev.cpp")
|
||||||
@@ -267,6 +275,10 @@ set_target_properties( ${PROJECT_NAME}
|
|||||||
DEBUG_POSTFIX "_d"
|
DEBUG_POSTFIX "_d"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (WITH_OPENVR)
|
||||||
|
target_link_libraries(${PROJECT_NAME} openvr_api)
|
||||||
|
endif()
|
||||||
|
|
||||||
find_package(GLFW3 REQUIRED)
|
find_package(GLFW3 REQUIRED)
|
||||||
include_directories(${GLFW3_INCLUDE_DIR})
|
include_directories(${GLFW3_INCLUDE_DIR})
|
||||||
target_link_libraries(${PROJECT_NAME} ${GLFW3_LIBRARIES})
|
target_link_libraries(${PROJECT_NAME} ${GLFW3_LIBRARIES})
|
||||||
|
|||||||
2
EU07.cpp
2
EU07.cpp
@@ -34,7 +34,7 @@ int main( int argc, char *argv[] )
|
|||||||
auto result { Application.init( argc, argv ) };
|
auto result { Application.init( argc, argv ) };
|
||||||
if( result == 0 ) {
|
if( result == 0 ) {
|
||||||
result = Application.run();
|
result = Application.run();
|
||||||
Application.exit();
|
Application.exit();
|
||||||
}
|
}
|
||||||
std::_Exit(0); // skip destructors, there are ordering errors which causes segfaults
|
std::_Exit(0); // skip destructors, there are ordering errors which causes segfaults
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ public:
|
|||||||
void deserialize_float64(std::istream&);
|
void deserialize_float64(std::istream&);
|
||||||
void serialize_float32(std::ostream&);
|
void serialize_float32(std::ostream&);
|
||||||
float4x4(void){};
|
float4x4(void){};
|
||||||
float4x4(float f[16])
|
float4x4(const float f[16])
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 16; ++i)
|
for (int i = 0; i < 16; ++i)
|
||||||
e[i] = f[i];
|
e[i] = f[i];
|
||||||
|
|||||||
14
Globals.cpp
14
Globals.cpp
@@ -943,7 +943,7 @@ global_settings::ConfigParse(cParser &Parser) {
|
|||||||
extra_viewports.push_back(conf);
|
extra_viewports.push_back(conf);
|
||||||
if (gl::vao::use_vao && conf.monitor != "MAIN") {
|
if (gl::vao::use_vao && conf.monitor != "MAIN") {
|
||||||
gl::vao::use_vao = false;
|
gl::vao::use_vao = false;
|
||||||
WriteLog("using multiple viewports, disabling vao!");
|
WriteLog("using multiple windows, disabling vao!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (token == "map.highlightdistance") {
|
else if (token == "map.highlightdistance") {
|
||||||
@@ -968,6 +968,14 @@ global_settings::ConfigParse(cParser &Parser) {
|
|||||||
Parser >> headtrack_conf.rot_axes[0] >> headtrack_conf.rot_axes[1] >> headtrack_conf.rot_axes[2];
|
Parser >> headtrack_conf.rot_axes[0] >> headtrack_conf.rot_axes[1] >> headtrack_conf.rot_axes[2];
|
||||||
Parser >> headtrack_conf.rot_mul[0] >> headtrack_conf.rot_mul[1] >> headtrack_conf.rot_mul[2];
|
Parser >> headtrack_conf.rot_mul[0] >> headtrack_conf.rot_mul[1] >> headtrack_conf.rot_mul[2];
|
||||||
}
|
}
|
||||||
|
else if (token == "vr.enabled") {
|
||||||
|
Parser.getTokens(1);
|
||||||
|
Parser >> vr;
|
||||||
|
}
|
||||||
|
else if (token == "vr.backend") {
|
||||||
|
Parser.getTokens(1);
|
||||||
|
Parser >> vr_backend;
|
||||||
|
}
|
||||||
} while ((token != "") && (token != "endconfig")); //(!Parser->EndOfFile)
|
} while ((token != "") && (token != "endconfig")); //(!Parser->EndOfFile)
|
||||||
// na koniec trochę zależności
|
// na koniec trochę zależności
|
||||||
if (!bLoadTraction) // wczytywanie drutów i słupów
|
if (!bLoadTraction) // wczytywanie drutów i słupów
|
||||||
@@ -975,6 +983,10 @@ global_settings::ConfigParse(cParser &Parser) {
|
|||||||
bEnableTraction = false; // false = pantograf się nie połamie
|
bEnableTraction = false; // false = pantograf się nie połamie
|
||||||
bLiveTraction = false; // false = pantografy zawsze zbierają 95% MaxVoltage
|
bLiveTraction = false; // false = pantografy zawsze zbierają 95% MaxVoltage
|
||||||
}
|
}
|
||||||
|
if (vr) {
|
||||||
|
gfx_skippipeline = false;
|
||||||
|
VSync = false;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
fFpsMin = fFpsAverage -
|
fFpsMin = fFpsAverage -
|
||||||
fFpsDeviation; // dolna granica FPS, przy której promień scenerii będzie zmniejszany
|
fFpsDeviation; // dolna granica FPS, przy której promień scenerii będzie zmniejszany
|
||||||
|
|||||||
@@ -231,6 +231,8 @@ struct global_settings {
|
|||||||
bool gfx_extraeffects = true;
|
bool gfx_extraeffects = true;
|
||||||
bool gfx_shadergamma = false;
|
bool gfx_shadergamma = false;
|
||||||
bool gfx_usegles = false;
|
bool gfx_usegles = false;
|
||||||
|
bool vr = false;
|
||||||
|
std::string vr_backend;
|
||||||
|
|
||||||
float map_highlight_distance = 3000.0f;
|
float map_highlight_distance = 3000.0f;
|
||||||
|
|
||||||
@@ -271,7 +273,7 @@ struct global_settings {
|
|||||||
headtrack_config headtrack_conf;
|
headtrack_config headtrack_conf;
|
||||||
|
|
||||||
glm::vec3 viewport_move;
|
glm::vec3 viewport_move;
|
||||||
glm::vec3 viewport_rotate;
|
glm::mat3 viewport_rotate;
|
||||||
|
|
||||||
std::vector<std::pair<std::string, std::string>> network_servers;
|
std::vector<std::pair<std::string, std::string>> network_servers;
|
||||||
std::optional<std::pair<std::string, std::string>> network_client;
|
std::optional<std::pair<std::string, std::string>> network_client;
|
||||||
|
|||||||
38
Model3d.cpp
38
Model3d.cpp
@@ -61,7 +61,7 @@ void TSubModel::Name_Material(std::string const &Name)
|
|||||||
// ile nie jest wczytany z E3D
|
// ile nie jest wczytany z E3D
|
||||||
if (iFlags & 0x0200)
|
if (iFlags & 0x0200)
|
||||||
{ // tylko jeżeli submodel zosta utworzony przez new
|
{ // tylko jeżeli submodel zosta utworzony przez new
|
||||||
m_materialname = Name;
|
m_materialname = Name;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1244,6 +1244,16 @@ void TSubModel::ParentMatrix( float4x4 *m ) const {
|
|||||||
*/
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void TSubModel::ReplaceMatrix(const glm::mat4 &mat)
|
||||||
|
{
|
||||||
|
*fMatrix = float4x4(glm::value_ptr(mat));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSubModel::ReplaceMaterial(const std::string &name)
|
||||||
|
{
|
||||||
|
m_material = GfxRenderer.Fetch_Material(name);
|
||||||
|
}
|
||||||
|
|
||||||
// obliczenie maksymalnej wysokości, na początek ślizgu w pantografie
|
// obliczenie maksymalnej wysokości, na początek ślizgu w pantografie
|
||||||
float TSubModel::MaxY( float4x4 const &m ) {
|
float TSubModel::MaxY( float4x4 const &m ) {
|
||||||
// tylko dla trójkątów liczymy
|
// tylko dla trójkątów liczymy
|
||||||
@@ -1926,6 +1936,32 @@ void TModel3d::LoadFromBinFile(std::string const &FileName, bool dynamic)
|
|||||||
WriteLog( "Finished loading 3d model data from \"" + FileName + "\"", logtype::model );
|
WriteLog( "Finished loading 3d model data from \"" + FileName + "\"", logtype::model );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TSubModel* TModel3d::AppendChildFromGeometry(const std::string &name, const std::string &parent, const gfx::vertex_array &data)
|
||||||
|
{
|
||||||
|
iFlags |= 0x0200;
|
||||||
|
|
||||||
|
TSubModel *sm = new TSubModel();
|
||||||
|
sm->Parent = AddToNamed(parent.c_str(), sm);
|
||||||
|
sm->iNumVerts = data.size();
|
||||||
|
sm->eType = GL_TRIANGLES;
|
||||||
|
sm->pName = name;
|
||||||
|
sm->m_material = GfxRenderer.Fetch_Material("colored");
|
||||||
|
sm->fMatrix = new float4x4();
|
||||||
|
sm->fMatrix->Identity();
|
||||||
|
sm->iFlags |= 0x10;
|
||||||
|
sm->iFlags |= 0x8000;
|
||||||
|
sm->WillBeAnimated();
|
||||||
|
if (data.empty())
|
||||||
|
sm->iFlags &= ~0x3F;
|
||||||
|
sm->Vertices = data;
|
||||||
|
iNumVerts += data.size();
|
||||||
|
|
||||||
|
if (!Root)
|
||||||
|
Root = sm;
|
||||||
|
|
||||||
|
return sm;
|
||||||
|
}
|
||||||
|
|
||||||
void TModel3d::LoadFromTextFile(std::string const &FileName, bool dynamic)
|
void TModel3d::LoadFromTextFile(std::string const &FileName, bool dynamic)
|
||||||
{ // wczytanie submodelu z pliku tekstowego
|
{ // wczytanie submodelu z pliku tekstowego
|
||||||
WriteLog( "Loading text format 3d model data from \"" + FileName + "\"...", logtype::model );
|
WriteLog( "Loading text format 3d model data from \"" + FileName + "\"...", logtype::model );
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ public:
|
|||||||
static std::string *pasText; // tekst dla wyświetlacza (!!!! do przemyślenia)
|
static std::string *pasText; // tekst dla wyświetlacza (!!!! do przemyślenia)
|
||||||
TSubModel() = default;
|
TSubModel() = default;
|
||||||
~TSubModel();
|
~TSubModel();
|
||||||
int Load(cParser &Parser, TModel3d *Model, /*int Pos,*/ bool dynamic);
|
int Load(cParser &Parser, TModel3d *Model, /*int Pos,*/ bool dynamic);
|
||||||
void ChildAdd(TSubModel *SubModel);
|
void ChildAdd(TSubModel *SubModel);
|
||||||
void NextAdd(TSubModel *SubModel);
|
void NextAdd(TSubModel *SubModel);
|
||||||
TSubModel * NextGet() { return Next; };
|
TSubModel * NextGet() { return Next; };
|
||||||
@@ -217,6 +217,8 @@ public:
|
|||||||
material_handle GetMaterial() const {
|
material_handle GetMaterial() const {
|
||||||
return m_material; }
|
return m_material; }
|
||||||
void ParentMatrix(float4x4 *m) const;
|
void ParentMatrix(float4x4 *m) const;
|
||||||
|
void ReplaceMatrix(const glm::mat4 &mat);
|
||||||
|
void ReplaceMaterial(const std::string &name);
|
||||||
float MaxY( float4x4 const &m );
|
float MaxY( float4x4 const &m );
|
||||||
std::shared_ptr<std::vector<glm::vec2>> screen_touch_list; // for python screen touching
|
std::shared_ptr<std::vector<glm::vec2>> screen_touch_list; // for python screen touching
|
||||||
std::optional<gl::query> occlusion_query;
|
std::optional<gl::query> occlusion_query;
|
||||||
@@ -267,7 +269,8 @@ public:
|
|||||||
void AddTo(TSubModel *tmp, TSubModel *SubModel);
|
void AddTo(TSubModel *tmp, TSubModel *SubModel);
|
||||||
void LoadFromTextFile(std::string const &FileName, bool dynamic);
|
void LoadFromTextFile(std::string const &FileName, bool dynamic);
|
||||||
void LoadFromBinFile(std::string const &FileName, bool dynamic);
|
void LoadFromBinFile(std::string const &FileName, bool dynamic);
|
||||||
bool LoadFromFile(std::string const &FileName, bool dynamic);
|
bool LoadFromFile(std::string const &FileName, bool dynamic);
|
||||||
|
TSubModel *AppendChildFromGeometry(const std::string &name, const std::string &parent, const gfx::vertex_array &data);
|
||||||
void SaveToBinFile(std::string const &FileName);
|
void SaveToBinFile(std::string const &FileName);
|
||||||
uint32_t Flags() const { return iFlags; };
|
uint32_t Flags() const { return iFlags; };
|
||||||
void Init();
|
void Init();
|
||||||
|
|||||||
33
Texture.cpp
33
Texture.cpp
@@ -164,7 +164,7 @@ opengl_texture::load() {
|
|||||||
if (data_state == resource_state::good)
|
if (data_state == resource_state::good)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( type == "make:" ) {
|
if( type == "make:" || type == "internalsrc:" ) {
|
||||||
// for generated texture we delay data creation until texture is bound
|
// for generated texture we delay data creation until texture is bound
|
||||||
// this ensures the script will receive all simulation data it might potentially want
|
// this ensures the script will receive all simulation data it might potentially want
|
||||||
// as any binding will happen after simulation is loaded, initialized and running
|
// as any binding will happen after simulation is loaded, initialized and running
|
||||||
@@ -279,8 +279,8 @@ void opengl_texture::load_STBI()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
opengl_texture::make_stub() {
|
opengl_texture::make_stub()
|
||||||
|
{
|
||||||
data_width = 2;
|
data_width = 2;
|
||||||
data_height = 2;
|
data_height = 2;
|
||||||
data.resize( data_width * data_height * 3 );
|
data.resize( data_width * data_height * 3 );
|
||||||
@@ -289,6 +289,26 @@ opengl_texture::make_stub() {
|
|||||||
data_format = GL_RGB;
|
data_format = GL_RGB;
|
||||||
data_components = GL_RGB;
|
data_components = GL_RGB;
|
||||||
data_state = resource_state::good;
|
data_state = resource_state::good;
|
||||||
|
|
||||||
|
is_texstub = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
opengl_texture::make_from_memory(size_t width, size_t height, const uint8_t *raw)
|
||||||
|
{
|
||||||
|
release();
|
||||||
|
|
||||||
|
data_width = width;
|
||||||
|
data_height = width;
|
||||||
|
data.resize(data_width * data_height * 4);
|
||||||
|
memcpy(data.data(), raw, data.size());
|
||||||
|
|
||||||
|
data_format = GL_RGBA;
|
||||||
|
data_components = GL_RGBA;
|
||||||
|
data_mapcount = 1;
|
||||||
|
data_state = resource_state::good;
|
||||||
|
|
||||||
|
is_texstub = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1113,8 +1133,9 @@ texture_manager::create(std::string Filename, bool const Loadnow , GLint fh) {
|
|||||||
// discern textures generated by a script
|
// discern textures generated by a script
|
||||||
// TBD: support file: for file resources?
|
// TBD: support file: for file resources?
|
||||||
auto const isgenerated { Filename.find( "make:" ) == 0 };
|
auto const isgenerated { Filename.find( "make:" ) == 0 };
|
||||||
|
auto const isinternalsrc { Filename.find( "internal_src:" ) == 0 };
|
||||||
// process supplied resource name
|
// process supplied resource name
|
||||||
if( isgenerated ) {
|
if( isgenerated || isinternalsrc ) {
|
||||||
// generated resource
|
// generated resource
|
||||||
// scheme:(user@)path?query
|
// scheme:(user@)path?query
|
||||||
|
|
||||||
@@ -1159,6 +1180,10 @@ texture_manager::create(std::string Filename, bool const Loadnow , GLint fh) {
|
|||||||
locator.first = Filename;
|
locator.first = Filename;
|
||||||
locator.second = "make:";
|
locator.second = "make:";
|
||||||
}
|
}
|
||||||
|
else if ( isinternalsrc ) {
|
||||||
|
locator.first = Filename;
|
||||||
|
locator.second = "internalsrc:";
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// ...for file resources check if it's on disk
|
// ...for file resources check if it's on disk
|
||||||
locator = find_on_disk( Filename );
|
locator = find_on_disk( Filename );
|
||||||
|
|||||||
@@ -42,8 +42,13 @@ struct opengl_texture {
|
|||||||
int
|
int
|
||||||
height() const {
|
height() const {
|
||||||
return data_height; }
|
return data_height; }
|
||||||
|
inline
|
||||||
|
bool
|
||||||
|
is_stub() const {
|
||||||
|
return is_texstub; }
|
||||||
|
|
||||||
void make_stub();
|
void make_stub();
|
||||||
|
void make_from_memory(size_t width, size_t height, const uint8_t *data);
|
||||||
void alloc_rendertarget(GLint format, GLint components, int width, int height, int samples = 1, GLint wrap = GL_CLAMP_TO_BORDER);
|
void alloc_rendertarget(GLint format, GLint components, int width, int height, int samples = 1, GLint wrap = GL_CLAMP_TO_BORDER);
|
||||||
void set_components_hint(GLint hint);
|
void set_components_hint(GLint hint);
|
||||||
static void reset_unit_cache();
|
static void reset_unit_cache();
|
||||||
@@ -77,6 +82,7 @@ private:
|
|||||||
// members
|
// members
|
||||||
bool is_rendertarget = false; // is used as postfx rendertarget, without loaded data
|
bool is_rendertarget = false; // is used as postfx rendertarget, without loaded data
|
||||||
int samples = 1;
|
int samples = 1;
|
||||||
|
bool is_texstub = false; // for make_from_memory internal_src: functionality
|
||||||
|
|
||||||
std::vector<unsigned char> data; // texture data (stored GL-style, bottom-left origin)
|
std::vector<unsigned char> data; // texture data (stored GL-style, bottom-left origin)
|
||||||
resource_state data_state{ resource_state::none }; // current state of texture data
|
resource_state data_state{ resource_state::none }; // current state of texture data
|
||||||
|
|||||||
@@ -354,6 +354,7 @@ eu07_application::exit() {
|
|||||||
for (auto &mode : m_modes)
|
for (auto &mode : m_modes)
|
||||||
mode.reset();
|
mode.reset();
|
||||||
|
|
||||||
|
GfxRenderer.Shutdown();
|
||||||
m_network.reset();
|
m_network.reset();
|
||||||
|
|
||||||
SafeDelete( simulation::Train );
|
SafeDelete( simulation::Train );
|
||||||
|
|||||||
@@ -74,11 +74,19 @@ void gl::framebuffer::blit(framebuffer *src, framebuffer *dst, int sx, int sy, i
|
|||||||
{
|
{
|
||||||
int attachment_n = attachment - GL_COLOR_ATTACHMENT0;
|
int attachment_n = attachment - GL_COLOR_ATTACHMENT0;
|
||||||
|
|
||||||
GLenum outputs[8] = { GL_NONE };
|
{
|
||||||
outputs[attachment_n] = attachment;
|
GLenum outputs[8] = { GL_NONE };
|
||||||
|
outputs[attachment_n] = src != 0 ? attachment : GL_BACK_LEFT;
|
||||||
|
|
||||||
glReadBuffer(attachment);
|
glReadBuffer(attachment);
|
||||||
glDrawBuffers(attachment_n + 1, outputs);
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
GLenum outputs[8] = { GL_NONE };
|
||||||
|
outputs[attachment_n] = dst != 0 ? attachment : GL_BACK_LEFT;
|
||||||
|
|
||||||
|
glDrawBuffers(attachment_n + 1, outputs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glBlitFramebuffer(sx, sy, sx + w, sy + h, 0, 0, w, h, mask, GL_NEAREST);
|
glBlitFramebuffer(sx, sy, sx + w, sy + h, 0, 0, w, h, mask, GL_NEAREST);
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ void headtrack::update()
|
|||||||
{
|
{
|
||||||
if (joy_id == -1 || !glfwJoystickPresent(joy_id)) {
|
if (joy_id == -1 || !glfwJoystickPresent(joy_id)) {
|
||||||
Global.viewport_move = glm::vec3();
|
Global.viewport_move = glm::vec3();
|
||||||
Global.viewport_rotate = glm::vec3();
|
Global.viewport_rotate = glm::mat3();
|
||||||
find_joy();
|
find_joy();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -59,5 +59,5 @@ void headtrack::update()
|
|||||||
rotate.z = get_axis(axes, count, rot_axes.z, rot_mul.z);
|
rotate.z = get_axis(axes, count, rot_axes.z, rot_mul.z);
|
||||||
|
|
||||||
Global.viewport_move = move;
|
Global.viewport_move = move;
|
||||||
Global.viewport_rotate = rotate;
|
Global.viewport_rotate = glm::orientate3(rotate);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -313,7 +313,7 @@ material_manager::create( std::string const &Filename, bool const Loadnow ) {
|
|||||||
|
|
||||||
// discern references to textures generated by a script
|
// discern references to textures generated by a script
|
||||||
// TBD: support file: for file resources?
|
// TBD: support file: for file resources?
|
||||||
auto const isgenerated { filename.find( "make:" ) == 0 };
|
auto const isgenerated { filename.find( "make:" ) == 0 || filename.find( "internal_src:" ) == 0 };
|
||||||
|
|
||||||
// process supplied resource name
|
// process supplied resource name
|
||||||
if( isgenerated ) {
|
if( isgenerated ) {
|
||||||
|
|||||||
@@ -147,11 +147,11 @@ network::tcp::server::server(std::shared_ptr<std::istream> buf, asio::io_context
|
|||||||
}
|
}
|
||||||
|
|
||||||
void network::tcp::server::accept_conn()
|
void network::tcp::server::accept_conn()
|
||||||
{
|
{/*
|
||||||
std::shared_ptr<connection> conn = std::make_shared<connection>(m_acceptor.get_executor().context());
|
std::shared_ptr<connection> conn = std::make_shared<connection>(m_acceptor.get_executor().context());
|
||||||
conn->set_handler(std::bind(&server::handle_message, this, conn, std::placeholders::_1));
|
conn->set_handler(std::bind(&server::handle_message, this, conn, std::placeholders::_1));
|
||||||
|
|
||||||
m_acceptor.async_accept(conn->m_socket, std::bind(&server::handle_accept, this, conn, std::placeholders::_1));
|
m_acceptor.async_accept(conn->m_socket, std::bind(&server::handle_accept, this, conn, std::placeholders::_1));*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void network::tcp::server::handle_accept(std::shared_ptr<connection> conn, const asio::error_code &err)
|
void network::tcp::server::handle_accept(std::shared_ptr<connection> conn, const asio::error_code &err)
|
||||||
|
|||||||
179
renderer.cpp
179
renderer.cpp
@@ -291,6 +291,33 @@ bool opengl_renderer::Init(GLFWwindow *Window)
|
|||||||
default_viewport.window = m_window;
|
default_viewport.window = m_window;
|
||||||
default_viewport.draw_range = 1.0f;
|
default_viewport.draw_range = 1.0f;
|
||||||
|
|
||||||
|
if (Global.vr)
|
||||||
|
vr = vr_interface_factory::get_instance()->create(Global.vr_backend);
|
||||||
|
|
||||||
|
if (vr) {
|
||||||
|
glm::ivec2 target_size = vr->get_target_size();
|
||||||
|
WriteLog("using vr rendertarget: " + glm::to_string(target_size));
|
||||||
|
|
||||||
|
// hijack main window for left eye
|
||||||
|
default_viewport.width = target_size.x;
|
||||||
|
default_viewport.height = target_size.y;
|
||||||
|
default_viewport.custom_backbuffer = true;
|
||||||
|
default_viewport.proj_type = viewport_config::vr_left;
|
||||||
|
|
||||||
|
// create right eye viewport
|
||||||
|
m_viewports.push_back(std::make_unique<viewport_config>());
|
||||||
|
m_viewports.back()->width = target_size.x;
|
||||||
|
m_viewports.back()->height = target_size.y;
|
||||||
|
m_viewports.back()->window = m_window; // we can reuse context
|
||||||
|
m_viewports.back()->real_window = false; // but don't draw anything to it
|
||||||
|
m_viewports.back()->custom_backbuffer = true;
|
||||||
|
m_viewports.back()->proj_type = viewport_config::vr_right;
|
||||||
|
m_viewports.back()->draw_range = 1.0f;
|
||||||
|
|
||||||
|
if (!init_viewport(*m_viewports.back()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!init_viewport(default_viewport))
|
if (!init_viewport(default_viewport))
|
||||||
return false;
|
return false;
|
||||||
glfwMakeContextCurrent(m_window);
|
glfwMakeContextCurrent(m_window);
|
||||||
@@ -418,6 +445,11 @@ bool opengl_renderer::Init(GLFWwindow *Window)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void opengl_renderer::Shutdown()
|
||||||
|
{
|
||||||
|
vr.reset();
|
||||||
|
}
|
||||||
|
|
||||||
bool opengl_renderer::AddViewport(const global_settings::extraviewport_config &conf)
|
bool opengl_renderer::AddViewport(const global_settings::extraviewport_config &conf)
|
||||||
{
|
{
|
||||||
viewport_config *vp;
|
viewport_config *vp;
|
||||||
@@ -434,7 +466,7 @@ bool opengl_renderer::AddViewport(const global_settings::extraviewport_config &c
|
|||||||
vp->width = conf.width;
|
vp->width = conf.width;
|
||||||
vp->height = conf.height;
|
vp->height = conf.height;
|
||||||
vp->projection = conf.projection;
|
vp->projection = conf.projection;
|
||||||
vp->custom_projection = true;
|
vp->proj_type = viewport_config::custom;
|
||||||
vp->draw_range = conf.draw_range;
|
vp->draw_range = conf.draw_range;
|
||||||
|
|
||||||
bool ret = init_viewport(*vp);
|
bool ret = init_viewport(*vp);
|
||||||
@@ -453,7 +485,8 @@ bool opengl_renderer::init_viewport(viewport_config &vp)
|
|||||||
|
|
||||||
WriteLog("init viewport: " + std::to_string(vp.width) + ", " + std::to_string(vp.height));
|
WriteLog("init viewport: " + std::to_string(vp.width) + ", " + std::to_string(vp.height));
|
||||||
|
|
||||||
glfwSwapInterval( Global.VSync ? 1 : 0 );
|
if (vp.real_window)
|
||||||
|
glfwSwapInterval( Global.VSync ? 1 : 0 );
|
||||||
|
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||||
@@ -542,6 +575,17 @@ bool opengl_renderer::init_viewport(viewport_config &vp)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vp.custom_backbuffer)
|
||||||
|
{
|
||||||
|
vp.backbuffer_tex = std::make_unique<opengl_texture>();
|
||||||
|
vp.backbuffer_tex->alloc_rendertarget(GL_SRGB8, GL_RGB, vp.width, vp.height);
|
||||||
|
|
||||||
|
vp.backbuffer_fb = std::make_unique<gl::framebuffer>();
|
||||||
|
vp.backbuffer_fb->attach(*vp.backbuffer_tex, GL_COLOR_ATTACHMENT0);
|
||||||
|
if (!vp.backbuffer_fb->is_complete())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
vp.initialized = true;
|
vp.initialized = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -579,6 +623,9 @@ bool opengl_renderer::Render()
|
|||||||
m_renderpass.draw_mode = rendermode::none; // force setup anew
|
m_renderpass.draw_mode = rendermode::none; // force setup anew
|
||||||
m_debugstats = debug_stats();
|
m_debugstats = debug_stats();
|
||||||
|
|
||||||
|
if (vr)
|
||||||
|
vr->begin_frame();
|
||||||
|
|
||||||
for (auto &viewport : m_viewports) {
|
for (auto &viewport : m_viewports) {
|
||||||
Render_pass(*viewport, rendermode::color);
|
Render_pass(*viewport, rendermode::color);
|
||||||
}
|
}
|
||||||
@@ -620,10 +667,13 @@ void opengl_renderer::SwapBuffers()
|
|||||||
Timer::subsystem.gfx_swap.start();
|
Timer::subsystem.gfx_swap.start();
|
||||||
|
|
||||||
for (auto &viewport : m_viewports) {
|
for (auto &viewport : m_viewports) {
|
||||||
if (viewport->window)
|
if (viewport->window && viewport->real_window)
|
||||||
glfwSwapBuffers(viewport->window);
|
glfwSwapBuffers(viewport->window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vr)
|
||||||
|
vr->finish_frame();
|
||||||
|
|
||||||
// swapbuffers() could unbind current buffers so we prepare for it on our end
|
// swapbuffers() could unbind current buffers so we prepare for it on our end
|
||||||
gfx::opengl_vbogeometrybank::reset();
|
gfx::opengl_vbogeometrybank::reset();
|
||||||
Timer::subsystem.gfx_swap.stop();
|
Timer::subsystem.gfx_swap.stop();
|
||||||
@@ -725,7 +775,7 @@ void opengl_renderer::Render_pass(viewport_config &vp, rendermode const Mode)
|
|||||||
setup_drawing(false);
|
setup_drawing(false);
|
||||||
|
|
||||||
glm::ivec2 target_size(vp.width, vp.height);
|
glm::ivec2 target_size(vp.width, vp.height);
|
||||||
if (vp.main) // TODO: update window sizes also for extra viewports
|
if (vp.main && !vp.custom_backbuffer) // TODO: update window sizes also for extra viewports
|
||||||
target_size = glm::ivec2(Global.iWindowWidth, Global.iWindowHeight);
|
target_size = glm::ivec2(Global.iWindowWidth, Global.iWindowHeight);
|
||||||
|
|
||||||
if (!Global.gfx_skippipeline)
|
if (!Global.gfx_skippipeline)
|
||||||
@@ -745,7 +795,8 @@ void opengl_renderer::Render_pass(viewport_config &vp, rendermode const Mode)
|
|||||||
{
|
{
|
||||||
if (!Global.gfx_usegles && !Global.gfx_shadergamma)
|
if (!Global.gfx_usegles && !Global.gfx_shadergamma)
|
||||||
glEnable(GL_FRAMEBUFFER_SRGB);
|
glEnable(GL_FRAMEBUFFER_SRGB);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
glViewport(0, 0, target_size.x, target_size.y);
|
glViewport(0, 0, target_size.x, target_size.y);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
@@ -796,6 +847,8 @@ void opengl_renderer::Render_pass(viewport_config &vp, rendermode const Mode)
|
|||||||
|
|
||||||
Render(simulation::Region);
|
Render(simulation::Region);
|
||||||
|
|
||||||
|
Render_vr_models();
|
||||||
|
|
||||||
// ...translucent parts
|
// ...translucent parts
|
||||||
glDebug("render translucent region");
|
glDebug("render translucent region");
|
||||||
setup_drawing(true);
|
setup_drawing(true);
|
||||||
@@ -856,9 +909,25 @@ void opengl_renderer::Render_pass(viewport_config &vp, rendermode const Mode)
|
|||||||
glEnable(GL_FRAMEBUFFER_SRGB);
|
glEnable(GL_FRAMEBUFFER_SRGB);
|
||||||
|
|
||||||
glViewport(0, 0, target_size.x, target_size.y);
|
glViewport(0, 0, target_size.x, target_size.y);
|
||||||
m_pfx_tonemapping->apply(*vp.main2_tex, nullptr);
|
|
||||||
|
gl::framebuffer *target = nullptr;
|
||||||
|
if (vp.custom_backbuffer)
|
||||||
|
target = vp.backbuffer_fb.get();
|
||||||
|
m_pfx_tonemapping->apply(*vp.main2_tex, target);
|
||||||
|
|
||||||
|
if (vr) {
|
||||||
|
if (vp.proj_type == viewport_config::vr_left)
|
||||||
|
vr->submit(vr_interface::eye_left, vp.backbuffer_tex.get());
|
||||||
|
if (vp.proj_type == viewport_config::vr_right)
|
||||||
|
vr->submit(vr_interface::eye_right, vp.backbuffer_tex.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vp.custom_backbuffer && vp.real_window) {
|
||||||
|
vp.backbuffer_fb->blit_to(nullptr, vp.width, vp.height, GL_COLOR_BUFFER_BIT, GL_COLOR_ATTACHMENT0);
|
||||||
|
}
|
||||||
|
|
||||||
opengl_texture::reset_unit_cache();
|
opengl_texture::reset_unit_cache();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Global.gfx_usegles && !Global.gfx_shadergamma)
|
if (!Global.gfx_usegles && !Global.gfx_shadergamma)
|
||||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||||
@@ -900,6 +969,8 @@ void opengl_renderer::Render_pass(viewport_config &vp, rendermode const Mode)
|
|||||||
scene_ubo->update(scene_ubs);
|
scene_ubo->update(scene_ubs);
|
||||||
Render(simulation::Region);
|
Render(simulation::Region);
|
||||||
|
|
||||||
|
Render_vr_models();
|
||||||
|
|
||||||
m_shadowpass = m_renderpass;
|
m_shadowpass = m_renderpass;
|
||||||
|
|
||||||
m_shadow_fb->unbind();
|
m_shadow_fb->unbind();
|
||||||
@@ -1210,46 +1281,43 @@ void opengl_renderer::setup_pass(viewport_config &Viewport, renderpass_config &C
|
|||||||
|
|
||||||
glm::mat4 frustumtest_proj;
|
glm::mat4 frustumtest_proj;
|
||||||
|
|
||||||
if (!Viewport.custom_projection && Viewport.main) {
|
|
||||||
// TODO: update window sizes also for extra viewports
|
|
||||||
float const fovy = glm::radians(Global.FieldOfView / Global.ZoomFactor);
|
|
||||||
|
|
||||||
// setup virtual screen
|
|
||||||
glm::vec2 screen_h = glm::vec2(Global.iWindowWidth, Global.iWindowHeight) / 2.0f;
|
|
||||||
float const dist = screen_h.y / glm::tan(fovy / 2.0f);
|
|
||||||
|
|
||||||
Viewport.projection.pa = glm::vec3(-screen_h.x, -screen_h.y, -dist);
|
|
||||||
Viewport.projection.pb = glm::vec3( screen_h.x, -screen_h.y, -dist);
|
|
||||||
Viewport.projection.pc = glm::vec3(-screen_h.x, screen_h.y, -dist);
|
|
||||||
Viewport.projection.pe = glm::vec3(0.0f, 0.0f, 0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Global.headtrack_conf.magic_window)
|
|
||||||
Viewport.projection.pe = Global.viewport_move;
|
|
||||||
|
|
||||||
Config.viewport_camera.position() = Global.pCamera.Pos;
|
Config.viewport_camera.position() = Global.pCamera.Pos;
|
||||||
|
|
||||||
switch (Mode)
|
switch (Mode)
|
||||||
{
|
{
|
||||||
case rendermode::color:
|
case rendermode::color:
|
||||||
{
|
{
|
||||||
if (!Global.headtrack_conf.magic_window) {
|
if (Viewport.proj_type == viewport_config::normal && Viewport.main) {
|
||||||
Global.pCamera.Pos += Global.viewport_move;
|
// TODO: update window sizes also for extra viewports
|
||||||
Global.pCamera.LookAt += Global.viewport_move;
|
float const fovy = glm::radians(Global.FieldOfView / Global.ZoomFactor);
|
||||||
Global.pCamera.Angle += Global.viewport_rotate;
|
|
||||||
|
// setup virtual screen
|
||||||
|
glm::vec2 screen_h = glm::vec2(Global.iWindowWidth, Global.iWindowHeight) / 2.0f;
|
||||||
|
float const dist = screen_h.y / glm::tan(fovy / 2.0f);
|
||||||
|
|
||||||
|
Viewport.projection.pa = glm::vec3(-screen_h.x, -screen_h.y, -dist);
|
||||||
|
Viewport.projection.pb = glm::vec3( screen_h.x, -screen_h.y, -dist);
|
||||||
|
Viewport.projection.pc = glm::vec3(-screen_h.x, screen_h.y, -dist);
|
||||||
|
Viewport.projection.pe = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// modelview
|
if (vr && (Viewport.proj_type == viewport_config::vr_left || Viewport.proj_type == viewport_config::vr_right)) {
|
||||||
if ((false == DebugCameraFlag) || (true == Ignoredebug))
|
Viewport.projection = vr->get_proj_config(Viewport.proj_type == viewport_config::vr_left ? vr_interface::eye_left : vr_interface::eye_right);
|
||||||
{
|
Global.pCamera.Angle.x = 0.0;
|
||||||
camera.position() = Global.pCamera.Pos;
|
Global.pCamera.Angle.z = 0.0;
|
||||||
Global.pCamera.SetMatrix(viewmatrix);
|
}
|
||||||
}
|
|
||||||
else
|
if (Global.headtrack_conf.magic_window)
|
||||||
{
|
Viewport.projection.pe = Global.viewport_move;
|
||||||
camera.position() = Global.pDebugCamera.Pos;
|
|
||||||
Global.pDebugCamera.SetMatrix(viewmatrix);
|
TCamera *cam = ((false == DebugCameraFlag) || (true == Ignoredebug)) ? &Global.pCamera : &Global.pDebugCamera;
|
||||||
}
|
camera.position() = cam->Pos;
|
||||||
|
cam->SetMatrix(viewmatrix);
|
||||||
|
|
||||||
|
if (!Global.headtrack_conf.magic_window || vr) {
|
||||||
|
camera.position() += Global.viewport_move * glm::mat3(viewmatrix);
|
||||||
|
viewmatrix = glm::dmat4(glm::inverse(Global.viewport_rotate)) * viewmatrix;
|
||||||
|
}
|
||||||
|
|
||||||
// projection
|
// projection
|
||||||
auto const zfar = Config.draw_range * Global.fDistanceFactor * Zfar;
|
auto const zfar = Config.draw_range * Global.fDistanceFactor * Zfar;
|
||||||
@@ -1320,12 +1388,18 @@ void opengl_renderer::setup_pass(viewport_config &Viewport, renderpass_config &C
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case rendermode::cabshadows:
|
case rendermode::cabshadows:
|
||||||
{
|
{
|
||||||
|
renderpass_config worldview;
|
||||||
|
setup_pass(Viewport, worldview, rendermode::color, 0.f, Zfar, true);
|
||||||
|
//glm::dmat4 tmpmat;
|
||||||
|
//Global.pCamera.SetMatrix(tmpmat);
|
||||||
|
|
||||||
// fixed size cube large enough to enclose a vehicle compartment
|
// fixed size cube large enough to enclose a vehicle compartment
|
||||||
// modelview
|
// modelview
|
||||||
auto const lightvector = glm::normalize(glm::vec3{m_sunlight.direction.x, std::min(m_sunlight.direction.y, -0.2f), m_sunlight.direction.z});
|
auto const lightvector = glm::normalize(glm::vec3{m_sunlight.direction.x, std::min(m_sunlight.direction.y, -0.2f), m_sunlight.direction.z});
|
||||||
camera.position() = Global.pCamera.Pos - glm::dvec3{lightvector};
|
camera.position() = worldview.pass_camera.position() - glm::dvec3{lightvector};
|
||||||
viewmatrix *= glm::lookAt(camera.position(), glm::dvec3{Global.pCamera.Pos}, glm::dvec3{0.f, 1.f, 0.f});
|
viewmatrix *= glm::lookAt(camera.position(), worldview.pass_camera.position(), glm::dvec3{0.f, 1.f, 0.f});
|
||||||
|
|
||||||
// projection
|
// projection
|
||||||
auto const maphalfsize{Config.draw_range * 0.5f};
|
auto const maphalfsize{Config.draw_range * 0.5f};
|
||||||
camera.projection() = ortho_projection(-maphalfsize, maphalfsize, -maphalfsize, maphalfsize, -Config.draw_range, Config.draw_range);
|
camera.projection() = ortho_projection(-maphalfsize, maphalfsize, -maphalfsize, maphalfsize, -Config.draw_range, Config.draw_range);
|
||||||
@@ -2494,7 +2568,7 @@ bool opengl_renderer::Render_cab(TDynamicObject const *Dynamic, float const Ligh
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// opaque parts
|
// opaque parts
|
||||||
Render(Dynamic->mdKabina, Dynamic->Material(), 0.0);
|
Render(Dynamic->mdKabina, Dynamic->Material(), 0.0);
|
||||||
}
|
}
|
||||||
// post-render restore
|
// post-render restore
|
||||||
if (Dynamic->fShade > 0.0f)
|
if (Dynamic->fShade > 0.0f)
|
||||||
@@ -3020,6 +3094,25 @@ void opengl_renderer::Render_particles()
|
|||||||
m_particlerenderer.render();
|
m_particlerenderer.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void opengl_renderer::Render_vr_models()
|
||||||
|
{
|
||||||
|
if (!vr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
glDebug("Render_vr_models");
|
||||||
|
|
||||||
|
::glPushMatrix();
|
||||||
|
glm::dmat4 tmpmat;
|
||||||
|
Global.pCamera.SetMatrix(tmpmat);
|
||||||
|
tmpmat = glm::dmat3(tmpmat);
|
||||||
|
glMultMatrixd(glm::value_ptr(glm::inverse(tmpmat)));
|
||||||
|
std::vector<TModel3d*> list = vr->get_render_models();
|
||||||
|
material_data data;
|
||||||
|
for (TModel3d *mdl : list)
|
||||||
|
Render(mdl, &data, 0.0);
|
||||||
|
::glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
void opengl_renderer::Render_precipitation()
|
void opengl_renderer::Render_precipitation()
|
||||||
{
|
{
|
||||||
if (Global.Overcast <= 1.f)
|
if (Global.Overcast <= 1.f)
|
||||||
|
|||||||
23
renderer.h
23
renderer.h
@@ -20,6 +20,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "scene.h"
|
#include "scene.h"
|
||||||
#include "light.h"
|
#include "light.h"
|
||||||
#include "particles.h"
|
#include "particles.h"
|
||||||
|
#include "vr/vr_interface.h"
|
||||||
#include "gl/ubo.h"
|
#include "gl/ubo.h"
|
||||||
#include "gl/framebuffer.h"
|
#include "gl/framebuffer.h"
|
||||||
#include "gl/renderbuffer.h"
|
#include "gl/renderbuffer.h"
|
||||||
@@ -167,6 +168,7 @@ class opengl_renderer
|
|||||||
|
|
||||||
// methods
|
// methods
|
||||||
bool Init(GLFWwindow *Window);
|
bool Init(GLFWwindow *Window);
|
||||||
|
void Shutdown();
|
||||||
bool AddViewport(const global_settings::extraviewport_config &conf);
|
bool AddViewport(const global_settings::extraviewport_config &conf);
|
||||||
|
|
||||||
// main draw call. returns false on error
|
// main draw call. returns false on error
|
||||||
@@ -281,23 +283,37 @@ class opengl_renderer
|
|||||||
float draw_range;
|
float draw_range;
|
||||||
|
|
||||||
bool main = false;
|
bool main = false;
|
||||||
GLFWwindow *window = nullptr;
|
GLFWwindow *window = nullptr; // ogl window context
|
||||||
|
bool real_window = true; // whether we need to blit onto GLFWwindow surface
|
||||||
|
bool custom_backbuffer = false; // whether we want to render to our offscreen LDR backbuffer (pipeline required)
|
||||||
|
|
||||||
bool custom_projection = false;
|
enum vp_type {
|
||||||
|
normal,
|
||||||
|
custom,
|
||||||
|
vr_left,
|
||||||
|
vr_right
|
||||||
|
} proj_type;
|
||||||
viewport_proj_config projection;
|
viewport_proj_config projection;
|
||||||
|
|
||||||
|
// main msaa render target for pipeline mode
|
||||||
std::unique_ptr<gl::framebuffer> msaa_fb;
|
std::unique_ptr<gl::framebuffer> msaa_fb;
|
||||||
std::unique_ptr<gl::renderbuffer> msaa_rbc;
|
std::unique_ptr<gl::renderbuffer> msaa_rbc;
|
||||||
std::unique_ptr<gl::renderbuffer> msaa_rbv;
|
std::unique_ptr<gl::renderbuffer> msaa_rbv;
|
||||||
std::unique_ptr<gl::renderbuffer> msaa_rbd;
|
std::unique_ptr<gl::renderbuffer> msaa_rbd;
|
||||||
|
|
||||||
|
// msaa resolve buffer (when using motion blur)
|
||||||
std::unique_ptr<gl::framebuffer> main_fb;
|
std::unique_ptr<gl::framebuffer> main_fb;
|
||||||
std::unique_ptr<opengl_texture> main_texv;
|
std::unique_ptr<opengl_texture> main_texv;
|
||||||
std::unique_ptr<opengl_texture> main_tex;
|
std::unique_ptr<opengl_texture> main_tex;
|
||||||
|
|
||||||
|
// final HDR buffer (also serving as msaa resolve buffer when not using motion blur)
|
||||||
std::unique_ptr<gl::framebuffer> main2_fb;
|
std::unique_ptr<gl::framebuffer> main2_fb;
|
||||||
std::unique_ptr<opengl_texture> main2_tex;
|
std::unique_ptr<opengl_texture> main2_tex;
|
||||||
|
|
||||||
|
// LDR backbuffer for offscreen rendering
|
||||||
|
std::unique_ptr<gl::framebuffer> backbuffer_fb;
|
||||||
|
std::unique_ptr<opengl_texture> backbuffer_tex;
|
||||||
|
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -334,6 +350,7 @@ class opengl_renderer
|
|||||||
void Render(TMemCell *Memcell);
|
void Render(TMemCell *Memcell);
|
||||||
void Render_particles();
|
void Render_particles();
|
||||||
void Render_precipitation();
|
void Render_precipitation();
|
||||||
|
void Render_vr_models();
|
||||||
void Render_Alpha(scene::basic_region *Region);
|
void Render_Alpha(scene::basic_region *Region);
|
||||||
void Render_Alpha(cell_sequence::reverse_iterator First, cell_sequence::reverse_iterator Last);
|
void Render_Alpha(cell_sequence::reverse_iterator First, cell_sequence::reverse_iterator Last);
|
||||||
void Render_Alpha(TAnimModel *Instance);
|
void Render_Alpha(TAnimModel *Instance);
|
||||||
@@ -497,6 +514,8 @@ class opengl_renderer
|
|||||||
};
|
};
|
||||||
|
|
||||||
headlight_config_s headlight_config;
|
headlight_config_s headlight_config;
|
||||||
|
|
||||||
|
std::unique_ptr<vr_interface> vr;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern opengl_renderer GfxRenderer;
|
extern opengl_renderer GfxRenderer;
|
||||||
|
|||||||
2
stdafx.h
2
stdafx.h
@@ -95,6 +95,7 @@
|
|||||||
#include <glm/gtc/type_ptr.hpp>
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
#include <glm/gtc/epsilon.hpp>
|
#include <glm/gtc/epsilon.hpp>
|
||||||
#include <glm/gtx/rotate_vector.hpp>
|
#include <glm/gtx/rotate_vector.hpp>
|
||||||
|
#include <glm/gtx/euler_angles.hpp>
|
||||||
#include <glm/gtx/norm.hpp>
|
#include <glm/gtx/norm.hpp>
|
||||||
#include <glm/gtx/string_cast.hpp>
|
#include <glm/gtx/string_cast.hpp>
|
||||||
|
|
||||||
@@ -106,4 +107,5 @@ int const null_handle = 0;
|
|||||||
#define glDebug(x) if (GLAD_GL_GREMEDY_string_marker) glStringMarkerGREMEDY(0, __FILE__ ":" STRINGIZE(__LINE__) ": " x);
|
#define glDebug(x) if (GLAD_GL_GREMEDY_string_marker) glStringMarkerGREMEDY(0, __FILE__ ":" STRINGIZE(__LINE__) ": " x);
|
||||||
|
|
||||||
#include "imgui/imgui.h"
|
#include "imgui/imgui.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
293
vr/openvr_imp.cpp
Normal file
293
vr/openvr_imp.cpp
Normal file
@@ -0,0 +1,293 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "openvr_imp.h"
|
||||||
|
#include "Logs.h"
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "renderer.h"
|
||||||
|
|
||||||
|
vr_openvr::vr_openvr()
|
||||||
|
{
|
||||||
|
vr::EVRInitError vr_error;
|
||||||
|
vr_system = vr::VR_Init(&vr_error, vr::VRApplication_Scene);
|
||||||
|
if (vr_error != vr::VRInitError_None) {
|
||||||
|
ErrorLog("failed to init openvr!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vr::VRCompositor()->SetTrackingSpace(vr::TrackingUniverseSeated);
|
||||||
|
vr::VRInput()->GetInputSourceHandle("/user/hand/left", &inputhandle_left);
|
||||||
|
vr::VRInput()->GetInputSourceHandle("/user/hand/right", &inputhandle_right);
|
||||||
|
|
||||||
|
std::string action_path = std::filesystem::current_path().string() + "/openvr_actions.json";
|
||||||
|
vr::VRInput()->SetActionManifestPath(action_path.c_str());
|
||||||
|
|
||||||
|
vr::VRInput()->GetActionSetHandle("/actions/main", &actionset);
|
||||||
|
vr::VRInput()->GetActionHandle("/actions/main/in/PrimaryAction", &primary_action);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::ivec2 vr_openvr::get_target_size()
|
||||||
|
{
|
||||||
|
uint32_t vr_w, vr_h;
|
||||||
|
vr_system->GetRecommendedRenderTargetSize(&vr_w, &vr_h);
|
||||||
|
return glm::ivec2(vr_w, vr_h);
|
||||||
|
}
|
||||||
|
|
||||||
|
viewport_proj_config vr_openvr::get_proj_config(eye_e e)
|
||||||
|
{
|
||||||
|
vr::EVREye eye = (e == vr_interface::eye_left) ? vr::Eye_Left : vr::Eye_Right;
|
||||||
|
|
||||||
|
float left, right, top, bottom; // tangents of half-angles from center view axis
|
||||||
|
vr_system->GetProjectionRaw(eye, &left, &right, &top, &bottom);
|
||||||
|
|
||||||
|
float ipd = vr_system->GetEyeToHeadTransform(eye).m[0][3];
|
||||||
|
|
||||||
|
viewport_proj_config proj;
|
||||||
|
|
||||||
|
proj.pe = glm::vec3(ipd, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
proj.pa = glm::vec3(ipd + left, top, -1.0f);
|
||||||
|
proj.pc = glm::vec3(ipd + left, bottom, -1.0f);
|
||||||
|
|
||||||
|
proj.pb = glm::vec3(ipd + right, top, -1.0f);
|
||||||
|
|
||||||
|
return proj;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::mat4 vr_openvr::get_matrix(vr::HmdMatrix34_t &src)
|
||||||
|
{
|
||||||
|
return glm::mat4(glm::transpose(glm::make_mat3x4((float*)(src.m))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void vr_openvr::begin_frame()
|
||||||
|
{
|
||||||
|
vr::TrackedDevicePose_t devicePose[MAX_DEVICES];
|
||||||
|
vr::VRCompositor()->WaitGetPoses(devicePose, MAX_DEVICES, nullptr, 0);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MAX_DEVICES; i++) {
|
||||||
|
if (!vr_system->IsTrackedDeviceConnected(i)) {
|
||||||
|
if (controllers[i])
|
||||||
|
controllers[i].reset();
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::mat4 device_pose = get_matrix(devicePose[i].mDeviceToAbsoluteTracking);
|
||||||
|
|
||||||
|
vr::ETrackedDeviceClass device_class = vr_system->GetTrackedDeviceClass(i);
|
||||||
|
|
||||||
|
if (device_class == vr::TrackedDeviceClass_HMD) {
|
||||||
|
Global.viewport_move = glm::vec3(device_pose[3]);
|
||||||
|
Global.viewport_rotate = glm::mat3(device_pose);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (device_class == vr::TrackedDeviceClass_Controller) {
|
||||||
|
if (!controllers[i]) {
|
||||||
|
controllers[i] = std::make_shared<controller_info>();
|
||||||
|
|
||||||
|
vr::ETrackedControllerRole role = (vr::ETrackedControllerRole)vr_system->GetInt32TrackedDeviceProperty(i, vr::Prop_ControllerRoleHint_Int32);
|
||||||
|
if (role == vr::TrackedControllerRole_LeftHand)
|
||||||
|
controllers[i]->inputhandle = inputhandle_left;
|
||||||
|
else if (role == vr::TrackedControllerRole_RightHand)
|
||||||
|
controllers[i]->inputhandle = inputhandle_right;
|
||||||
|
|
||||||
|
char model_name[128];
|
||||||
|
size_t ret = vr_system->GetStringTrackedDeviceProperty(i, vr::Prop_RenderModelName_String, model_name, sizeof(model_name));
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
controllers[i]->rendermodel = std::string(model_name);
|
||||||
|
|
||||||
|
uint32_t component_count = vr::VRRenderModels()->GetComponentCount(model_name);
|
||||||
|
if (component_count == 0 || !controllers[i]->inputhandle) {
|
||||||
|
controllers[i]->pending_components.push_back(-1);
|
||||||
|
} else {
|
||||||
|
for (size_t c = 0; c < component_count; c++)
|
||||||
|
controllers[i]->pending_components.push_back(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
controllers[i]->model = std::make_unique<TModel3d>();
|
||||||
|
controllers[i]->model->AppendChildFromGeometry("__root", "none", gfx::vertex_array());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t c = controllers[i]->pending_components.size(); c-- != 0;) {
|
||||||
|
uint32_t component = controllers[i]->pending_components[c];
|
||||||
|
const char *rendermodel = controllers[i]->rendermodel.c_str();
|
||||||
|
|
||||||
|
char rendermodel_name[256];
|
||||||
|
char component_name[128];
|
||||||
|
|
||||||
|
gfx::vertex_array data;
|
||||||
|
std::string submodel_name;
|
||||||
|
vr::RenderModel_t *model;
|
||||||
|
vr::EVRRenderModelError ret;
|
||||||
|
TSubModel *sm;
|
||||||
|
|
||||||
|
if (component == -1) {
|
||||||
|
const char *name = controllers[i]->rendermodel.c_str();
|
||||||
|
strncpy(rendermodel_name, name, sizeof(rendermodel_name) - 1);
|
||||||
|
rendermodel_name[255] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
vr::VRRenderModels()->GetComponentName(rendermodel, component, component_name, sizeof(component_name));
|
||||||
|
if (!vr::VRRenderModels()->GetComponentRenderModelName(rendermodel, component_name, rendermodel_name, sizeof(rendermodel_name)))
|
||||||
|
goto component_done;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = vr::VRRenderModels()->LoadRenderModel_Async(rendermodel_name, &model);
|
||||||
|
|
||||||
|
if (ret == vr::VRRenderModelError_Loading)
|
||||||
|
continue;
|
||||||
|
else if (ret != vr::VRRenderModelError_None)
|
||||||
|
goto component_done;
|
||||||
|
|
||||||
|
data.resize(model->unTriangleCount * 3);
|
||||||
|
|
||||||
|
for (size_t v = 0; v < model->unTriangleCount * 3; v++) {
|
||||||
|
const vr::RenderModel_Vertex_t *vertex = &model->rVertexData[model->rIndexData[v]];
|
||||||
|
data[v] = gfx::basic_vertex(
|
||||||
|
glm::vec3(vertex->vPosition.v[0], vertex->vPosition.v[1], vertex->vPosition.v[2]),
|
||||||
|
glm::vec3(vertex->vNormal.v[0], vertex->vNormal.v[1], vertex->vNormal.v[2]),
|
||||||
|
glm::vec2(vertex->rfTextureCoord[0], vertex->rfTextureCoord[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
submodel_name = std::string(component == -1 ? rendermodel_name : component_name);
|
||||||
|
sm = controllers[i]->model->AppendChildFromGeometry(submodel_name, "__root", data);
|
||||||
|
|
||||||
|
if (model->diffuseTextureId >= 0)
|
||||||
|
controllers[i]->pending_textures.push_back(std::make_pair(sm, model->diffuseTextureId));
|
||||||
|
|
||||||
|
vr::VRRenderModels()->FreeRenderModel(model);
|
||||||
|
|
||||||
|
if (component != -1 && update_component(controllers[i]->rendermodel, controllers[i]->inputhandle, sm))
|
||||||
|
controllers[i]->active_components.push_back(sm);
|
||||||
|
|
||||||
|
component_done:
|
||||||
|
controllers[i]->pending_components.erase(controllers[i]->pending_components.begin() + c);
|
||||||
|
|
||||||
|
if (controllers[i]->pending_components.empty())
|
||||||
|
controllers[i]->model->Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t t = controllers[i]->pending_textures.size(); t-- != 0;) {
|
||||||
|
TSubModel *sm = controllers[i]->pending_textures[t].first;
|
||||||
|
const vr::TextureID_t texture_id = controllers[i]->pending_textures[t].second;
|
||||||
|
|
||||||
|
if (GfxRenderer.Material(sm->GetMaterial()).textures[0] == null_handle)
|
||||||
|
sm->ReplaceMaterial("internal_src:OPENVR" + std::to_string(texture_id));
|
||||||
|
opengl_texture &tex = GfxRenderer.Texture(GfxRenderer.Material(sm->GetMaterial()).textures[0]);
|
||||||
|
|
||||||
|
if (tex.is_stub()) {
|
||||||
|
vr::RenderModel_TextureMap_t *texturemap;
|
||||||
|
auto ret = vr::VRRenderModels()->LoadTexture_Async(texture_id, &texturemap);
|
||||||
|
|
||||||
|
if (ret == vr::VRRenderModelError_Loading)
|
||||||
|
continue;
|
||||||
|
else if (ret != vr::VRRenderModelError_None)
|
||||||
|
goto texture_done;
|
||||||
|
|
||||||
|
if (texturemap->format == vr::VRRenderModelTextureFormat_RGBA8_SRGB)
|
||||||
|
tex.make_from_memory(texturemap->unWidth, texturemap->unHeight, texturemap->rubTextureMapData);
|
||||||
|
else
|
||||||
|
ErrorLog("openvr texture format " + std::to_string(texturemap->format) + " not supported");
|
||||||
|
|
||||||
|
vr::VRRenderModels()->FreeTexture(texturemap);
|
||||||
|
}
|
||||||
|
|
||||||
|
texture_done:
|
||||||
|
controllers[i]->pending_textures.erase(controllers[i]->pending_textures.begin() + t);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (controllers[i]->model) {
|
||||||
|
glm::vec3 trans = glm::vec3(device_pose[3]);
|
||||||
|
glm::mat3 rot = glm::mat3(device_pose);
|
||||||
|
trans -= Global.viewport_move;
|
||||||
|
|
||||||
|
controllers[i]->model->GetSMRoot()->ReplaceMatrix(glm::translate(glm::mat4(), trans) * glm::mat4(rot));
|
||||||
|
|
||||||
|
for (TSubModel *component : controllers[i]->active_components)
|
||||||
|
update_component(controllers[i]->rendermodel, controllers[i]->inputhandle, component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vr::VRActiveActionSet_t active_actionset;
|
||||||
|
active_actionset.ulActionSet = actionset;
|
||||||
|
active_actionset.ulRestrictedToDevice = vr::k_ulInvalidInputValueHandle;
|
||||||
|
active_actionset.nPriority = 0;
|
||||||
|
|
||||||
|
vr::VRInput()->UpdateActionState(&active_actionset, sizeof(active_actionset), 1);
|
||||||
|
|
||||||
|
vr::InputDigitalActionData_t actiondata;
|
||||||
|
vr::VRInput()->GetDigitalActionData(primary_action, &actiondata, sizeof(actiondata), vr::k_ulInvalidInputValueHandle);
|
||||||
|
if (actiondata.bChanged && actiondata.bState) {
|
||||||
|
WriteLog("VR click!");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool prev_should_pause = should_pause;
|
||||||
|
should_pause = vr_system->ShouldApplicationPause();
|
||||||
|
if (prev_should_pause != should_pause)
|
||||||
|
relay.post(user_command::focuspauseset, should_pause ? 1.0 : 0.0, 0.0, GLFW_PRESS, 0);
|
||||||
|
|
||||||
|
draw_controllers = !vr_system->IsSteamVRDrawingControllers();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool vr_openvr::update_component(const std::string &rendermodel, vr::VRInputValueHandle_t handle, TSubModel *component)
|
||||||
|
{
|
||||||
|
vr::RenderModel_ControllerMode_State_t state;
|
||||||
|
state.bScrollWheelVisible = false;
|
||||||
|
|
||||||
|
vr::RenderModel_ComponentState_t component_state;
|
||||||
|
|
||||||
|
vr::VRRenderModels()->GetComponentStateForDevicePath(rendermodel.c_str(), component->pName.c_str(), handle, &state, &component_state);
|
||||||
|
|
||||||
|
glm::mat4 component_pose = get_matrix(component_state.mTrackingToComponentRenderModel);
|
||||||
|
bool visible = (component_state.uProperties & vr::VRComponentProperty_IsVisible);
|
||||||
|
|
||||||
|
component->ReplaceMatrix(component_pose);
|
||||||
|
component->iVisible = (visible ? 1 : 0);
|
||||||
|
|
||||||
|
return !(component_state.uProperties & vr::VRComponentProperty_IsStatic);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vr_openvr::submit(vr_openvr::eye_e eye, opengl_texture* tex)
|
||||||
|
{
|
||||||
|
vr::Texture_t hmd_tex =
|
||||||
|
{ (void*)(uint64_t)tex->id,
|
||||||
|
vr::TextureType_OpenGL,
|
||||||
|
Global.gfx_shadergamma ? vr::ColorSpace_Linear : vr::ColorSpace_Gamma };
|
||||||
|
|
||||||
|
vr::VRCompositor()->Submit(eye == vr_interface::eye_left ? vr::Eye_Left : vr::Eye_Right, &hmd_tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<TModel3d*> vr_openvr::get_render_models()
|
||||||
|
{
|
||||||
|
std::vector<TModel3d*> list;
|
||||||
|
|
||||||
|
if (!draw_controllers)
|
||||||
|
return list;
|
||||||
|
|
||||||
|
for (auto entry : controllers)
|
||||||
|
{
|
||||||
|
if (entry && entry->model && entry->pending_components.empty())
|
||||||
|
list.push_back(entry->model.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vr_openvr::finish_frame()
|
||||||
|
{
|
||||||
|
vr::VRCompositor()->PostPresentHandoff();
|
||||||
|
}
|
||||||
|
|
||||||
|
vr_openvr::~vr_openvr()
|
||||||
|
{
|
||||||
|
vr::VR_Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<vr_interface> vr_openvr::create_func()
|
||||||
|
{
|
||||||
|
return std::unique_ptr<vr_interface>(new vr_openvr());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool vr_openvr::backend_register = vr_interface_factory::get_instance()->register_backend("openvr", vr_openvr::create_func);
|
||||||
|
|
||||||
49
vr/openvr_imp.h
Normal file
49
vr/openvr_imp.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "vr_interface.h"
|
||||||
|
#include <openvr/openvr.h>
|
||||||
|
|
||||||
|
class vr_openvr : vr_interface
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
struct controller_info {
|
||||||
|
std::unique_ptr<TModel3d> model;
|
||||||
|
std::string rendermodel;
|
||||||
|
std::vector<uint32_t> pending_components;
|
||||||
|
std::vector<TSubModel*> active_components;
|
||||||
|
std::vector<std::pair<TSubModel*, vr::TextureID_t>> pending_textures;
|
||||||
|
vr::VRInputValueHandle_t inputhandle = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const size_t MAX_DEVICES = 16;
|
||||||
|
|
||||||
|
vr::IVRSystem *vr_system = nullptr;
|
||||||
|
std::array<std::shared_ptr<controller_info>, MAX_DEVICES> controllers;
|
||||||
|
std::unordered_map<vr::TextureID_t, std::shared_ptr<opengl_texture>> textures;
|
||||||
|
vr::VRInputValueHandle_t inputhandle_left = 0;
|
||||||
|
vr::VRInputValueHandle_t inputhandle_right = 0;
|
||||||
|
|
||||||
|
bool update_component(const std::string &rendermodel, vr::VRInputValueHandle_t handle, TSubModel *component);
|
||||||
|
glm::mat4 get_matrix(vr::HmdMatrix34_t &src);
|
||||||
|
|
||||||
|
vr::VRActionSetHandle_t actionset = 0;
|
||||||
|
vr::VRActionHandle_t primary_action = 0;
|
||||||
|
bool should_pause = false;
|
||||||
|
bool draw_controllers = true;
|
||||||
|
|
||||||
|
command_relay relay;
|
||||||
|
|
||||||
|
public:
|
||||||
|
vr_openvr();
|
||||||
|
viewport_proj_config get_proj_config(eye_e) override;
|
||||||
|
glm::ivec2 get_target_size() override;
|
||||||
|
void begin_frame() override;
|
||||||
|
void submit(eye_e, opengl_texture*) override;
|
||||||
|
std::vector<TModel3d*> get_render_models() override;
|
||||||
|
void finish_frame() override;
|
||||||
|
~vr_openvr() override;
|
||||||
|
|
||||||
|
static std::unique_ptr<vr_interface> create_func();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool backend_register;
|
||||||
|
};
|
||||||
31
vr/vr_interface.cpp
Normal file
31
vr/vr_interface.cpp
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "vr_interface.h"
|
||||||
|
#include "Logs.h"
|
||||||
|
|
||||||
|
vr_interface::~vr_interface() {}
|
||||||
|
|
||||||
|
bool vr_interface_factory::register_backend(const std::string &backend, vr_interface_factory::create_method func)
|
||||||
|
{
|
||||||
|
backends[backend] = func;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<vr_interface> vr_interface_factory::create(const std::string &backend)
|
||||||
|
{
|
||||||
|
auto it = backends.find(backend);
|
||||||
|
if (it != backends.end())
|
||||||
|
return it->second();
|
||||||
|
|
||||||
|
ErrorLog("vr backend \"" + backend + "\" not found!");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
vr_interface_factory *vr_interface_factory::get_instance()
|
||||||
|
{
|
||||||
|
if (!instance)
|
||||||
|
instance = new vr_interface_factory();
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
vr_interface_factory *vr_interface_factory::instance;
|
||||||
36
vr/vr_interface.h
Normal file
36
vr/vr_interface.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Camera.h"
|
||||||
|
#include "Model3d.h"
|
||||||
|
#include "Texture.h"
|
||||||
|
|
||||||
|
class vr_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum eye_e {
|
||||||
|
eye_left,
|
||||||
|
eye_right
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual viewport_proj_config get_proj_config(eye_e) = 0;
|
||||||
|
virtual glm::ivec2 get_target_size() = 0;
|
||||||
|
virtual void begin_frame() = 0;
|
||||||
|
virtual void submit(eye_e, opengl_texture*) = 0;
|
||||||
|
virtual std::vector<TModel3d*> get_render_models() = 0;
|
||||||
|
virtual void finish_frame() = 0;
|
||||||
|
virtual ~vr_interface() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class vr_interface_factory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using create_method = std::unique_ptr<vr_interface>(*)();
|
||||||
|
|
||||||
|
bool register_backend(const std::string &backend, create_method func);
|
||||||
|
std::unique_ptr<vr_interface> create(const std::string &name);
|
||||||
|
|
||||||
|
static vr_interface_factory* get_instance();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<std::string, create_method> backends;
|
||||||
|
static vr_interface_factory *instance;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user