add openvr support, switch to 8.1 sdk, prepare for vr ui
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -40,3 +40,6 @@
|
|||||||
[submodule "libs/sqlite3"]
|
[submodule "libs/sqlite3"]
|
||||||
path = libs/sqlite3
|
path = libs/sqlite3
|
||||||
url = https://bitbucket.org/omigamedev/sqlite3.git
|
url = https://bitbucket.org/omigamedev/sqlite3.git
|
||||||
|
[submodule "libs/openvr"]
|
||||||
|
path = libs/openvr
|
||||||
|
url = https://github.com/ValveSoftware/openvr.git
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
<ProjectGuid>{6D5028CE-4D76-4B6A-A7C2-DE5A3268D433}</ProjectGuid>
|
<ProjectGuid>{6D5028CE-4D76-4B6A-A7C2-DE5A3268D433}</ProjectGuid>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
<RootNamespace>PanoPainter</RootNamespace>
|
<RootNamespace>PanoPainter</RootNamespace>
|
||||||
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||||
<ProjectName>PanoPainter</ProjectName>
|
<ProjectName>PanoPainter</ProjectName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
@@ -77,8 +77,8 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<LinkIncremental>true</LinkIncremental>
|
<LinkIncremental>true</LinkIncremental>
|
||||||
<IncludePath>libs\glm;libs\glew-2.0.0\include;libs\stb;libs\tinyxml2;libs\yoga;libs\curl-win\include;libs\jpeg;libs\wacom;libs\bugtrap-client\include;libs\poly2tri\poly2tri;libs\base64;libs\sqlite3;$(IncludePath)</IncludePath>
|
<IncludePath>libs\glm;libs\glew-2.0.0\include;libs\stb;libs\tinyxml2;libs\yoga;libs\curl-win\include;libs\jpeg;libs\wacom;libs\bugtrap-client\include;libs\poly2tri\poly2tri;libs\base64;libs\sqlite3;libs\openvr\headers;$(IncludePath)</IncludePath>
|
||||||
<LibraryPath>libs\curl-win\lib\dll-$(Configuration)-$(PlatformShortName);libs\glew-2.0.0\lib\Release\$(Platform);libs\bugtrap-client\lib;$(LibraryPath)</LibraryPath>
|
<LibraryPath>libs\curl-win\lib\dll-$(Configuration)-$(PlatformShortName);libs\glew-2.0.0\lib\Release\$(Platform);libs\bugtrap-client\lib;libs\openvr\lib\win64;$(LibraryPath)</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
@@ -87,8 +87,8 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
<IncludePath>libs\glm;libs\glew-2.0.0\include;libs\stb;libs\tinyxml2;libs\yoga;libs\curl-win\include;libs\jpeg;libs\wacom;libs\bugtrap-client\include;libs\poly2tri\poly2tri;libs\base64;libs\sqlite3;$(IncludePath)</IncludePath>
|
<IncludePath>libs\glm;libs\glew-2.0.0\include;libs\stb;libs\tinyxml2;libs\yoga;libs\curl-win\include;libs\jpeg;libs\wacom;libs\bugtrap-client\include;libs\poly2tri\poly2tri;libs\base64;libs\sqlite3;libs\openvr\headers;$(IncludePath)</IncludePath>
|
||||||
<LibraryPath>libs\curl-win\lib\dll-$(Configuration)-$(PlatformShortName);libs\glew-2.0.0\lib\Release\$(Platform);libs\bugtrap-client\lib;$(LibraryPath)</LibraryPath>
|
<LibraryPath>libs\curl-win\lib\dll-$(Configuration)-$(PlatformShortName);libs\glew-2.0.0\lib\Release\$(Platform);libs\bugtrap-client\lib;libs\openvr\lib\win64;$(LibraryPath)</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@@ -179,6 +179,7 @@
|
|||||||
<ClCompile Include="src\app_events.cpp" />
|
<ClCompile Include="src\app_events.cpp" />
|
||||||
<ClCompile Include="src\app_layout.cpp" />
|
<ClCompile Include="src\app_layout.cpp" />
|
||||||
<ClCompile Include="src\app_shaders.cpp" />
|
<ClCompile Include="src\app_shaders.cpp" />
|
||||||
|
<ClCompile Include="src\app_vr.cpp" />
|
||||||
<ClCompile Include="src\asset.cpp" />
|
<ClCompile Include="src\asset.cpp" />
|
||||||
<ClCompile Include="src\bezier.cpp" />
|
<ClCompile Include="src\bezier.cpp" />
|
||||||
<ClCompile Include="src\brush.cpp" />
|
<ClCompile Include="src\brush.cpp" />
|
||||||
@@ -186,6 +187,7 @@
|
|||||||
<ClCompile Include="src\canvas_modes.cpp" />
|
<ClCompile Include="src\canvas_modes.cpp" />
|
||||||
<ClCompile Include="src\event.cpp" />
|
<ClCompile Include="src\event.cpp" />
|
||||||
<ClCompile Include="src\font.cpp" />
|
<ClCompile Include="src\font.cpp" />
|
||||||
|
<ClCompile Include="src\hmd.cpp" />
|
||||||
<ClCompile Include="src\image.cpp" />
|
<ClCompile Include="src\image.cpp" />
|
||||||
<ClCompile Include="src\layout.cpp" />
|
<ClCompile Include="src\layout.cpp" />
|
||||||
<ClCompile Include="src\log.cpp" />
|
<ClCompile Include="src\log.cpp" />
|
||||||
@@ -307,6 +309,7 @@
|
|||||||
<ClInclude Include="src\canvas_modes.h" />
|
<ClInclude Include="src\canvas_modes.h" />
|
||||||
<ClInclude Include="src\event.h" />
|
<ClInclude Include="src\event.h" />
|
||||||
<ClInclude Include="src\font.h" />
|
<ClInclude Include="src\font.h" />
|
||||||
|
<ClInclude Include="src\hmd.h" />
|
||||||
<ClInclude Include="src\image.h" />
|
<ClInclude Include="src\image.h" />
|
||||||
<ClInclude Include="src\keymap.h" />
|
<ClInclude Include="src\keymap.h" />
|
||||||
<ClInclude Include="src\layout.h" />
|
<ClInclude Include="src\layout.h" />
|
||||||
|
|||||||
@@ -270,6 +270,12 @@
|
|||||||
<ClCompile Include="libs\sqlite3\sqlite3.c">
|
<ClCompile Include="libs\sqlite3\sqlite3.c">
|
||||||
<Filter>libs\sqlite3</Filter>
|
<Filter>libs\sqlite3</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\hmd.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\app_vr.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="src\app.h">
|
<ClInclude Include="src\app.h">
|
||||||
@@ -485,6 +491,9 @@
|
|||||||
<ClInclude Include="libs\sqlite3\sqlite3ext.h">
|
<ClInclude Include="libs\sqlite3\sqlite3ext.h">
|
||||||
<Filter>libs\sqlite3</Filter>
|
<Filter>libs\sqlite3</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\hmd.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="PanoPainter.rc">
|
<ResourceCompile Include="PanoPainter.rc">
|
||||||
|
|||||||
@@ -125,9 +125,9 @@
|
|||||||
<Content Include="Images\Wide310x150Logo.scale-200.png" />
|
<Content Include="Images\Wide310x150Logo.scale-200.png" />
|
||||||
<Content Include="Images\Wide310x150Logo.scale-400.png" />
|
<Content Include="Images\Wide310x150Logo.scale-400.png" />
|
||||||
<Content Include="$(SolutionDir)libs\curl-win\lib\dll-release-x64\libcurl.dll" />
|
<Content Include="$(SolutionDir)libs\curl-win\lib\dll-release-x64\libcurl.dll" />
|
||||||
<Content Include="$(SolutionDir)libs\curl-win\lib\dll-debug-x64\libcurl_debug.dll" />
|
|
||||||
<Content Include="$(SolutionDir)libs\bugtrap-client\lib\BugTrapU-x64.dll" />
|
<Content Include="$(SolutionDir)libs\bugtrap-client\lib\BugTrapU-x64.dll" />
|
||||||
<Content Include="$(SolutionDir)libs\glew-2.0.0\bin\Release\x64\glew32.dll" />
|
<Content Include="$(SolutionDir)libs\glew-2.0.0\bin\Release\x64\glew32.dll" />
|
||||||
|
<Content Include="$(SolutionDir)libs\openvr\bin\win64\openvr_api.dll" />
|
||||||
<Content Include="$(SolutionDir)data\**">
|
<Content Include="$(SolutionDir)data\**">
|
||||||
<Link>PanoPainter\data\%(RecursiveDir)%(FileName)%(Extension)</Link>
|
<Link>PanoPainter\data\%(RecursiveDir)%(FileName)%(Extension)</Link>
|
||||||
</Content>
|
</Content>
|
||||||
|
|||||||
@@ -969,11 +969,9 @@ Here's a list of what's available in this release.
|
|||||||
|
|
||||||
<!--main-->
|
<!--main-->
|
||||||
<layout id="main">
|
<layout id="main">
|
||||||
|
<canvas id="paint-canvas" positioning="absolute" width="100%" height="100%" grow="1"/>
|
||||||
<node dir="col" wrap="0" width="100%" height="100%" pad="0">
|
<node dir="col" wrap="0" width="100%" height="100%" pad="0">
|
||||||
<!-- content panel -->
|
<!-- content panel -->
|
||||||
<node positioning="absolute" width="100%" height="100%" grow="1" color=".1" pad="0">
|
|
||||||
<canvas id="paint-canvas" grow="1"/>
|
|
||||||
</node>
|
|
||||||
<!-- menu bar -->
|
<!-- menu bar -->
|
||||||
<border flood-events="1" margin="0 0 0 0" pad="0 0 0 0" color=".1" width="100%" height="30" dir="row" align="center">
|
<border flood-events="1" margin="0 0 0 0" pad="0 0 0 0" color=".1" width="100%" height="30" dir="row" align="center">
|
||||||
<!--
|
<!--
|
||||||
|
|||||||
1
libs/openvr
Submodule
1
libs/openvr
Submodule
Submodule libs/openvr added at 1fb1030f2a
13
src/app.cpp
13
src/app.cpp
@@ -113,6 +113,9 @@ void App::initAssets()
|
|||||||
|
|
||||||
LOG("initializing assets create sampler");
|
LOG("initializing assets create sampler");
|
||||||
sampler.create(GL_NEAREST);
|
sampler.create(GL_NEAREST);
|
||||||
|
sampler_stencil.create(GL_LINEAR, GL_REPEAT);
|
||||||
|
sampler_linear.create(GL_LINEAR);
|
||||||
|
m_face_plane.create<1>(2, 2);
|
||||||
LOG("initializing assets load uvs texture");
|
LOG("initializing assets load uvs texture");
|
||||||
LOG("initializing assets completed");
|
LOG("initializing assets completed");
|
||||||
}
|
}
|
||||||
@@ -235,12 +238,13 @@ void App::download(std::string url, std::string dest_filepath, std::function<voi
|
|||||||
|
|
||||||
bool App::check_license()
|
bool App::check_license()
|
||||||
{
|
{
|
||||||
// return true; // TODO: for distribuiton only
|
return true; // TODO: for distribuiton only
|
||||||
|
|
||||||
|
/*
|
||||||
CURL *curl = curl_easy_init();
|
CURL *curl = curl_easy_init();
|
||||||
if (curl)
|
if (curl)
|
||||||
{
|
{
|
||||||
std::string url = "http://panopainter.com/license/53C5DE19-7B8F-42B8-8399-C99D28B66401.php";
|
std::string url = "https://panopainter.com/license/53C5DE19-7B8F-42B8-8399-C99D28B66401.php";
|
||||||
//std::string url = "https://panopainter.com/license/E8EDC2FE-E1BD-4AB1-91BD-FCCD926739BD.php"; // wacom
|
//std::string url = "https://panopainter.com/license/E8EDC2FE-E1BD-4AB1-91BD-FCCD926739BD.php"; // wacom
|
||||||
//std::string url = "https://panopainter.com/license/A744FBA9-BC6C-43C8-BD24-0CCE24B3D985.php"; // others
|
//std::string url = "https://panopainter.com/license/A744FBA9-BC6C-43C8-BD24-0CCE24B3D985.php"; // others
|
||||||
|
|
||||||
@@ -260,10 +264,11 @@ bool App::check_license()
|
|||||||
curl_easy_cleanup(curl);
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
LOG("License check: %s", ret.c_str());
|
LOG("License check: %s", ret.c_str());
|
||||||
if (err == CURLcode::CURLE_OK)
|
if (err == CURLcode::CURLE_OK && ret == "success")
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::upload(std::string filename, std::string name, std::function<void(float)> progress)
|
void App::upload(std::string filename, std::string name, std::function<void(float)> progress)
|
||||||
@@ -343,7 +348,7 @@ void App::init()
|
|||||||
for (int i = 0; i < n_exts; i++)
|
for (int i = 0; i < n_exts; i++)
|
||||||
{
|
{
|
||||||
std::string ext = (const char*)glGetStringi(GL_EXTENSIONS, i);
|
std::string ext = (const char*)glGetStringi(GL_EXTENSIONS, i);
|
||||||
if (ext.find("debug") != std::string::npos)
|
//if (ext.find("debug") != std::string::npos)
|
||||||
{
|
{
|
||||||
LOG("%s", glGetStringi(GL_EXTENSIONS, i));
|
LOG("%s", glGetStringi(GL_EXTENSIONS, i));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
#include "layout.h"
|
#include "layout.h"
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
|
#include "rtt.h"
|
||||||
#include "node_message_box.h"
|
#include "node_message_box.h"
|
||||||
#include "node_settings.h"
|
#include "node_settings.h"
|
||||||
#include "node_popup_menu.h"
|
#include "node_popup_menu.h"
|
||||||
@@ -46,7 +47,11 @@ public:
|
|||||||
std::condition_variable rec_cv;
|
std::condition_variable rec_cv;
|
||||||
std::deque<std::unique_ptr<uint8_t[]>> rec_frames;
|
std::deque<std::unique_ptr<uint8_t[]>> rec_frames;
|
||||||
|
|
||||||
|
RTT uirtt;
|
||||||
Sampler sampler;
|
Sampler sampler;
|
||||||
|
Sampler sampler_stencil;
|
||||||
|
Sampler sampler_linear;
|
||||||
|
ui::Plane m_face_plane;
|
||||||
LayoutManager layout;
|
LayoutManager layout;
|
||||||
NodeMessageBox* msgbox;
|
NodeMessageBox* msgbox;
|
||||||
NodeSettings* settings;
|
NodeSettings* settings;
|
||||||
@@ -116,6 +121,7 @@ public:
|
|||||||
void clear();
|
void clear();
|
||||||
void tick(float dt);
|
void tick(float dt);
|
||||||
void update(float dt);
|
void update(float dt);
|
||||||
|
void vr_draw(const glm::mat4& proj, const glm::mat4& view);
|
||||||
void async_start();
|
void async_start();
|
||||||
void async_update();
|
void async_update();
|
||||||
void async_redraw();
|
void async_redraw();
|
||||||
|
|||||||
@@ -298,8 +298,8 @@ bool App::key_char(char key)
|
|||||||
void App::toggle_ui()
|
void App::toggle_ui()
|
||||||
{
|
{
|
||||||
static bool fullscreen = false;
|
static bool fullscreen = false;
|
||||||
auto m = layout[main_id]->m_children[0];
|
auto m = layout[main_id]->m_children[1];
|
||||||
for (int i = 2; i < m->m_children.size(); i++)
|
for (int i = 1; i < m->m_children.size(); i++)
|
||||||
m->m_children[i]->m_display = fullscreen;
|
m->m_children[i]->m_display = fullscreen;
|
||||||
fullscreen = !fullscreen;
|
fullscreen = !fullscreen;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -374,7 +374,7 @@ void App::initShaders()
|
|||||||
" fg.rgb = mix(fg.rgb, mbg.rgb, mix_alpha * mbg.a);\n"
|
" fg.rgb = mix(fg.rgb, mbg.rgb, mix_alpha * mbg.a);\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" mediump float contribution = (1.0 - bg.a) * fg.a;\n"
|
" mediump float contribution = (1.0 - bg.a) * fg.a;\n"
|
||||||
" mediump float alpha_tot = bg.a + contribution;"
|
" mediump float alpha_tot = bg.a + contribution;\n"
|
||||||
" mediump vec3 rgb = mix(bg.rgb, fg.rgb, fg.a / alpha_tot);\n"
|
" mediump vec3 rgb = mix(bg.rgb, fg.rgb, fg.a / alpha_tot);\n"
|
||||||
" mediump vec4 frag_wet = vec4(rgb, max(bg.a, fg.a * 1.2));\n"
|
" mediump vec4 frag_wet = vec4(rgb, max(bg.a, fg.a * 1.2));\n"
|
||||||
" mediump vec4 frag_dry = vec4(rgb, alpha_tot);\n"
|
" mediump vec4 frag_dry = vec4(rgb, alpha_tot);\n"
|
||||||
|
|||||||
105
src/app_vr.cpp
Normal file
105
src/app_vr.cpp
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "app.h"
|
||||||
|
|
||||||
|
void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera)
|
||||||
|
{
|
||||||
|
using namespace ui;
|
||||||
|
|
||||||
|
//glm::mat4 ortho_proj = glm::ortho(0.f, box.z, 0.f, box.w, -1000.f, 1000.f);
|
||||||
|
//glm::mat4 proj = glm::perspective(glm::radians(m_canvas->m_cam_fov), box.z / box.w, 0.01f, 1000.f);
|
||||||
|
//glm::mat4 camera = glm::eulerAngleXY(m_canvas->m_cam_rot.y, m_canvas->m_cam_rot.x) *
|
||||||
|
// glm::translate(m_canvas->m_cam_pos);
|
||||||
|
|
||||||
|
// auto plane_mvp = proj * camera * transform *
|
||||||
|
// glm::scale(glm::vec3(sz, 1));
|
||||||
|
|
||||||
|
|
||||||
|
sampler.bind(0);
|
||||||
|
sampler.bind(1);
|
||||||
|
sampler.bind(2);
|
||||||
|
sampler_stencil.bind(3);
|
||||||
|
auto blend = glIsEnabled(GL_BLEND);
|
||||||
|
auto depth = glIsEnabled(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
for (int plane_index = 0; plane_index < 6; plane_index++)
|
||||||
|
{
|
||||||
|
auto plane_mvp = proj * camera *
|
||||||
|
glm::scale(glm::vec3(canvas->m_canvas->m_order.size() + 500)) *
|
||||||
|
canvas->m_canvas->m_plane_transform[plane_index] *
|
||||||
|
glm::translate(glm::vec3(0, 0, -1));
|
||||||
|
|
||||||
|
ui::ShaderManager::use(kShader::Checkerboard);
|
||||||
|
ui::ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp);
|
||||||
|
m_face_plane.draw_fill();
|
||||||
|
}
|
||||||
|
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < canvas->m_canvas->m_order.size(); i++)
|
||||||
|
{
|
||||||
|
auto layer_index = canvas->m_canvas->m_order[i];
|
||||||
|
for (int plane_index = 0; plane_index < 6; plane_index++)
|
||||||
|
{
|
||||||
|
if (canvas->m_canvas->m_layers[layer_index].m_opacity == .0f)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int z = (int)(canvas->m_canvas->m_order.size() - i);
|
||||||
|
auto plane_mvp_z = proj * camera *
|
||||||
|
glm::scale(glm::vec3(z + 1)) *
|
||||||
|
//glm::eulerAngleYXZ(yaw, pitch, roll) *
|
||||||
|
canvas->m_canvas->m_plane_transform[plane_index] *
|
||||||
|
glm::translate(glm::vec3(0, 0, -1));
|
||||||
|
|
||||||
|
{
|
||||||
|
sampler.bind(0);
|
||||||
|
sampler_linear.bind(1);
|
||||||
|
ui::ShaderManager::use(kShader::TextureAlphaSep);
|
||||||
|
ui::ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||||
|
ui::ShaderManager::u_int(kShaderUniform::TexA, 1);
|
||||||
|
ui::ShaderManager::u_float(kShaderUniform::Alpha, canvas->m_canvas->m_layers[layer_index].m_opacity);
|
||||||
|
ui::ShaderManager::u_int(kShaderUniform::Highlight, canvas->m_canvas->m_layers[layer_index].m_hightlight);
|
||||||
|
ui::ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp_z);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
canvas->m_canvas->m_layers[layer_index].m_rtt[plane_index].bindTexture();
|
||||||
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
canvas->m_canvas->m_layers[layer_index].m_rtt[plane_index].bindTexture();
|
||||||
|
|
||||||
|
m_face_plane.draw_fill();
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
canvas->m_canvas->m_layers[layer_index].m_rtt[plane_index].unbindTexture();
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
canvas->m_canvas->m_layers[layer_index].m_rtt[plane_index].unbindTexture();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
for (auto& mode : *m_canvas->m_mode)
|
||||||
|
mode->on_Draw(ortho_proj, proj, camera);
|
||||||
|
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
if (m_canvas->m_smask_active)
|
||||||
|
{
|
||||||
|
m_canvas->modes[(int)Canvas::kCanvasMode::MaskFree][0]->on_Draw(ortho_proj, proj, camera);
|
||||||
|
m_canvas->modes[(int)Canvas::kCanvasMode::MaskLine][0]->on_Draw(ortho_proj, proj, camera);
|
||||||
|
}
|
||||||
|
|
||||||
|
// keep drawing the grids
|
||||||
|
if (m_canvas->m_state != ui::Canvas::kCanvasMode::Grid)
|
||||||
|
for (auto& mode : ui::Canvas::modes[(int)ui::Canvas::kCanvasMode::Grid])
|
||||||
|
mode->on_Draw(ortho_proj, proj, camera);
|
||||||
|
*/
|
||||||
|
|
||||||
|
blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
|
||||||
|
depth ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST);
|
||||||
|
sampler.unbind();
|
||||||
|
}
|
||||||
|
|
||||||
231
src/hmd.cpp
Normal file
231
src/hmd.cpp
Normal file
@@ -0,0 +1,231 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "hmd.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
Vive::Vive()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
controllers[i].active = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Vive::Initialize()
|
||||||
|
{
|
||||||
|
vr::EVRInitError error;
|
||||||
|
hmd = vr::VR_Init(&error, vr::EVRApplicationType::VRApplication_Scene);
|
||||||
|
if (error != vr::EVRInitError::VRInitError_None)
|
||||||
|
return false;
|
||||||
|
comp = vr::VRCompositor();
|
||||||
|
if (!comp)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
hmd->GetRecommendedRenderTargetSize(&eyeWidth, &eyeHeight);
|
||||||
|
LOG("Eye target resolution: %dx%d\n", eyeWidth, eyeHeight);
|
||||||
|
for (int eye = 0; eye < 2; ++eye)
|
||||||
|
{
|
||||||
|
eyes[eye].create(eyeWidth, eyeHeight);
|
||||||
|
eyes[eye].bindFramebuffer();
|
||||||
|
eyes[eye].clear({ 1, 0, 0, 1 });
|
||||||
|
eyes[eye].unbindFramebuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
int attempts = 50;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int nc = 0;
|
||||||
|
for (int nDevice = 0; nDevice < vr::k_unMaxTrackedDeviceCount; ++nDevice)
|
||||||
|
{
|
||||||
|
if (hmd->GetTrackedDeviceClass(nDevice) == vr::TrackedDeviceClass_HMD)
|
||||||
|
{
|
||||||
|
auto read_string = [nDevice, this](vr::ETrackedDeviceProperty p) -> std::string {
|
||||||
|
size_t len = hmd->GetStringTrackedDeviceProperty(nDevice, p, nullptr, 0);
|
||||||
|
std::string str(len, '\0');
|
||||||
|
hmd->GetStringTrackedDeviceProperty(nDevice, p, (char*)str.data(), len);
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
dev_tracksys = read_string(vr::Prop_TrackingSystemName_String);
|
||||||
|
dev_serial = read_string(vr::Prop_SerialNumber_String);
|
||||||
|
dev_model = read_string(vr::Prop_ModelNumber_String);
|
||||||
|
dev_manufacturer = read_string(vr::Prop_ManufacturerName_String);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
attempts--;
|
||||||
|
} while (attempts > 0 && dev_serial.empty());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vive::Terminate()
|
||||||
|
{
|
||||||
|
vr::VR_Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vive::ResetYaw()
|
||||||
|
{
|
||||||
|
yaw_offset = euler.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vive::Draw()
|
||||||
|
{
|
||||||
|
if (!(hmd && comp && comp_attempts < 10))
|
||||||
|
return;
|
||||||
|
|
||||||
|
vr::TrackedDevicePose_t poses[vr::k_unMaxTrackedDeviceCount];
|
||||||
|
comp->WaitGetPoses(poses, vr::k_unMaxTrackedDeviceCount, NULL, 0);
|
||||||
|
auto& hmdPose = poses[vr::k_unTrackedDeviceIndex_Hmd];
|
||||||
|
|
||||||
|
for (int eye = 0; eye < 2; ++eye)
|
||||||
|
{
|
||||||
|
eyes[eye].bindFramebuffer();
|
||||||
|
eyes[eye].clear(background);
|
||||||
|
glViewport(0, 0, eyes[eye].getWidth(), eyes[eye].getHeight());
|
||||||
|
|
||||||
|
// Get view and projection matrices
|
||||||
|
vr::HmdMatrix44_t p = hmd->GetProjectionMatrix((vr::EVREye)eye, 0.2f, 1000.f);
|
||||||
|
float eyeProj[4][4] = {
|
||||||
|
p.m[0][0], p.m[1][0], p.m[2][0], p.m[3][0],
|
||||||
|
p.m[0][1], p.m[1][1], p.m[2][1], p.m[3][1],
|
||||||
|
p.m[0][2], p.m[1][2], p.m[2][2], p.m[3][2],
|
||||||
|
p.m[0][3], p.m[1][3], p.m[2][3], p.m[3][3],
|
||||||
|
};
|
||||||
|
|
||||||
|
vr::HmdMatrix34_t e = hmd->GetEyeToHeadTransform((vr::EVREye)eye);
|
||||||
|
float eyePose[4][4] = {
|
||||||
|
e.m[0][0], e.m[1][0], e.m[2][0], 0,
|
||||||
|
e.m[0][1], e.m[1][1], e.m[2][1], 0,
|
||||||
|
e.m[0][2], e.m[1][2], e.m[2][2], 0,
|
||||||
|
e.m[0][3], e.m[1][3], e.m[2][3], 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
vr::HmdMatrix34_t h = hmdPose.mDeviceToAbsoluteTracking;
|
||||||
|
float hmdPose[4][4] = {
|
||||||
|
h.m[0][0], h.m[1][0], h.m[2][0], 0,
|
||||||
|
h.m[0][1], h.m[1][1], h.m[2][1], 0,
|
||||||
|
h.m[0][2], h.m[1][2], h.m[2][2], 0,
|
||||||
|
h.m[0][3], h.m[1][3], h.m[2][3], 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
auto mat_proj = glm::make_mat4((float*)eyeProj);
|
||||||
|
auto mat_pose = glm::inverse(glm::make_mat4((float*)hmdPose));
|
||||||
|
auto mat_eye = glm::inverse(glm::make_mat4((float*)eyePose));
|
||||||
|
|
||||||
|
proj[eye] = mat_proj;
|
||||||
|
view[eye] = mat_eye * mat_pose;
|
||||||
|
pose = glm::make_mat4((float*)hmdPose);
|
||||||
|
|
||||||
|
for (auto& c : controllers)
|
||||||
|
c.valid = false;
|
||||||
|
for (auto& c : trackers)
|
||||||
|
c.valid = false;
|
||||||
|
|
||||||
|
int nc = 0;
|
||||||
|
int nt = 0;
|
||||||
|
for (int nDevice = 0; nDevice < vr::k_unMaxTrackedDeviceCount; ++nDevice)
|
||||||
|
{
|
||||||
|
if (poses[nDevice].bPoseIsValid)
|
||||||
|
{
|
||||||
|
vr::HmdMatrix34_t p = poses[nDevice].mDeviceToAbsoluteTracking;
|
||||||
|
float mat[4][4] = {
|
||||||
|
p.m[0][0], p.m[1][0], p.m[2][0], 0,
|
||||||
|
p.m[0][1], p.m[1][1], p.m[2][1], 0,
|
||||||
|
p.m[0][2], p.m[1][2], p.m[2][2], 0,
|
||||||
|
p.m[0][3], p.m[1][3], p.m[2][3], 1,
|
||||||
|
};
|
||||||
|
switch (hmd->GetTrackedDeviceClass(nDevice))
|
||||||
|
{
|
||||||
|
case vr::TrackedDeviceClass_Controller:
|
||||||
|
{
|
||||||
|
vr::EVRInitError error;
|
||||||
|
vr::ETrackedControllerRole controllerRole = (vr::ETrackedControllerRole)
|
||||||
|
hmd->GetInt32TrackedDeviceProperty(nDevice, vr::ETrackedDeviceProperty::Prop_ControllerRoleHint_Int32);
|
||||||
|
|
||||||
|
auto& c = controllers[nc];
|
||||||
|
c.index = nc;
|
||||||
|
c.active = true;
|
||||||
|
c.valid = true;
|
||||||
|
hmd->GetControllerState(nDevice, &c.state, sizeof(vr::VRControllerState_t));
|
||||||
|
c.update(glm::make_mat4((float*)mat));
|
||||||
|
c.buttons_bits = c.state.ulButtonPressed;
|
||||||
|
c.role = controllerRole;
|
||||||
|
for (int axi = 0; axi < 5; axi++)
|
||||||
|
{
|
||||||
|
c.axis[axi].x = c.state.rAxis[axi].x;
|
||||||
|
c.axis[axi].y = c.state.rAxis[axi].y;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto btn = c.state.ulButtonPressed;
|
||||||
|
for (auto b : { Controller::Button::Trigger, Controller::Button::Grip })
|
||||||
|
{
|
||||||
|
if ((btn & (uint64_t)b) != 0 && !c.buttons[(uint64_t)b])
|
||||||
|
{
|
||||||
|
c.buttons[(uint64_t)b] = true;
|
||||||
|
if (on_button)
|
||||||
|
on_button(c, b, Controller::Action::Press);
|
||||||
|
}
|
||||||
|
if ((btn & (uint64_t)b) == 0 && c.buttons[(uint64_t)b])
|
||||||
|
{
|
||||||
|
c.buttons[(uint64_t)b] = false;
|
||||||
|
if (on_button)
|
||||||
|
on_button(c, b, Controller::Action::Release);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nc++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case vr::TrackedDeviceClass_HMD:
|
||||||
|
break;
|
||||||
|
case vr::TrackedDeviceClass_Invalid:
|
||||||
|
break;
|
||||||
|
case vr::TrackedDeviceClass_GenericTracker:
|
||||||
|
{
|
||||||
|
auto& c = trackers[nt];
|
||||||
|
c.index = nt;
|
||||||
|
c.active = true;
|
||||||
|
c.valid = true;
|
||||||
|
c.update(glm::make_mat4((float*)mat));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case vr::TrackedDeviceClass_TrackingReference:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nc > 1 && swap_controllers)
|
||||||
|
{
|
||||||
|
std::swap(controllers[0], controllers[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (on_draw)
|
||||||
|
on_draw(proj[eye], view[eye]);
|
||||||
|
|
||||||
|
eyes[eye].unbindFramebuffer();
|
||||||
|
}
|
||||||
|
vr::Texture_t eyeTexture0 = { (void*)eyes[0].getTextureID(), vr::ETextureType::TextureType_OpenGL, vr::ColorSpace_Linear };
|
||||||
|
if (auto err = comp->Submit(vr::EVREye::Eye_Left, &eyeTexture0) != vr::EVRCompositorError::VRCompositorError_None)
|
||||||
|
{
|
||||||
|
LOG("Compositor error %d", err);
|
||||||
|
comp_attempts++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vr::Texture_t eyeTexture1 = { (void*)eyes[1].getTextureID(), vr::ETextureType::TextureType_OpenGL, vr::ColorSpace_Linear };
|
||||||
|
if (auto err = comp->Submit(vr::EVREye::Eye_Right, &eyeTexture1) != vr::EVRCompositorError::VRCompositorError_None)
|
||||||
|
{
|
||||||
|
LOG("Compositor error %d", err);
|
||||||
|
comp_attempts++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
comp_attempts = 0;
|
||||||
|
|
||||||
|
glFlush();
|
||||||
|
// glFinish();
|
||||||
|
// glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Vive::Valid()
|
||||||
|
{
|
||||||
|
return comp && comp_attempts < 10;
|
||||||
|
}
|
||||||
73
src/hmd.h
Normal file
73
src/hmd.h
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "rtt.h"
|
||||||
|
|
||||||
|
struct Controller
|
||||||
|
{
|
||||||
|
enum class Button : uint64_t
|
||||||
|
{
|
||||||
|
Trigger = 0x200000000,
|
||||||
|
Pad = 0x100000000,
|
||||||
|
Menu = 0x000000002,
|
||||||
|
Grip = 0x000000004,
|
||||||
|
};
|
||||||
|
enum class Action
|
||||||
|
{
|
||||||
|
Press,
|
||||||
|
Release,
|
||||||
|
};
|
||||||
|
int index = 0;
|
||||||
|
bool active = false;
|
||||||
|
std::map<uint64_t, bool> buttons;
|
||||||
|
uint64_t buttons_bits{ 0 };
|
||||||
|
glm::vec2 axis[5];
|
||||||
|
glm::mat4 xform{ 1 };
|
||||||
|
glm::vec3 pos{ 0 };
|
||||||
|
glm::vec3 rot{ 0 };
|
||||||
|
vr::VRControllerState_t state;
|
||||||
|
bool valid = false;
|
||||||
|
int role = 0;
|
||||||
|
|
||||||
|
void update(const glm::mat4& m)
|
||||||
|
{
|
||||||
|
xform = m;
|
||||||
|
pos = glm::vec3(m[3]);
|
||||||
|
//float sx = glm::length(glm::vec3(m[0]));
|
||||||
|
//float sy = glm::length(glm::vec3(m[1]));
|
||||||
|
//float sz = glm::length(glm::vec3(m[2]));
|
||||||
|
glm::extractEulerAngleXYZ(m, rot.x, rot.y, rot.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Vive
|
||||||
|
{
|
||||||
|
int comp_attempts = 0;
|
||||||
|
uint32_t eyeWidth = 0, eyeHeight = 0;
|
||||||
|
RTT eyes[2];
|
||||||
|
vr::IVRSystem* hmd = nullptr;
|
||||||
|
vr::IVRCompositor* comp = nullptr;
|
||||||
|
glm::vec3 euler{ 0 };
|
||||||
|
glm::vec4 background{ .5, .2, .2, 1 };
|
||||||
|
float yaw_offset = 0;
|
||||||
|
glm::mat4 view[2];
|
||||||
|
glm::mat4 proj[2];
|
||||||
|
glm::mat4 pose;
|
||||||
|
Controller controllers[32];
|
||||||
|
Controller trackers[32];
|
||||||
|
bool swap_controllers = false;
|
||||||
|
std::string dev_serial{ "0000001" };
|
||||||
|
std::string dev_model{ "Vive" };
|
||||||
|
std::string dev_tracksys{ "lighthouse" };
|
||||||
|
std::string dev_manufacturer{ "HTC" };
|
||||||
|
std::function<void(const glm::mat4& proj, const glm::mat4& view)> on_draw = nullptr;
|
||||||
|
std::function<void(const Controller&, Controller::Button, Controller::Action)> on_button = nullptr;
|
||||||
|
|
||||||
|
Vive();
|
||||||
|
bool Initialize();
|
||||||
|
void Terminate();
|
||||||
|
void ResetYaw();
|
||||||
|
void Draw();
|
||||||
|
bool Valid();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
47
src/main.cpp
47
src/main.cpp
@@ -6,6 +6,7 @@
|
|||||||
#include "image.h"
|
#include "image.h"
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
#include "keymap.h"
|
#include "keymap.h"
|
||||||
|
#include "hmd.h"
|
||||||
#include "../resource.h"
|
#include "../resource.h"
|
||||||
|
|
||||||
#include <shellscalingapi.h>
|
#include <shellscalingapi.h>
|
||||||
@@ -564,6 +565,21 @@ int main(int argc, char** argv)
|
|||||||
LOG("init app");
|
LOG("init app");
|
||||||
App::I.init();
|
App::I.init();
|
||||||
|
|
||||||
|
Vive* vive = nullptr;
|
||||||
|
if (!sandboxed)
|
||||||
|
{
|
||||||
|
vive = new Vive;
|
||||||
|
vive->on_draw = [](const glm::mat4& proj, const glm::mat4& view) { App::I.vr_draw(proj, view); };
|
||||||
|
async_lock();
|
||||||
|
if (!vive->Initialize())
|
||||||
|
{
|
||||||
|
delete vive;
|
||||||
|
vive = nullptr;
|
||||||
|
LOG("VR: failed to initialize vive");
|
||||||
|
}
|
||||||
|
async_unlock();
|
||||||
|
}
|
||||||
|
|
||||||
LOG("show main window");
|
LOG("show main window");
|
||||||
ShowWindow(hWnd, SW_NORMAL);
|
ShowWindow(hWnd, SW_NORMAL);
|
||||||
|
|
||||||
@@ -689,6 +705,35 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
std::mutex hmd_render_mutex;
|
||||||
|
std::condition_variable hmd_render_cv;
|
||||||
|
|
||||||
|
std::thread hmd_renderer([&] {
|
||||||
|
BT_SetTerminate();
|
||||||
|
LOG("start hmd render thread");
|
||||||
|
|
||||||
|
const float target_tick_rate = 90;
|
||||||
|
unsigned long t0 = GetTickCount();
|
||||||
|
while (running && vive->Valid())
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(hmd_render_mutex);
|
||||||
|
unsigned long t1 = GetTickCount();
|
||||||
|
float dt = (float)(t1 - t0) / 1000.0f;
|
||||||
|
|
||||||
|
async_lock();
|
||||||
|
vive->Draw();
|
||||||
|
async_unlock();
|
||||||
|
|
||||||
|
const int framerate = (1.f / target_tick_rate) * 1000;
|
||||||
|
const int diff = framerate - (t1 - t0);
|
||||||
|
hmd_render_cv.wait_for(lock, std::chrono::milliseconds(diff));
|
||||||
|
}
|
||||||
|
async_lock();
|
||||||
|
vive->Terminate();
|
||||||
|
async_unlock();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
MSG msg;
|
MSG msg;
|
||||||
LOG("start main loop");
|
LOG("start main loop");
|
||||||
while (running)
|
while (running)
|
||||||
@@ -710,6 +755,8 @@ int main(int argc, char** argv)
|
|||||||
render_cv.notify_all();
|
render_cv.notify_all();
|
||||||
if (renderer.joinable())
|
if (renderer.joinable())
|
||||||
renderer.join();
|
renderer.join();
|
||||||
|
if (hmd_renderer.joinable())
|
||||||
|
hmd_renderer.join();
|
||||||
App::I.terminate();
|
App::I.terminate();
|
||||||
// Clean up
|
// Clean up
|
||||||
WacomTablet::I.terminate();
|
WacomTablet::I.terminate();
|
||||||
|
|||||||
@@ -21,4 +21,5 @@
|
|||||||
#pragma comment(lib, "wbemuuid.lib")
|
#pragma comment(lib, "wbemuuid.lib")
|
||||||
#pragma comment(lib, "Shlwapi.lib")
|
#pragma comment(lib, "Shlwapi.lib")
|
||||||
#pragma comment(lib, "Shcore.lib")
|
#pragma comment(lib, "Shcore.lib")
|
||||||
|
#pragma comment(lib, "openvr_api.lib")
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|||||||
@@ -65,6 +65,7 @@
|
|||||||
#include <BugTrap.h>
|
#include <BugTrap.h>
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#include <shlwapi.h>
|
#include <shlwapi.h>
|
||||||
|
#include <openvr.h>
|
||||||
|
|
||||||
#define SHADER_VERSION "#version 150\n"
|
#define SHADER_VERSION "#version 150\n"
|
||||||
#define PP_OS "win"
|
#define PP_OS "win"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "rtt.h"
|
#include "rtt.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
RTT::RTT()
|
RTT::RTT()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -179,10 +179,3 @@ size_t curl_data_write(void *ptr, size_t size, size_t nmemb, FILE *stream)
|
|||||||
size_t written = fwrite(ptr, size, nmemb, stream);
|
size_t written = fwrite(ptr, size, nmemb, stream);
|
||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
#define GL(stmt) stmt; CheckOpenGLError(#stmt, __FILE__, __LINE__);
|
|
||||||
#else
|
|
||||||
#define GL(stmt) stmt
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#define GL(stmt) stmt; check_OpenGLError(#stmt, __FILE__, __LINE__);
|
||||||
|
#else
|
||||||
|
#define GL(stmt) stmt
|
||||||
|
#endif
|
||||||
|
|
||||||
uint16_t constexpr const_hash(const char* input)
|
uint16_t constexpr const_hash(const char* input)
|
||||||
{
|
{
|
||||||
return *input ?
|
return *input ?
|
||||||
|
|||||||
Reference in New Issue
Block a user