diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index ab8f1f7897..eee8bccf2c 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -32,6 +32,7 @@ add_library( # Sets the name of the library. src/main/cpp/GestureDelegate.cpp src/main/cpp/LoadingAnimation.cpp src/main/cpp/JNIUtil.cpp + src/main/cpp/Pointer.cpp src/main/cpp/Skybox.cpp src/main/cpp/SplashAnimation.cpp src/main/cpp/VRBrowser.cpp diff --git a/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java b/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java index 2785ea9eb8..e26e5032a5 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java @@ -9,6 +9,10 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.PorterDuff; import android.graphics.SurfaceTexture; import android.net.Uri; import android.opengl.GLES11Ext; @@ -605,6 +609,34 @@ void resumeGeckoViewCompositor() { }, 20); } + @Keep + @SuppressWarnings("unused") + void renderPointerLayer(final Surface aSurface) { + runOnUiThread(() -> { + try { + Canvas canvas = aSurface.lockHardwareCanvas(); + canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); + Paint paint = new Paint(); + paint.setAntiAlias(true); + paint.setDither(true); + paint.setColor(Color.WHITE); + paint.setStyle(Paint.Style.FILL); + final float x = canvas.getWidth() * 0.5f; + final float y = canvas.getHeight() * 0.5f; + final float radius = canvas.getWidth() * 0.4f; + canvas.drawCircle(x, y, radius, paint); + paint.setColor(Color.BLACK); + paint.setStrokeWidth(5); + paint.setStyle(Paint.Style.STROKE); + canvas.drawCircle(x, y, radius, paint); + aSurface.unlockCanvasAndPost(canvas); + } + catch (Exception ex) { + ex.printStackTrace(); + } + }); + } + @Keep @SuppressWarnings("unused") String getStorageAbsolutePath() { diff --git a/app/src/main/cpp/BrowserWorld.cpp b/app/src/main/cpp/BrowserWorld.cpp index e359fa45d9..c557a7964f 100644 --- a/app/src/main/cpp/BrowserWorld.cpp +++ b/app/src/main/cpp/BrowserWorld.cpp @@ -15,6 +15,7 @@ #include "LoadingAnimation.h" #include "Skybox.h" #include "SplashAnimation.h" +#include "Pointer.h" #include "Widget.h" #include "WidgetPlacement.h" #include "Quad.h" @@ -182,7 +183,7 @@ struct BrowserWorld::State { rootController->AddLight(light); cullVisitor = CullVisitor::Create(create); drawList = DrawableList::Create(create); - controllers = ControllerContainer::Create(create); + controllers = ControllerContainer::Create(create, rootTransparent); externalVR = ExternalVR::Create(); blitter = ExternalBlitter::Create(create); fadeAnimation = FadeAnimation::Create(create); @@ -254,14 +255,13 @@ ThrottleHoverEvent(Controller& aController, const double aTimestamp, const bool void BrowserWorld::State::UpdateControllers(bool& aRelayoutWidgets) { - std::vector active; - for (const WidgetPtr& widget: widgets) { - widget->TogglePointer(false); - } for (Controller& controller: controllers->GetControllers()) { if (!controller.enabled || (controller.index < 0)) { continue; } + if (controller.pointer && !controller.pointer->IsLoaded()) { + controller.pointer->Load(device); + } if (!(controller.lastButtonState & ControllerDelegate::BUTTON_APP) && (controller.buttonState & ControllerDelegate::BUTTON_APP)) { VRBrowser::HandleBack(); @@ -290,12 +290,18 @@ BrowserWorld::State::UpdateControllers(bool& aRelayoutWidgets) { resizingWidget.reset(); } + controller.pointer->SetVisible(hitWidget.get() != nullptr); + controller.pointer->SetHitWidget(hitWidget); + if (hitWidget) { + vrb::Matrix translate = vrb::Matrix::Translation(vrb::Vector(hitPoint.x(), hitPoint.y(), 0.001f)); + controller.pointer->SetTransform(hitWidget->GetTransform().PostMultiply(translate)); + } + const bool pressed = controller.buttonState & ControllerDelegate::BUTTON_TRIGGER || controller.buttonState & ControllerDelegate::BUTTON_TOUCHPAD; const bool wasPressed = controller.lastButtonState & ControllerDelegate::BUTTON_TRIGGER || controller.lastButtonState & ControllerDelegate::BUTTON_TOUCHPAD; if (hitWidget && hitWidget->IsResizing()) { - active.push_back(hitWidget.get()); bool aResized = false, aResizeEnded = false; hitWidget->HandleResize(hitPoint, pressed, aResized, aResizeEnded); @@ -316,7 +322,6 @@ BrowserWorld::State::UpdateControllers(bool& aRelayoutWidgets) { } } else if (hitWidget) { - active.push_back(hitWidget.get()); float theX = 0.0f, theY = 0.0f; hitWidget->ConvertToWidgetCoordinates(hitPoint, theX, theY); const uint32_t handle = hitWidget->GetHandle(); @@ -366,10 +371,6 @@ BrowserWorld::State::UpdateControllers(bool& aRelayoutWidgets) { } controller.lastButtonState = controller.buttonState; } - for (Widget* widget: active) { - widget->TogglePointer(true); - } - active.clear(); if (gestures) { const int32_t gestureCount = gestures->GetGestureCount(); for (int32_t count = 0; count < gestureCount; count++) { @@ -497,7 +498,7 @@ BrowserWorld::InitializeJava(JNIEnv* aEnv, jobject& aActivity, jobject& aAssetMa m.controllers->LoadControllerModel(index, m.loader, fileName); } } - m.controllers->InitializePointer(); + m.controllers->InitializeBeam(); m.controllers->SetPointerColor(vrb::Color(VRBrowser::GetPointerColor())); m.loadingAnimation->LoadModels(m.loader); m.rootController->AddNode(m.controllers->GetRoot()); @@ -656,9 +657,6 @@ BrowserWorld::UpdatePointerColor() { int32_t color = VRBrowser::GetPointerColor(); VRB_LOG("Setting pointer color to: %d:", color); - for (const WidgetPtr& widget: m.widgets) { - widget->SetPointerColor(vrb::Color(color)); - } if (m.controllers) m.controllers->SetPointerColor(vrb::Color(color)); } @@ -714,12 +712,6 @@ BrowserWorld::AddWidget(int32_t aHandle, const WidgetPlacementPtr& aPlacement) { m.widgets.push_back(widget); UpdateWidget(widget->GetHandle(), aPlacement); - - if (!aPlacement->showPointer) { - vrb::NodePtr emptyNode = vrb::Group::Create(m.create); - widget->SetPointerGeometry(emptyNode); - } - widget->SetPointerColor(vrb::Color(VRBrowser::GetPointerColor())); } void @@ -938,8 +930,8 @@ BrowserWorld::DrawWorld() { m.skybox->SetTransform(vrb::Matrix::Translation(headPosition)); } m.rootTransparent->SortNodes([=](const NodePtr& a, const NodePtr& b) { - float da = DistanceToPlane(GetWidgetFromNode(a), headPosition, headDirection); - float db = DistanceToPlane(GetWidgetFromNode(b), headPosition, headDirection); + float da = DistanceToPlane(a, headPosition, headDirection); + float db = DistanceToPlane(b, headPosition, headDirection); if (da < 0.0f) { da = std::numeric_limits::max(); } @@ -1119,41 +1111,35 @@ BrowserWorld::CreateFloor() { } float -BrowserWorld::DistanceToNode(const vrb::NodePtr& aTargetNode, const vrb::Vector& aPosition) const { - ASSERT_ON_RENDER_THREAD(0.0f); - float result = -1; - Node::Traverse(aTargetNode, [&](const NodePtr &aNode, const GroupPtr &aTraversingFrom) { - vrb::TransformPtr transform = std::dynamic_pointer_cast(aNode); - if (transform) { - vrb::Vector targetPos = transform->GetTransform().GetTranslation(); - result = (targetPos - aPosition).Magnitude(); - return true; - } - return false; - }); - - return result; -} - -WidgetPtr -BrowserWorld::GetWidgetFromNode(const vrb::NodePtr& aNode) const { +BrowserWorld::DistanceToPlane(const vrb::NodePtr& aNode, const vrb::Vector& aPosition, const vrb::Vector& aDirection) const { + WidgetPtr target; + bool pointer = false; for (const auto & widget: m.widgets) { if (widget->GetRoot() == aNode) { - return widget; + target = widget; + break; + } + } + if (!target) { + for (Controller& controller: m.controllers->GetControllers()) { + if (controller.pointer && controller.pointer->GetRoot() == aNode) { + target = controller.pointer->GetHitWidget(); + pointer = true; + break; + } } } - return nullptr; -} -float -BrowserWorld::DistanceToPlane(const WidgetPtr& aWidget, const vrb::Vector& aPosition, const vrb::Vector& aDirection) const { - if (!aWidget) { + if (!target) { return -1.0f; } vrb::Vector result; bool inside = false; float distance = -1.0f; - aWidget->GetQuad()->TestIntersection(aPosition, aDirection, result, false, inside, distance); + target->GetQuad()->TestIntersection(aPosition, aDirection, result, false, inside, distance); + if (pointer) { + distance-= 0.001f; + } return distance; } diff --git a/app/src/main/cpp/BrowserWorld.h b/app/src/main/cpp/BrowserWorld.h index a25a173d91..949cce73ee 100644 --- a/app/src/main/cpp/BrowserWorld.h +++ b/app/src/main/cpp/BrowserWorld.h @@ -67,9 +67,7 @@ class BrowserWorld { void DrawSplashAnimation(); void CreateSkyBox(const std::string& basePath); void CreateFloor(); - float DistanceToNode(const vrb::NodePtr& aNode, const vrb::Vector& aPosition) const; - WidgetPtr GetWidgetFromNode(const vrb::NodePtr& aNode) const; - float DistanceToPlane(const WidgetPtr& aNode, const vrb::Vector& aPosition, const vrb::Vector& aDirection) const; + float DistanceToPlane(const vrb::NodePtr& aNode, const vrb::Vector& aPosition, const vrb::Vector& aDirection) const; private: State& m; BrowserWorld() = delete; diff --git a/app/src/main/cpp/Controller.h b/app/src/main/cpp/Controller.h index cc6c6dccd0..715bcc8237 100644 --- a/app/src/main/cpp/Controller.h +++ b/app/src/main/cpp/Controller.h @@ -12,6 +12,9 @@ namespace crow { +class Pointer; +typedef std::shared_ptr PointerPtr; + static const int kControllerMaxButtonCount = 4; static const int kControllerMaxAxes = 6; @@ -32,6 +35,7 @@ struct Controller { float scrollDeltaX; float scrollDeltaY; vrb::TransformPtr transform; + PointerPtr pointer; vrb::Matrix transformMatrix; std::string immersiveName; uint64_t immersivePressedState; diff --git a/app/src/main/cpp/ControllerContainer.cpp b/app/src/main/cpp/ControllerContainer.cpp index 856de22d6e..3af41c015d 100644 --- a/app/src/main/cpp/ControllerContainer.cpp +++ b/app/src/main/cpp/ControllerContainer.cpp @@ -5,6 +5,7 @@ #include "ControllerContainer.h" #include "Controller.h" +#include "Pointer.h" #include "vrb/ConcreteClass.h" #include "vrb/Color.h" @@ -26,8 +27,9 @@ struct ControllerContainer::State { std::vector list; CreationContextWeak context; TogglePtr root; + GroupPtr pointerContainer; std::vector models; - GeometryPtr pointerModel; + GeometryPtr beamModel; bool visible; void Initialize(vrb::CreationContextPtr& aContext) { @@ -52,8 +54,10 @@ struct ControllerContainer::State { }; ControllerContainerPtr -ControllerContainer::Create(vrb::CreationContextPtr& aContext) { - return std::make_shared >(aContext); +ControllerContainer::Create(vrb::CreationContextPtr& aContext, const vrb::GroupPtr& aPointerContainer) { + auto result = std::make_shared >(aContext); + result->m.pointerContainer = aPointerContainer; + return result; } @@ -70,8 +74,8 @@ ControllerContainer::LoadControllerModel(const int32_t aModelIndex, const ModelL } void -ControllerContainer::InitializePointer() { - if (m.pointerModel) { +ControllerContainer::InitializeBeam() { + if (m.beamModel) { return; } CreationContextPtr create = m.context.lock(); @@ -125,10 +129,10 @@ ControllerContainer::InitializePointer() { index.push_back(5); geometry->AddFace(index, uvIndex, index); - m.pointerModel = std::move(geometry); + m.beamModel = std::move(geometry); for (Controller& controller: m.list) { if (controller.transform) { - controller.transform->AddNode(m.pointerModel); + controller.transform->AddNode(m.beamModel); } } } @@ -139,6 +143,9 @@ ControllerContainer::Reset() { if (controller.transform) { controller.transform->RemoveFromParents(); } + if (controller.pointer) { + controller.pointer->GetRoot()->RemoveFromParents(); + } controller.Reset(); } } @@ -167,15 +174,19 @@ ControllerContainer::CreateController(const int32_t aControllerIndex, const int3 m.SetUpModelsGroup(aModelIndex); CreationContextPtr create = m.context.lock(); controller.transform = Transform::Create(create); + controller.pointer = Pointer::Create(create); if ((m.models.size() >= aModelIndex) && m.models[aModelIndex]) { controller.transform->AddNode(m.models[aModelIndex]); - if (m.pointerModel) { - controller.transform->AddNode(m.pointerModel); + if (m.beamModel) { + controller.transform->AddNode(m.beamModel); } if (m.root) { m.root->AddNode(controller.transform); m.root->ToggleChild(*controller.transform, false); } + if (m.pointerContainer) { + m.pointerContainer->AddNode(controller.pointer->GetRoot()); + } } else { VRB_ERROR("Failed to add controller model"); } @@ -209,6 +220,9 @@ ControllerContainer::SetVisible(const int32_t aControllerIndex, const bool aVisi if (controller.transform && m.visible) { m.root->ToggleChild(*controller.transform, aVisible); } + if (controller.pointer && !aVisible) { + controller.pointer->SetVisible(false); + } } void @@ -322,6 +336,9 @@ void ControllerContainer::SetPointerColor(const vrb::Color& aColor) const { GeometryPtr geometry = std::dynamic_pointer_cast(controller.transform->GetNode(1)); geometry->GetRenderState()->SetMaterial(aColor, aColor, vrb::Color(0.0f, 0.0f, 0.0f), 0.0f); } + if (controller.pointer) { + controller.pointer->SetPointerColor(aColor); + } } } diff --git a/app/src/main/cpp/ControllerContainer.h b/app/src/main/cpp/ControllerContainer.h index af758531e5..417f8a3aaf 100644 --- a/app/src/main/cpp/ControllerContainer.h +++ b/app/src/main/cpp/ControllerContainer.h @@ -24,10 +24,10 @@ typedef std::shared_ptr ControllerContainerPtr; class ControllerContainer : public crow::ControllerDelegate { public: enum class HandEnum { Left, Right }; - static ControllerContainerPtr Create(vrb::CreationContextPtr& aContext); + static ControllerContainerPtr Create(vrb::CreationContextPtr& aContext, const vrb::GroupPtr& aPointerContainer); vrb::TogglePtr GetRoot() const; void LoadControllerModel(const int32_t aModelIndex, const vrb::ModelLoaderAndroidPtr& aLoader, const std::string& aFileName); - void InitializePointer(); + void InitializeBeam(); void Reset(); std::vector& GetControllers(); const std::vector& GetControllers() const; diff --git a/app/src/main/cpp/Pointer.cpp b/app/src/main/cpp/Pointer.cpp new file mode 100644 index 0000000000..c80ef6c834 --- /dev/null +++ b/app/src/main/cpp/Pointer.cpp @@ -0,0 +1,199 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "Pointer.h" +#include "DeviceDelegate.h" +#include "VRLayer.h" +#include "VRLayerNode.h" +#include "VRBrowser.h" +#include "Widget.h" +#include "vrb/ConcreteClass.h" +#include "vrb/Color.h" +#include "vrb/CreationContext.h" +#include "vrb/Geometry.h" +#include "vrb/Matrix.h" +#include "vrb/ModelLoaderAndroid.h" +#include "vrb/RenderState.h" +#include "vrb/RenderContext.h" +#include "vrb/TextureCubeMap.h" +#include "vrb/Toggle.h" +#include "vrb/Transform.h" +#include "vrb/VertexArray.h" + +#include + +#define POINTER_COLOR_OUTER vrb::Color(0.239f, 0.239f, 0.239f) +#define POINTER_COLOR_INNER vrb::Color(1.0f, 1.0f, 1.0f) + +using namespace vrb; + +namespace crow { + +const float kOffset = 0.01f; +const float kScale = 0.02f; +const int kResolution = 24; +const float kRadius = 0.25f; + +struct Pointer::State { + vrb::CreationContextWeak context; + vrb::TogglePtr root; + VRLayerQuadPtr layer; + vrb::TransformPtr transform; + vrb::TransformPtr pointerScale; + vrb::GeometryPtr geometry; + WidgetPtr hitWidget; + + State() + {} + + void Initialize() { + vrb::CreationContextPtr create = context.lock(); + root = vrb::Toggle::Create(create); + transform = vrb::Transform::Create(create); + pointerScale = vrb::Transform::Create(create); + pointerScale->SetTransform(vrb::Matrix::Identity()); + transform->AddNode(pointerScale); + root->AddNode(transform); + root->ToggleAll(false); + } + + vrb::GeometryPtr createCircle(const int resolution, const float radius, const float scale, const float offset) { + vrb::CreationContextPtr create = context.lock(); + vrb::GeometryPtr geometry = vrb::Geometry::Create(create); + vrb::VertexArrayPtr array = vrb::VertexArray::Create(create); + geometry->SetVertexArray(array); + + array->AppendNormal(vrb::Vector(0.0f, 0.0f, 1.0f)); + + for (int i = 0; i <= resolution; i++) { + std::vector normalIndex; + normalIndex.push_back(0); + normalIndex.push_back(0); + normalIndex.push_back(0); + + std::vector index; + + array->AppendVertex(vrb::Vector(0.0f, 0.0f, offset)); + index.push_back(i*3 + 1); + + array->AppendVertex(vrb::Vector( + (radius * cos(i * M_PI * 2 / resolution)) * scale, + (radius * sin(i * M_PI * 2 / resolution)) * scale, + offset)); + index.push_back(i*3 + 2); + + array->AppendVertex(vrb::Vector( + (radius * cos((i + 1) * M_PI * 2 / resolution)) * scale, + (radius * sin((i + 1) * M_PI * 2 / resolution)) * scale, + offset)); + index.push_back(i*3 + 3); + + std::vector uvIndex; + + geometry->AddFace(index, uvIndex, normalIndex); + } + + return geometry; + } + + void LoadGeometry() { + vrb::CreationContextPtr create = context.lock(); + geometry = createCircle(kResolution, kRadius, kScale, kOffset); + vrb::GeometryPtr geometryOuter = createCircle(kResolution, kRadius + 0.08f, kScale, kOffset); + + vrb::RenderStatePtr state = vrb::RenderState::Create(create); + state->SetMaterial(POINTER_COLOR_INNER, POINTER_COLOR_INNER, vrb::Color(0.0f, 0.0f, 0.0f), 0.0f); + geometry->SetRenderState(state); + vrb::RenderStatePtr stateOuter = vrb::RenderState::Create(create); + stateOuter->SetMaterial(POINTER_COLOR_OUTER, POINTER_COLOR_OUTER, vrb::Color(0.0f, 0.0f, 0.0f), 0.0f); + geometryOuter->SetRenderState(stateOuter); + pointerScale->AddNode(geometry); + pointerScale->AddNode(geometryOuter); + } + +}; + +bool +Pointer::IsLoaded() const { + return m.layer || m.geometry; +} + +void +Pointer::Load(const DeviceDelegatePtr& aDevice) { + VRLayerQuadPtr layer = aDevice->CreateLayerQuad(36, 36, VRLayerQuad::SurfaceType::AndroidSurface); + if (layer) { + m.layer = layer; + const float size = kRadius * kScale * 2.0f; + layer->SetWorldSize(size, size); + layer->SetInitializeDelegate([](const VRLayer& aLayer) { + const VRLayerQuad& quad = static_cast(aLayer); + if (quad.IsInitialized()) { + VRBrowser::RenderPointerLayer(quad.GetSurface()); + } + }); + vrb::CreationContextPtr create = m.context.lock(); + m.pointerScale->AddNode(VRLayerNode::Create(create, layer)); + } else { + m.LoadGeometry(); + } +} + +void +Pointer::SetVisible(bool aVisible) { + m.root->ToggleAll(aVisible); +} + +void +Pointer::SetTransform(const vrb::Matrix& aTransform) { + m.transform->SetTransform(aTransform); + vrb::Vector point; + point = aTransform.MultiplyPosition(point); + const float scale = fabsf(point.z()); + m.pointerScale->SetTransform(vrb::Matrix::Identity().ScaleInPlace(vrb::Vector(scale, scale, scale))); +} + +void +Pointer::SetPointerColor(const vrb::Color& aColor) { + if (m.layer) { + m.layer->SetTintColor(aColor); + } if (m.geometry) { + m.geometry->GetRenderState()->SetMaterial(aColor, aColor, vrb::Color(0.0f, 0.0f, 0.0f), 0.0f); + } +} + +void +Pointer::SetHitWidget(const crow::WidgetPtr &aWidget) { + m.hitWidget = aWidget; + if (m.layer) { + m.layer->SetDrawInFront(aWidget && aWidget->IsResizing()); + } +} + +vrb::NodePtr +Pointer::GetRoot() const { + return m.root; +} + +const WidgetPtr& +Pointer::GetHitWidget() const { + return m.hitWidget; +} + + +PointerPtr +Pointer::Create(vrb::CreationContextPtr aContext) { + PointerPtr result = std::make_shared >(aContext); + result->m.Initialize(); + return result; +} + + +Pointer::Pointer(State& aState, vrb::CreationContextPtr& aContext) : m(aState) { + m.context = aContext; +} + +Pointer::~Pointer() {} + +} // namespace crow diff --git a/app/src/main/cpp/Pointer.h b/app/src/main/cpp/Pointer.h new file mode 100644 index 0000000000..1a66e33aac --- /dev/null +++ b/app/src/main/cpp/Pointer.h @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef VRBROWSER_POINTER_H +#define VRBROWSER_POINTER_H + +#include "vrb/Forward.h" +#include "vrb/MacroUtils.h" + +namespace crow { + +class DeviceDelegate; +typedef std::shared_ptr DeviceDelegatePtr; + +class Pointer; +typedef std::shared_ptr PointerPtr; + +class Widget; +typedef std::shared_ptr WidgetPtr; + +class Pointer { +public: + static PointerPtr Create(vrb::CreationContextPtr aContext); + void Load(const DeviceDelegatePtr& aDevice); + bool IsLoaded() const; + void SetVisible(bool aVisible); + void SetTransform(const vrb::Matrix& aTransform); + void SetPointerColor(const vrb::Color& aColor); + void SetHitWidget(const WidgetPtr& aWidget); + + vrb::NodePtr GetRoot() const; + const WidgetPtr& GetHitWidget() const; + + struct State; + Pointer(State& aState, vrb::CreationContextPtr& aContext); + ~Pointer(); +private: + State& m; + Pointer() = delete; + VRB_NO_DEFAULTS(Pointer) +}; + +} // namespace crow + +#endif // VRBROWSER_POINTER_H diff --git a/app/src/main/cpp/VRBrowser.cpp b/app/src/main/cpp/VRBrowser.cpp index 377ea13716..e9fd5d6655 100644 --- a/app/src/main/cpp/VRBrowser.cpp +++ b/app/src/main/cpp/VRBrowser.cpp @@ -32,6 +32,8 @@ static const char* kPauseCompositorName = "pauseGeckoViewCompositor"; static const char* kPauseCompositorSignature = "()V"; static const char* kResumeCompositorName = "resumeGeckoViewCompositor"; static const char* kResumeCompositorSignature = "()V"; +static const char* kRenderPointerLayerName = "renderPointerLayer"; +static const char* kRenderPointerLayerSignature = "(Landroid/view/Surface;)V"; static const char* kGetStorageAbsolutePathName = "getStorageAbsolutePath"; static const char* kGetStorageAbsolutePathSignature = "()Ljava/lang/String;"; static const char* kIsOverrideEnvPathEnabledName = "isOverrideEnvPathEnabled"; @@ -56,6 +58,7 @@ static jmethodID sHandleBack; static jmethodID sRegisterExternalContext; static jmethodID sPauseCompositor; static jmethodID sResumeCompositor; +static jmethodID sRenderPointerLayer; static jmethodID sGetStorageAbsolutePath; static jmethodID sIsOverrideEnvPathEnabled; static jmethodID sGetActiveEnvironment; @@ -91,6 +94,7 @@ VRBrowser::InitializeJava(JNIEnv* aEnv, jobject aActivity) { sRegisterExternalContext = FindJNIMethodID(sEnv, browserClass, kRegisterExternalContextName, kRegisterExternalContextSignature); sPauseCompositor = FindJNIMethodID(sEnv, browserClass, kPauseCompositorName, kPauseCompositorSignature); sResumeCompositor = FindJNIMethodID(sEnv, browserClass, kResumeCompositorName, kResumeCompositorSignature); + sRenderPointerLayer = FindJNIMethodID(sEnv, browserClass, kRenderPointerLayerName, kRenderPointerLayerSignature); sGetStorageAbsolutePath = FindJNIMethodID(sEnv, browserClass, kGetStorageAbsolutePathName, kGetStorageAbsolutePathSignature); sIsOverrideEnvPathEnabled = FindJNIMethodID(sEnv, browserClass, kIsOverrideEnvPathEnabledName, kIsOverrideEnvPathEnabledSignature); sGetActiveEnvironment = FindJNIMethodID(sEnv, browserClass, kGetActiveEnvironment, kGetActiveEnvironmentSignature); @@ -119,6 +123,7 @@ VRBrowser::ShutdownJava() { sRegisterExternalContext = nullptr; sPauseCompositor = nullptr; sResumeCompositor = nullptr; + sRenderPointerLayer = nullptr; sEnv = nullptr; } @@ -201,6 +206,13 @@ VRBrowser::ResumeCompositor() { CheckJNIException(sEnv, __FUNCTION__); } +void +VRBrowser::RenderPointerLayer(jobject aSurface) { + if (!ValidateMethodID(sEnv, sActivity, sRenderPointerLayer, __FUNCTION__)) { return; } + sEnv->CallVoidMethod(sActivity, sRenderPointerLayer, aSurface); + CheckJNIException(sEnv, __FUNCTION__); +} + std::string VRBrowser::GetStorageAbsolutePath(const std::string& aRelativePath) { if (!ValidateMethodID(sEnv, sActivity, sGetStorageAbsolutePath, __FUNCTION__)) { return ""; } diff --git a/app/src/main/cpp/VRBrowser.h b/app/src/main/cpp/VRBrowser.h index 8527dd75c3..575b97ed78 100644 --- a/app/src/main/cpp/VRBrowser.h +++ b/app/src/main/cpp/VRBrowser.h @@ -28,6 +28,7 @@ void HandleBack(); void RegisterExternalContext(jlong aContext); void PauseCompositor(); void ResumeCompositor(); +void RenderPointerLayer(jobject aSurface); std::string GetStorageAbsolutePath(const std::string& aRelativePath); bool isOverrideEnvPathEnabled(); std::string GetActiveEnvironment(); diff --git a/app/src/main/cpp/VRLayer.cpp b/app/src/main/cpp/VRLayer.cpp index a005b5ceb4..a33efec61a 100644 --- a/app/src/main/cpp/VRLayer.cpp +++ b/app/src/main/cpp/VRLayer.cpp @@ -17,6 +17,7 @@ struct VRLayer::State { int32_t priority; uint64_t drawIndex; bool drawRequested; + bool drawInFront; VRLayer::LayerType layerType; vrb::Matrix modelTransform[2]; vrb::Matrix modelView[2]; @@ -29,6 +30,7 @@ struct VRLayer::State { priority(0), drawIndex(0), drawRequested(false), + drawInFront(false), currentEye(device::Eye::Left), tintColor(1.0f, 1.0f, 1.0f, 1.0f) { @@ -86,6 +88,11 @@ VRLayer::GetTextureRect(crow::device::Eye aEye) const { return m.textureRect[device::EyeIndex(aEye)]; } +bool +VRLayer::GetDrawInFront() const { + return m.drawInFront; +} + bool VRLayer::ShouldDrawBefore(const VRLayer& aLayer) { if (m.layerType == VRLayer::LayerType::CUBEMAP || m.layerType == VRLayer::LayerType::EQUIRECTANGULAR) { @@ -167,7 +174,11 @@ VRLayer::SetInitializeDelegate(const VRLayer::InitializeDelegate& aDelegate) { if (m.initialized && m.initDelegate) { m.initDelegate(*this); } +} +void +VRLayer::SetDrawInFront(bool aDrawInFront) { + m.drawInFront = aDrawInFront; } // Layer Quad diff --git a/app/src/main/cpp/VRLayer.h b/app/src/main/cpp/VRLayer.h index 746d137866..b77562fca3 100644 --- a/app/src/main/cpp/VRLayer.h +++ b/app/src/main/cpp/VRLayer.h @@ -40,6 +40,7 @@ class VRLayer { int32_t GetPriority() const; const vrb::Color& GetTintColor() const; const device::EyeRect& GetTextureRect(device::Eye aEye) const; + bool GetDrawInFront() const; bool ShouldDrawBefore(const VRLayer& aLayer); void SetInitialized(bool aInitialized); @@ -52,6 +53,7 @@ class VRLayer { void SetTintColor(const vrb::Color& aTintColor); void SetTextureRect(device::Eye aEye, const device::EyeRect& aTextureRect); void SetInitializeDelegate(const InitializeDelegate& aDelegate); + void SetDrawInFront(bool aDrawInFront); protected: struct State; VRLayer(State& aState, LayerType aLayerType); diff --git a/app/src/main/cpp/Widget.cpp b/app/src/main/cpp/Widget.cpp index 4029b32ade..dff4ed9562 100644 --- a/app/src/main/cpp/Widget.cpp +++ b/app/src/main/cpp/Widget.cpp @@ -23,9 +23,6 @@ #include "vrb/Vector.h" #include "vrb/VertexArray.h" -#define POINTER_COLOR_OUTER vrb::Color(0.239f, 0.239f, 0.239f) -#define POINTER_COLOR_INNER vrb::Color(1.0f, 1.0f, 1.0f) - namespace crow { struct Widget::State { @@ -37,10 +34,6 @@ struct Widget::State { vrb::TogglePtr root; vrb::TransformPtr transform; vrb::TextureSurfacePtr surface; - vrb::TogglePtr pointerToggle; - vrb::TransformPtr pointer; - vrb::TransformPtr pointerScale; - vrb::NodePtr pointerGeometry; WidgetPlacementPtr placement; WidgetResizerPtr resizer; bool resizing; @@ -52,50 +45,6 @@ struct Widget::State { , toggleState(false) {} - vrb::GeometryPtr createCircle(const int resolution, const float radius, const float scale, const float offset) { - vrb::RenderContextPtr render = context.lock(); - if (!render) { - return nullptr; - } - - vrb::CreationContextPtr create = render->GetRenderThreadCreationContext(); - vrb::GeometryPtr geometry = vrb::Geometry::Create(create); - vrb::VertexArrayPtr array = vrb::VertexArray::Create(create); - geometry->SetVertexArray(array); - - array->AppendNormal(vrb::Vector(0.0f, 0.0f, 1.0f)); - - for (int i = 0; i <= resolution; i++) { - std::vector normalIndex; - normalIndex.push_back(0); - normalIndex.push_back(0); - normalIndex.push_back(0); - - std::vector index; - - array->AppendVertex(vrb::Vector(0.0f, 0.0f, offset)); - index.push_back(i*3 + 1); - - array->AppendVertex(vrb::Vector( - (radius * cos(i * M_PI * 2 / resolution)) * scale, - (radius * sin(i * M_PI * 2 / resolution)) * scale, - offset)); - index.push_back(i*3 + 2); - - array->AppendVertex(vrb::Vector( - (radius * cos((i + 1) * M_PI * 2 / resolution)) * scale, - (radius * sin((i + 1) * M_PI * 2 / resolution)) * scale, - offset)); - index.push_back(i*3 + 3); - - std::vector uvIndex; - - geometry->AddFace(index, uvIndex, normalIndex); - } - - return geometry; - } - void Initialize(const int aHandle, const vrb::Vector& aWindowMin, const vrb::Vector& aWindowMax, const int32_t aTextureWidth, const int32_t aTextureHeight, const VRLayerQuadPtr& aLayer) { handle = aHandle; @@ -121,34 +70,10 @@ struct Widget::State { } transform = vrb::Transform::Create(create); - pointerToggle = vrb::Toggle::Create(create); - transform->AddNode(pointerToggle); transform->AddNode(quad->GetRoot()); root = vrb::Toggle::Create(create); root->AddNode(transform); - const float kOffset = 0.01f; - const float kScale = 0.02f; - const int kResolution = 24; - const float radius = 0.25f; - - vrb::GeometryPtr geometry = createCircle(kResolution, radius, kScale, kOffset); - vrb::GeometryPtr geometryOuter = createCircle(kResolution, radius + 0.08f, kScale, kOffset); - - vrb::RenderStatePtr state = vrb::RenderState::Create(create); - state->SetMaterial(POINTER_COLOR_INNER, POINTER_COLOR_INNER, vrb::Color(0.0f, 0.0f, 0.0f), 0.0f); - geometry->SetRenderState(state); - vrb::RenderStatePtr stateOuter = vrb::RenderState::Create(create); - stateOuter->SetMaterial(POINTER_COLOR_OUTER, POINTER_COLOR_OUTER, vrb::Color(0.0f, 0.0f, 0.0f), 0.0f); - geometryOuter->SetRenderState(stateOuter); - pointerScale = vrb::Transform::Create(create); - pointerScale->SetTransform(vrb::Matrix::Identity()); - pointerScale->AddNode(geometry); - pointerScale->AddNode(geometryOuter); - pointer = vrb::Transform::Create(create); - pointer->AddNode(pointerScale); - pointerGeometry = geometry; - pointerToggle->AddNode(pointer); if (layer) { toggleState = true; root->ToggleAll(true); @@ -267,10 +192,6 @@ Widget::TestControllerIntersection(const vrb::Vector& aStartPoint, const vrb::Ve aIsInWidget = m.resizer->TestIntersection(aResult); } - if (result && m.pointer) { - m.pointer->SetTransform(vrb::Matrix::Translation(vrb::Vector(aResult.x(), aResult.y(), 0.0f))); - } - return result; } @@ -292,10 +213,6 @@ Widget::GetTransform() const { void Widget::SetTransform(const vrb::Matrix& aTransform) { - vrb::Vector point; - point = aTransform.MultiplyPosition(point); - const float scale = fabsf(point.z()); - m.pointerScale->SetTransform(vrb::Matrix::Identity().ScaleInPlace(vrb::Vector(scale, scale, scale))); m.transform->SetTransform(aTransform); } @@ -305,11 +222,6 @@ Widget::ToggleWidget(const bool aEnabled) { m.root->ToggleAll(aEnabled && m.FirstDraw()); } -void -Widget::TogglePointer(const bool aEnabled) { - m.pointerToggle->ToggleAll(aEnabled); -} - bool Widget::IsVisible() const { return m.toggleState; @@ -336,23 +248,6 @@ Widget::GetTransformNode() const { return m.transform; } -vrb::NodePtr -Widget::GetPointerGeometry() const { - return m.pointerGeometry; -} - -void -Widget::SetPointerGeometry(vrb::NodePtr& aNode) { - if (!aNode) { - return; - } - if (m.pointerGeometry) { - m.pointer->RemoveNode(*m.pointerGeometry); - } - m.pointerGeometry = aNode; - m.pointer->AddNode(aNode); -} - const WidgetPlacementPtr& Widget::GetPlacement() const { return m.placement; @@ -416,12 +311,6 @@ Widget::HoverExitResize() { } } -void -Widget::SetPointerColor(const vrb::Color& aColor) { - vrb::GeometryPtr geometry = std::dynamic_pointer_cast(m.pointerGeometry); - geometry->GetRenderState()->SetMaterial(aColor, aColor, vrb::Color(0.0f, 0.0f, 0.0f), 0.0f); -} - Widget::Widget(State& aState, vrb::RenderContextPtr& aContext) : m(aState) { m.context = aContext; } diff --git a/app/src/main/cpp/Widget.h b/app/src/main/cpp/Widget.h index c6770c186a..b2b2159678 100644 --- a/app/src/main/cpp/Widget.h +++ b/app/src/main/cpp/Widget.h @@ -49,14 +49,11 @@ class Widget { const vrb::Matrix GetTransform() const; void SetTransform(const vrb::Matrix& aTransform); void ToggleWidget(const bool aEnabled); - void TogglePointer(const bool aEnabled); bool IsVisible() const; vrb::NodePtr GetRoot() const; QuadPtr GetQuad() const; const VRLayerQuadPtr& GetLayer() const; vrb::TransformPtr GetTransformNode() const; - vrb::NodePtr GetPointerGeometry() const; - void SetPointerGeometry(vrb::NodePtr& aNode); const WidgetPlacementPtr& GetPlacement() const; void SetPlacement(const WidgetPlacementPtr& aPlacement); void StartResize(); @@ -64,7 +61,6 @@ class Widget { bool IsResizing() const; void HandleResize(const vrb::Vector& aPoint, bool aPressed, bool& aResized, bool &aResizeEnded); void HoverExitResize(); - void SetPointerColor(const vrb::Color& aColor); protected: struct State; Widget(State& aState, vrb::RenderContextPtr& aContext); diff --git a/app/src/oculusvr/cpp/DeviceDelegateOculusVR.cpp b/app/src/oculusvr/cpp/DeviceDelegateOculusVR.cpp index e9c35eec2f..173769e3c8 100644 --- a/app/src/oculusvr/cpp/DeviceDelegateOculusVR.cpp +++ b/app/src/oculusvr/cpp/DeviceDelegateOculusVR.cpp @@ -144,6 +144,10 @@ class OculusLayer { return swapChain && layer->IsDrawRequested(); } + bool GetDrawInFront() const { + return layer->GetDrawInFront(); + } + void ClearRequestDraw() const { layer->ClearRequestDraw(); } @@ -892,8 +896,9 @@ DeviceDelegateOculusVR::EndFrame(const bool aDiscard) { return a->layer->ShouldDrawBefore(*b->layer); }); + // Draw back layers for (const OculusLayerQuadPtr& layer: m.uiLayers) { - if (layer->IsDrawRequested() && layerCount < ovrMaxLayerCount) { + if (!layer->GetDrawInFront() && layer->IsDrawRequested() && layerCount < ovrMaxLayerCount) { layer->Update(m.predictedTracking); layers[layerCount++] = layer->Header(); layer->ClearRequestDraw(); @@ -914,9 +919,18 @@ DeviceDelegateOculusVR::EndFrame(const bool aDiscard) { projection.Textures[i].TexCoordsFromTanAngles = ovrMatrix4f_TanAngleMatrixFromProjection( &m.predictedTracking.Eye[i].ProjectionMatrix); } - layers[layerCount++] = &projection.Header; + // Draw front layers + for (const OculusLayerQuadPtr& layer: m.uiLayers) { + if (layer->GetDrawInFront() && layer->IsDrawRequested() && layerCount < ovrMaxLayerCount) { + layer->Update(m.predictedTracking); + layers[layerCount++] = layer->Header(); + layer->ClearRequestDraw(); + } + } + + // Submit all layers to TimeWarp ovrSubmitFrameDescription2 frameDesc = {}; frameDesc.Flags = 0;