review vr stuff, fix controller-ui ray casting

This commit is contained in:
2019-06-05 16:27:29 +02:00
parent 02b92cf382
commit dc9da77cf8
10 changed files with 96 additions and 47 deletions

View File

@@ -9,8 +9,8 @@
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application android:label="@string/app_name" <application android:label="@string/app_name"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:allowBackup="false"> android:allowBackup="false">
@@ -25,8 +25,8 @@
<meta-data android:name="android.app.lib_name" <meta-data android:name="android.app.lib_name"
android:value="native-lib" /> android:value="native-lib" />
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.INFO" /> <category android:name="android.intent.category.INFO"/>
</intent-filter> </intent-filter>
</activity> </activity>
</application> </application>

View File

@@ -22,7 +22,7 @@ struct QuestController : public VRController
void update_state(double predictedDisplayTime, glm::vec3 head_pos) void update_state(double predictedDisplayTime, glm::vec3 head_pos)
{ {
vrapi_GetInputTrackingState(ovr_context, id, predictedDisplayTime, &tracking); vrapi_GetInputTrackingState(ovr_context, id, predictedDisplayTime, &tracking);
glm::vec3 c_pos = glm::make_vec3((float*)&tracking.HeadPose.Pose.Position) - head_pos; glm::vec3 c_pos = glm::make_vec3((float*)&tracking.HeadPose.Pose.Position);
auto c_rot_ovr = ovrMatrix4f_CreateFromQuaternion(&tracking.HeadPose.Pose.Orientation); auto c_rot_ovr = ovrMatrix4f_CreateFromQuaternion(&tracking.HeadPose.Pose.Orientation);
auto c_rot_ovr_tp = ovrMatrix4f_Transpose(&c_rot_ovr); auto c_rot_ovr_tp = ovrMatrix4f_Transpose(&c_rot_ovr);
glm::mat4 c_rot = glm::make_mat4((float*)&c_rot_ovr_tp); glm::mat4 c_rot = glm::make_mat4((float*)&c_rot_ovr_tp);

View File

@@ -624,7 +624,7 @@ void App::update(float dt)
auto observer = std::bind(&App::update_ui_observer, this, std::placeholders::_1); auto observer = std::bind(&App::update_ui_observer, this, std::placeholders::_1);
if (vr_active) if (vr_active && ui_visible)
{ {
uirtt.bindFramebuffer(); uirtt.bindFramebuffer();
uirtt.clear(); uirtt.clear();

View File

@@ -31,7 +31,7 @@ void App::tick(float dt)
void App::resize(float w, float h) void App::resize(float w, float h)
{ {
LOG("App::resize %d %d", (int)w, (int)h); LOG("App::resize %d %d", (int)w, (int)h);
uirtt.create(w, h); uirtt.create(w, h, -1, GL_RGBA8, true);
redraw = true; redraw = true;
width = w; width = w;
height = h; height = h;

View File

@@ -6,6 +6,7 @@
#ifdef _WIN32 #ifdef _WIN32
bool win32_vr_start(); bool win32_vr_start();
void win32_vr_stop(); void win32_vr_stop();
void win32_render_thread_notify();
#endif #endif
bool trigger_down = false; bool trigger_down = false;
@@ -16,6 +17,7 @@ glm::vec2 controller_cursor;
bool ui_inside = false; bool ui_inside = false;
bool ui_capture = false; bool ui_capture = false;
Sphere controller_ray; Sphere controller_ray;
glm::mat4 head_pose;
bool App::vr_start() bool App::vr_start()
{ {
@@ -52,42 +54,57 @@ void App::vr_draw_ui()
void App::vr_update(float dt) void App::vr_update(float dt)
{ {
glm::vec3 hit; canvas->m_canvas->m_cam_fov = 45;
float t; float tan_fov = glm::tan(glm::radians(canvas->m_canvas->m_cam_fov / 2.f));
glm::mat3 m = glm::transpose(Canvas::I->m_cam_rot); glm::vec3 aspect = { (float)uirtt.getWidth() / (float)uirtt.getHeight(), 1.f, 1.f };
auto o = m * glm::vec3(0, 0, -1); glm::mat4 m = (
auto r = m * glm::vec3(1, 0, 0); glm::scale(glm::vec3(100)) *
auto n = m * glm::vec3(0, 0, 1); glm::transpose(canvas->m_canvas->m_cam_rot) *
auto u = m * glm::vec3(0, 1, 0); glm::translate(glm::vec3(0, 0, -1)) *
glm::scale(aspect * tan_fov)
);
glm::mat4 mm = glm::inverse(m);
auto o = glm::vec3(m * glm::vec4(0, 0, 0, 1));
auto r = glm::normalize(glm::vec3(glm::vec4(1, 0, 0, 0) * mm));
auto n = glm::normalize(glm::vec3(glm::vec4(0, 0, 1, 0) * mm));
auto u = glm::normalize(glm::vec3(glm::vec4(0, 1, 0, 0) * mm));
auto co = vr_controllers[0].get_pos(); auto co = vr_controllers[0].get_pos();
auto cd = co + glm::mat3(vr_controllers[0].m_mat) * glm::vec3(0, 0, -1); auto cd = co + glm::mat3(vr_controllers[0].m_mat) * glm::vec3(0, 0, -1);
ui_inside = false; ui_inside = false;
glm::vec3 hit;
float t;
if (ray_intersect(co, cd, o, n, r, hit, t)) if (ray_intersect(co, cd, o, n, r, hit, t))
{ {
glm::mat4 plane_camera = glm::lookAt(o, n, u); glm::mat4 plane_camera = m;
glm::vec4 plane_local = (plane_camera * glm::vec4(hit, 1)) * 2.f; glm::vec4 plane_local = (mm * glm::vec4(hit, 1));
if (glm::all(glm::lessThanEqual(glm::abs(xy(plane_local)), glm::vec2(1.0f)))) if (glm::all(glm::lessThanEqual(glm::abs(xy(plane_local)), glm::vec2(1.0f))))
{ {
controller_cursor.x = -(plane_local.x * 0.5f - 0.5f) * width; controller_cursor.x = -(-plane_local.x * 0.5f - 0.5f) * width;
controller_cursor.y = height - (plane_local.y * 0.5f + 0.5f) * height - 1; controller_cursor.y = (-plane_local.y * 0.5f + 0.5f) * height;
if (!down_controller && ui_visible) if (!down_controller && ui_visible)
{ {
async_start(); async_start();
mouse_move(controller_cursor.x, controller_cursor.y, 1.f, kEventSource::Mouse, false); mouse_move(controller_cursor.x, controller_cursor.y, 1.f, kEventSource::Mouse, false);
async_end(); async_end();
ui_inside = true; ui_inside = true;
#ifdef _WIN32
win32_render_thread_notify();
#endif
} }
} }
} }
if (down_controller) if (down_controller)
{ {
controller_points.add(down_controller->get_pos_n() * 800.f); glm::vec3 head_position = head_pose[3];
glm::vec3 c_pos = glm::normalize(down_controller->get_pos() - head_position) * 800.f;
controller_points.add(c_pos);
auto p = controller_points.average(); auto p = controller_points.average();
if (glm::distance(p, controller_last_point) > 10) if (glm::distance(p, controller_last_point) > 1)
{ {
async_start(); async_start();
Canvas::I->stroke_update(p, down_controller->get_trigger_value()); Canvas::I->stroke_update(p, down_controller->get_trigger_value());
Canvas::I->stroke_draw();
async_end(); async_end();
controller_last_point = p; controller_last_point = p;
redraw = true; redraw = true;
@@ -106,11 +123,17 @@ void App::vr_analog(const VRController& c, VRController::kButton b, VRController
{ {
mouse_down(0, controller_cursor.x, controller_cursor.y, 1.f, kEventSource::Mouse, false); mouse_down(0, controller_cursor.x, controller_cursor.y, 1.f, kEventSource::Mouse, false);
ui_capture = true; ui_capture = true;
#ifdef _WIN32
win32_render_thread_notify();
#endif
} }
else else
{ {
mouse_up(0, controller_cursor.x, controller_cursor.y, kEventSource::Mouse, false); mouse_up(0, controller_cursor.x, controller_cursor.y, kEventSource::Mouse, false);
ui_capture = false; ui_capture = false;
#ifdef _WIN32
win32_render_thread_notify();
#endif
} }
async_end(); async_end();
} }
@@ -118,11 +141,12 @@ void App::vr_analog(const VRController& c, VRController::kButton b, VRController
{ {
if (a == VRController::kAction::Press) if (a == VRController::kAction::Press)
{ {
glm::vec3 pos = c.get_pos_n() * 800.f; glm::vec3 head_position = head_pose[3];
glm::vec3 c_pos = glm::normalize(c.get_pos() - head_position) * 800.f;
async_start(); async_start();
Canvas::I->stroke_start(pos, force.x); Canvas::I->stroke_start(c_pos, force.x);
async_end(); async_end();
controller_last_point = pos; controller_last_point = c_pos;
controller_points.clear(); controller_points.clear();
down_controller = &c; down_controller = &c;
} }
@@ -179,7 +203,7 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat
for (int plane_index = 0; plane_index < 6; plane_index++) for (int plane_index = 0; plane_index < 6; plane_index++)
{ {
auto plane_mvp = proj * camera * auto plane_mvp = proj * camera *
glm::scale(glm::vec3(canvas->m_canvas->m_order.size() + 500)) * glm::scale(glm::vec3(canvas->m_canvas->m_order.size() * 20)) *
canvas->m_canvas->m_plane_transform[plane_index] * canvas->m_canvas->m_plane_transform[plane_index] *
glm::translate(glm::vec3(0, 0, -1)); glm::translate(glm::vec3(0, 0, -1));
@@ -206,7 +230,7 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat
int z = (int)(canvas->m_canvas->m_order.size() - i); int z = (int)(canvas->m_canvas->m_order.size() - i);
auto plane_mvp_z = proj * camera * auto plane_mvp_z = proj * camera *
glm::scale(glm::vec3(z + 1) * 100.f) * glm::scale(glm::vec3(z) * 20.f) *
//glm::eulerAngleYXZ(yaw, pitch, roll) * //glm::eulerAngleYXZ(yaw, pitch, roll) *
canvas->m_canvas->m_plane_transform[plane_index] * canvas->m_canvas->m_plane_transform[plane_index] *
glm::translate(glm::vec3(0, 0, -1)); glm::translate(glm::vec3(0, 0, -1));
@@ -310,7 +334,9 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat
} }
} }
float tan_fov = glm::tan(glm::radians(canvas->m_canvas->m_cam_fov / 2.f)) * 0.5f; App::I.grid->draw_heightmap(proj, camera, false);
float tan_fov = glm::tan(glm::radians(canvas->m_canvas->m_cam_fov / 2.f));
glm::vec3 aspect = { (float)uirtt.getWidth() / (float)uirtt.getHeight(), 1.f, 1.f }; glm::vec3 aspect = { (float)uirtt.getWidth() / (float)uirtt.getHeight(), 1.f, 1.f };
// draw the frame // draw the frame
@@ -397,16 +423,17 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat
m_face_plane.draw_fill(); m_face_plane.draw_fill();
} }
/*
// draw the motion controller sphere // draw the motion controller sphere
if (ui_visible && ui_inside)
{ {
auto mvp = proj * camera * glm::translate(glm::normalize(vr_controller_pos)); auto mvp = proj * camera * vr_controllers[0].m_mat;
ShaderManager::use(kShader::Color); ShaderManager::use(kShader::Color);
ShaderManager::u_vec4(kShaderUniform::Col, { 0, 0, 0, 1 }); ShaderManager::u_vec4(kShaderUniform::Col, { 1, 0, 1, 1 });
ShaderManager::u_mat4(kShaderUniform::MVP, mvp * glm::scale(glm::vec3(.025))); ShaderManager::u_mat4(kShaderUniform::MVP, mvp * glm::scale(glm::vec3(.0125, .0125, .07)));
sphere.draw_fill(); sphere.draw_fill();
} }
*/
// draw the motion controller brush // draw the motion controller brush
if (!ui_visible || !ui_inside) if (!ui_visible || !ui_inside)

View File

@@ -10,11 +10,16 @@
#define CANVAS_RES 1536 #define CANVAS_RES 1536
class LayerFrame
{
};
class Layer class Layer
{ {
public: public:
//Layer() = default; Layer() = default;
//Layer(const Layer&) = delete; Layer(const Layer&) = delete;
RTT m_rtt[6]; RTT m_rtt[6];
glm::vec4 m_dirty_box[6] = SIXPLETTE(glm::vec4(0)); glm::vec4 m_dirty_box[6] = SIXPLETTE(glm::vec4(0));
bool m_dirty_face[6] = SIXPLETTE(false); bool m_dirty_face[6] = SIXPLETTE(false);

View File

@@ -87,17 +87,22 @@ void Vive::Update()
h.m[0][0], h.m[1][0], h.m[2][0], 0, 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][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][2], h.m[1][2], h.m[2][2], 0,
0, 0, 0, 1, // rotation only // 0, 0, 0, 1, // rotation only
//h.m[0][3], h.m[1][3], h.m[2][3], 1, h.m[0][3], h.m[1][3], h.m[2][3], 1,
}; };
if (!m_position_valid)
{
m_initial_position = { h.m[0][3], h.m[1][3], h.m[2][3] };
m_position_valid = true;
}
auto mat_proj = glm::make_mat4(data_eye_proj); auto mat_proj = glm::make_mat4(data_eye_proj);
auto mat_pose = glm::inverse(glm::make_mat4(data_hmd_pose)); auto mat_pose = glm::inverse(glm::make_mat4(data_hmd_pose));
auto mat_eye = glm::inverse(glm::make_mat4(data_eye_pose)); auto mat_eye = glm::inverse(glm::make_mat4(data_eye_pose));
glm::vec3 head_position(h.m[0][3], h.m[1][3], h.m[2][3]);
m_proj[eye] = mat_proj; m_proj[eye] = mat_proj;
m_view[eye] = mat_eye * mat_pose; m_view[eye] = mat_eye * mat_pose * glm::translate(m_initial_position);
m_pose = glm::make_mat4(data_hmd_pose); m_pose = glm::make_mat4(data_hmd_pose);
// invalidate controller state // invalidate controller state
@@ -120,7 +125,7 @@ void Vive::Update()
{ {
m_controllers[controller_index].m_valid = true; m_controllers[controller_index].m_valid = true;
m_hmd->GetControllerState(id, &m_controllers[controller_index].m_state, sizeof(vr::VRControllerState_t)); m_hmd->GetControllerState(id, &m_controllers[controller_index].m_state, sizeof(vr::VRControllerState_t));
m_controllers[controller_index].m_mat = glm::translate(-head_position) * Pose2Mat(poses[id].mDeviceToAbsoluteTracking); m_controllers[controller_index].m_mat = glm::translate(-m_initial_position) * Pose2Mat(poses[id].mDeviceToAbsoluteTracking);
auto pressed_mask = m_controllers[controller_index].m_state.ulButtonPressed; auto pressed_mask = m_controllers[controller_index].m_state.ulButtonPressed;
for (uint8_t bi = 0; bi < (uint8_t)ViveController::kButton::COUNT; bi++) for (uint8_t bi = 0; bi < (uint8_t)ViveController::kButton::COUNT; bi++)

View File

@@ -40,6 +40,8 @@ struct Vive
glm::mat4 m_view[2]; glm::mat4 m_view[2];
glm::mat4 m_proj[2]; glm::mat4 m_proj[2];
glm::mat4 m_pose; glm::mat4 m_pose;
glm::vec3 m_initial_position;
bool m_position_valid = false;
bool m_active = false; bool m_active = false;
std::function<void(const glm::mat4& m_proj, const glm::mat4& m_view, const glm::mat4& m_pose)> on_draw = nullptr; std::function<void(const glm::mat4& m_proj, const glm::mat4& m_view, const glm::mat4& m_pose)> on_draw = nullptr;
std::function<void(const ViveController&, ViveController::kButton, ViveController::kAction, glm::vec2 axis)> on_button = nullptr; std::function<void(const ViveController&, ViveController::kButton, ViveController::kAction, glm::vec2 axis)> on_button = nullptr;

View File

@@ -164,6 +164,11 @@ void async_unlock()
} }
} }
void win32_render_thread_notify()
{
render_cv.notify_all();
}
void win32_show_cursor(bool visible) void win32_show_cursor(bool visible)
{ {
std::lock_guard<std::mutex> lock(main_task_mutex); std::lock_guard<std::mutex> lock(main_task_mutex);
@@ -551,8 +556,8 @@ bool win32_vr_start()
const int framerate = (1.f / target_tick_rate) * 1000; const int framerate = (1.f / target_tick_rate) * 1000;
const int diff = framerate - (t1 - t0); const int diff = framerate - (t1 - t0);
t0 = t1;
hmd_render_cv.wait_for(lock, std::chrono::milliseconds(diff)); hmd_render_cv.wait_for(lock, std::chrono::milliseconds(diff));
t0 = t1;
} }
App::I.vr_active = false; App::I.vr_active = false;
App::I.has_vr = false; App::I.has_vr = false;
@@ -817,9 +822,9 @@ int main(int argc, char** argv)
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
WGL_COLOR_BITS_ARB, 32, WGL_COLOR_BITS_ARB, 32,
WGL_DEPTH_BITS_ARB, 24, WGL_DEPTH_BITS_ARB, 24,
WGL_STENCIL_BITS_ARB, 8, //WGL_STENCIL_BITS_ARB, 8,
WGL_SAMPLE_BUFFERS_ARB, 1, // Number of buffers (must be 1 at time of writing) //WGL_SAMPLE_BUFFERS_ARB, 1, // Number of buffers (must be 1 at time of writing)
WGL_SAMPLES_ARB, 4, // Number of samples //WGL_SAMPLES_ARB, 4, // Number of samples
0 0
}; };
UINT numFormat; UINT numFormat;
@@ -844,6 +849,8 @@ int main(int argc, char** argv)
return -1; // A negative number because you are a negative one return -1; // A negative number because you are a negative one
} }
//wglSwapIntervalEXT(1);
bool start_in_vr = false; bool start_in_vr = false;
if (argc > 1) if (argc > 1)
{ {
@@ -894,7 +901,7 @@ int main(int argc, char** argv)
BT_SetTerminate(); BT_SetTerminate();
LOG("start render thread"); LOG("start render thread");
const float target_fps = 10; const float target_fps = 10;
const float target_tick_rate = 60; const float target_tick_rate = 10;
unsigned long t0 = GetTickCount64(); unsigned long t0 = GetTickCount64();
unsigned long t1; unsigned long t1;
bool first_frame = true; bool first_frame = true;
@@ -912,7 +919,6 @@ int main(int argc, char** argv)
timer_stylus += dt; timer_stylus += dt;
timer_ink_touch += dt; timer_ink_touch += dt;
timer_ink_pen += dt; timer_ink_pen += dt;
t0 = t1;
if (one_sec > 1.f) if (one_sec > 1.f)
{ {
@@ -993,20 +999,20 @@ int main(int argc, char** argv)
if (App::I.redraw) if (App::I.redraw)
{ {
async_lock(); async_lock();
App::I.redraw = true;
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
App::I.clear(); App::I.clear();
App::I.update(frame_timer); App::I.update(frame_timer);
SwapBuffers(hDC); SwapBuffers(hDC);
async_unlock(); async_unlock();
frame_timer = 0; frame_timer = 0;
//LOG("swap main");
frames++; frames++;
} }
const int framerate = (1.f / target_tick_rate) * 1000; const int framerate = (1.f / target_tick_rate) * 1000;
const int diff = framerate - (t1 - t0); const int diff = framerate - (t1 - t0);
render_cv.wait_for(lock, std::chrono::milliseconds(diff)); render_cv.wait_for(lock, std::chrono::milliseconds(diff));
//std::this_thread::sleep_for(std::chrono::milliseconds(30));
t0 = t1;
} }
LOG("renderer terminated"); LOG("renderer terminated");
}); });

View File

@@ -224,8 +224,10 @@ void NodePanelGrid::draw_heightmap(const glm::mat4& proj, const glm::mat4& camer
auto nav = m_hm_image.m_data ? -(m_hm_preview_nav->m_value - 0.5f) : glm::vec2(0); auto nav = m_hm_image.m_data ? -(m_hm_preview_nav->m_value - 0.5f) : glm::vec2(0);
auto mvp = proj * camera auto mvp = proj * camera
* glm::scale(glm::vec3(100))
* glm::translate(glm::vec3(0, get_offset(), 0)) * glm::translate(glm::vec3(0, get_offset(), 0))
* glm::translate(glm::vec3(nav.x, get_offset(), nav.y)); * glm::translate(glm::vec3(nav.x, get_offset(), nav.y))
;
auto light_yaw = m_hm_lyaw->get_value() * glm::pi<float>() * 2.f; auto light_yaw = m_hm_lyaw->get_value() * glm::pi<float>() * 2.f;
auto light_pitch = m_hm_lpitch->get_value() * 5; auto light_pitch = m_hm_lpitch->get_value() * 5;
@@ -303,9 +305,11 @@ void NodePanelGrid::draw_heightmap(const glm::mat4& proj, const glm::mat4& camer
glGetIntegerv(GL_VIEWPORT, vp); glGetIntegerv(GL_VIEWPORT, vp);
auto aspect_ratio = (float)vp[3] / (float)vp[2]; auto aspect_ratio = (float)vp[3] / (float)vp[2];
glEnable(GL_BLEND); glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
ShaderManager::use(kShader::Texture); ShaderManager::use(kShader::Texture);
ShaderManager::u_int(kShaderUniform::Tex, 0); ShaderManager::u_int(kShaderUniform::Tex, 0);
ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-1.f, 1.f, -1.f, 1.f) * ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-1.f, 1.f, -1.f, 1.f) *
glm::scale(glm::vec3(100)) *
glm::translate(glm::vec3(p2d, 0)) * glm::scale(glm::vec3(.1f * aspect_ratio, .1f, 1.f))); glm::translate(glm::vec3(p2d, 0)) * glm::scale(glm::vec3(.1f * aspect_ratio, .1f, 1.f)));
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
m_sampler_linear.bind(0); m_sampler_linear.bind(0);