diff --git a/android/app/build.gradle b/android/app/build.gradle index ba3d16ad4d..97267258e2 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -23,8 +23,8 @@ android { '-DRELEASE_NUMBER=' + RELEASE_NUMBER, '-DRELEASE_TYPE=' + RELEASE_TYPE, '-DBUILD_BRANCH=' + BUILD_BRANCH, - '-DDISABLE_QML=ON', - '-DDISABLE_KTX_CACHE=ON' + '-DDISABLE_QML=OFF', + '-DDISABLE_KTX_CACHE=OFF' } } } diff --git a/android/build.gradle b/android/build.gradle index 9e5e76f0e3..22273f9059 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -77,8 +77,8 @@ if (Os.isFamily(Os.FAMILY_MAC)) { qtVersionId='HygCmtMLPYioyil0DfXckGVzhw2SXZA9' } else if (Os.isFamily(Os.FAMILY_WINDOWS)) { qtFile = 'qt-5.9.3_win_armv8-libcpp_openssl.tgz' - qtChecksum='a93d22c0c59aa112fda18c4c6d157d17' - qtVersionId='0Bl9NSUWb5CBKLT_NXaxTt75SNBBZ9sB' + qtChecksum='c3e25db64002d0f43cf565e0ef708911' + qtVersionId='HeVObSVLCBoc7yY7He1oBMvPIH0VkClT' } def packages = [ @@ -112,6 +112,13 @@ def packages = [ versionId: 'UTberAIFraEfF9IVjoV66u1DTPTopgeY', checksum: '57fd02baa069176ba18597a29b6b4fc7', ], + nvtt: [ + file: 'nvtt_armv8-libcpp.zip', + versionId: 'vLqrqThvpq4gp75BHMAqO6HhfTXaa0An', + checksum: 'eb46d0b683e66987190ed124aabf8910', + sharedLibFolder: 'lib', + includeLibs: ['libnvtt.so', 'libnvmath.so', 'libnvimage.so', 'libnvcore.so'], + ], openssl: [ file: 'openssl-1.1.0g_armv8.tgz', versionId: 'DmahmSGFS4ltpHyTdyQvv35WOeUOiib9', diff --git a/cmake/macros/TargetNvtt.cmake b/cmake/macros/TargetNvtt.cmake new file mode 100644 index 0000000000..b8198c0cf0 --- /dev/null +++ b/cmake/macros/TargetNvtt.cmake @@ -0,0 +1,26 @@ +# +# Copyright 2015 High Fidelity, Inc. +# Created by Bradley Austin Davis on 2015/10/10 +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +# +macro(TARGET_NVTT) + if (ANDROID) + set(NVTT_INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/nvtt) + set(NVTT_LIB_DIR "${NVTT_INSTALL_DIR}/lib") + set(NVTT_INCLUDE_DIRS "${NVTT_INSTALL_DIR}/include" CACHE TYPE INTERNAL) + list(APPEND NVTT_LIBS "${NVTT_LIB_DIR}/libnvcore.so") + list(APPEND NVTT_LIBS "${NVTT_LIB_DIR}/libnvmath.so") + list(APPEND NVTT_LIBS "${NVTT_LIB_DIR}/libnvimage.so") + list(APPEND NVTT_LIBS "${NVTT_LIB_DIR}/libnvtt.so") + set(NVTT_LIBRARIES ${NVTT_LIBS} CACHE TYPE INTERNAL) + else() + add_dependency_external_projects(nvtt) + find_package(NVTT REQUIRED) + add_paths_to_fixup_libs(${NVTT_DLL_PATH}) + endif() + + target_include_directories(${TARGET_NAME} PRIVATE ${NVTT_INCLUDE_DIRS}) + target_link_libraries(${TARGET_NAME} ${NVTT_LIBRARIES}) +endmacro() diff --git a/interface/resources/controllers/touchscreenvirtualpad.json b/interface/resources/controllers/touchscreenvirtualpad.json new file mode 100644 index 0000000000..8c21044c3b --- /dev/null +++ b/interface/resources/controllers/touchscreenvirtualpad.json @@ -0,0 +1,12 @@ +{ + "name": "TouchscreenVirtualPad to Actions", + "channels": [ + { "from": "TouchscreenVirtualPad.LY", "when": "!Application.CameraIndependent", "filters": { "type": "deadZone", "min": 0.05 }, "to": "Actions.TranslateZ" }, + + { "from": "TouchscreenVirtualPad.LX", "when": "!Application.CameraIndependent", "filters": { "type": "deadZone", "min": 0.05 }, "to": "Actions.TranslateX" }, + + { "from": "TouchscreenVirtualPad.RX", "when": "!Application.CameraIndependent", "filters": { "type": "deadZone", "min": 0.05 }, "to": "Actions.Yaw" }, + + { "from": "TouchscreenVirtualPad.RY", "when": "!Application.CameraIndependent", "to": "Actions.Pitch" } + ] +} diff --git a/interface/resources/icons/+android/backward.svg b/interface/resources/icons/+android/backward.svg new file mode 100644 index 0000000000..ae0893fc66 --- /dev/null +++ b/interface/resources/icons/+android/backward.svg @@ -0,0 +1,70 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/interface/resources/icons/+android/forward.svg b/interface/resources/icons/+android/forward.svg new file mode 100644 index 0000000000..d03c4097d7 --- /dev/null +++ b/interface/resources/icons/+android/forward.svg @@ -0,0 +1,71 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/interface/resources/icons/+android/go-a.svg b/interface/resources/icons/+android/go-a.svg new file mode 100755 index 0000000000..faecb15292 --- /dev/null +++ b/interface/resources/icons/+android/go-a.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + diff --git a/interface/resources/icons/+android/go-i.svg b/interface/resources/icons/+android/go-i.svg new file mode 100644 index 0000000000..0f1298d573 --- /dev/null +++ b/interface/resources/icons/+android/go-i.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + diff --git a/interface/resources/icons/+android/goto-a.svg b/interface/resources/icons/+android/goto-a.svg new file mode 100755 index 0000000000..5fb3e52e4c --- /dev/null +++ b/interface/resources/icons/+android/goto-a.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + diff --git a/interface/resources/icons/+android/goto-i.svg b/interface/resources/icons/+android/goto-i.svg new file mode 100644 index 0000000000..7613beb9e7 --- /dev/null +++ b/interface/resources/icons/+android/goto-i.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + diff --git a/interface/resources/icons/+android/hide.svg b/interface/resources/icons/+android/hide.svg new file mode 100644 index 0000000000..e09d517b08 --- /dev/null +++ b/interface/resources/icons/+android/hide.svg @@ -0,0 +1,947 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/interface/resources/icons/+android/home.svg b/interface/resources/icons/+android/home.svg new file mode 100644 index 0000000000..414c179e79 --- /dev/null +++ b/interface/resources/icons/+android/home.svg @@ -0,0 +1,82 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/interface/resources/icons/+android/mic-mute-a.svg b/interface/resources/icons/+android/mic-mute-a.svg new file mode 100644 index 0000000000..73555ce21b --- /dev/null +++ b/interface/resources/icons/+android/mic-mute-a.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + diff --git a/interface/resources/icons/+android/mic-mute-i.svg b/interface/resources/icons/+android/mic-mute-i.svg new file mode 100644 index 0000000000..56e33eab6b --- /dev/null +++ b/interface/resources/icons/+android/mic-mute-i.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + diff --git a/interface/resources/icons/+android/mic-unmute-a.svg b/interface/resources/icons/+android/mic-unmute-a.svg new file mode 100644 index 0000000000..bb28dc0f2b --- /dev/null +++ b/interface/resources/icons/+android/mic-unmute-a.svg @@ -0,0 +1,70 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/interface/resources/icons/+android/mic-unmute-i.svg b/interface/resources/icons/+android/mic-unmute-i.svg new file mode 100644 index 0000000000..76f98d7f0c --- /dev/null +++ b/interface/resources/icons/+android/mic-unmute-i.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + diff --git a/interface/resources/icons/+android/myview-a.svg b/interface/resources/icons/+android/myview-a.svg new file mode 100755 index 0000000000..307b559c95 --- /dev/null +++ b/interface/resources/icons/+android/myview-a.svg @@ -0,0 +1,56 @@ + + + +image/svg+xmlAsset 3 \ No newline at end of file diff --git a/interface/resources/icons/+android/myview-hover.svg b/interface/resources/icons/+android/myview-hover.svg new file mode 100755 index 0000000000..49656ad294 --- /dev/null +++ b/interface/resources/icons/+android/myview-hover.svg @@ -0,0 +1,54 @@ + + + +image/svg+xmlAsset 3 \ No newline at end of file diff --git a/interface/resources/icons/+android/myview-i.svg b/interface/resources/icons/+android/myview-i.svg new file mode 100755 index 0000000000..574f51c615 --- /dev/null +++ b/interface/resources/icons/+android/myview-i.svg @@ -0,0 +1,56 @@ + + + +image/svg+xmlAsset 3 \ No newline at end of file diff --git a/interface/resources/icons/+android/radar-a.svg b/interface/resources/icons/+android/radar-a.svg new file mode 100755 index 0000000000..e4b157f827 --- /dev/null +++ b/interface/resources/icons/+android/radar-a.svg @@ -0,0 +1 @@ +Asset 1 \ No newline at end of file diff --git a/interface/resources/icons/+android/radar-hover.svg b/interface/resources/icons/+android/radar-hover.svg new file mode 100755 index 0000000000..e4b157f827 --- /dev/null +++ b/interface/resources/icons/+android/radar-hover.svg @@ -0,0 +1 @@ +Asset 1 \ No newline at end of file diff --git a/interface/resources/icons/+android/radar-i.svg b/interface/resources/icons/+android/radar-i.svg new file mode 100755 index 0000000000..3994a775d3 --- /dev/null +++ b/interface/resources/icons/+android/radar-i.svg @@ -0,0 +1 @@ +Asset 1 \ No newline at end of file diff --git a/interface/resources/icons/+android/show-up.svg b/interface/resources/icons/+android/show-up.svg new file mode 100644 index 0000000000..0736b9a794 --- /dev/null +++ b/interface/resources/icons/+android/show-up.svg @@ -0,0 +1,8 @@ + + + + + + diff --git a/interface/resources/images/analog_stick.png b/interface/resources/images/analog_stick.png new file mode 100644 index 0000000000..e9457c7307 Binary files /dev/null and b/interface/resources/images/analog_stick.png differ diff --git a/interface/resources/images/analog_stick_base.png b/interface/resources/images/analog_stick_base.png new file mode 100644 index 0000000000..3b7b8aa8a9 Binary files /dev/null and b/interface/resources/images/analog_stick_base.png differ diff --git a/interface/resources/meshes/+gles/defaultAvatar_full.fst b/interface/resources/meshes/+gles/defaultAvatar_full.fst deleted file mode 100644 index 7d917318dd..0000000000 --- a/interface/resources/meshes/+gles/defaultAvatar_full.fst +++ /dev/null @@ -1,135 +0,0 @@ -name = being_of_light -type = body+head -scale = 1 -filename = being_of_light/being_of_light.fbx -texdir = being_of_light/textures -joint = jointRoot = Hips -joint = jointLeftHand = LeftHand -joint = jointHead = HeadTop_End -joint = jointLean = Spine -joint = jointEyeLeft = LeftEye -joint = jointRightHand = RightHand -joint = jointNeck = Head -joint = jointEyeRight = RightEye -freeJoint = LeftArm -freeJoint = LeftForeArm -freeJoint = RightArm -freeJoint = RightForeArm -bs = MouthFrown_L = Frown_Left = 1 -bs = MouthLeft = Midmouth_Left = 1 -bs = BrowsU_R = BrowsUp_Right = 1 -bs = ChinUpperRaise = UpperLipUp_Right = 0.5 -bs = ChinUpperRaise = UpperLipUp_Left = 0.5 -bs = MouthSmile_R = Smile_Right = 1 -bs = MouthDimple_L = Smile_Left = 0.25 -bs = EyeBlink_L = Blink_Left = 1 -bs = BrowsD_L = BrowsDown_Left = 1 -bs = MouthFrown_R = Frown_Right = 1 -bs = MouthDimple_R = Smile_Right = 0.25 -bs = Sneer = Squint_Right = 0.5 -bs = Sneer = Squint_Left = 0.5 -bs = Sneer = NoseScrunch_Right = 0.75 -bs = Sneer = NoseScrunch_Left = 0.75 -bs = EyeSquint_L = Squint_Left = 1 -bs = EyeBlink_R = Blink_Right = 1 -bs = JawLeft = JawRotateY_Left = 0.5 -bs = BrowsD_R = BrowsDown_Right = 1 -bs = EyeSquint_R = Squint_Right = 1 -bs = Puff = CheekPuff_Right = 1 -bs = Puff = CheekPuff_Left = 1 -bs = LipsUpperClose = UpperLipIn = 1 -bs = JawOpen = MouthOpen = 0.69999999999999996 -bs = LipsUpperUp = UpperLipUp_Right = 0.69999999999999996 -bs = LipsUpperUp = UpperLipUp_Left = 0.69999999999999996 -bs = LipsLowerDown = LowerLipDown_Right = 0.69999999999999996 -bs = LipsLowerDown = LowerLipDown_Left = 0.69999999999999996 -bs = LipsLowerOpen = LowerLipOut = 1 -bs = EyeOpen_L = EyesWide_Left = 1 -bs = LipsPucker = MouthNarrow_Right = 1 -bs = LipsPucker = MouthNarrow_Left = 1 -bs = EyeOpen_R = EyesWide_Right = 1 -bs = JawRight = Jaw_Right = 1 -bs = MouthRight = Midmouth_Right = 1 -bs = ChinLowerRaise = Jaw_Up = 1 -bs = LipsUpperOpen = UpperLipOut = 1 -bs = BrowsU_C = BrowsUp_Right = 1 -bs = BrowsU_C = BrowsUp_Left = 1 -bs = JawFwd = JawForeward = 1 -bs = BrowsU_L = BrowsUp_Left = 1 -bs = MouthSmile_L = Smile_Left = 1 -bs = LipsLowerClose = LowerLipIn = 1 -bs = LipsFunnel = TongueUp = 1 -bs = LipsFunnel = MouthWhistle_NarrowAdjust_Right = 0.5 -bs = LipsFunnel = MouthWhistle_NarrowAdjust_Left = 0.5 -bs = LipsFunnel = MouthNarrow_Right = 1 -bs = LipsFunnel = MouthNarrow_Left = 1 -bs = LipsFunnel = Jaw_Down = 0.35999999999999999 -bs = LipsFunnel = JawForeward = 0.39000000000000001 -jointIndex = LeftHandIndex1 = 50 -jointIndex = LeftHandIndex2 = 51 -jointIndex = LeftHandIndex3 = 52 -jointIndex = LeftHandIndex4 = 53 -jointIndex = Spine1 = 12 -jointIndex = Spine2 = 13 -jointIndex = RightHandThumb1 = 18 -jointIndex = RightHandThumb2 = 19 -jointIndex = RightHandThumb3 = 20 -jointIndex = RightHandThumb4 = 21 -jointIndex = LeftFoot = 8 -jointIndex = LeftForeArm = 40 -jointIndex = Neck = 62 -jointIndex = Head = 63 -jointIndex = Hips = 0 -jointIndex = RightHandPinky1 = 30 -jointIndex = RightHandPinky2 = 31 -jointIndex = RightHandPinky3 = 32 -jointIndex = RightHandPinky4 = 33 -jointIndex = RightLeg = 2 -jointIndex = RightForeArm = 16 -jointIndex = LeftHandRing1 = 46 -jointIndex = LeftHandRing2 = 47 -jointIndex = LeftHandRing3 = 48 -jointIndex = LeftHandRing4 = 49 -jointIndex = LeftHandThumb1 = 54 -jointIndex = LeftHandThumb2 = 55 -jointIndex = LeftHandThumb3 = 56 -jointIndex = LeftHandThumb4 = 57 -jointIndex = HeadTop_End = 66 -jointIndex = LeftUpLeg = 6 -jointIndex = LeftToeBase = 9 -jointIndex = LeftHandPinky1 = 42 -jointIndex = LeftHandPinky2 = 43 -jointIndex = LeftHandPinky3 = 44 -jointIndex = LeftHandPinky4 = 45 -jointIndex = LeftLeg = 7 -jointIndex = RightEye = 65 -jointIndex = RightHand = 17 -jointIndex = RightToeBase = 4 -jointIndex = RightUpLeg = 1 -jointIndex = RightArm = 15 -jointIndex = RightHandRing1 = 26 -jointIndex = RightHandRing2 = 27 -jointIndex = RightHandRing3 = 28 -jointIndex = RightHandRing4 = 29 -jointIndex = RightHandIndex1 = 22 -jointIndex = RightHandIndex2 = 23 -jointIndex = RightHandIndex3 = 24 -jointIndex = RightHandIndex4 = 25 -jointIndex = LeftToe_End = 10 -jointIndex = LeftHandMiddle1 = 58 -jointIndex = LeftHandMiddle2 = 59 -jointIndex = LeftHandMiddle3 = 60 -jointIndex = LeftShoulder = 38 -jointIndex = LeftHandMiddle4 = 61 -jointIndex = RightFoot = 3 -jointIndex = LeftHand = 41 -jointIndex = RightHandMiddle1 = 34 -jointIndex = RightHandMiddle2 = 35 -jointIndex = RightHandMiddle3 = 36 -jointIndex = RightShoulder = 14 -jointIndex = LeftEye = 64 -jointIndex = RightHandMiddle4 = 37 -jointIndex = Body = 67 -jointIndex = LeftArm = 39 -jointIndex = RightToe_End = 5 -jointIndex = Spine = 11 diff --git a/interface/resources/meshes/being_of_light/being_of_light.fbx b/interface/resources/meshes/being_of_light/being_of_light.fbx deleted file mode 100644 index 20e71abd6d..0000000000 Binary files a/interface/resources/meshes/being_of_light/being_of_light.fbx and /dev/null differ diff --git a/interface/resources/meshes/being_of_light/textures/BaseMesh_BeingofLight_DiffuseMap.png b/interface/resources/meshes/being_of_light/textures/BaseMesh_BeingofLight_DiffuseMap.png deleted file mode 100644 index 8fcf588643..0000000000 Binary files a/interface/resources/meshes/being_of_light/textures/BaseMesh_BeingofLight_DiffuseMap.png and /dev/null differ diff --git a/interface/resources/meshes/being_of_light/textures/BaseMesh_BeingofLight_EmissiveMap.png b/interface/resources/meshes/being_of_light/textures/BaseMesh_BeingofLight_EmissiveMap.png deleted file mode 100644 index d836aebde8..0000000000 Binary files a/interface/resources/meshes/being_of_light/textures/BaseMesh_BeingofLight_EmissiveMap.png and /dev/null differ diff --git a/interface/resources/meshes/being_of_light/textures/BaseMesh_BeingofLight_NormalMap.png b/interface/resources/meshes/being_of_light/textures/BaseMesh_BeingofLight_NormalMap.png deleted file mode 100644 index f5000b86e9..0000000000 Binary files a/interface/resources/meshes/being_of_light/textures/BaseMesh_BeingofLight_NormalMap.png and /dev/null differ diff --git a/interface/resources/meshes/mannequin/+gles/Eyes.ktx b/interface/resources/meshes/mannequin/+gles/Eyes.ktx new file mode 100644 index 0000000000..0cccc03dc5 Binary files /dev/null and b/interface/resources/meshes/mannequin/+gles/Eyes.ktx differ diff --git a/interface/resources/meshes/mannequin/+gles/lambert1_Base_Color.ktx b/interface/resources/meshes/mannequin/+gles/lambert1_Base_Color.ktx new file mode 100644 index 0000000000..b0baa696d5 Binary files /dev/null and b/interface/resources/meshes/mannequin/+gles/lambert1_Base_Color.ktx differ diff --git a/interface/resources/meshes/mannequin/+gles/lambert1_Normal_OpenGL.ktx b/interface/resources/meshes/mannequin/+gles/lambert1_Normal_OpenGL.ktx new file mode 100644 index 0000000000..0960d30ce6 Binary files /dev/null and b/interface/resources/meshes/mannequin/+gles/lambert1_Normal_OpenGL.ktx differ diff --git a/interface/resources/meshes/mannequin/+gles/lambert1_Roughness.ktx b/interface/resources/meshes/mannequin/+gles/lambert1_Roughness.ktx new file mode 100644 index 0000000000..6d87e6e337 Binary files /dev/null and b/interface/resources/meshes/mannequin/+gles/lambert1_Roughness.ktx differ diff --git a/interface/resources/qml/+android/AddressBarDialog.qml b/interface/resources/qml/+android/AddressBarDialog.qml new file mode 100644 index 0000000000..0b12301561 --- /dev/null +++ b/interface/resources/qml/+android/AddressBarDialog.qml @@ -0,0 +1,230 @@ +// +// AddressBarDialog.qml +// +// Created by Austin Davis on 2015/04/14 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import Hifi 1.0 +import QtQuick 2.4 +import "../controls" +import "../styles" +import "../hifi" as QmlHifi +import "../hifi/toolbars" +import "../styles-uit" as HifiStyles +import "../controls-uit" as HifiControls + +Item { + QmlHifi.HifiConstants { id: android } + + width: parent ? parent.width - android.dimen.windowLessWidth : 0 + height: parent ? parent.height - android.dimen.windowLessHeight : 0 + z: android.dimen.windowZ + anchors { horizontalCenter: parent.horizontalCenter; bottom: parent.bottom } + + id: bar + property bool isCursorVisible: false // Override default cursor visibility. + property bool shown: true + + onShownChanged: { + bar.visible = shown; + sendToScript({method: 'shownChanged', params: { shown: shown }}); + if (shown) { + updateLocationText(false); + } + } + + function hide() { + shown = false; + sendToScript ({ type: "hide" }); + } + + Component.onCompleted: { + updateLocationText(false); + } + + HifiConstants { id: hifi } + HifiStyles.HifiConstants { id: hifiStyleConstants } + + signal sendToScript(var message); + + AddressBarDialog { + id: addressBarDialog + } + + + Rectangle { + id: background + gradient: Gradient { + GradientStop { position: 0.0; color: android.color.gradientTop } + GradientStop { position: 1.0; color: android.color.gradientBottom } + } + anchors { + fill: parent + } + + QmlHifi.WindowHeader { + id: header + iconSource: "../../../icons/goto-i.svg" + titleText: "GO TO" + } + + HifiStyles.RalewayRegular { + id: notice + text: "YOUR LOCATION" + font.pixelSize: hifi.fonts.pixelSize * 2.15; + color: "#2CD7FF" + anchors { + bottom: addressBackground.top + bottomMargin: 45 + left: addressBackground.left + leftMargin: 60 + } + + } + + property int inputAreaHeight: 210 + property int inputAreaStep: (height - inputAreaHeight) / 2 + + ToolbarButton { + id: homeButton + y: 280 + imageURL: "../../icons/home.svg" + onClicked: { + addressBarDialog.loadHome(); + bar.shown = false; + } + anchors { + leftMargin: 75 + left: parent.left + } + size: 150 + } + + ToolbarButton { + id: backArrow; + imageURL: "../../icons/backward.svg"; + onClicked: addressBarDialog.loadBack(); + anchors { + left: homeButton.right + leftMargin: 70 + verticalCenter: homeButton.verticalCenter + } + size: 150 + } + ToolbarButton { + id: forwardArrow; + imageURL: "../../icons/forward.svg"; + onClicked: addressBarDialog.loadForward(); + anchors { + left: backArrow.right + leftMargin: 60 + verticalCenter: homeButton.verticalCenter + } + size: 150 + } + + HifiStyles.FiraSansRegular { + id: location; + font.pixelSize: addressLine.font.pixelSize; + color: "gray"; + clip: true; + anchors.fill: addressLine; + visible: addressLine.text.length === 0 + z: 1 + } + + Rectangle { + id: addressBackground + x: 780 + y: 280 + width: 1440 + height: 150 + color: "#FFFFFF" + } + + TextInput { + id: addressLine + focus: true + x: 870 + y: 450 + width: 1350 + height: 120 + inputMethodHints: Qt.ImhNoPredictiveText + //helperText: "Hint is here" + anchors { + verticalCenter: homeButton.verticalCenter + } + font.pixelSize: hifi.fonts.pixelSize * 3.75 + onTextChanged: { + //filterChoicesByText(); + updateLocationText(addressLine.text.length > 0); + if (!isCursorVisible && text.length > 0) { + isCursorVisible = true; + cursorVisible = true; + } + } + + onActiveFocusChanged: { + //cursorVisible = isCursorVisible && focus; + } + } + + + + function toggleOrGo() { + if (addressLine.text !== "") { + addressBarDialog.loadAddress(addressLine.text); + } + bar.shown = false; + } + + Keys.onPressed: { + switch (event.key) { + case Qt.Key_Escape: + case Qt.Key_Back: + clearAddressLineTimer.start(); + event.accepted = true + bar.shown = false; + break + case Qt.Key_Enter: + case Qt.Key_Return: + toggleOrGo(); + clearAddressLineTimer.start(); + event.accepted = true + break + } + } + + } + + Timer { + // Delay clearing address line so as to avoid flicker of "not connected" being displayed after entering an address. + id: clearAddressLineTimer + running: false + interval: 100 // ms + repeat: false + onTriggered: { + addressLine.text = ""; + isCursorVisible = false; + } + } + + function updateLocationText(enteringAddress) { + if (enteringAddress) { + notice.text = "Go to a place, @user, path or network address"; + notice.color = "#ffffff"; // hifiStyleConstants.colors.baseGrayHighlight; + location.visible = false; + } else { + notice.text = AddressManager.isConnected ? "YOUR LOCATION:" : "NOT CONNECTED"; + notice.color = AddressManager.isConnected ? hifiStyleConstants.colors.blueHighlight : hifiStyleConstants.colors.redHighlight; + // Display hostname, which includes ip address, localhost, and other non-placenames. + location.text = (AddressManager.placename || AddressManager.hostname || '') + (AddressManager.pathname ? AddressManager.pathname.match(/\/[^\/]+/)[0] : ''); + location.visible = true; + } + } + +} \ No newline at end of file diff --git a/interface/resources/qml/hifi/+android/AudioBar.qml b/interface/resources/qml/hifi/+android/AudioBar.qml new file mode 100644 index 0000000000..f524595ef5 --- /dev/null +++ b/interface/resources/qml/hifi/+android/AudioBar.qml @@ -0,0 +1,71 @@ +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.3 +import Qt.labs.settings 1.0 +import "../../styles-uit" +import "../../controls-uit" as HifiControlsUit +import "../../controls" as HifiControls +import ".." + +Item { + id: bar + x:0 + y:0 + width: 300 + height: 300 + z: -1 + + signal sendToScript(var message); + signal windowClosed(); + + property bool shown: true + + onShownChanged: { + bar.visible = shown; + } + + Rectangle { + anchors.fill : parent + color: "transparent" + Flow { + id: flowMain + spacing: 10 + flow: Flow.TopToBottom + layoutDirection: Flow.TopToBottom + anchors.fill: parent + anchors.margins: 4 + } + } + + Component.onCompleted: { + // put on bottom + x = 0; + y = 0; + width = 300; + height = 300; + } + + function addButton(properties) { + var component = Qt.createComponent("button.qml"); + if (component.status == Component.Ready) { + var button = component.createObject(flowMain); + // copy all properites to button + var keys = Object.keys(properties).forEach(function (key) { + button[key] = properties[key]; + }); + return button; + } else if( component.status == Component.Error) { + console.log("Load button errors " + component.errorString()); + } + } + + function urlHelper(src) { + if (src.match(/\bhttp/)) { + return src; + } else { + return "../../../" + src; + } + } + +} diff --git a/interface/resources/qml/hifi/+android/HifiConstants.qml b/interface/resources/qml/hifi/+android/HifiConstants.qml new file mode 100644 index 0000000000..ee6d92ed38 --- /dev/null +++ b/interface/resources/qml/hifi/+android/HifiConstants.qml @@ -0,0 +1,54 @@ +// +// HifiAndroidConstants.qml +// interface/resources/qml/+android +// +// Created by Gabriel Calero & Cristian Duarte on 23 Oct 2017 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.4 + +Item { + + id: android + + readonly property alias dimen: dimen + readonly property alias color: color + + Item { + id: dimen + readonly property real windowLessWidth: 126 + readonly property real windowLessHeight: 64 + + readonly property real windowZ: 100 + + readonly property real headerHeight: 276 + + readonly property real headerIconPosX: 90 + readonly property real headerIconPosY: 108 + readonly property real headerIconWidth: 111 + readonly property real headerIconHeight: 111 + readonly property real headerIconTitleDistance: 151 + + readonly property real headerHideWidth: 150 + readonly property real headerHideHeight: 150 + readonly property real headerHideRightMargin: 110 + readonly property real headerHideTopMargin: 90 + readonly property real headerHideIconWidth: 70 + readonly property real headerHideIconHeight: 45 + readonly property real headerHideTextTopMargin: 36 + + readonly property real botomHudWidth: 366 + readonly property real botomHudHeight: 180 + + } + + Item { + id: color + readonly property color gradientTop: "#4E4E4E" + readonly property color gradientBottom: "#242424" + } +} diff --git a/interface/resources/qml/hifi/+android/WindowHeader.qml b/interface/resources/qml/hifi/+android/WindowHeader.qml new file mode 100644 index 0000000000..4ec0a0c6e6 --- /dev/null +++ b/interface/resources/qml/hifi/+android/WindowHeader.qml @@ -0,0 +1,113 @@ +// +// WindowHeader.qml +// interface/resources/qml/android +// +// Created by Gabriel Calero & Cristian Duarte on 23 Oct 2017 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.3 +import Qt.labs.settings 1.0 +import "." +import "../styles" as HifiStyles +import "../styles-uit" +import "../controls-uit" as HifiControlsUit +import "../controls" as HifiControls +import ".." + + +// header +Rectangle { + id: header + + // properties + property string iconSource: "" + property string titleText: "" + property var extraItemInCenter: Item {} + + HifiStyles.HifiConstants { id: hifiStylesConstants } + + /*property var mockRectangle: Rectangle { + anchors.fill: parent + color: "#44FFFF00" + }*/ + color: "#00000000" + //color: "#55FF0000" + width: parent.width + height: android.dimen.headerHeight + anchors.top : parent.top + + Image { + id: windowIcon + source: iconSource + x: android.dimen.headerIconPosX + y: android.dimen.headerIconPosY + width: android.dimen.headerIconWidth + height: android.dimen.headerIconHeight + } + + /*HifiStylesUit.*/FiraSansSemiBold { + id: windowTitle + x: windowIcon.x + android.dimen.headerIconTitleDistance + anchors.verticalCenter: windowIcon.verticalCenter + text: titleText + color: "#FFFFFF" + font.letterSpacing: 2 + font.pixelSize: hifiStylesConstants.fonts.headerPixelSize * 2.15 + } + Item { + height: 60 + anchors { + left: windowTitle.right + right: hideButton.left + verticalCenter: windowIcon.verticalCenter + } + children: [ extraItemInCenter/*, mockRectangle */] + } + + Rectangle { + id: hideButton + height: android.dimen.headerHideWidth + width: android.dimen.headerHideHeight + color: "#00000000" + //color: "#CC00FF00" + anchors { + top: parent.top + right: parent.right + rightMargin: android.dimen.headerHideRightMargin + topMargin: android.dimen.headerHideTopMargin + } + Image { + id: hideIcon + source: "../../../icons/hide.svg" + width: android.dimen.headerHideIconWidth + height: android.dimen.headerHideIconHeight + anchors { + horizontalCenter: parent.horizontalCenter + } + } + /*HifiStyles.*/FiraSansRegular { + anchors { + top: hideIcon.bottom + horizontalCenter: hideIcon.horizontalCenter + topMargin: android.dimen.headerHideTextTopMargin + } + text: "HIDE" + color: "#FFFFFF" + font.pixelSize: hifiStylesConstants.fonts.pixelSize * 2.15 + } + + MouseArea { + anchors.fill: parent + onClicked: { + hide(); + } + } + } +} \ No newline at end of file diff --git a/interface/resources/qml/hifi/+android/bottomHudOptions.qml b/interface/resources/qml/hifi/+android/bottomHudOptions.qml new file mode 100644 index 0000000000..860298149f --- /dev/null +++ b/interface/resources/qml/hifi/+android/bottomHudOptions.qml @@ -0,0 +1,89 @@ +// +// bottomHudOptions.qml +// interface/resources/qml/android +// +// Created by Cristian Duarte & Gabriel Calero on 24 Nov 2017 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import Hifi 1.0 +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.3 +import Qt.labs.settings 1.0 +import "../../styles" as HifiStyles +import "../../styles-uit" +import "../../controls-uit" as HifiControlsUit +import "../../controls" as HifiControls +import ".." +import "." + +Item { + id: bottomHud + + property bool shown: false + + signal sendToScript(var message); + + HifiConstants { id: android } + + onShownChanged: { + bottomHud.visible = shown; + } + + function hide() { + shown = false; + } + + Rectangle { + anchors.fill : parent + color: "transparent" + Flow { + id: flowMain + spacing: 0 + flow: Flow.LeftToRight + layoutDirection: Flow.LeftToRight + anchors.fill: parent + anchors.margins: 12 + + Rectangle { + id: hideButton + height: android.dimen.headerHideWidth + width: android.dimen.headerHideHeight + color: "#00000000" + anchors { + horizontalCenter: parent.horizontalCenter + } + Image { + id: hideIcon + source: "../../../icons/show-up.svg" + width: android.dimen.headerHideIconWidth + height: android.dimen.headerHideIconHeight + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + } + + MouseArea { + anchors.fill: parent + onClicked: { + sendToScript ({ method: "showUpBar" }); + } + } + } + } + } + + Component.onCompleted: { + width = android.dimen.botomHudWidth; + height = android.dimen.botomHudHeight; + x=Window.innerWidth - width; + y=Window.innerHeight - height; + } + +} diff --git a/interface/resources/qml/hifi/+android/bottombar.qml b/interface/resources/qml/hifi/+android/bottombar.qml new file mode 100644 index 0000000000..2a34b7fe19 --- /dev/null +++ b/interface/resources/qml/hifi/+android/bottombar.qml @@ -0,0 +1,135 @@ +// +// bottomHudOptions.qml +// interface/resources/qml/android +// +// Created by Gabriel Calero & Cristian Duarte on 19 Jan 2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import Hifi 1.0 +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.3 +import Qt.labs.settings 1.0 +import "../../styles" as Styles +import "../../styles-uit" +import "../../controls-uit" as HifiControlsUit +import "../../controls" as HifiControls +import ".." +import "." + +Item { + id: bar + x:0 + + property bool shown: true + + signal sendToScript(var message); + + onShownChanged: { + bar.visible = shown; + } + + function hide() { + //shown = false; + sendToScript({ method: "hide" }); + } + + Styles.HifiConstants { id: hifi } + HifiConstants { id: android } + + Rectangle { + id: background + anchors.fill : parent + color: "#FF000000" + border.color: "#FFFFFF" + anchors.bottomMargin: -1 + anchors.leftMargin: -1 + anchors.rightMargin: -1 + Flow { + id: flowMain + spacing: 10 + anchors.fill: parent + anchors.topMargin: 12 + anchors.bottomMargin: 12 + anchors.rightMargin: 12 + anchors.leftMargin: 72 + } + + + Rectangle { + id: hideButton + height: android.dimen.headerHideWidth + width: android.dimen.headerHideHeight + color: "#00000000" + anchors { + right: parent.right + rightMargin: android.dimen.headerHideRightMargin + top: parent.top + topMargin: android.dimen.headerHideTopMargin + } + + Image { + id: hideIcon + source: "../../../icons/hide.svg" + width: android.dimen.headerHideIconWidth + height: android.dimen.headerHideIconHeight + anchors { + horizontalCenter: parent.horizontalCenter + top: parent.top + } + } + FiraSansRegular { + anchors { + top: hideIcon.bottom + horizontalCenter: hideIcon.horizontalCenter + topMargin: 12 + } + text: "HIDE" + color: "#FFFFFF" + font.pixelSize: hifi.fonts.pixelSize * 2.5; + } + + MouseArea { + anchors.fill: parent + onClicked: { + hide(); + } + } + } + } + + Component.onCompleted: { + // put on bottom + width = Window.innerWidth; + height = 255; + y = Window.innerHeight - height; + } + + function addButton(properties) { + var component = Qt.createComponent("button.qml"); + if (component.status == Component.Ready) { + var button = component.createObject(flowMain); + // copy all properites to button + var keys = Object.keys(properties).forEach(function (key) { + button[key] = properties[key]; + }); + return button; + } else if( component.status == Component.Error) { + console.log("Load button errors " + component.errorString()); + } + } + + function urlHelper(src) { + if (src.match(/\bhttp/)) { + return src; + } else { + return "../../../" + src; + } + } + +} diff --git a/interface/resources/qml/hifi/+android/button.qml b/interface/resources/qml/hifi/+android/button.qml new file mode 100644 index 0000000000..ec7af2ab92 --- /dev/null +++ b/interface/resources/qml/hifi/+android/button.qml @@ -0,0 +1,230 @@ +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.3 + +Item { + id: button + property string icon: "icons/edit-icon.svg" + property string hoverIcon: button.icon + property string activeIcon: button.icon + property string activeHoverIcon: button.activeIcon + property int stableOrder: 0 + + property int iconSize: 165 + property string text: "." + property string hoverText: button.text + property string activeText: button.text + property string activeHoverText: button.activeText + + property string bgColor: "#ffffff" + property string hoverBgColor: button.bgColor + property string activeBgColor: button.bgColor + property string activeHoverBgColor: button.bgColor + + property real bgOpacity: 0 + property real hoverBgOpacity: 1 + property real activeBgOpacity: 0.5 + property real activeHoverBgOpacity: 1 + + property string textColor: "#ffffff" + property int textSize: 54 + property string hoverTextColor: "#ffffff" + property string activeTextColor: "#ffffff" + property string activeHoverTextColor: "#ffffff" + property int bottomMargin: 30 + + property bool isEntered: false + property double sortOrder: 100 + + property bool isActive: false + + signal clicked() + + onIsActiveChanged: { + if (button.isEntered) { + button.state = (button.isActive) ? "hover active state" : "hover state"; + } else { + button.state = (button.isActive) ? "active state" : "base state"; + } + } + + function editProperties(props) { + for (var prop in props) { + button[prop] = props[prop]; + } + } + + + width: 300 + height: 300 + + Rectangle { + id: buttonBg + color: bgColor + opacity: bgOpacity + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.bottom: parent.bottom + anchors.bottomMargin: 0 + anchors.top: parent.top + anchors.topMargin: 0 + } + Image { + id: icon + width: iconSize + height: iconSize + anchors.bottom: text.top + anchors.bottomMargin: 6 + anchors.horizontalCenter: parent.horizontalCenter + fillMode: Image.Stretch + source: urlHelper(button.icon) + } + FontLoader { + id: firaSans + source: "../../../fonts/FiraSans-Regular.ttf" + } + Text { + id: text + color: "#ffffff" + text: button.text + font.family: "FiraSans" + //font.bold: true + font.pixelSize: textSize + anchors.bottom: parent.bottom + anchors.bottomMargin: bottomMargin + anchors.horizontalCenter: parent.horizontalCenter + horizontalAlignment: Text.AlignHCenter + } + MouseArea { + anchors.fill: parent + hoverEnabled: true + enabled: true + onClicked: { + console.log("Bottom bar button clicked!!"); + /*if (tabletButton.inDebugMode) { + if (tabletButton.isActive) { + tabletButton.isActive = false; + } else { + tabletButton.isActive = true; + } + }*/ + button.clicked(); + /*if (tabletRoot) { + tabletRoot.playButtonClickSound(); + }*/ + } + onEntered: { + button.isEntered = true; + if (button.isActive) { + button.state = "hover active state"; + } else { + button.state = "hover state"; + } + } + onExited: { + button.isEntered = false; + if (button.isActive) { + button.state = "active state"; + } else { + button.state = "base state"; + } + } + } + states: [ + State { + name: "hover state" + + PropertyChanges { + target: buttonBg + //color: "#cfcfcf" + //opacity: 1 + color: button.hoverBgColor + opacity: button.hoverBgOpacity + } + + PropertyChanges { + target: text + //color: "#ffffff" + color: button.hoverTextColor + text: button.hoverText + } + + PropertyChanges { + target: icon + source: urlHelper(button.hoverIcon) + } + }, + State { + name: "active state" + + PropertyChanges { + target: buttonBg + //color: "#1fc6a6" + //opacity: 1 + color: button.activeBgColor + opacity: button.activeBgOpacity + } + + PropertyChanges { + target: text + //color: "#333333" + color: button.activeTextColor + text: button.activeText + } + + PropertyChanges { + target: icon + source: urlHelper(button.activeIcon) + } + }, + State { + name: "hover active state" + + PropertyChanges { + target: buttonBg + //color: "#ff0000" + //opacity: 1 + color: button.activeHoverBgColor + opacity: button.activeHoverBgOpacity + } + + PropertyChanges { + target: text + //color: "#333333" + color: button.activeHoverTextColor + text: button.activeHoverText + } + + PropertyChanges { + target: icon + source: urlHelper(button.activeHoverIcon) + } + }, + State { + name: "base state" + + PropertyChanges { + target: buttonBg + //color: "#9A9A9A" + //opacity: 0.1 + color: button.bgColor + opacity: button.bgOpacity + } + + PropertyChanges { + target: text + //color: "#ffffff" + color: button.textColor + text: button.text + } + + PropertyChanges { + target: icon + source: urlHelper(button.icon) + } + } + ] +} \ No newline at end of file diff --git a/interface/resources/qml/hifi/+android/modesbar.qml b/interface/resources/qml/hifi/+android/modesbar.qml new file mode 100644 index 0000000000..8ce455c2c1 --- /dev/null +++ b/interface/resources/qml/hifi/+android/modesbar.qml @@ -0,0 +1,73 @@ +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.3 +import Qt.labs.settings 1.0 +import "../../styles-uit" +import "../../controls-uit" as HifiControlsUit +import "../../controls" as HifiControls +import ".." + +Item { + id: modesbar + y:60 + Rectangle { + anchors.fill : parent + color: "transparent" + Flow { + id: flowMain + spacing: 0 + flow: Flow.TopToBottom + layoutDirection: Flow.TopToBottom + anchors.fill: parent + anchors.margins: 4 + } + } + + Component.onCompleted: { + width = 330; + height = 330; + x=Window.innerWidth - width; + } + + function addButton(properties) { + var component = Qt.createComponent("button.qml"); + console.log("load button"); + if (component.status == Component.Ready) { + console.log("load button 2"); + var button = component.createObject(flowMain); + // copy all properites to button + var keys = Object.keys(properties).forEach(function (key) { + button[key] = properties[key]; + }); + return button; + } else if( component.status == Component.Error) { + console.log("Load button errors " + component.errorString()); + } + } + + function removeButton(name) { + } + + function urlHelper(src) { + if (src.match(/\bhttp/)) { + return src; + } else { + return "../../../" + src; + } + } + + function fromScript(message) { + switch (message.type) { + case "allButtonsShown": + modesbar.height = flowMain.children.length * 100 + 10; + break; + case "inactiveButtonsHidden": + modesbar.height = 100 + 10; + break; + default: + break; + } + } + +} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a373926361..7ba545114b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -69,6 +69,7 @@ #include #include #include +#include #include #include #include @@ -137,6 +138,7 @@ #include #include #include +#include #include #include #include @@ -777,6 +779,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); DependencyManager::set(); DependencyManager::set(std::bind(&Application::getUserAgent, qApp)); DependencyManager::set(); @@ -1522,12 +1525,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo return DependencyManager::get()->navigationFocused() ? 1 : 0; }); - // Setup the _keyboardMouseDevice, _touchscreenDevice and the user input mapper with the default bindings + // Setup the _keyboardMouseDevice, _touchscreenDevice, _touchscreenVirtualPadDevice and the user input mapper with the default bindings userInputMapper->registerDevice(_keyboardMouseDevice->getInputDevice()); // if the _touchscreenDevice is not supported it will not be registered if (_touchscreenDevice) { userInputMapper->registerDevice(_touchscreenDevice->getInputDevice()); } + if (_touchscreenVirtualPadDevice) { + userInputMapper->registerDevice(_touchscreenVirtualPadDevice->getInputDevice()); + } // this will force the model the look at the correct directory (weird order of operations issue) scriptEngines->reloadLocalFiles(); @@ -2615,6 +2621,9 @@ void Application::initializeUi() { if (TouchscreenDevice::NAME == inputPlugin->getName()) { _touchscreenDevice = std::dynamic_pointer_cast(inputPlugin); } + if (TouchscreenVirtualPadDevice::NAME == inputPlugin->getName()) { + _touchscreenVirtualPadDevice = std::dynamic_pointer_cast(inputPlugin); + } } auto compositorHelper = DependencyManager::get(); @@ -3021,7 +3030,9 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { // If this is a first run we short-circuit the address passed in if (firstRun.get()) { +#if !defined(Q_OS_ANDROID) showHelp(); +#endif if (sandboxIsRunning) { qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home."; DependencyManager::get()->goToLocalSandbox(); @@ -3805,6 +3816,9 @@ void Application::touchUpdateEvent(QTouchEvent* event) { if (_touchscreenDevice && _touchscreenDevice->isActive()) { _touchscreenDevice->touchUpdateEvent(event); } + if (_touchscreenVirtualPadDevice && _touchscreenVirtualPadDevice->isActive()) { + _touchscreenVirtualPadDevice->touchUpdateEvent(event); + } } void Application::touchBeginEvent(QTouchEvent* event) { @@ -3826,6 +3840,9 @@ void Application::touchBeginEvent(QTouchEvent* event) { if (_touchscreenDevice && _touchscreenDevice->isActive()) { _touchscreenDevice->touchBeginEvent(event); } + if (_touchscreenVirtualPadDevice && _touchscreenVirtualPadDevice->isActive()) { + _touchscreenVirtualPadDevice->touchBeginEvent(event); + } } @@ -3846,7 +3863,9 @@ void Application::touchEndEvent(QTouchEvent* event) { if (_touchscreenDevice && _touchscreenDevice->isActive()) { _touchscreenDevice->touchEndEvent(event); } - + if (_touchscreenVirtualPadDevice && _touchscreenVirtualPadDevice->isActive()) { + _touchscreenVirtualPadDevice->touchEndEvent(event); + } // put any application specific touch behavior below here.. } @@ -3854,6 +3873,9 @@ void Application::touchGestureEvent(QGestureEvent* event) { if (_touchscreenDevice && _touchscreenDevice->isActive()) { _touchscreenDevice->touchGestureEvent(event); } + if (_touchscreenVirtualPadDevice && _touchscreenVirtualPadDevice->isActive()) { + _touchscreenVirtualPadDevice->touchGestureEvent(event); + } } void Application::wheelEvent(QWheelEvent* event) const { @@ -5336,7 +5358,9 @@ void Application::update(float deltaTime) { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::update()"); +#if !defined(Q_OS_ANDROID) updateLOD(deltaTime); +#endif // TODO: break these out into distinct perfTimers when they prove interesting { @@ -6065,6 +6089,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe scriptEngine->registerFunction("OverlayWebWindow", QmlWebWindowClass::constructor); #endif scriptEngine->registerFunction("OverlayWindow", QmlWindowClass::constructor); + scriptEngine->registerFunction("QmlFragment", QmlFragmentClass::constructor); scriptEngine->registerGlobalObject("Menu", MenuScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("DesktopPreviewProvider", DependencyManager::get().data()); diff --git a/interface/src/Application.h b/interface/src/Application.h index 8a0d3c2351..1214ca4df4 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -554,6 +555,7 @@ private: std::shared_ptr _applicationStateDevice; // Default ApplicationDevice reflecting the state of different properties of the session std::shared_ptr _keyboardMouseDevice; // Default input device, the good old keyboard mouse and maybe touchpad std::shared_ptr _touchscreenDevice; // the good old touchscreen + std::shared_ptr _touchscreenVirtualPadDevice; SimpleMovingAverage _avatarSimsPerSecond {10}; int _avatarSimsPerSecondReport {0}; quint64 _lastAvatarSimsPerSecondUpdate {0}; diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 4848531de7..95be7b29e9 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -16,6 +16,7 @@ #include #include "Application.h" +#include "VirtualPadManager.h" bool ControllerScriptingInterface::isKeyCaptured(QKeyEvent* event) const { return isKeyCaptured(KeyEvent(*event)); @@ -83,6 +84,11 @@ QVariant ControllerScriptingInterface::getRecommendedHUDRect() const { return qRectToVariant(rect); } +void ControllerScriptingInterface::setVPadEnabled(const bool enable) { + auto& virtualPadManager = VirtualPad::Manager::instance(); + virtualPadManager.enable(enable); +} + void ControllerScriptingInterface::emitKeyPressEvent(QKeyEvent* event) { emit keyPressEvent(KeyEvent(*event)); } void ControllerScriptingInterface::emitKeyReleaseEvent(QKeyEvent* event) { emit keyReleaseEvent(KeyEvent(*event)); } diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index 7a2c964622..1f223814a3 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -65,6 +65,8 @@ public slots: virtual glm::vec2 getViewportDimensions() const; virtual QVariant getRecommendedHUDRect() const; + virtual void setVPadEnabled(bool enable); + signals: void keyPressEvent(const KeyEvent& event); void keyReleaseEvent(const KeyEvent& event); diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 8379151d1c..873d294303 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -53,10 +53,16 @@ #include "AudioClient.h" const int AudioClient::MIN_BUFFER_FRAMES = 1; + const int AudioClient::MAX_BUFFER_FRAMES = 20; static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 100; +#if defined(Q_OS_ANDROID) +static const int CHECK_INPUT_READS_MSECS = 2000; +static const int MIN_READS_TO_CONSIDER_INPUT_ALIVE = 100; +#endif + static const auto DEFAULT_POSITION_GETTER = []{ return Vectors::ZERO; }; static const auto DEFAULT_ORIENTATION_GETTER = [] { return Quaternions::IDENTITY; }; @@ -197,6 +203,9 @@ AudioClient::AudioClient() : _audioOutputIODevice(_localInjectorsStream, _receivedAudioStream, this), _stats(&_receivedAudioStream), _positionGetter(DEFAULT_POSITION_GETTER), +#if defined(Q_OS_ANDROID) + _checkInputTimer(this), +#endif _orientationGetter(DEFAULT_ORIENTATION_GETTER) { // avoid putting a lock in the device callback assert(_localSamplesAvailable.is_lock_free()); @@ -278,6 +287,9 @@ void AudioClient::cleanupBeforeQuit() { return; } +#if defined(Q_OS_ANDROID) + _shouldRestartInputSetup = false; +#endif stop(); _checkDevicesTimer->stop(); _checkPeakValuesTimer->stop(); @@ -622,6 +634,12 @@ void AudioClient::start() { qCDebug(audioclient) << "Unable to set up audio output because of a problem with output format."; qCDebug(audioclient) << "The closest format available is" << outputDeviceInfo.nearestFormat(_desiredOutputFormat); } +#if defined(Q_OS_ANDROID) + connect(&_checkInputTimer, &QTimer::timeout, [this] { + checkInputTimeout(); + }); + _checkInputTimer.start(CHECK_INPUT_READS_MSECS); +#endif } void AudioClient::stop() { @@ -631,6 +649,9 @@ void AudioClient::stop() { qCDebug(audioclient) << "AudioClient::stop(), requesting switchOutputToAudioDevice() to shut down"; switchOutputToAudioDevice(QAudioDeviceInfo(), true); +#if defined(Q_OS_ANDROID) + _checkInputTimer.stop(); +#endif } void AudioClient::handleAudioEnvironmentDataPacket(QSharedPointer message) { @@ -1090,6 +1111,10 @@ void AudioClient::handleMicAudioInput() { return; } +#if defined(Q_OS_ANDROID) + _inputReadsSinceLastCheck++; +#endif + // input samples required to produce exactly NETWORK_FRAME_SAMPLES of output const int inputSamplesRequired = (_inputToNetworkResampler ? _inputToNetworkResampler->getMinInput(AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL) : @@ -1434,6 +1459,10 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInf // NOTE: device start() uses the Qt internal device list Lock lock(_deviceMutex); +#if defined(Q_OS_ANDROID) + _shouldRestartInputSetup = false; // avoid a double call to _audioInput->start() from audioInputStateChanged +#endif + // cleanup any previously initialized device if (_audioInput) { // The call to stop() causes _inputDevice to be destructed. @@ -1514,7 +1543,10 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInf #if defined(Q_OS_ANDROID) if (_audioInput) { - connect(_audioInput, SIGNAL(stateChanged(QAudio::State)), this, SLOT(audioInputStateChanged(QAudio::State))); + _shouldRestartInputSetup = true; + connect(_audioInput, &QAudioInput::stateChanged, [this](QAudio::State state) { + audioInputStateChanged(state); + }); } #endif _inputDevice = _audioInput->start(); @@ -1555,14 +1587,14 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInf return supportedFormat; } -#if defined(Q_OS_ANDROID) void AudioClient::audioInputStateChanged(QAudio::State state) { +#if defined(Q_OS_ANDROID) switch (state) { case QAudio::StoppedState: if (!_audioInput) { break; } - // Stopped on purpose + // Stopped on purpose if (_shouldRestartInputSetup) { Lock lock(_deviceMutex); _inputDevice = _audioInput->start(); @@ -1577,8 +1609,18 @@ void AudioClient::audioInputStateChanged(QAudio::State state) { default: break; } -} #endif +} + +void AudioClient::checkInputTimeout() { +#if defined(Q_OS_ANDROID) + if (_audioInput && _inputReadsSinceLastCheck < MIN_READS_TO_CONSIDER_INPUT_ALIVE) { + _audioInput->stop(); + } else { + _inputReadsSinceLastCheck = 0; + } +#endif +} void AudioClient::outputNotify() { int recentUnfulfilled = _audioOutputIODevice.getRecentUnfulfilledReads(); diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 0643b8e52a..3e6e83b598 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -26,7 +26,6 @@ #include #include #include - #include #include #include @@ -183,9 +182,8 @@ public slots: void sendDownstreamAudioStatsPacket() { _stats.publish(); } void handleMicAudioInput(); -#if defined(Q_OS_ANDROID) void audioInputStateChanged(QAudio::State state); -#endif + void checkInputTimeout(); void handleDummyAudioInput(); void handleRecordedAudioInput(const QByteArray& audio); void reset(); @@ -276,6 +274,11 @@ private: float azimuthForSource(const glm::vec3& relativePosition); float gainForSource(float distance, float volume); +#ifdef Q_OS_ANDROID + QTimer _checkInputTimer; + long _inputReadsSinceLastCheck = 0l; +#endif + class Gate { public: Gate(AudioClient* audioClient); diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 588c43d534..1a1714ad56 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -6,6 +6,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "Basic2DWindowOpenGLDisplayPlugin.h" +#include "CompositorHelper.h" +#include "VirtualPadManager.h" #include @@ -14,13 +16,65 @@ #include #include +#include const QString Basic2DWindowOpenGLDisplayPlugin::NAME("Desktop"); static const QString FULLSCREEN = "Fullscreen"; +void Basic2DWindowOpenGLDisplayPlugin::customizeContext() { + auto iconPath = PathUtils::resourcesPath() + "images/analog_stick.png"; + auto image = QImage(iconPath); + if (image.format() != QImage::Format_ARGB32) { + image = image.convertToFormat(QImage::Format_ARGB32); + } + if ((image.width() > 0) && (image.height() > 0)) { + + _virtualPadStickTexture = gpu::Texture::createStrict( + gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), + image.width(), image.height(), + gpu::Texture::MAX_NUM_MIPS, + gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); + _virtualPadStickTexture->setSource("virtualPad stick"); + auto usage = gpu::Texture::Usage::Builder().withColor().withAlpha(); + _virtualPadStickTexture->setUsage(usage.build()); + _virtualPadStickTexture->setStoredMipFormat(gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); + _virtualPadStickTexture->assignStoredMip(0, image.byteCount(), image.constBits()); + _virtualPadStickTexture->setAutoGenerateMips(true); + } + + iconPath = PathUtils::resourcesPath() + "images/analog_stick_base.png"; + image = QImage(iconPath); + if (image.format() != QImage::Format_ARGB32) { + image = image.convertToFormat(QImage::Format_ARGB32); + } + if ((image.width() > 0) && (image.height() > 0)) { + _virtualPadStickBaseTexture = gpu::Texture::createStrict( + gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), + image.width(), image.height(), + gpu::Texture::MAX_NUM_MIPS, + gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); + _virtualPadStickBaseTexture->setSource("virtualPad base"); + auto usage = gpu::Texture::Usage::Builder().withColor().withAlpha(); + _virtualPadStickBaseTexture->setUsage(usage.build()); + _virtualPadStickBaseTexture->setStoredMipFormat(gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); + _virtualPadStickBaseTexture->assignStoredMip(0, image.byteCount(), image.constBits()); + _virtualPadStickBaseTexture->setAutoGenerateMips(true); + } + + + Parent::customizeContext(); +} + +void Basic2DWindowOpenGLDisplayPlugin::uncustomizeContext() { + Parent::uncustomizeContext(); +} + bool Basic2DWindowOpenGLDisplayPlugin::internalActivate() { _framerateActions.clear(); +#if defined(Q_OS_ANDROID) + _container->setFullscreen(nullptr, true); +#endif _container->addMenuItem(PluginType::DISPLAY_PLUGIN, MENU_PATH(), FULLSCREEN, [this](bool clicked) { if (clicked) { @@ -33,6 +87,37 @@ bool Basic2DWindowOpenGLDisplayPlugin::internalActivate() { return Parent::internalActivate(); } +void Basic2DWindowOpenGLDisplayPlugin::compositeExtra() { + auto& virtualPadManager = VirtualPad::Manager::instance(); + if(virtualPadManager.getLeftVirtualPad()->isBeingTouched()) { + // render stick base + auto stickBaseTransform = DependencyManager::get()->getPoint2DTransform(virtualPadManager.getLeftVirtualPad()->getFirstTouch()); + render([&](gpu::Batch& batch) { + batch.enableStereo(false); + batch.setProjectionTransform(mat4()); + batch.setPipeline(_cursorPipeline); + batch.setResourceTexture(0, _virtualPadStickBaseTexture); + batch.resetViewTransform(); + batch.setModelTransform(stickBaseTransform); + batch.setViewportTransform(ivec4(uvec2(0), getRecommendedRenderSize())); + batch.draw(gpu::TRIANGLE_STRIP, 4); + }); + // render stick head + auto stickTransform = DependencyManager::get()->getPoint2DTransform(virtualPadManager.getLeftVirtualPad()->getCurrentTouch()); + render([&](gpu::Batch& batch) { + batch.enableStereo(false); + batch.setProjectionTransform(mat4()); + batch.setPipeline(_cursorPipeline); + batch.setResourceTexture(0, _virtualPadStickTexture); + batch.resetViewTransform(); + batch.setModelTransform(stickTransform); + batch.setViewportTransform(ivec4(uvec2(0), getRecommendedRenderSize())); + batch.draw(gpu::TRIANGLE_STRIP, 4); + }); + } + Parent::compositeExtra(); +} + static const uint32_t MIN_THROTTLE_CHECK_FRAMES = 60; bool Basic2DWindowOpenGLDisplayPlugin::isThrottled() const { diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h index f3dd50602c..d9b942bd97 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h @@ -22,10 +22,15 @@ public: virtual float getTargetFrameRate() const override { return _framerateTarget ? (float) _framerateTarget : TARGET_FRAMERATE_Basic2DWindowOpenGL; } + virtual void customizeContext() override; + virtual void uncustomizeContext() override; + virtual bool internalActivate() override; virtual bool isThrottled() const override; + virtual void compositeExtra() override; + protected: mutable bool _isThrottled = false; @@ -36,4 +41,7 @@ private: QAction* _vsyncAction { nullptr }; uint32_t _framerateTarget { 0 }; int _fullscreenTarget{ -1 }; + + gpu::TexturePointer _virtualPadStickTexture; + gpu::TexturePointer _virtualPadStickBaseTexture; }; diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp index f3f81c0b2e..74225b5b39 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp @@ -458,6 +458,22 @@ glm::mat4 CompositorHelper::getReticleTransform(const glm::mat4& eyePose, const return result; } +glm::mat4 CompositorHelper::getPoint2DTransform(const glm::vec2& point) const { + glm::mat4 result; + static const float PIXEL_SIZE = 512.0f; + const auto canvasSize = vec2(toGlm(_renderingWidget->size()));; + QPoint qPoint(point.x,point.y); + vec2 position = toGlm(_renderingWidget->mapFromGlobal(qPoint)); + position /= canvasSize; + position *= 2.0; + position -= 1.0; + position.y *= -1.0f; + + vec2 size = PIXEL_SIZE / canvasSize; + result = glm::scale(glm::translate(glm::mat4(), vec3(position, 0.0f)), vec3(size, 1.0f)); + return result; +} + QVariant ReticleInterface::getPosition() const { return vec2toVariant(_compositor->getReticlePosition()); diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.h b/libraries/display-plugins/src/display-plugins/CompositorHelper.h index 6c2acb7e62..5b65315f45 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.h +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.h @@ -90,6 +90,7 @@ public: glm::vec2 getReticleMaximumPosition() const; glm::mat4 getReticleTransform(const glm::mat4& eyePose = glm::mat4(), const glm::vec3& headPosition = glm::vec3()) const; + glm::mat4 getPoint2DTransform(const glm::vec2& point = glm::vec2()) const; ReticleInterface* getReticleInterface() { return _reticleInterface; } diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index 090891fe62..119a46b68f 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -68,7 +68,6 @@ ShapeKey MaterialEntityRenderer::getShapeKey() { bool isTranslucent = drawMaterialKey.isTranslucent(); bool hasTangents = drawMaterialKey.isNormalMap(); - bool hasSpecular = drawMaterialKey.isMetallicMap(); bool hasLightmap = drawMaterialKey.isLightmapMap(); bool isUnlit = drawMaterialKey.isUnlit(); @@ -81,9 +80,6 @@ ShapeKey MaterialEntityRenderer::getShapeKey() { if (hasTangents) { builder.withTangents(); } - if (hasSpecular) { - builder.withSpecular(); - } if (hasLightmap) { builder.withLightmap(); } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index da80924184..0ed328315b 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1516,6 +1516,12 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c } } + if (isAdd && properties.getLocked() && !senderNode->isAllowedEditor()) { + // if a node can't change locks, don't allow them to create an already-locked entity + properties.setLocked(false); + bumpTimestamp(properties); + } + // If we got a valid edit packet, then it could be a new entity or it could be an update to // an existing entity... handle appropriately if (validEditPacket) { diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index c432e19368..7141a7eac7 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -14,9 +14,12 @@ #include +#include "GPULogging.h" + #if defined(NSIGHT_FOUND) #include "nvToolsExt.h" + ProfileRangeBatch::ProfileRangeBatch(gpu::Batch& batch, const char *name) : _batch(batch) { _batch.pushProfileRange(name); } @@ -30,6 +33,11 @@ ProfileRangeBatch::~ProfileRangeBatch() { using namespace gpu; +// FIXME make these backend / pipeline dependent. +static const int MAX_NUM_UNIFORM_BUFFERS = 12; +static const int MAX_NUM_RESOURCE_BUFFERS = 16; +static const int MAX_NUM_RESOURCE_TEXTURES = 16; + size_t Batch::_commandsMax { BATCH_PREALLOCATE_MIN }; size_t Batch::_commandOffsetsMax { BATCH_PREALLOCATE_MIN }; size_t Batch::_paramsMax { BATCH_PREALLOCATE_MIN }; @@ -281,7 +289,9 @@ void Batch::setStateScissorRect(const Vec4i& rect) { void Batch::setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size) { ADD_COMMAND(setUniformBuffer); - + if (slot >= MAX_NUM_UNIFORM_BUFFERS) { + qCWarning(gpulogging) << "Slot" << slot << "exceeds max uniform buffer count of" << MAX_NUM_UNIFORM_BUFFERS; + } _params.emplace_back(size); _params.emplace_back(offset); _params.emplace_back(_buffers.cache(buffer)); @@ -294,6 +304,9 @@ void Batch::setUniformBuffer(uint32 slot, const BufferView& view) { void Batch::setResourceBuffer(uint32 slot, const BufferPointer& buffer) { ADD_COMMAND(setResourceBuffer); + if (slot >= MAX_NUM_RESOURCE_BUFFERS) { + qCWarning(gpulogging) << "Slot" << slot << "exceeds max resources buffer count of" << MAX_NUM_RESOURCE_BUFFERS; + } _params.emplace_back(_buffers.cache(buffer)); _params.emplace_back(slot); @@ -302,6 +315,10 @@ void Batch::setResourceBuffer(uint32 slot, const BufferPointer& buffer) { void Batch::setResourceTexture(uint32 slot, const TexturePointer& texture) { ADD_COMMAND(setResourceTexture); + if (slot >= MAX_NUM_RESOURCE_TEXTURES) { + qCWarning(gpulogging) << "Slot" << slot << "exceeds max texture count of" << MAX_NUM_RESOURCE_TEXTURES; + } + _params.emplace_back(_textures.cache(texture)); _params.emplace_back(slot); } diff --git a/libraries/graphics/src/graphics/Light.slh b/libraries/graphics/src/graphics/Light.slh index 12ac1f3c4b..20394816c9 100644 --- a/libraries/graphics/src/graphics/Light.slh +++ b/libraries/graphics/src/graphics/Light.slh @@ -32,9 +32,16 @@ vec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradi // AMbient lighting needs extra info provided from a different Buffer <@include graphics/SphericalHarmonics.shared.slh@> // Light Ambient -struct LightAmbient { - vec4 _ambient; +#ifndef PRECISIONQ +#ifdef GL_ES +#define PRECISIONQ highp +#else +#define PRECISIONQ +#endif +#endif +struct LightAmbient { + PRECISIONQ vec4 _ambient; SphericalHarmonics _ambientSphere; mat4 transform; }; diff --git a/libraries/graphics/src/graphics/LightIrradiance.shared.slh b/libraries/graphics/src/graphics/LightIrradiance.shared.slh index 13d6cf4b93..ff42f57fd9 100644 --- a/libraries/graphics/src/graphics/LightIrradiance.shared.slh +++ b/libraries/graphics/src/graphics/LightIrradiance.shared.slh @@ -12,11 +12,17 @@ #define LightIrradianceConstRef LightIrradiance - +#ifndef PRECISIONQ +#ifdef GL_ES +#define PRECISIONQ highp +#else +#define PRECISIONQ +#endif +#endif struct LightIrradiance { - vec4 colorIntensity; + PRECISIONQ vec4 colorIntensity; // falloffRadius, cutoffRadius, falloffSpot, spare - vec4 attenuation; + PRECISIONQ vec4 attenuation; }; diff --git a/libraries/graphics/src/graphics/LightVolume.shared.slh b/libraries/graphics/src/graphics/LightVolume.shared.slh index 3f0cb135f5..48249e766f 100644 --- a/libraries/graphics/src/graphics/LightVolume.shared.slh +++ b/libraries/graphics/src/graphics/LightVolume.shared.slh @@ -15,9 +15,17 @@ #define LightVolumeConstRef LightVolume +#ifndef PRECISIONQ +#ifdef GL_ES +#define PRECISIONQ highp +#else +#define PRECISIONQ +#endif +#endif + struct LightVolume { - vec4 positionRadius; - vec4 directionSpotCos; + PRECISIONQ vec4 positionRadius; + PRECISIONQ vec4 directionSpotCos; }; bool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); } diff --git a/libraries/graphics/src/graphics/Material.slh b/libraries/graphics/src/graphics/Material.slh index 2faf2d8569..f9f4144748 100644 --- a/libraries/graphics/src/graphics/Material.slh +++ b/libraries/graphics/src/graphics/Material.slh @@ -11,11 +11,21 @@ <@if not MODEL_MATERIAL_SLH@> <@def MODEL_MATERIAL_SLH@> -struct Material { - vec4 _emissiveOpacity; - vec4 _albedoRoughness; - vec4 _fresnelMetallic; - vec4 _scatteringSpare2Key; +// The material values (at least the material key) must be precisely bitwise accurate +// to what is provided by the uniform buffer, or the material key has the wrong bits +#ifdef GL_ES +precision highp float; +#define BITFIELD highp int +#define PRECISIONQ highp +#else +#define BITFIELD int +#define PRECISIONQ +#endif +struct Material { + PRECISIONQ vec4 _emissiveOpacity; + PRECISIONQ vec4 _albedoRoughness; + PRECISIONQ vec4 _fresnelMetallic; + PRECISIONQ vec4 _scatteringSpare2Key; }; uniform materialBuffer { @@ -39,27 +49,29 @@ float getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); } float getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; } -int getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); } +BITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); } -const int EMISSIVE_VAL_BIT = 0x00000001; -const int UNLIT_VAL_BIT = 0x00000002; -const int ALBEDO_VAL_BIT = 0x00000004; -const int METALLIC_VAL_BIT = 0x00000008; -const int GLOSSY_VAL_BIT = 0x00000010; -const int OPACITY_VAL_BIT = 0x00000020; -const int OPACITY_MASK_MAP_BIT = 0x00000040; -const int OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080; -const int SCATTERING_VAL_BIT = 0x00000100; +const BITFIELD EMISSIVE_VAL_BIT = 0x00000001; +const BITFIELD UNLIT_VAL_BIT = 0x00000002; +const BITFIELD ALBEDO_VAL_BIT = 0x00000004; +const BITFIELD METALLIC_VAL_BIT = 0x00000008; +const BITFIELD GLOSSY_VAL_BIT = 0x00000010; +const BITFIELD OPACITY_VAL_BIT = 0x00000020; +const BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040; +const BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080; +const BITFIELD SCATTERING_VAL_BIT = 0x00000100; -const int EMISSIVE_MAP_BIT = 0x00000200; -const int ALBEDO_MAP_BIT = 0x00000400; -const int METALLIC_MAP_BIT = 0x00000800; -const int ROUGHNESS_MAP_BIT = 0x00001000; -const int NORMAL_MAP_BIT = 0x00002000; -const int OCCLUSION_MAP_BIT = 0x00004000; -const int LIGHTMAP_MAP_BIT = 0x00008000; -const int SCATTERING_MAP_BIT = 0x00010000; - +const BITFIELD EMISSIVE_MAP_BIT = 0x00000200; +const BITFIELD ALBEDO_MAP_BIT = 0x00000400; +const BITFIELD METALLIC_MAP_BIT = 0x00000800; +const BITFIELD ROUGHNESS_MAP_BIT = 0x00001000; +const BITFIELD NORMAL_MAP_BIT = 0x00002000; +const BITFIELD OCCLUSION_MAP_BIT = 0x00004000; +const BITFIELD LIGHTMAP_MAP_BIT = 0x00008000; +const BITFIELD SCATTERING_MAP_BIT = 0x00010000; +#ifdef GL_ES +precision lowp float; +#endif <@endif@> diff --git a/libraries/graphics/src/graphics/SphericalHarmonics.shared.slh b/libraries/graphics/src/graphics/SphericalHarmonics.shared.slh index 312824c5a3..72a505fa25 100644 --- a/libraries/graphics/src/graphics/SphericalHarmonics.shared.slh +++ b/libraries/graphics/src/graphics/SphericalHarmonics.shared.slh @@ -15,16 +15,24 @@ #define SphericalHarmonicsConstRef SphericalHarmonics +#ifndef PRECISIONQ +#ifdef GL_ES +#define PRECISIONQ highp +#else +#define PRECISIONQ +#endif +#endif + struct SphericalHarmonics { - vec4 L00; - vec4 L1m1; - vec4 L10; - vec4 L11; - vec4 L2m2; - vec4 L2m1; - vec4 L20; - vec4 L21; - vec4 L22; + PRECISIONQ vec4 L00; + PRECISIONQ vec4 L1m1; + PRECISIONQ vec4 L10; + PRECISIONQ vec4 L11; + PRECISIONQ vec4 L2m2; + PRECISIONQ vec4 L2m1; + PRECISIONQ vec4 L20; + PRECISIONQ vec4 L21; + PRECISIONQ vec4 L22; }; vec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) { diff --git a/libraries/image/CMakeLists.txt b/libraries/image/CMakeLists.txt index e6a1856327..8073cc2b5e 100644 --- a/libraries/image/CMakeLists.txt +++ b/libraries/image/CMakeLists.txt @@ -1,12 +1,4 @@ set(TARGET_NAME image) setup_hifi_library() link_hifi_libraries(shared gpu) - -if (NOT ANDROID) - add_dependency_external_projects(nvtt) - find_package(NVTT REQUIRED) - - target_include_directories(${TARGET_NAME} PRIVATE ${NVTT_INCLUDE_DIRS}) - target_link_libraries(${TARGET_NAME} ${NVTT_LIBRARIES}) - add_paths_to_fixup_libs(${NVTT_DLL_PATH}) -endif() +target_nvtt() diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index 9115dd09e2..696e311495 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -28,12 +28,8 @@ using namespace gpu; -#if defined(Q_OS_ANDROID) -#define CPU_MIPMAPS 1 -#else #define CPU_MIPMAPS 1 #include -#endif static const glm::uvec2 SPARSE_PAGE_SIZE(128); static const glm::uvec2 MAX_TEXTURE_SIZE(4096); @@ -679,7 +675,6 @@ void generateLDRMips(gpu::Texture* texture, QImage&& image, const std::atomic& abortProcessing = false, int face = -1) { #if CPU_MIPMAPS -#if !defined(Q_OS_ANDROID) PROFILE_RANGE(resource_parse, "generateMips"); if (image.format() == QIMAGE_HDR_FORMAT) { @@ -687,16 +682,6 @@ void generateMips(gpu::Texture* texture, QImage&& image, const std::atomic } else { generateLDRMips(texture, std::move(image), abortProcessing, face); } - -#else - //texture->setAutoGenerateMips(false); - texture->assignStoredMip(0, image.byteCount(), image.constBits()); - for (uint16 level = 1; level < texture->getNumMips(); ++level) { - QSize mipSize(texture->evalMipWidth(level), texture->evalMipHeight(level)); - QImage mipImage = image.scaled(mipSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - texture->assignStoredMip(level, mipImage.byteCount(), mipImage.constBits()); - } -#endif #else texture->setAutoGenerateMips(true); #endif @@ -737,15 +722,9 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(QImage&& srcIma bool validAlpha = image.hasAlphaChannel(); bool alphaAsMask = false; -#if !defined(Q_OS_ANDROID) if (image.format() != QImage::Format_ARGB32) { image = image.convertToFormat(QImage::Format_ARGB32); } -#else - if (image.format() != QImage::Format_RGBA8888) { - image = image.convertToFormat(QImage::Format_RGBA8888); - } -#endif if (validAlpha) { processTextureAlpha(image, validAlpha, alphaAsMask); @@ -766,7 +745,12 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(QImage&& srcIma } formatMip = formatGPU; } else { +#ifdef USE_GLES + // GLES does not support GL_BGRA + formatMip = gpu::Element::COLOR_SRGBA_32; +#else formatMip = gpu::Element::COLOR_SBGRA_32; +#endif formatGPU = gpu::Element::COLOR_SRGBA_32; } diff --git a/libraries/input-plugins/CMakeLists.txt b/libraries/input-plugins/CMakeLists.txt index b0ea13843b..b1fcc4076a 100644 --- a/libraries/input-plugins/CMakeLists.txt +++ b/libraries/input-plugins/CMakeLists.txt @@ -1,5 +1,5 @@ set(TARGET_NAME input-plugins) setup_hifi_library() -link_hifi_libraries(shared plugins ui-plugins controllers) +link_hifi_libraries(shared plugins ui-plugins controllers ui) GroupSources("src/input-plugins") diff --git a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp index acd7a20327..96f1daba8c 100644 --- a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp +++ b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp @@ -14,12 +14,16 @@ #include "KeyboardMouseDevice.h" #include "TouchscreenDevice.h" +#include "TouchscreenVirtualPadDevice.h" // TODO migrate to a DLL model where plugins are discovered and loaded at runtime by the PluginManager class InputPluginList getInputPlugins() { InputPlugin* PLUGIN_POOL[] = { new KeyboardMouseDevice(), new TouchscreenDevice(), +#if defined(Q_OS_ANDROID) + new TouchscreenVirtualPadDevice(), +#endif nullptr }; diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp new file mode 100644 index 0000000000..8e1e6c2fba --- /dev/null +++ b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp @@ -0,0 +1,247 @@ +// +// TouchscreenVirtualPadDevice.cpp +// input-plugins/src/input-plugins +// +// Created by Triplelexx on 01/31/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "TouchscreenVirtualPadDevice.h" +#include "KeyboardMouseDevice.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include "VirtualPadManager.h" + +const char* TouchscreenVirtualPadDevice::NAME = "TouchscreenVirtualPad"; + +bool TouchscreenVirtualPadDevice::isSupported() const { + for (auto touchDevice : QTouchDevice::devices()) { + if (touchDevice->type() == QTouchDevice::TouchScreen) { + return true; + } + } +#if defined(Q_OS_ANDROID) + // last chance, assume that if this is android, a touchscreen is indeed supported + return true; +#endif + return false; +} + +float clip(float n, float lower, float upper) { + return std::max(lower, std::min(n, upper)); +} + +void TouchscreenVirtualPadDevice::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { + auto userInputMapper = DependencyManager::get(); + userInputMapper->withLock([&, this]() { + _inputDevice->update(deltaTime, inputCalibrationData); + }); + + auto& virtualPadManager = VirtualPad::Manager::instance(); + if (_validTouchLeft) { + float leftDistanceScaleX, leftDistanceScaleY; + leftDistanceScaleX = (_currentTouchLeftPoint.x - _firstTouchLeftPoint.x) / _screenDPIScale.x; + leftDistanceScaleY = (_currentTouchLeftPoint.y - _firstTouchLeftPoint.y) / _screenDPIScale.y; + + leftDistanceScaleX = clip(leftDistanceScaleX, -STICK_RADIUS_INCHES, STICK_RADIUS_INCHES); + leftDistanceScaleY = clip(leftDistanceScaleY, -STICK_RADIUS_INCHES, STICK_RADIUS_INCHES); + + // NOW BETWEEN -1 1 + leftDistanceScaleX /= STICK_RADIUS_INCHES; + leftDistanceScaleY /= STICK_RADIUS_INCHES; + + _inputDevice->_axisStateMap[controller::LX] = leftDistanceScaleX; + _inputDevice->_axisStateMap[controller::LY] = leftDistanceScaleY; + + /* Shared variables for stick rendering (clipped to the stick radius)*/ + // Prevent this for being done when not in first person view + virtualPadManager.getLeftVirtualPad()->setBeingTouched(true); + virtualPadManager.getLeftVirtualPad()->setFirstTouch(_firstTouchLeftPoint); + virtualPadManager.getLeftVirtualPad()->setCurrentTouch( + glm::vec2(clip(_currentTouchLeftPoint.x, -STICK_RADIUS_INCHES * _screenDPIScale.x + _firstTouchLeftPoint.x, STICK_RADIUS_INCHES * _screenDPIScale.x + _firstTouchLeftPoint.x), + clip(_currentTouchLeftPoint.y, -STICK_RADIUS_INCHES * _screenDPIScale.y + _firstTouchLeftPoint.y, STICK_RADIUS_INCHES * _screenDPIScale.y + _firstTouchLeftPoint.y)) + ); + } else { + virtualPadManager.getLeftVirtualPad()->setBeingTouched(false); + } + + if (_validTouchRight) { + float rightDistanceScaleX, rightDistanceScaleY; + rightDistanceScaleX = (_currentTouchRightPoint.x - _firstTouchRightPoint.x) / _screenDPIScale.x; + rightDistanceScaleY = (_currentTouchRightPoint.y - _firstTouchRightPoint.y) / _screenDPIScale.y; + + rightDistanceScaleX = clip(rightDistanceScaleX, -STICK_RADIUS_INCHES, STICK_RADIUS_INCHES); + rightDistanceScaleY = clip(rightDistanceScaleY, -STICK_RADIUS_INCHES, STICK_RADIUS_INCHES); + + // NOW BETWEEN -1 1 + rightDistanceScaleX /= STICK_RADIUS_INCHES; + rightDistanceScaleY /= STICK_RADIUS_INCHES; + + _inputDevice->_axisStateMap[controller::RX] = rightDistanceScaleX; + _inputDevice->_axisStateMap[controller::RY] = rightDistanceScaleY; + } + +} + +void TouchscreenVirtualPadDevice::InputDevice::update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { + _axisStateMap.clear(); +} + +void TouchscreenVirtualPadDevice::InputDevice::focusOutEvent() { +} + +void TouchscreenVirtualPadDevice::debugPoints(const QTouchEvent* event, QString who) { + // convert the touch points into an average + const QList& tPoints = event->touchPoints(); + QVector points; + int touchPoints = tPoints.count(); + for (int i = 0; i < touchPoints; ++i) { + glm::vec2 thisPoint(tPoints[i].pos().x(), tPoints[i].pos().y()); + points << thisPoint; + } + QScreen* eventScreen = event->window()->screen(); + int midScreenX = eventScreen->size().width()/2; + int lefties = 0; + int righties = 0; + vec2 currentPoint; + for (int i = 0; i < points.length(); i++) { + currentPoint = points.at(i); + if (currentPoint.x < midScreenX) { + lefties++; + } else { + righties++; + } + } +} + +void TouchscreenVirtualPadDevice::touchBeginEvent(const QTouchEvent* event) { + // touch begin here is a big begin -> begins both pads? maybe it does nothing + debugPoints(event, " BEGIN ++++++++++++++++"); + KeyboardMouseDevice::enableTouch(false); + QScreen* eventScreen = event->window()->screen(); + _screenWidthCenter = eventScreen->size().width() / 2; + if (_screenDPI != eventScreen->physicalDotsPerInch()) { + _screenDPIScale.x = (float)eventScreen->physicalDotsPerInchX(); + _screenDPIScale.y = (float)eventScreen->physicalDotsPerInchY(); + _screenDPI = eventScreen->physicalDotsPerInch(); + } +} + +void TouchscreenVirtualPadDevice::touchEndEvent(const QTouchEvent* event) { + // touch end here is a big reset -> resets both pads + _touchPointCount = 0; + KeyboardMouseDevice::enableTouch(true); + debugPoints(event, " END ----------------"); + touchLeftEnd(); + touchRightEnd(); + _inputDevice->_axisStateMap.clear(); +} + +void TouchscreenVirtualPadDevice::touchUpdateEvent(const QTouchEvent* event) { + _touchPointCount = event->touchPoints().count(); + + const QList& tPoints = event->touchPoints(); + bool leftTouchFound = false; + bool rightTouchFound = false; + for (int i = 0; i < _touchPointCount; ++i) { + glm::vec2 thisPoint(tPoints[i].pos().x(), tPoints[i].pos().y()); + if (thisPoint.x < _screenWidthCenter) { + if (!leftTouchFound) { + leftTouchFound = true; + if (!_validTouchLeft) { + touchLeftBegin(thisPoint); + } else { + touchLeftUpdate(thisPoint); + } + } + } else { + if (!rightTouchFound) { + rightTouchFound = true; + if (!_validTouchRight) { + touchRightBegin(thisPoint); + } else { + touchRightUpdate(thisPoint); + } + } + } + } + if (!leftTouchFound) { + touchLeftEnd(); + } + if (!rightTouchFound) { + touchRightEnd(); + } +} + +void TouchscreenVirtualPadDevice::touchLeftBegin(glm::vec2 touchPoint) { + auto& virtualPadManager = VirtualPad::Manager::instance(); + if (virtualPadManager.isEnabled()) { + _firstTouchLeftPoint = touchPoint; + _validTouchLeft = true; + } +} + +void TouchscreenVirtualPadDevice::touchLeftUpdate(glm::vec2 touchPoint) { + _currentTouchLeftPoint = touchPoint; +} + +void TouchscreenVirtualPadDevice::touchLeftEnd() { + if (_validTouchLeft) { // do stuff once + _validTouchLeft = false; + _inputDevice->_axisStateMap[controller::LX] = 0; + _inputDevice->_axisStateMap[controller::LY] = 0; + } +} + +void TouchscreenVirtualPadDevice::touchRightBegin(glm::vec2 touchPoint) { + auto& virtualPadManager = VirtualPad::Manager::instance(); + if (virtualPadManager.isEnabled()) { + _firstTouchRightPoint = touchPoint; + _validTouchRight = true; + } +} + +void TouchscreenVirtualPadDevice::touchRightUpdate(glm::vec2 touchPoint) { + _currentTouchRightPoint = touchPoint; +} + +void TouchscreenVirtualPadDevice::touchRightEnd() { + if (_validTouchRight) { // do stuff once + _validTouchRight = false; + _inputDevice->_axisStateMap[controller::RX] = 0; + _inputDevice->_axisStateMap[controller::RY] = 0; + } +} + +void TouchscreenVirtualPadDevice::touchGestureEvent(const QGestureEvent* event) { + if (QGesture* gesture = event->gesture(Qt::PinchGesture)) { + QPinchGesture* pinch = static_cast(gesture); + _pinchScale = pinch->totalScaleFactor(); + } +} + +controller::Input::NamedVector TouchscreenVirtualPadDevice::InputDevice::getAvailableInputs() const { + using namespace controller; + QVector availableInputs{ + makePair(LX, "LX"), + makePair(LY, "LY"), + makePair(RX, "RX"), + makePair(RY, "RY") + }; + return availableInputs; +} + +QString TouchscreenVirtualPadDevice::InputDevice::getDefaultMappingConfig() const { + static const QString MAPPING_JSON = PathUtils::resourcesPath() + "/controllers/touchscreenvirtualpad.json"; + return MAPPING_JSON; +} diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h new file mode 100644 index 0000000000..fd74009ee8 --- /dev/null +++ b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h @@ -0,0 +1,89 @@ +// +// TouchscreenVirtualPadDevice.h +// input-plugins/src/input-plugins +// +// Created by Triplelexx on 1/31/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_TouchscreenVirtualPadDevice_h +#define hifi_TouchscreenVirtualPadDevice_h + +#include +#include "InputPlugin.h" +#include + +class QTouchEvent; +class QGestureEvent; + +const float STICK_RADIUS_INCHES = .3f; + +class TouchscreenVirtualPadDevice : public InputPlugin { +Q_OBJECT +public: + + // Plugin functions + virtual bool isSupported() const override; + virtual const QString getName() const override { return NAME; } + + bool isHandController() const override { return false; } + + virtual void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); } + virtual void pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; + + void touchBeginEvent(const QTouchEvent* event); + void touchEndEvent(const QTouchEvent* event); + void touchUpdateEvent(const QTouchEvent* event); + void touchGestureEvent(const QGestureEvent* event); + + static const char* NAME; + +protected: + + class InputDevice : public controller::InputDevice { + public: + InputDevice() : controller::InputDevice("TouchscreenVirtualPad") {} + private: + // Device functions + virtual controller::Input::NamedVector getAvailableInputs() const override; + virtual QString getDefaultMappingConfig() const override; + virtual void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; + virtual void focusOutEvent() override; + + friend class TouchscreenVirtualPadDevice; + }; + +public: + const std::shared_ptr& getInputDevice() const { return _inputDevice; } + +protected: + qreal _lastPinchScale; + qreal _pinchScale; + qreal _screenDPI; + glm::vec2 _screenDPIScale; + bool _validTouchLeft; + glm::vec2 _firstTouchLeftPoint; + glm::vec2 _currentTouchLeftPoint; + bool _validTouchRight; + glm::vec2 _firstTouchRightPoint; + glm::vec2 _currentTouchRightPoint; + int _touchPointCount; + int _screenWidthCenter; + std::shared_ptr _inputDevice { std::make_shared() }; + + void touchLeftBegin(glm::vec2 touchPoint); + void touchLeftUpdate(glm::vec2 touchPoint); + void touchLeftEnd(); + void touchRightBegin(glm::vec2 touchPoint); + void touchRightUpdate(glm::vec2 touchPoint); + void touchRightEnd(); +// just for debug +private: + void debugPoints(const QTouchEvent* event, QString who); + +}; + +#endif // hifi_TouchscreenVirtualPadDevice_h diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 3a29139ee7..912a44cb97 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -37,7 +37,7 @@ #include #include - +#include #include #include @@ -50,10 +50,12 @@ Q_LOGGING_CATEGORY(trace_resource_parse_image, "trace.resource.parse.image") Q_LOGGING_CATEGORY(trace_resource_parse_image_raw, "trace.resource.parse.image.raw") Q_LOGGING_CATEGORY(trace_resource_parse_image_ktx, "trace.resource.parse.image.ktx") -#if !defined(DISABLE_KTX_CACHE) -const std::string TextureCache::KTX_DIRNAME { "ktx_cache" }; -const std::string TextureCache::KTX_EXT { "ktx" }; +#if defined(USE_GLES) +const std::string TextureCache::KTX_DIRNAME { "ktx_cache_gles" }; +#else +const std::string TextureCache::KTX_DIRNAME{ "ktx_cache" }; #endif +const std::string TextureCache::KTX_EXT { "ktx" }; static const QString RESOURCE_SCHEME = "resource"; static const QUrl SPECTATOR_CAMERA_FRAME_URL("resource://spectatorCameraFrame"); @@ -63,8 +65,9 @@ static const float SKYBOX_LOAD_PRIORITY { 10.0f }; // Make sure skybox loads fir static const float HIGH_MIPS_LOAD_PRIORITY { 9.0f }; // Make sure high mips loads after skybox but before models TextureCache::TextureCache() { -#if !defined(DISABLE_KTX_CACHE) _ktxCache->initialize(); +#if defined(DISABLE_KTX_CACHE) + _ktxCache->wipe(); #endif setUnusedResourceCacheSize(0); setObjectName("TextureCache"); @@ -296,6 +299,10 @@ _maxNumPixels(100) _loaded = true; } +static bool isLocalUrl(const QUrl& url) { + auto scheme = url.scheme(); + return (scheme == URL_SCHEME_FILE || scheme == URL_SCHEME_QRC || scheme == RESOURCE_SCHEME); +} NetworkTexture::NetworkTexture(const QUrl& url, image::TextureUsage::Type type, const QByteArray& content, int maxNumPixels) : Resource(url), @@ -389,6 +396,21 @@ void NetworkTexture::makeRequest() { return; } + if (isLocalUrl(_url)) { + auto self = _self; + QtConcurrent::run(QThreadPool::globalInstance(), [self] { + auto resource = self.lock(); + if (!resource) { + return; + } + + NetworkTexture* networkTexture = static_cast(resource.data()); + networkTexture->makeLocalRequest(); + }); + return; + } + + // We special-handle ktx requests to run 2 concurrent requests right off the bat PROFILE_ASYNC_BEGIN(resource, "Resource:" + getType(), QString::number(_requestID), { { "url", _url.toString() }, { "activeURL", _activeUrl.toString() } }); @@ -437,6 +459,74 @@ void NetworkTexture::makeRequest() { } +void NetworkTexture::makeLocalRequest() { + const QString scheme = _url.scheme(); + QString path; + if (scheme == URL_SCHEME_FILE) { + path = _url.toLocalFile(); + } else { + path = ":" + _url.path(); + } + + path = FileUtils::selectFile(path); + + auto storage = std::make_shared(path); + std::unique_ptr ktxFile; + if (storage) { + ktxFile = ktx::KTX::create(storage); + } + std::shared_ptr ktxDescriptor; + if (ktxFile) { + ktxDescriptor = std::make_shared(ktxFile->toDescriptor()); + } + + gpu::TexturePointer texture; + if (ktxDescriptor) { + std::string hash; + // Create bare ktx in memory + auto found = std::find_if(ktxDescriptor->keyValues.begin(), ktxDescriptor->keyValues.end(), [](const ktx::KeyValue& val) -> bool { + return val._key.compare(gpu::SOURCE_HASH_KEY) == 0; + }); + + if (found == ktxDescriptor->keyValues.end() || found->_value.size() != gpu::SOURCE_HASH_BYTES) { + hash = _url.toString().toLocal8Bit().toHex().toStdString(); + } else { + // at this point the source hash is in binary 16-byte form + // and we need it in a hexadecimal string + auto binaryHash = QByteArray(reinterpret_cast(found->_value.data()), gpu::SOURCE_HASH_BYTES); + hash = binaryHash.toHex().toStdString(); + } + + auto textureCache = DependencyManager::get(); + texture = textureCache->getTextureByHash(hash); + if (!texture) { + texture = gpu::Texture::build(*ktxDescriptor); + if (texture) { + texture->setKtxBacking(path.toStdString()); + texture->setSource(path.toStdString()); + texture = textureCache->cacheTextureByHash(hash, texture); + } + } + } + + if (!texture) { + qCDebug(networking).noquote() << "Failed load local KTX from" << path; + QMetaObject::invokeMethod(this, "setImage", + Q_ARG(gpu::TexturePointer, nullptr), + Q_ARG(int, 0), + Q_ARG(int, 0)); + return; + } + + _ktxResourceState = PENDING_MIP_REQUEST; + _lowestKnownPopulatedMip = texture->minAvailableMipLevel(); + QMetaObject::invokeMethod(this, "setImage", + Q_ARG(gpu::TexturePointer, texture), + Q_ARG(int, texture->getWidth()), + Q_ARG(int, texture->getHeight())); + +} + bool NetworkTexture::handleFailedRequest(ResourceRequest::Result result) { if (!_sourceIsKTX && result == ResourceRequest::Result::RedirectFail) { auto newPath = _request->getRelativePathUrl(); @@ -752,7 +842,6 @@ void NetworkTexture::handleFinishedInitialLoad() { gpu::TexturePointer texture = textureCache->getTextureByHash(hash); -#if !defined(DISABLE_KTX_CACHE) if (!texture) { auto ktxFile = textureCache->_ktxCache->getFile(hash); if (ktxFile) { @@ -765,9 +854,8 @@ void NetworkTexture::handleFinishedInitialLoad() { } } } -#endif - if (!texture) { + if (!texture) { auto memKtx = ktx::KTX::createBare(*header, keyValues); if (!memKtx) { qWarning() << " Ktx could not be created, bailing"; @@ -780,7 +868,6 @@ void NetworkTexture::handleFinishedInitialLoad() { // Move ktx to file const char* data = reinterpret_cast(memKtx->_storage->data()); -#if !defined(DISABLE_KTX_CACHE) size_t length = memKtx->_storage->size(); cache::FilePointer file; auto& ktxCache = textureCache->_ktxCache; @@ -792,14 +879,11 @@ void NetworkTexture::handleFinishedInitialLoad() { Q_ARG(int, 0)); return; } -#endif auto newKtxDescriptor = memKtx->toDescriptor(); texture = gpu::Texture::build(newKtxDescriptor); -#if !defined(DISABLE_KTX_CACHE) texture->setKtxBacking(file); -#endif texture->setSource(filename); auto& images = originalKtxDescriptor->images; @@ -942,7 +1026,6 @@ void ImageReader::read() { // If we already have a live texture with the same hash, use it auto texture = textureCache->getTextureByHash(hash); -#if !defined(DISABLE_KTX_CACHE) // If there is no live texture, check if there's an existing KTX file if (!texture) { auto ktxFile = textureCache->_ktxCache->getFile(hash); @@ -955,7 +1038,6 @@ void ImageReader::read() { } } } -#endif // If we found the texture either because it's in use or via KTX deserialization, // set the image and return immediately. @@ -991,7 +1073,6 @@ void ImageReader::read() { // Save the image into a KTXFile if (texture && textureCache) { -#if !defined(DISABLE_KTX_CACHE) auto memKtx = gpu::Texture::serialize(*texture); // Move the texture into a memory mapped file @@ -1008,7 +1089,7 @@ void ImageReader::read() { } else { qCWarning(modelnetworking) << "Unable to serialize texture to KTX " << _url; } -#endif + // We replace the texture with the one stored in the cache. This deals with the possible race condition of two different // images with the same hash being loaded concurrently. Only one of them will make it into the cache by hash first and will // be the winner diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index ffa3150b43..71714f0c10 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -70,6 +70,7 @@ public slots: protected: void makeRequest() override; + void makeLocalRequest(); virtual bool isCacheable() const override { return _loaded; } @@ -193,12 +194,11 @@ private: TextureCache(); virtual ~TextureCache(); -#if !defined(DISABLE_KTX_CACHE) static const std::string KTX_DIRNAME; static const std::string KTX_EXT; std::shared_ptr _ktxCache { std::make_shared(KTX_DIRNAME, KTX_EXT) }; -#endif + // Map from image hashes to texture weak pointers std::unordered_map> _texturesByHashes; std::mutex _texturesByHashesMutex; diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 9296f61ad3..a8eec66067 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -104,11 +104,17 @@ QUrl AddressManager::currentFacingShareableAddress() const { } void AddressManager::loadSettings(const QString& lookupString) { +#if defined(USE_GLES) && defined(Q_OS_WIN) + handleUrl(QUrl("hifi://127.0.0.0"), LookupTrigger::StartupFromSettings); +#elif defined(Q_OS_ANDROID) + handleUrl(QUrl("hifi://pikachu/167.11,0.745735,181.529/0,0.887027,0,-0.461717"), LookupTrigger::StartupFromSettings); +#else if (lookupString.isEmpty()) { handleUrl(currentAddressHandle.get(), LookupTrigger::StartupFromSettings); } else { handleUrl(lookupString, LookupTrigger::StartupFromSettings); } +#endif } void AddressManager::goBack() { diff --git a/libraries/networking/src/FileResourceRequest.cpp b/libraries/networking/src/FileResourceRequest.cpp index b55f1839a0..7cbb401f7f 100644 --- a/libraries/networking/src/FileResourceRequest.cpp +++ b/libraries/networking/src/FileResourceRequest.cpp @@ -18,6 +18,7 @@ #include #include +#include "NetworkLogging.h" #include "ResourceManager.h" void FileResourceRequest::doSend() { @@ -38,9 +39,15 @@ void FileResourceRequest::doSend() { // Allow platform specific versions of files loaded out of a resource cache via file:// - QFileSelector fileSelector; - fileSelector.setExtraSelectors(FileUtils::getFileSelectors()); - filename = fileSelector.select(filename); + { + QString originalFilename = filename; + QFileSelector fileSelector; + fileSelector.setExtraSelectors(FileUtils::getFileSelectors()); + filename = fileSelector.select(filename); + if (filename != originalFilename) { + qCDebug(resourceLog) << "Using" << filename << "instead of" << originalFilename; + } + } if (!_byteRange.isValid()) { _result = ResourceRequest::InvalidByteRange; diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index 52c56d1e7d..d8b72c8838 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -187,6 +187,10 @@ void Procedural::setProceduralData(const ProceduralData& proceduralData) { } bool Procedural::isReady() const { +#if defined(USE_GLES) + return false; +#endif + if (!_enabled) { return false; } diff --git a/libraries/qml/src/qml/OffscreenSurface.cpp b/libraries/qml/src/qml/OffscreenSurface.cpp index a84f3feb4d..56b2c13e95 100644 --- a/libraries/qml/src/qml/OffscreenSurface.cpp +++ b/libraries/qml/src/qml/OffscreenSurface.cpp @@ -154,17 +154,45 @@ bool OffscreenSurface::eventFilter(QObject* originalDestination, QEvent* event) QPointF transformedPos = mapToVirtualScreen(mouseEvent->localPos()); QMouseEvent mappedEvent(mouseEvent->type(), transformedPos, mouseEvent->screenPos(), mouseEvent->button(), mouseEvent->buttons(), mouseEvent->modifiers()); - if (event->type() == QEvent::MouseMove) { - // TODO - this line necessary for the QML Tooltop to work (which is not currently being used), but it causes interface to crash on launch on a fresh install - // need to investigate into why this crash is happening. - //_qmlContext->setContextProperty("lastMousePosition", transformedPos); - } mappedEvent.ignore(); if (QCoreApplication::sendEvent(_sharedObject->getWindow(), &mappedEvent)) { return mappedEvent.isAccepted(); } break; } + +#if defined(Q_OS_ANDROID) + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: { + QTouchEvent *originalEvent = static_cast(event); + QTouchEvent fakeEvent(*originalEvent); + auto newTouchPoints = fakeEvent.touchPoints(); + for (size_t i = 0; i < newTouchPoints.size(); ++i) { + const auto &originalPoint = originalEvent->touchPoints()[i]; + auto &newPoint = newTouchPoints[i]; + newPoint.setPos(originalPoint.pos()); + } + fakeEvent.setTouchPoints(newTouchPoints); + if (QCoreApplication::sendEvent(_sharedObject->getWindow(), &fakeEvent)) { + qInfo() << __FUNCTION__ << "sent fake touch event:" << fakeEvent.type() + << "_quickWindow handled it... accepted:" << fakeEvent.isAccepted(); + return false; //event->isAccepted(); + } + break; + } + case QEvent::InputMethod: + case QEvent::InputMethodQuery: { + if (_sharedObject->getWindow() && _sharedObject->getWindow()->activeFocusItem()) { + event->ignore(); + if (QCoreApplication::sendEvent(_sharedObject->getWindow()->activeFocusItem(), event)) { + return event->isAccepted(); + } + return false; + } + break; + } +#endif default: break; } diff --git a/libraries/render-utils/src/AnimDebugDraw.cpp b/libraries/render-utils/src/AnimDebugDraw.cpp index 5174126243..02ff234c01 100644 --- a/libraries/render-utils/src/AnimDebugDraw.cpp +++ b/libraries/render-utils/src/AnimDebugDraw.cpp @@ -7,15 +7,17 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include +#include "AnimDebugDraw.h" #include +#include + #include "AbstractViewStateInterface.h" #include "RenderUtilsLogging.h" -#include "GLMHelpers.h" #include "DebugDraw.h" -#include "AnimDebugDraw.h" +#include "animdebugdraw_vert.h" +#include "animdebugdraw_frag.h" #include "animdebugdraw_vert.h" #include "animdebugdraw_frag.h" diff --git a/libraries/render-utils/src/AnimDebugDraw.h b/libraries/render-utils/src/AnimDebugDraw.h index 20336ed6dd..03101c9f86 100644 --- a/libraries/render-utils/src/AnimDebugDraw.h +++ b/libraries/render-utils/src/AnimDebugDraw.h @@ -12,8 +12,9 @@ #include -#include "render/Scene.h" -#include "gpu/Pipeline.h" +#include +#include + #include "AnimNode.h" #include "AnimSkeleton.h" diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index c94fe717f1..c09aa99988 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -34,8 +34,12 @@ render::ShapePipeline::BatchSetter FadeEffect::getBatchSetter() const { auto program = shapePipeline.pipeline->getProgram(); auto maskMapLocation = program->getTextures().findLocation("fadeMaskMap"); auto bufferLocation = program->getUniformBuffers().findLocation("fadeParametersBuffer"); - batch.setResourceTexture(maskMapLocation, _maskMap); - batch.setUniformBuffer(bufferLocation, _configurations); + if (maskMapLocation != -1) { + batch.setResourceTexture(maskMapLocation, _maskMap); + } + if (bufferLocation != -1) { + batch.setUniformBuffer(bufferLocation, _configurations); + } }; } diff --git a/libraries/render-utils/src/ForwardBuffer.slh b/libraries/render-utils/src/ForwardBuffer.slh deleted file mode 100644 index 4d1dc89aa4..0000000000 --- a/libraries/render-utils/src/ForwardBuffer.slh +++ /dev/null @@ -1,68 +0,0 @@ - -<@if not FORWARD_BUFFER_SLH@> -<@def FORWARD_BUFFER_SLH@> - -<@include gpu/PackedNormal.slh@> - -// Unpack the metallic-mode value -const float FRAG_PACK_SHADED_NON_METALLIC = 0.0; -const float FRAG_PACK_SHADED_METALLIC = 0.1; -const float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC); - -const float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2; -const float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3; -const float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC); - -const float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4; -const float FRAG_PACK_SCATTERING_METALLIC = 0.5; -const float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC); - -const float FRAG_PACK_UNLIT = 0.6; - -const int FRAG_MODE_UNLIT = 0; -const int FRAG_MODE_SHADED = 1; -const int FRAG_MODE_LIGHTMAPPED = 2; -const int FRAG_MODE_SCATTERING = 3; - -void unpackModeMetallic(float rawValue, out int mode, out float metallic) { - if (rawValue <= FRAG_PACK_SHADED_METALLIC) { - mode = FRAG_MODE_SHADED; - metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0); - } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) { - mode = FRAG_MODE_LIGHTMAPPED; - metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0); - } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) { - mode = FRAG_MODE_SCATTERING; - metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0); - } else if (rawValue >= FRAG_PACK_UNLIT) { - mode = FRAG_MODE_UNLIT; - metallic = 0.0; - } -} - -float packShadedMetallic(float metallic) { - return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic); -} - -float packLightmappedMetallic(float metallic) { - return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic); -} - -float packScatteringMetallic(float metallic) { - return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic); -} - -float packUnlit() { - return FRAG_PACK_UNLIT; -} - -<@endif@> diff --git a/libraries/render-utils/src/ForwardBufferWrite.slh b/libraries/render-utils/src/ForwardBufferWrite.slh deleted file mode 100644 index 873514d51f..0000000000 --- a/libraries/render-utils/src/ForwardBufferWrite.slh +++ /dev/null @@ -1,63 +0,0 @@ - -<@if not FORWARD_BUFFER_WRITE_SLH@> -<@def FORWARD_BUFFER_WRITE_SLH@> - -<@include ForwardBuffer.slh@> - - -layout(location = 0) out vec4 _fragColor0; - -// the alpha threshold -const float alphaThreshold = 0.5; -float evalOpaqueFinalAlpha(float alpha, float mapAlpha) { - return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold)); -} - -const float DEFAULT_ROUGHNESS = 0.9; -const float DEFAULT_SHININESS = 10.0; -const float DEFAULT_METALLIC = 0.0; -const vec3 DEFAULT_SPECULAR = vec3(0.1); -const vec3 DEFAULT_EMISSIVE = vec3(0.0); -const float DEFAULT_OCCLUSION = 1.0; -const float DEFAULT_SCATTERING = 0.0; -const vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE; - -void packForwardFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) { - if (alpha != 1.0) { - discard; - } - _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic))); -} - -void packForwardFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) { - if (alpha != 1.0) { - discard; - } - - _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic)); -} - -void packForwardFragmentUnlit(vec3 normal, float alpha, vec3 color) { - if (alpha != 1.0) { - discard; - } - _fragColor0 = vec4(color, packUnlit()); -} - -void packForwardFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) { - if (alpha <= 0.0) { - discard; - } - _fragColor0 = vec4(albedo.rgb, alpha); -} - -<@endif@> diff --git a/libraries/render-utils/src/ForwardGlobalLight.slh b/libraries/render-utils/src/ForwardGlobalLight.slh index a55e2ea651..a945acb8c4 100644 --- a/libraries/render-utils/src/ForwardGlobalLight.slh +++ b/libraries/render-utils/src/ForwardGlobalLight.slh @@ -124,8 +124,6 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu color += ambientDiffuse; color += ambientSpecular; - - // Directional vec3 directionalDiffuse; vec3 directionalSpecular; evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation @@ -136,6 +134,12 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu color += directionalDiffuse; color += directionalSpecular; + // FIXME - temporarily removed until we support it for forward... + // Attenuate the light if haze effect selected + // if ((hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) { + // color = computeHazeColorKeyLightAttenuation(color, lightDirection, position); + // } + return color; } @@ -168,6 +172,7 @@ vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscur +<@include Haze.slh@> <@func declareEvalGlobalLightingAlphaBlended()@> @@ -198,6 +203,47 @@ vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, fl return color; } +vec3 evalGlobalLightingAlphaBlendedWithHaze( + mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, + vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) +{ + <$prepareGlobalLight()$> + + SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir); + + color += emissive * isEmissiveEnabled(); + + // Ambient + vec3 ambientDiffuse; + vec3 ambientSpecular; + evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance); + color += ambientDiffuse; + color += ambientSpecular / opacity; + + // Directional + vec3 directionalDiffuse; + vec3 directionalSpecular; + evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation); + color += directionalDiffuse; + color += directionalSpecular / opacity; + + // Haze + // FIXME - temporarily removed until we support it for forward... + /* if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { + vec4 colorV4 = computeHazeColor( + vec4(color, 1.0), // fragment original color + position, // fragment position in eye coordinates + fragEyeVector, // fragment position in world coordinates + invViewMat[3].y, // eye height in world coordinates + lightDirection // keylight direction vector + ); + + color = colorV4.rgb; + }*/ + + return color; +} + <@endfunc@> diff --git a/libraries/render-utils/src/LightAmbient.slh b/libraries/render-utils/src/LightAmbient.slh index 3f52760eff..008f29da01 100644 --- a/libraries/render-utils/src/LightAmbient.slh +++ b/libraries/render-utils/src/LightAmbient.slh @@ -12,9 +12,14 @@ uniform samplerCube skyboxMap; vec4 evalSkyboxLight(vec3 direction, float lod) { // textureQueryLevels is not available until #430, so we require explicit lod + // float mipmapLevel = lod * textureQueryLevels(skyboxMap); + +#if !defined(GL_ES) float filterLod = textureQueryLod(skyboxMap, direction).x; // Keep texture filtering LOD as limit to prevent aliasing on specular reflection lod = max(lod, filterLod); +#endif + return textureLod(skyboxMap, direction, lod); } <@endfunc@> diff --git a/libraries/render-utils/src/LightingModel.slh b/libraries/render-utils/src/LightingModel.slh index ddcbf8229c..2280d12465 100644 --- a/libraries/render-utils/src/LightingModel.slh +++ b/libraries/render-utils/src/LightingModel.slh @@ -311,4 +311,14 @@ void evalFragShadingGloss(out vec3 diffuse, out vec3 specular, specular = shading.xyz; } + +<@if not GETFRESNEL0@> +<@def GETFRESNEL0@> +vec3 getFresnelF0(float metallic, vec3 metalF0) { + // Enable continuous metallness value by lerping between dielectric + // and metal fresnel F0 value based on the "metallic" parameter + return mix(vec3(0.03), metalF0, metallic); +} +<@endif@> + <@endif@> diff --git a/libraries/render-utils/src/MaterialTextures.slh b/libraries/render-utils/src/MaterialTextures.slh index 40709b3668..b3662385b0 100644 --- a/libraries/render-utils/src/MaterialTextures.slh +++ b/libraries/render-utils/src/MaterialTextures.slh @@ -154,7 +154,7 @@ vec3 fetchLightmapMap(vec2 uv) { vec3 normalizedTangent = normalize(<$interpolatedTangent$>.xyz); vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent)); vec3 localNormal = <$fetchedNormal$>; - <$normal$> = vec3(normalizedTangent * localNormal.x + normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z); + <$normal$> = vec3(normalizedTangent * localNormal.x + normalizedNormal * localNormal.y + normalizedBitangent * localNormal.z); } <@endfunc@> diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 2637d24d67..5231b3e4d0 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -128,9 +128,6 @@ ShapeKey MeshPartPayload::getShapeKey() const { if (drawMaterialKey.isNormalMap()) { builder.withTangents(); } - if (drawMaterialKey.isMetallicMap()) { - builder.withSpecular(); - } if (drawMaterialKey.isLightmapMap()) { builder.withLightmap(); } @@ -387,14 +384,13 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, bool isWireframe bool isTranslucent = drawMaterialKey.isTranslucent(); bool hasTangents = drawMaterialKey.isNormalMap() && _hasTangents; - bool hasSpecular = drawMaterialKey.isMetallicMap(); bool hasLightmap = drawMaterialKey.isLightmapMap(); bool isUnlit = drawMaterialKey.isUnlit(); bool isSkinned = _isSkinned; if (isWireframe) { - isTranslucent = hasTangents = hasSpecular = hasLightmap = isSkinned = false; + isTranslucent = hasTangents = hasLightmap = isSkinned = false; } ShapeKey::Builder builder; @@ -406,9 +402,6 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, bool isWireframe if (hasTangents) { builder.withTangents(); } - if (hasSpecular) { - builder.withSpecular(); - } if (hasLightmap) { builder.withLightmap(); } diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index c201e8a106..4829e5c85b 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -19,9 +19,12 @@ #include #include +#include + #include "StencilMaskPass.h" #include "ZoneRenderer.h" #include "FadeEffect.h" +#include "ToneMappingEffect.h" #include "BackgroundStage.h" #include "FramebufferCache.h" #include "TextureCache.h" @@ -56,6 +59,7 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend fadeEffect->build(task, opaques); // Prepare objects shared by several jobs + const auto deferredFrameTransform = task.addJob("DeferredFrameTransform"); const auto lightingModel = task.addJob("LightingModel"); // Filter zones from the general metas bucket @@ -87,15 +91,23 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend task.addJob("DrawTransparentBounds", transparents); task.addJob("DrawZones", zones); + task.addJob("DrawZoneStack", deferredFrameTransform); + } - // Layered Overlays + // Lighting Buffer ready for tone mapping + // Forward rendering on GLES doesn't support tonemapping to and from the same FBO, so we specify + // the output FBO as null, which causes the tonemapping to target the blit framebuffer + const auto toneMappingInputs = ToneMappingDeferred::Inputs(framebuffer, nullptr).asVarying(); + task.addJob("ToneMapping", toneMappingInputs); + // Layered Overlays // Composite the HUD and HUD overlays task.addJob("HUD"); + // Disable blit because we do tonemapping and compositing directly to the blit FBO // Blit! - task.addJob("Blit", framebuffer); + // task.addJob("Blit", framebuffer); } void PrepareFramebuffer::run(const RenderContextPointer& renderContext, gpu::FramebufferPointer& framebuffer) { @@ -130,40 +142,12 @@ void PrepareFramebuffer::run(const RenderContextPointer& renderContext, gpu::Fra batch.setFramebuffer(_framebuffer); batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH | gpu::Framebuffer::BUFFER_STENCIL, - vec4(vec3(0, 1.0, 0.0), 0), 1.0, 0, true); + vec4(vec3(0), 0), 1.0, 0, true); }); framebuffer = _framebuffer; } -enum ForwardShader_MapSlot { - DEFERRED_BUFFER_COLOR_UNIT = 0, - DEFERRED_BUFFER_NORMAL_UNIT = 1, - DEFERRED_BUFFER_EMISSIVE_UNIT = 2, - DEFERRED_BUFFER_DEPTH_UNIT = 3, - DEFERRED_BUFFER_OBSCURANCE_UNIT = 4, - SHADOW_MAP_UNIT = 5, - SKYBOX_MAP_UNIT = SHADOW_MAP_UNIT + 4, - DEFERRED_BUFFER_LINEAR_DEPTH_UNIT, - DEFERRED_BUFFER_CURVATURE_UNIT, - DEFERRED_BUFFER_DIFFUSED_CURVATURE_UNIT, - SCATTERING_LUT_UNIT, - SCATTERING_SPECULAR_UNIT, -}; -enum ForwardShader_BufferSlot { - DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT = 0, - CAMERA_CORRECTION_BUFFER_SLOT, - SCATTERING_PARAMETERS_BUFFER_SLOT, - LIGHTING_MODEL_BUFFER_SLOT = render::ShapePipeline::Slot::LIGHTING_MODEL, - LIGHT_GPU_SLOT = render::ShapePipeline::Slot::LIGHT, - LIGHT_AMBIENT_SLOT = render::ShapePipeline::Slot::LIGHT_AMBIENT_BUFFER, - HAZE_MODEL_BUFFER_SLOT = render::ShapePipeline::Slot::HAZE_MODEL, - LIGHT_INDEX_GPU_SLOT, - LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, - LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, - LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, -}; - void PrepareForward::run(const RenderContextPointer& renderContext, const Inputs& inputs) { RenderArgs* args = renderContext->args; gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { @@ -181,18 +165,14 @@ void PrepareForward::run(const RenderContextPointer& renderContext, const Inputs } if (keySunLight) { - if (LIGHT_GPU_SLOT >= 0) { - batch.setUniformBuffer(LIGHT_GPU_SLOT, keySunLight->getLightSchemaBuffer()); - } + batch.setUniformBuffer(render::ShapePipeline::Slot::KEY_LIGHT, keySunLight->getLightSchemaBuffer()); } if (keyAmbiLight) { - if (LIGHT_AMBIENT_SLOT >= 0) { - batch.setUniformBuffer(LIGHT_AMBIENT_SLOT, keyAmbiLight->getAmbientSchemaBuffer()); - } + batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHT_AMBIENT_BUFFER, keyAmbiLight->getAmbientSchemaBuffer()); - if (keyAmbiLight->getAmbientMap() && (SKYBOX_MAP_UNIT >= 0)) { - batch.setResourceTexture(SKYBOX_MAP_UNIT, keyAmbiLight->getAmbientMap()); + if (keyAmbiLight->getAmbientMap()) { + batch.setResourceTexture(render::ShapePipeline::Slot::LIGHT_AMBIENT, keyAmbiLight->getAmbientMap()); } } }); diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 3fedae1778..4cbc6ef3af 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -32,7 +32,6 @@ #include "model_lightmap_fade_vert.h" #include "model_lightmap_normal_map_fade_vert.h" #include "model_translucent_vert.h" -#include "model_translucent_normal_map_vert.h" #include "skin_model_fade_vert.h" #include "skin_model_normal_map_fade_vert.h" #include "skin_model_fade_dq_vert.h" @@ -53,38 +52,26 @@ #include "model_frag.h" #include "model_unlit_frag.h" #include "model_normal_map_frag.h" -#include "model_normal_specular_map_frag.h" -#include "model_specular_map_frag.h" - #include "model_fade_vert.h" #include "model_normal_map_fade_vert.h" #include "model_fade_frag.h" #include "model_unlit_fade_frag.h" #include "model_normal_map_fade_frag.h" -#include "model_normal_specular_map_fade_frag.h" -#include "model_specular_map_fade_frag.h" #include "forward_model_frag.h" #include "forward_model_unlit_frag.h" #include "forward_model_normal_map_frag.h" -#include "forward_model_normal_specular_map_frag.h" -#include "forward_model_specular_map_frag.h" +#include "forward_model_translucent_frag.h" #include "model_lightmap_frag.h" #include "model_lightmap_normal_map_frag.h" -#include "model_lightmap_normal_specular_map_frag.h" -#include "model_lightmap_specular_map_frag.h" #include "model_translucent_frag.h" #include "model_translucent_unlit_frag.h" -#include "model_translucent_normal_map_frag.h" #include "model_lightmap_fade_frag.h" #include "model_lightmap_normal_map_fade_frag.h" -#include "model_lightmap_normal_specular_map_fade_frag.h" -#include "model_lightmap_specular_map_fade_frag.h" #include "model_translucent_fade_frag.h" -#include "model_translucent_normal_map_fade_frag.h" #include "model_translucent_unlit_fade_frag.h" #include "overlay3D_vert.h" @@ -124,6 +111,7 @@ void addPlumberPipeline(ShapePlumber& plumber, void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args); void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args); +static bool forceLightBatchSetter{ false }; void initOverlay3DPipelines(ShapePlumber& plumber, bool depthTest) { auto vertex = overlay3D_vert::getShader(); @@ -198,7 +186,6 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip auto modelLightmapVertex = model_lightmap_vert::getShader(); auto modelLightmapNormalMapVertex = model_lightmap_normal_map_vert::getShader(); auto modelTranslucentVertex = model_translucent_vert::getShader(); - auto modelTranslucentNormalMapVertex = model_translucent_normal_map_vert::getShader(); auto modelShadowVertex = model_shadow_vert::getShader(); auto modelLightmapFadeVertex = model_lightmap_fade_vert::getShader(); @@ -236,29 +223,19 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip auto modelPixel = model_frag::getShader(); auto modelUnlitPixel = model_unlit_frag::getShader(); auto modelNormalMapPixel = model_normal_map_frag::getShader(); - auto modelSpecularMapPixel = model_specular_map_frag::getShader(); - auto modelNormalSpecularMapPixel = model_normal_specular_map_frag::getShader(); auto modelTranslucentPixel = model_translucent_frag::getShader(); - auto modelTranslucentNormalMapPixel = model_translucent_normal_map_frag::getShader(); auto modelTranslucentUnlitPixel = model_translucent_unlit_frag::getShader(); auto modelShadowPixel = model_shadow_frag::getShader(); auto modelLightmapPixel = model_lightmap_frag::getShader(); auto modelLightmapNormalMapPixel = model_lightmap_normal_map_frag::getShader(); - auto modelLightmapSpecularMapPixel = model_lightmap_specular_map_frag::getShader(); - auto modelLightmapNormalSpecularMapPixel = model_lightmap_normal_specular_map_frag::getShader(); auto modelLightmapFadePixel = model_lightmap_fade_frag::getShader(); auto modelLightmapNormalMapFadePixel = model_lightmap_normal_map_fade_frag::getShader(); - auto modelLightmapSpecularMapFadePixel = model_lightmap_specular_map_fade_frag::getShader(); - auto modelLightmapNormalSpecularMapFadePixel = model_lightmap_normal_specular_map_fade_frag::getShader(); auto modelFadePixel = model_fade_frag::getShader(); auto modelUnlitFadePixel = model_unlit_fade_frag::getShader(); auto modelNormalMapFadePixel = model_normal_map_fade_frag::getShader(); - auto modelSpecularMapFadePixel = model_specular_map_fade_frag::getShader(); - auto modelNormalSpecularMapFadePixel = model_normal_specular_map_fade_frag::getShader(); auto modelShadowFadePixel = model_shadow_fade_frag::getShader(); auto modelTranslucentFadePixel = model_translucent_fade_frag::getShader(); - auto modelTranslucentNormalMapFadePixel = model_translucent_normal_map_fade_frag::getShader(); auto modelTranslucentUnlitFadePixel = model_translucent_unlit_fade_frag::getShader(); auto simpleFadePixel = simple_textured_fade_frag::getShader(); auto simpleUnlitFadePixel = simple_textured_unlit_fade_frag::getShader(); @@ -284,12 +261,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip addPipeline( Key::Builder().withMaterial().withTangents(), modelNormalMapVertex, modelNormalMapPixel, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withSpecular(), - modelVertex, modelSpecularMapPixel, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withTangents().withSpecular(), - modelNormalMapVertex, modelNormalSpecularMapPixel, nullptr, nullptr); + // Same thing but with Fade on addPipeline( Key::Builder().withMaterial().withFade(), @@ -306,12 +278,6 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip addPipeline( Key::Builder().withMaterial().withTangents().withFade(), modelNormalMapFadeVertex, modelNormalMapFadePixel, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withSpecular().withFade(), - modelFadeVertex, modelSpecularMapFadePixel, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withTangents().withSpecular().withFade(), - modelNormalMapFadeVertex, modelNormalSpecularMapFadePixel, batchSetter, itemSetter); // Translucents addPipeline( @@ -328,13 +294,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip simpleVertex, simpleTranslucentUnlitPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withTranslucent().withTangents(), - modelTranslucentNormalMapVertex, modelTranslucentNormalMapPixel, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withTranslucent().withSpecular(), modelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withTranslucent().withTangents().withSpecular(), - modelTranslucentNormalMapVertex, modelTranslucentNormalMapPixel, nullptr, nullptr); addPipeline( // FIXME: Ignore lightmap for translucents meshpart Key::Builder().withMaterial().withTranslucent().withLightmap(), @@ -354,13 +314,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip simpleFadeVertex, simpleTranslucentUnlitFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withTranslucent().withTangents().withFade(), - modelTranslucentNormalMapVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withTranslucent().withSpecular().withFade(), - modelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withTranslucent().withTangents().withSpecular().withFade(), - modelTranslucentNormalMapVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter); + modelNormalMapFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); addPipeline( // FIXME: Ignore lightmap for translucents meshpart Key::Builder().withMaterial().withTranslucent().withLightmap().withFade(), @@ -373,12 +327,6 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip addPipeline( Key::Builder().withMaterial().withLightmap().withTangents(), modelLightmapNormalMapVertex, modelLightmapNormalMapPixel, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withLightmap().withSpecular(), - modelLightmapVertex, modelLightmapSpecularMapPixel, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withLightmap().withTangents().withSpecular(), - modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel, nullptr, nullptr); // Same thing but with Fade on addPipeline( Key::Builder().withMaterial().withLightmap().withFade(), @@ -386,12 +334,6 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip addPipeline( Key::Builder().withMaterial().withLightmap().withTangents().withFade(), modelLightmapNormalMapFadeVertex, modelLightmapNormalMapFadePixel, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withLightmap().withSpecular().withFade(), - modelLightmapFadeVertex, modelLightmapSpecularMapFadePixel, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withLightmap().withTangents().withSpecular().withFade(), - modelLightmapNormalMapFadeVertex, modelLightmapNormalSpecularMapFadePixel, batchSetter, itemSetter); // matrix palette skinned addPipeline( @@ -400,12 +342,6 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip addPipeline( Key::Builder().withMaterial().withSkinned().withTangents(), skinModelNormalMapVertex, modelNormalMapPixel, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withSkinned().withSpecular(), - skinModelVertex, modelSpecularMapPixel, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withSkinned().withTangents().withSpecular(), - skinModelNormalMapVertex, modelNormalSpecularMapPixel, nullptr, nullptr); // Same thing but with Fade on addPipeline( Key::Builder().withMaterial().withSkinned().withFade(), @@ -413,12 +349,6 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip addPipeline( Key::Builder().withMaterial().withSkinned().withTangents().withFade(), skinModelNormalMapFadeVertex, modelNormalMapFadePixel, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withSkinned().withSpecular().withFade(), - skinModelFadeVertex, modelSpecularMapFadePixel, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withSkinned().withTangents().withSpecular().withFade(), - skinModelNormalMapFadeVertex, modelNormalSpecularMapFadePixel, batchSetter, itemSetter); // matrix palette skinned and translucent addPipeline( @@ -426,26 +356,14 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip skinModelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents(), - skinModelNormalMapTranslucentVertex, modelTranslucentNormalMapPixel, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withSkinned().withTranslucent().withSpecular(), - skinModelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular(), - skinModelNormalMapTranslucentVertex, modelTranslucentNormalMapPixel, nullptr, nullptr); + skinModelNormalMapTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); // Same thing but with Fade on addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withFade(), skinModelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withFade(), - skinModelNormalMapFadeVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withSkinned().withTranslucent().withSpecular().withFade(), - skinModelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular().withFade(), - skinModelNormalMapFadeVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter); + skinModelNormalMapFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); // dual quaternion skinned addPipeline( @@ -454,12 +372,6 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip addPipeline( Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTangents(), skinModelNormalMapDualQuatVertex, modelNormalMapPixel, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withSpecular(), - skinModelDualQuatVertex, modelSpecularMapPixel, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTangents().withSpecular(), - skinModelNormalMapDualQuatVertex, modelNormalSpecularMapPixel, nullptr, nullptr); // Same thing but with Fade on addPipeline( Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withFade(), @@ -467,12 +379,6 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip addPipeline( Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTangents().withFade(), skinModelNormalMapFadeDualQuatVertex, modelNormalMapFadePixel, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withSpecular().withFade(), - skinModelFadeDualQuatVertex, modelSpecularMapFadePixel, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTangents().withSpecular().withFade(), - skinModelNormalMapFadeDualQuatVertex, modelNormalSpecularMapFadePixel, batchSetter, itemSetter); // dual quaternion skinned and translucent addPipeline( @@ -480,26 +386,14 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip skinModelTranslucentDualQuatVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withTangents(), - skinModelNormalMapTranslucentDualQuatVertex, modelTranslucentNormalMapPixel, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withSpecular(), - skinModelTranslucentDualQuatVertex, modelTranslucentPixel, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withTangents().withSpecular(), - skinModelNormalMapTranslucentDualQuatVertex, modelTranslucentNormalMapPixel, nullptr, nullptr); + skinModelNormalMapTranslucentDualQuatVertex, modelTranslucentPixel, nullptr, nullptr); // Same thing but with Fade on addPipeline( Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withFade(), skinModelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withTangents().withFade(), - skinModelNormalMapFadeDualQuatVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withSpecular().withFade(), - skinModelFadeDualQuatVertex, modelTranslucentFadePixel, batchSetter, itemSetter); - addPipeline( - Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withTangents().withSpecular().withFade(), - skinModelNormalMapFadeDualQuatVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter); + skinModelNormalMapFadeDualQuatVertex, modelTranslucentFadePixel, batchSetter, itemSetter); // Depth-only addPipeline( @@ -523,51 +417,44 @@ void initForwardPipelines(ShapePlumber& plumber, const render::ShapePipeline::Ba auto modelNormalMapVertex = model_normal_map_vert::getShader(); auto skinModelVertex = skin_model_vert::getShader(); auto skinModelNormalMapVertex = skin_model_normal_map_vert::getShader(); - auto skinModelNormalMapFadeVertex = skin_model_normal_map_fade_vert::getShader(); // Pixel shaders auto modelPixel = forward_model_frag::getShader(); auto modelUnlitPixel = forward_model_unlit_frag::getShader(); auto modelNormalMapPixel = forward_model_normal_map_frag::getShader(); - auto modelSpecularMapPixel = forward_model_specular_map_frag::getShader(); - auto modelNormalSpecularMapPixel = forward_model_normal_specular_map_frag::getShader(); - auto modelNormalMapFadePixel = model_normal_map_fade_frag::getShader(); + auto modelTranslucentPixel = forward_model_translucent_frag::getShader(); using Key = render::ShapeKey; - auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3, _4, _5); - // Opaques - addPipeline( - Key::Builder().withMaterial(), - modelVertex, modelPixel, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withUnlit(), - modelVertex, modelUnlitPixel, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withTangents(), - modelNormalMapVertex, modelNormalMapPixel, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withSpecular(), - modelVertex, modelSpecularMapPixel, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withTangents().withSpecular(), - modelNormalMapVertex, modelNormalSpecularMapPixel, nullptr, nullptr); - // Skinned - addPipeline( - Key::Builder().withMaterial().withSkinned(), - skinModelVertex, modelPixel, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withSkinned().withTangents(), - skinModelNormalMapVertex, modelNormalMapPixel, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withSkinned().withSpecular(), - skinModelVertex, modelSpecularMapPixel, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withSkinned().withTangents().withSpecular(), - skinModelNormalMapVertex, modelNormalSpecularMapPixel, nullptr, nullptr); - addPipeline( - Key::Builder().withMaterial().withSkinned().withTangents().withFade(), - skinModelNormalMapFadeVertex, modelNormalMapFadePixel, batchSetter, itemSetter, nullptr, nullptr); + auto addPipelineBind = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3, _4, _5); + // Disable fade on the forward pipeline, all shaders get added twice, once with the fade key and once without + auto addPipeline = [&](const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel) { + addPipelineBind(key, vertex, pixel, nullptr, nullptr); + addPipelineBind(Key::Builder(key).withFade(), vertex, pixel, nullptr, nullptr); + }; + + // Forward pipelines need the lightBatchSetter for opaques and transparents + // forceLightBatchSetter = true; + forceLightBatchSetter = false; + + // Opaques + addPipeline(Key::Builder().withMaterial(), modelVertex, modelPixel); + addPipeline(Key::Builder().withMaterial().withUnlit(), modelVertex, modelUnlitPixel); + addPipeline(Key::Builder().withMaterial().withTangents(), modelNormalMapVertex, modelNormalMapPixel); + + // Skinned Opaques + addPipeline(Key::Builder().withMaterial().withSkinned(), skinModelVertex, modelPixel); + addPipeline(Key::Builder().withMaterial().withSkinned().withTangents(), skinModelNormalMapVertex, modelNormalMapPixel); + + // Translucents + addPipeline(Key::Builder().withMaterial().withTranslucent(), modelVertex, modelTranslucentPixel); + addPipeline(Key::Builder().withMaterial().withTranslucent().withTangents(), modelNormalMapVertex, modelTranslucentPixel); + + // Skinned Translucents + addPipeline(Key::Builder().withMaterial().withSkinned().withTranslucent(), skinModelVertex, modelTranslucentPixel); + addPipeline(Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents(), skinModelNormalMapVertex, modelTranslucentPixel); + + forceLightBatchSetter = false; } void addPlumberPipeline(ShapePlumber& plumber, @@ -609,7 +496,7 @@ void addPlumberPipeline(ShapePlumber& plumber, state->setDepthBiasSlopeScale(1.0f); } - auto baseBatchSetter = key.isTranslucent() ? &lightBatchSetter : &batchSetter; + auto baseBatchSetter = (forceLightBatchSetter || key.isTranslucent()) ? &lightBatchSetter : &batchSetter; render::ShapePipeline::BatchSetter finalBatchSetter; if (extraBatchSetter) { finalBatchSetter = [baseBatchSetter, extraBatchSetter](const ShapePipeline& pipeline, gpu::Batch& batch, render::Args* args) { diff --git a/libraries/render-utils/src/ToneMappingEffect.cpp b/libraries/render-utils/src/ToneMappingEffect.cpp index e1abefd681..0cc5be5ff9 100644 --- a/libraries/render-utils/src/ToneMappingEffect.cpp +++ b/libraries/render-utils/src/ToneMappingEffect.cpp @@ -57,10 +57,16 @@ void ToneMappingEffect::setToneCurve(ToneCurve curve) { } } -void ToneMappingEffect::render(RenderArgs* args, const gpu::TexturePointer& lightingBuffer, const gpu::FramebufferPointer& destinationFramebuffer) { +void ToneMappingEffect::render(RenderArgs* args, const gpu::TexturePointer& lightingBuffer, const gpu::FramebufferPointer& requestedDestinationFramebuffer) { if (!_blitLightBuffer) { init(); } + + auto destinationFramebuffer = requestedDestinationFramebuffer; + if (!destinationFramebuffer) { + destinationFramebuffer = args->_blitFramebuffer; + } + auto framebufferSize = glm::ivec2(lightingBuffer->getDimensions()); gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.enableStereo(false); diff --git a/libraries/render-utils/src/ZoneRenderer.cpp b/libraries/render-utils/src/ZoneRenderer.cpp index 1d358ff895..b6d0e61577 100644 --- a/libraries/render-utils/src/ZoneRenderer.cpp +++ b/libraries/render-utils/src/ZoneRenderer.cpp @@ -52,25 +52,25 @@ void ZoneRendererTask::build(JobModel& task, const Varying& input, Varying& oupu } void SetupZones::run(const RenderContextPointer& context, const Inputs& inputs) { + // Grab light, background and haze stages and clear them + auto lightStage = context->_scene->getStage(); + assert(lightStage); + lightStage->_currentFrame.clear(); + auto backgroundStage = context->_scene->getStage(); assert(backgroundStage); backgroundStage->_currentFrame.clear(); - // Haze auto hazeStage = context->_scene->getStage(); assert(hazeStage); hazeStage->_currentFrame.clear(); - // call render in the correct order first... + // call render over the zones to grab their components in the correct order first... render::renderItems(context, inputs); // Finally add the default lights and background: - auto lightStage = context->_scene->getStage(); - assert(lightStage); - lightStage->_currentFrame.pushSunLight(lightStage->getDefaultLight()); lightStage->_currentFrame.pushAmbientLight(lightStage->getDefaultLight()); - backgroundStage->_currentFrame.pushBackground(0); hazeStage->_currentFrame.pushHaze(0); } diff --git a/libraries/render-utils/src/forward_model.slf b/libraries/render-utils/src/forward_model.slf index 65556e2939..9241503902 100644 --- a/libraries/render-utils/src/forward_model.slf +++ b/libraries/render-utils/src/forward_model.slf @@ -1,18 +1,16 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> +// // forward_model.frag // fragment shader // -// Created by Andrzej Kapolka on 10/14/13. -// Copyright 2013 High Fidelity, Inc. +// Created by Sam Gateau on 2/15/2016. +// Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - - !> - <@include ForwardGlobalLight.slh@> <$declareEvalSkyboxGlobalColor()$> @@ -22,21 +20,21 @@ <$declareStandardCameraTransform()$> <@include MaterialTextures.slh@> -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, _SCRIBE_NULL)$> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$> in vec4 _position; -in vec3 _normal; -in vec3 _color; in vec2 _texCoord0; in vec2 _texCoord1; +in vec3 _normal; +in vec3 _color; -out vec4 _fragColor; +layout(location = 0) out vec4 _fragColor0; void main(void) { Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$> - !> + BITFIELD matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> float opacity = 1.0; <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; @@ -46,41 +44,33 @@ void main(void) { <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; albedo *= _color; - float metallic = getMaterialMetallic(mat); - vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value - if (metallic <= 0.5) { - metallic = 0.0; - } else { - fresnel = albedo; - metallic = 1.0; - } - float roughness = getMaterialRoughness(mat); <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; vec3 emissive = getMaterialEmissive(mat); <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + float metallic = getMaterialMetallic(mat); + <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; + vec3 fresnel = getFresnelF0(metallic, albedo); vec3 fragPosition = _position.xyz; + vec3 fragNormal = normalize(_normal); TransformCamera cam = getTransformCamera(); - vec3 fragNormal; - <$transformEyeToWorldDir(cam, _normal, fragNormal)$> vec4 color = vec4(evalSkyboxGlobalColor( cam._viewInverse, 1.0, - 1.0, + occlusionTex, fragPosition, fragNormal, albedo, fresnel, metallic, roughness), - opacity); - color.rgb += emissive * isEmissiveEnabled(); + opacity); + color.rgb += emissive * isEmissiveEnabled(); -// _fragColor = vec4(albedo, opacity); - _fragColor = color; + _fragColor0 = color; } diff --git a/libraries/render-utils/src/forward_model_normal_map.slf b/libraries/render-utils/src/forward_model_normal_map.slf index d22cc667e1..b32ed862d6 100644 --- a/libraries/render-utils/src/forward_model_normal_map.slf +++ b/libraries/render-utils/src/forward_model_normal_map.slf @@ -5,15 +5,13 @@ // forward_model_normal_map.frag // fragment shader // -// Created by Andrzej Kapolka on 10/29/13. -// Copyright 2013 High Fidelity, Inc. +// Created by Sam Gateau on 2/15/2016. +// Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - !> - <@include ForwardGlobalLight.slh@> <$declareEvalSkyboxGlobalColor()$> @@ -23,7 +21,7 @@ <$declareStandardCameraTransform()$> <@include MaterialTextures.slh@> -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, _SCRIBE_NULL, EMISSIVE, OCCLUSION, SCATTERING)$> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION)$> in vec4 _position; in vec2 _texCoord0; @@ -32,61 +30,51 @@ in vec3 _normal; in vec3 _tangent; in vec3 _color; -out vec4 _fragColor; +layout(location = 0) out vec4 _fragColor0; void main(void) { Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, _SCRIBE_NULL, emissiveTex, scatteringTex)$> + BITFIELD matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex)$> <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; <$discardTransparent(opacity)$>; vec3 albedo = getMaterialAlbedo(mat); <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; albedo *= _color; - float metallic = getMaterialMetallic(mat); - vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value - if (metallic <= 0.5) { - metallic = 0.0; - } else { - fresnel = albedo; - metallic = 1.0; - } - float roughness = getMaterialRoughness(mat); <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; vec3 emissive = getMaterialEmissive(mat); <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - vec3 viewNormal; - <$tangentToViewSpace(normalTex, _normal, _tangent, viewNormal)$> - - float scattering = getMaterialScattering(mat); - <$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>; + float metallic = getMaterialMetallic(mat); + <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; + vec3 fresnel = getFresnelF0(metallic, albedo); vec3 fragPosition = _position.xyz; + vec3 fragNormal; + <$tangentToViewSpace(normalTex, _normal, _tangent, fragNormal)$> TransformCamera cam = getTransformCamera(); - + vec4 color = vec4(evalSkyboxGlobalColor( cam._viewInverse, 1.0, - 1.0, + occlusionTex, fragPosition, - viewNormal, + fragNormal, albedo, fresnel, metallic, roughness), - opacity); + opacity); color.rgb += emissive * isEmissiveEnabled(); -// _fragColor = vec4(albedo, opacity); - _fragColor = color; + _fragColor0 = color; } diff --git a/libraries/render-utils/src/forward_model_normal_specular_map.slf b/libraries/render-utils/src/forward_model_normal_specular_map.slf deleted file mode 100644 index 68e5b755f8..0000000000 --- a/libraries/render-utils/src/forward_model_normal_specular_map.slf +++ /dev/null @@ -1,91 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// forward_model_normal_specular_map.frag -// fragment shader -// -// Created by Andrzej Kapolka on 5/6/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - - - !> - -<@include ForwardGlobalLight.slh@> -<$declareEvalSkyboxGlobalColor()$> - -<@include graphics/Material.slh@> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<@include MaterialTextures.slh@> -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION)$> - -in vec4 _position; -in vec2 _texCoord0; -in vec2 _texCoord1; -in vec3 _normal; -in vec3 _tangent; -in vec3 _color; - -out vec4 _fragColor; - -void main(void) { - Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - vec3 viewNormal; - <$tangentToViewSpace(normalTex, _normal, _tangent, viewNormal)$> - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value - if (metallic <= 0.5) { - metallic = 0.0; - } - else { - fresnel = albedo; - metallic = 1.0; - } - vec3 fragPosition = _position.xyz; - - TransformCamera cam = getTransformCamera(); - - vec4 color = vec4(evalSkyboxGlobalColor( - cam._viewInverse, - 1.0, - 1.0, - fragPosition, - viewNormal, - albedo, - fresnel, - metallic, - roughness), - opacity); - - color.rgb += emissive * isEmissiveEnabled(); - - // _fragColor = vec4(albedo, opacity); - _fragColor = color; -} diff --git a/libraries/render-utils/src/forward_model_specular_map.slf b/libraries/render-utils/src/forward_model_specular_map.slf deleted file mode 100644 index 057ec2cf53..0000000000 --- a/libraries/render-utils/src/forward_model_specular_map.slf +++ /dev/null @@ -1,100 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// forward_model_specular_map.frag -// fragment shader -// -// Created by Andrzej Kapolka on 5/6/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - - - !> - -<@include ForwardGlobalLight.slh@> -<$declareEvalSkyboxGlobalColor()$> - -<@include graphics/Material.slh@> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - -<@include MaterialTextures.slh@> -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$> - -in vec4 _position; -in vec2 _texCoord0; -in vec2 _texCoord1; -in vec3 _normal; -in vec3 _color; - -out vec4 _fragColor; - -void main(void) { - Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex)$> - !> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value - if (metallic <= 0.5) { - metallic = 0.0; - } - else { - fresnel = albedo; - metallic = 1.0; - }/* - float scattering = getMaterialScattering(mat); - - packForwardFragment( - normalize(_normal), - opacity, - albedo, - roughness, - metallic, - emissive, - occlusionTex, - scattering); - */ - vec3 fragPosition = _position.xyz; - - TransformCamera cam = getTransformCamera(); - vec3 fragNormal; - <$transformEyeToWorldDir(cam, _normal, fragNormal)$> - - vec4 color = vec4(evalSkyboxGlobalColor( - cam._viewInverse, - 1.0, - 1.0, - fragPosition, - fragNormal, - albedo, - fresnel, - metallic, - roughness), - opacity); - color.rgb += emissive * isEmissiveEnabled(); - - // _fragColor = vec4(albedo, opacity); - _fragColor = color; -} diff --git a/libraries/render-utils/src/forward_model_translucent.slf b/libraries/render-utils/src/forward_model_translucent.slf index 7f752d893a..2892a6bbf5 100644 --- a/libraries/render-utils/src/forward_model_translucent.slf +++ b/libraries/render-utils/src/forward_model_translucent.slf @@ -22,7 +22,7 @@ <$declareStandardCameraTransform()$> <@include MaterialTextures.slh@> -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$> in vec2 _texCoord0; in vec2 _texCoord1; @@ -31,12 +31,12 @@ in vec3 _normal; in vec3 _color; in float _alpha; -out vec4 _fragColor; +layout(location = 0) out vec4 _fragColor0; void main(void) { Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$> + BITFIELD matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex)$> <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> float opacity = getMaterialOpacity(mat) * _alpha; @@ -50,13 +50,8 @@ void main(void) { <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; float metallic = getMaterialMetallic(mat); - vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value - if (metallic <= 0.5) { - metallic = 0.0; - } else { - fresnel = albedo; - metallic = 1.0; - } + <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; + vec3 fresnel = getFresnelF0(metallic, albedo); vec3 emissive = getMaterialEmissive(mat); <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; @@ -66,7 +61,7 @@ void main(void) { TransformCamera cam = getTransformCamera(); - _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze( + _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( cam._viewInverse, 1.0, occlusionTex, diff --git a/libraries/render-utils/src/forward_model_unlit.slf b/libraries/render-utils/src/forward_model_unlit.slf index 72ee61e28c..fda001dba9 100644 --- a/libraries/render-utils/src/forward_model_unlit.slf +++ b/libraries/render-utils/src/forward_model_unlit.slf @@ -12,7 +12,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include ForwardBufferWrite.slh@> <@include LightingModel.slh@> <@include graphics/Material.slh@> @@ -24,10 +23,12 @@ in vec3 _normal; in vec3 _color; in float _alpha; +layout(location = 0) out vec4 _fragColor0; + void main(void) { Material mat = getMaterial(); - int matKey = getMaterialKey(mat); + BITFIELD matKey = getMaterialKey(mat); <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> float opacity = 1.0; @@ -38,8 +39,8 @@ void main(void) { <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; albedo *= _color; - packForwardFragmentUnlit( - normalize(_normal), - opacity, - albedo * isUnlitEnabled()); + if (opacity != 1.0) { + discard; + } + _fragColor0 = vec4(albedo * isUnlitEnabled(), 1.0); } diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index 4747b69278..94929f4943 100644 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -1,11 +1,12 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> -// model.frag +// +// model_specular_map.frag // fragment shader // -// Created by Andrzej Kapolka on 10/14/13. -// Copyright 2013 High Fidelity, Inc. +// Created by Andrzej Kapolka on 5/6/14. +// Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -16,19 +17,19 @@ <@include graphics/Material.slh@> <@include MaterialTextures.slh@> -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION, SCATTERING)$> in vec4 _position; -in vec3 _normal; -in vec3 _color; in vec2 _texCoord0; in vec2 _texCoord1; +in vec3 _normal; +in vec3 _color; void main(void) { Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$> + BITFIELD matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex, scatteringTex)$> <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> float opacity = 1.0; @@ -45,14 +46,18 @@ void main(void) { vec3 emissive = getMaterialEmissive(mat); <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + float metallic = getMaterialMetallic(mat); + <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; + float scattering = getMaterialScattering(mat); + <$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>; packDeferredFragment( - normalize(_normal.xyz), + normalize(_normal), opacity, albedo, roughness, - getMaterialMetallic(mat), + metallic, emissive, occlusionTex, scattering); diff --git a/libraries/render-utils/src/model_fade.slf b/libraries/render-utils/src/model_fade.slf index 40c156a3a4..577324f97a 100644 --- a/libraries/render-utils/src/model_fade.slf +++ b/libraries/render-utils/src/model_fade.slf @@ -1,10 +1,11 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> +// // model_fade.frag // fragment shader // -// Created by Olivier Prat on 04/19/17. +// Created by Olivier Prat on 06/05/17. // Copyright 2017 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. @@ -16,18 +17,17 @@ <@include graphics/Material.slh@> <@include MaterialTextures.slh@> -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$> <@include Fade.slh@> <$declareFadeFragment()$> in vec4 _position; -in vec4 _worldPosition; -in vec3 _normal; -in vec3 _color; in vec2 _texCoord0; in vec2 _texCoord1; - +in vec3 _normal; +in vec3 _color; +in vec4 _worldPosition; void main(void) { vec3 fadeEmissive; @@ -37,8 +37,8 @@ void main(void) { applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$> + BITFIELD matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex)$> <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> float opacity = 1.0; @@ -54,17 +54,19 @@ void main(void) { vec3 emissive = getMaterialEmissive(mat); <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - emissive += fadeEmissive; + + float metallic = getMaterialMetallic(mat); + <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; float scattering = getMaterialScattering(mat); packDeferredFragment( - normalize(_normal.xyz), + normalize(_normal), opacity, albedo, roughness, - getMaterialMetallic(mat), - emissive, + metallic, + emissive+fadeEmissive, occlusionTex, scattering); } diff --git a/libraries/render-utils/src/model_lightmap.slf b/libraries/render-utils/src/model_lightmap.slf index b22a1029f9..33195fce00 100644 --- a/libraries/render-utils/src/model_lightmap.slf +++ b/libraries/render-utils/src/model_lightmap.slf @@ -2,11 +2,11 @@ <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // -// model_lightmap.frag +// model_lightmap_specular_map.frag // fragment shader // // Created by Samuel Gateau on 11/19/14. -// Copyright 2013 High Fidelity, Inc. +// Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -17,7 +17,7 @@ <@include graphics/Material.slh@> <@include MaterialTextures.slh@> -<$declareMaterialTextures(ALBEDO, ROUGHNESS)$> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC)$> <$declareMaterialLightmap()$> in vec4 _position; @@ -28,17 +28,16 @@ in vec3 _color; void main(void) { Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness)$> + BITFIELD matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, _SCRIBE_NULL, metallicTex)$> <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$> - packDeferredFragmentLightmap( normalize(_normal), evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a), getMaterialAlbedo(mat) * albedo.rgb * _color, getMaterialRoughness(mat) * roughness, - getMaterialMetallic(mat), - getMaterialFresnel(mat), + getMaterialMetallic(mat) * metallicTex, + /*metallicTex, // no use of */getMaterialFresnel(mat), lightmapVal); } diff --git a/libraries/render-utils/src/model_lightmap_fade.slf b/libraries/render-utils/src/model_lightmap_fade.slf index 55cb24d35d..1dfc6a1b9e 100644 --- a/libraries/render-utils/src/model_lightmap_fade.slf +++ b/libraries/render-utils/src/model_lightmap_fade.slf @@ -17,7 +17,7 @@ <@include graphics/Material.slh@> <@include MaterialTextures.slh@> -<$declareMaterialTextures(ALBEDO, ROUGHNESS)$> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC)$> <$declareMaterialLightmap()$> <@include Fade.slh@> @@ -38,17 +38,16 @@ void main(void) { applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness)$> + BITFIELD matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, _SCRIBE_NULL, metallicTex)$> <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$> - packDeferredFragmentLightmap( normalize(_normal), evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a), getMaterialAlbedo(mat) * albedo.rgb * _color, getMaterialRoughness(mat) * roughness, - getMaterialMetallic(mat), - getMaterialFresnel(mat), + getMaterialMetallic(mat) * metallicTex, + /*metallicTex, // no use of */getMaterialFresnel(mat), lightmapVal+fadeEmissive); } diff --git a/libraries/render-utils/src/model_lightmap_normal_map.slf b/libraries/render-utils/src/model_lightmap_normal_map.slf index 1510ea9ba3..8734ea74b8 100644 --- a/libraries/render-utils/src/model_lightmap_normal_map.slf +++ b/libraries/render-utils/src/model_lightmap_normal_map.slf @@ -6,7 +6,7 @@ // fragment shader // // Created by Samuel Gateau on 11/19/14. -// Copyright 2013 High Fidelity, Inc. +// Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -17,7 +17,7 @@ <@include graphics/Material.slh@> <@include MaterialTextures.slh@> -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL)$> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC)$> <$declareMaterialLightmap()$> in vec4 _position; @@ -29,10 +29,10 @@ in vec3 _color; void main(void) { Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel)$> + BITFIELD matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel, metallicTex)$> <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$> - + vec3 viewNormal; <$tangentToViewSpaceLOD(_position, normalTexel, _normal, _tangent, viewNormal)$> @@ -40,8 +40,8 @@ void main(void) { normalize(viewNormal.xyz), evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a), getMaterialAlbedo(mat) * albedo.rgb * _color, - getMaterialRoughness(mat), - getMaterialMetallic(mat), - getMaterialFresnel(mat), + getMaterialRoughness(mat) * roughness, + getMaterialMetallic(mat) * metallicTex, + /*specular, // no use of */ getMaterialFresnel(mat), lightmapVal); } diff --git a/libraries/render-utils/src/model_lightmap_normal_map_fade.slf b/libraries/render-utils/src/model_lightmap_normal_map_fade.slf index 6b63943a9a..e6cb35ec4f 100644 --- a/libraries/render-utils/src/model_lightmap_normal_map_fade.slf +++ b/libraries/render-utils/src/model_lightmap_normal_map_fade.slf @@ -17,7 +17,7 @@ <@include graphics/Material.slh@> <@include MaterialTextures.slh@> -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL)$> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC)$> <$declareMaterialLightmap()$> <@include Fade.slh@> @@ -39,10 +39,10 @@ void main(void) { applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel)$> + BITFIELD matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel, metallicTex)$> <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$> - + vec3 viewNormal; <$tangentToViewSpaceLOD(_position, normalTexel, _normal, _tangent, viewNormal)$> @@ -50,8 +50,8 @@ void main(void) { normalize(viewNormal.xyz), evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a), getMaterialAlbedo(mat) * albedo.rgb * _color, - getMaterialRoughness(mat), - getMaterialMetallic(mat), - getMaterialFresnel(mat), + getMaterialRoughness(mat) * roughness, + getMaterialMetallic(mat) * metallicTex, + /*specular, // no use of */ getMaterialFresnel(mat), lightmapVal+fadeEmissive); } diff --git a/libraries/render-utils/src/model_lightmap_normal_specular_map.slf b/libraries/render-utils/src/model_lightmap_normal_specular_map.slf deleted file mode 100644 index 3a66aaad3d..0000000000 --- a/libraries/render-utils/src/model_lightmap_normal_specular_map.slf +++ /dev/null @@ -1,47 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// model_lightmap_normal_specular_map.frag -// fragment shader -// -// Created by Samuel Gateau on 11/19/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DeferredBufferWrite.slh@> - -<@include graphics/Material.slh@> - -<@include MaterialTextures.slh@> -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC)$> -<$declareMaterialLightmap()$> - -in vec4 _position; -in vec2 _texCoord0; -in vec2 _texCoord1; -in vec3 _normal; -in vec3 _tangent; -in vec3 _color; - -void main(void) { - Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel, metallicTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$> - - vec3 viewNormal; - <$tangentToViewSpaceLOD(_position, normalTexel, _normal, _tangent, viewNormal)$> - - packDeferredFragmentLightmap( - normalize(viewNormal.xyz), - evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a), - getMaterialAlbedo(mat) * albedo.rgb * _color, - getMaterialRoughness(mat) * roughness, - getMaterialMetallic(mat) * metallicTex, - /*specular, // no use of */ getMaterialFresnel(mat), - lightmapVal); -} diff --git a/libraries/render-utils/src/model_lightmap_normal_specular_map_fade.slf b/libraries/render-utils/src/model_lightmap_normal_specular_map_fade.slf deleted file mode 100644 index b785a8a6ab..0000000000 --- a/libraries/render-utils/src/model_lightmap_normal_specular_map_fade.slf +++ /dev/null @@ -1,57 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// model_lightmap_normal_specular_map_fade.frag -// fragment shader -// -// Created by Olivier Prat on 06/05/17. -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DeferredBufferWrite.slh@> - -<@include graphics/Material.slh@> - -<@include MaterialTextures.slh@> -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC)$> -<$declareMaterialLightmap()$> - -<@include Fade.slh@> -<$declareFadeFragment()$> - -in vec4 _position; -in vec2 _texCoord0; -in vec2 _texCoord1; -in vec3 _normal; -in vec3 _tangent; -in vec3 _color; -in vec4 _worldPosition; - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - - <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); - - Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel, metallicTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$> - - vec3 viewNormal; - <$tangentToViewSpaceLOD(_position, normalTexel, _normal, _tangent, viewNormal)$> - - packDeferredFragmentLightmap( - normalize(viewNormal.xyz), - evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a), - getMaterialAlbedo(mat) * albedo.rgb * _color, - getMaterialRoughness(mat) * roughness, - getMaterialMetallic(mat) * metallicTex, - /*specular, // no use of */ getMaterialFresnel(mat), - lightmapVal+fadeEmissive); -} diff --git a/libraries/render-utils/src/model_lightmap_specular_map.slf b/libraries/render-utils/src/model_lightmap_specular_map.slf deleted file mode 100644 index 1c97d435bd..0000000000 --- a/libraries/render-utils/src/model_lightmap_specular_map.slf +++ /dev/null @@ -1,43 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// model_lightmap_specular_map.frag -// fragment shader -// -// Created by Samuel Gateau on 11/19/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DeferredBufferWrite.slh@> - -<@include graphics/Material.slh@> - -<@include MaterialTextures.slh@> -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC)$> -<$declareMaterialLightmap()$> - -in vec4 _position; -in vec2 _texCoord0; -in vec2 _texCoord1; -in vec3 _normal; -in vec3 _color; - -void main(void) { - Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, _SCRIBE_NULL, metallicTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$> - - packDeferredFragmentLightmap( - normalize(_normal), - evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a), - getMaterialAlbedo(mat) * albedo.rgb * _color, - getMaterialRoughness(mat) * roughness, - getMaterialMetallic(mat) * metallicTex, - /*metallicTex, // no use of */getMaterialFresnel(mat), - lightmapVal); -} diff --git a/libraries/render-utils/src/model_lightmap_specular_map_fade.slf b/libraries/render-utils/src/model_lightmap_specular_map_fade.slf deleted file mode 100644 index 1adedb9328..0000000000 --- a/libraries/render-utils/src/model_lightmap_specular_map_fade.slf +++ /dev/null @@ -1,53 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// model_lightmap_specular_map_fade.frag -// fragment shader -// -// Created by Olivier Prat on 06/05/17. -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DeferredBufferWrite.slh@> - -<@include graphics/Material.slh@> - -<@include MaterialTextures.slh@> -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC)$> -<$declareMaterialLightmap()$> - -<@include Fade.slh@> -<$declareFadeFragment()$> - -in vec4 _position; -in vec2 _texCoord0; -in vec2 _texCoord1; -in vec3 _normal; -in vec3 _color; -in vec4 _worldPosition; - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - - <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); - - Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, _SCRIBE_NULL, metallicTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$> - - packDeferredFragmentLightmap( - normalize(_normal), - evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a), - getMaterialAlbedo(mat) * albedo.rgb * _color, - getMaterialRoughness(mat) * roughness, - getMaterialMetallic(mat) * metallicTex, - /*metallicTex, // no use of */getMaterialFresnel(mat), - lightmapVal+fadeEmissive); -} diff --git a/libraries/render-utils/src/model_normal_map.slf b/libraries/render-utils/src/model_normal_map.slf index b41e226e23..82f667bf73 100644 --- a/libraries/render-utils/src/model_normal_map.slf +++ b/libraries/render-utils/src/model_normal_map.slf @@ -5,8 +5,8 @@ // model_normal_map.frag // fragment shader // -// Created by Andrzej Kapolka on 10/29/13. -// Copyright 2013 High Fidelity, Inc. +// Created by Andrzej Kapolka on 5/6/14. +// Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -17,7 +17,7 @@ <@include graphics/Material.slh@> <@include MaterialTextures.slh@> -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, _SCRIBE_NULL, EMISSIVE, OCCLUSION, SCATTERING)$> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION, SCATTERING)$> in vec4 _position; in vec2 _texCoord0; @@ -28,12 +28,12 @@ in vec3 _color; void main(void) { Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, _SCRIBE_NULL, emissiveTex, scatteringTex)$> + BITFIELD matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex, scatteringTex)$> <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; <$discardTransparent(opacity)$>; vec3 albedo = getMaterialAlbedo(mat); @@ -49,15 +49,18 @@ void main(void) { vec3 viewNormal; <$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, viewNormal)$> + float metallic = getMaterialMetallic(mat); + <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; + float scattering = getMaterialScattering(mat); <$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>; packDeferredFragment( - viewNormal, + normalize(viewNormal.xyz), opacity, albedo, roughness, - getMaterialMetallic(mat), + metallic, emissive, occlusionTex, scattering); diff --git a/libraries/render-utils/src/model_normal_map_fade.slf b/libraries/render-utils/src/model_normal_map_fade.slf index 5a166b1c2c..67bea98cf0 100644 --- a/libraries/render-utils/src/model_normal_map_fade.slf +++ b/libraries/render-utils/src/model_normal_map_fade.slf @@ -2,10 +2,10 @@ <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // -// model_normal_map_fade.frag +// model_normal_specular_map_fade.frag // fragment shader // -// Created by Olivier Prat on 04/19/17. +// Created by Olivier Prat on 06/05/17. // Copyright 2017 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. @@ -17,18 +17,18 @@ <@include graphics/Material.slh@> <@include MaterialTextures.slh@> -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, _SCRIBE_NULL, EMISSIVE, OCCLUSION, SCATTERING)$> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION)$> <@include Fade.slh@> <$declareFadeFragment()$> in vec4 _position; -in vec4 _worldPosition; in vec2 _texCoord0; in vec2 _texCoord1; in vec3 _normal; in vec3 _tangent; in vec3 _color; +in vec4 _worldPosition; void main(void) { vec3 fadeEmissive; @@ -38,12 +38,12 @@ void main(void) { applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, _SCRIBE_NULL, emissiveTex, scatteringTex)$> + BITFIELD matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex)$> <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; <$discardTransparent(opacity)$>; vec3 albedo = getMaterialAlbedo(mat); @@ -57,17 +57,19 @@ void main(void) { <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; vec3 viewNormal; - <$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, viewNormal)$> + <$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, viewNormal)$> + + float metallic = getMaterialMetallic(mat); + <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; float scattering = getMaterialScattering(mat); - <$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>; packDeferredFragment( - viewNormal, + normalize(viewNormal.xyz), opacity, albedo, roughness, - getMaterialMetallic(mat), + metallic, emissive+fadeEmissive, occlusionTex, scattering); diff --git a/libraries/render-utils/src/model_normal_specular_map.slf b/libraries/render-utils/src/model_normal_specular_map.slf deleted file mode 100644 index 3eb3d43fdc..0000000000 --- a/libraries/render-utils/src/model_normal_specular_map.slf +++ /dev/null @@ -1,66 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// model_normal_specular_map.frag -// fragment shader -// -// Created by Andrzej Kapolka on 5/6/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DeferredBufferWrite.slh@> - -<@include graphics/Material.slh@> - -<@include MaterialTextures.slh@> -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION)$> - -in vec4 _position; -in vec2 _texCoord0; -in vec2 _texCoord1; -in vec3 _normal; -in vec3 _tangent; -in vec3 _color; - -void main(void) { - Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - vec3 viewNormal; - <$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, viewNormal)$> - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - float scattering = getMaterialScattering(mat); - - packDeferredFragment( - normalize(viewNormal.xyz), - opacity, - albedo, - roughness, - metallic, - emissive, - occlusionTex, - scattering); -} diff --git a/libraries/render-utils/src/model_normal_specular_map_fade.slf b/libraries/render-utils/src/model_normal_specular_map_fade.slf deleted file mode 100644 index 0985d5d493..0000000000 --- a/libraries/render-utils/src/model_normal_specular_map_fade.slf +++ /dev/null @@ -1,76 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// model_normal_specular_map_fade.frag -// fragment shader -// -// Created by Olivier Prat on 06/05/17. -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DeferredBufferWrite.slh@> - -<@include graphics/Material.slh@> - -<@include MaterialTextures.slh@> -<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION)$> - -<@include Fade.slh@> -<$declareFadeFragment()$> - -in vec4 _position; -in vec2 _texCoord0; -in vec2 _texCoord1; -in vec3 _normal; -in vec3 _tangent; -in vec3 _color; -in vec4 _worldPosition; - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - - <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); - - Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - vec3 viewNormal; - <$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, viewNormal)$> - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - float scattering = getMaterialScattering(mat); - - packDeferredFragment( - normalize(viewNormal.xyz), - opacity, - albedo, - roughness, - metallic, - emissive+fadeEmissive, - occlusionTex, - scattering); -} diff --git a/libraries/render-utils/src/model_specular_map.slf b/libraries/render-utils/src/model_specular_map.slf deleted file mode 100644 index e65dbaeda6..0000000000 --- a/libraries/render-utils/src/model_specular_map.slf +++ /dev/null @@ -1,63 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// model_specular_map.frag -// fragment shader -// -// Created by Andrzej Kapolka on 5/6/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DeferredBufferWrite.slh@> - -<@include graphics/Material.slh@> - -<@include MaterialTextures.slh@> -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$> - -in vec4 _position; -in vec2 _texCoord0; -in vec2 _texCoord1; -in vec3 _normal; -in vec3 _color; - - -void main(void) { - Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - float scattering = getMaterialScattering(mat); - - packDeferredFragment( - normalize(_normal), - opacity, - albedo, - roughness, - metallic, - emissive, - occlusionTex, - scattering); -} diff --git a/libraries/render-utils/src/model_specular_map_fade.slf b/libraries/render-utils/src/model_specular_map_fade.slf deleted file mode 100644 index 17173d8bc3..0000000000 --- a/libraries/render-utils/src/model_specular_map_fade.slf +++ /dev/null @@ -1,72 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// model_specular_map_fade.frag -// fragment shader -// -// Created by Olivier Prat on 06/05/17. -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DeferredBufferWrite.slh@> - -<@include graphics/Material.slh@> - -<@include MaterialTextures.slh@> -<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$> - -<@include Fade.slh@> -<$declareFadeFragment()$> - -in vec4 _position; -in vec2 _texCoord0; -in vec2 _texCoord1; -in vec3 _normal; -in vec3 _color; -in vec4 _worldPosition; - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - - <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); - - Material mat = getMaterial(); - int matKey = getMaterialKey(mat); - <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex)$> - <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> - - float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <$discardTransparent(opacity)$>; - - vec3 albedo = getMaterialAlbedo(mat); - <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; - albedo *= _color; - - float roughness = getMaterialRoughness(mat); - <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; - - vec3 emissive = getMaterialEmissive(mat); - <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - - float metallic = getMaterialMetallic(mat); - <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; - - float scattering = getMaterialScattering(mat); - - packDeferredFragment( - normalize(_normal), - opacity, - albedo, - roughness, - metallic, - emissive+fadeEmissive, - occlusionTex, - scattering); -} diff --git a/libraries/render-utils/src/model_translucent.slf b/libraries/render-utils/src/model_translucent.slf index 67a5651ab8..bac97f2546 100644 --- a/libraries/render-utils/src/model_translucent.slf +++ b/libraries/render-utils/src/model_translucent.slf @@ -38,7 +38,7 @@ out vec4 _fragColor; void main(void) { Material mat = getMaterial(); - int matKey = getMaterialKey(mat); + BITFIELD matKey = getMaterialKey(mat); <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$> <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> diff --git a/libraries/render-utils/src/model_translucent_fade.slf b/libraries/render-utils/src/model_translucent_fade.slf index e767d0ffa5..b81ed06479 100644 --- a/libraries/render-utils/src/model_translucent_fade.slf +++ b/libraries/render-utils/src/model_translucent_fade.slf @@ -40,7 +40,7 @@ void main(void) { applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); Material mat = getMaterial(); - int matKey = getMaterialKey(mat); + BITFIELD matKey = getMaterialKey(mat); <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$> <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> diff --git a/libraries/render-utils/src/model_translucent_unlit.slf b/libraries/render-utils/src/model_translucent_unlit.slf index 4c3a0f0195..ebe9901616 100644 --- a/libraries/render-utils/src/model_translucent_unlit.slf +++ b/libraries/render-utils/src/model_translucent_unlit.slf @@ -26,7 +26,7 @@ out vec4 _fragColor; void main(void) { Material mat = getMaterial(); - int matKey = getMaterialKey(mat); + BITFIELD matKey = getMaterialKey(mat); <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> float opacity = getMaterialOpacity(mat) * _alpha; diff --git a/libraries/render-utils/src/model_translucent_unlit_fade.slf b/libraries/render-utils/src/model_translucent_unlit_fade.slf index 210060d54d..ea8a912a86 100644 --- a/libraries/render-utils/src/model_translucent_unlit_fade.slf +++ b/libraries/render-utils/src/model_translucent_unlit_fade.slf @@ -36,7 +36,7 @@ void main(void) { applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); Material mat = getMaterial(); - int matKey = getMaterialKey(mat); + BITFIELD matKey = getMaterialKey(mat); <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> float opacity = getMaterialOpacity(mat) * _alpha; diff --git a/libraries/render-utils/src/model_unlit.slf b/libraries/render-utils/src/model_unlit.slf index ccfc7d4935..d786c94634 100644 --- a/libraries/render-utils/src/model_unlit.slf +++ b/libraries/render-utils/src/model_unlit.slf @@ -27,7 +27,7 @@ in float _alpha; void main(void) { Material mat = getMaterial(); - int matKey = getMaterialKey(mat); + BITFIELD matKey = getMaterialKey(mat); <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> float opacity = 1.0; diff --git a/libraries/render-utils/src/model_unlit_fade.slf b/libraries/render-utils/src/model_unlit_fade.slf index 65c97f9e21..50c1681c0d 100644 --- a/libraries/render-utils/src/model_unlit_fade.slf +++ b/libraries/render-utils/src/model_unlit_fade.slf @@ -36,7 +36,7 @@ void main(void) { applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); Material mat = getMaterial(); - int matKey = getMaterialKey(mat); + BITFIELD matKey = getMaterialKey(mat); <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> float opacity = 1.0; diff --git a/libraries/render-utils/src/overlay3D_model.slf b/libraries/render-utils/src/overlay3D_model.slf index d4de0ee69f..8e8c3e6077 100644 --- a/libraries/render-utils/src/overlay3D_model.slf +++ b/libraries/render-utils/src/overlay3D_model.slf @@ -33,7 +33,7 @@ out vec4 _fragColor; void main(void) { Material mat = getMaterial(); - int matKey = getMaterialKey(mat); + BITFIELD matKey = getMaterialKey(mat); <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$> <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> diff --git a/libraries/render-utils/src/overlay3D_model_translucent.slf b/libraries/render-utils/src/overlay3D_model_translucent.slf index b66c114f4a..040b491346 100644 --- a/libraries/render-utils/src/overlay3D_model_translucent.slf +++ b/libraries/render-utils/src/overlay3D_model_translucent.slf @@ -32,7 +32,7 @@ out vec4 _fragColor; void main(void) { Material mat = getMaterial(); - int matKey = getMaterialKey(mat); + BITFIELD matKey = getMaterialKey(mat); <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$> <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> diff --git a/libraries/render-utils/src/overlay3D_model_translucent_unlit.slf b/libraries/render-utils/src/overlay3D_model_translucent_unlit.slf index 3b79818cd9..6753b02a05 100644 --- a/libraries/render-utils/src/overlay3D_model_translucent_unlit.slf +++ b/libraries/render-utils/src/overlay3D_model_translucent_unlit.slf @@ -27,7 +27,7 @@ out vec4 _fragColor; void main(void) { Material mat = getMaterial(); - int matKey = getMaterialKey(mat); + BITFIELD matKey = getMaterialKey(mat); <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> float opacity = 1.0; diff --git a/libraries/render-utils/src/overlay3D_model_unlit.slf b/libraries/render-utils/src/overlay3D_model_unlit.slf index eab975e810..8b7eb06d41 100644 --- a/libraries/render-utils/src/overlay3D_model_unlit.slf +++ b/libraries/render-utils/src/overlay3D_model_unlit.slf @@ -27,7 +27,7 @@ out vec4 _fragColor; void main(void) { Material mat = getMaterial(); - int matKey = getMaterialKey(mat); + BITFIELD matKey = getMaterialKey(mat); <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> float opacity = 1.0; diff --git a/libraries/render-utils/src/surfaceGeometry_downsampleDepthNormal.slf b/libraries/render-utils/src/surfaceGeometry_downsampleDepthNormal.slf index 205dad124e..82895d4684 100644 --- a/libraries/render-utils/src/surfaceGeometry_downsampleDepthNormal.slf +++ b/libraries/render-utils/src/surfaceGeometry_downsampleDepthNormal.slf @@ -17,8 +17,8 @@ uniform sampler2D normalMap; in vec2 varTexCoord0; -out vec4 outLinearDepth; -out vec4 outNormal; +layout(location = 0) out vec4 outLinearDepth; +layout(location = 1) out vec4 outNormal; void main(void) { // Gather 2 by 2 quads from texture and downsample diff --git a/libraries/render-utils/src/text/Font.cpp b/libraries/render-utils/src/text/Font.cpp index f9508b343f..d3d25431d0 100644 --- a/libraries/render-utils/src/text/Font.cpp +++ b/libraries/render-utils/src/text/Font.cpp @@ -368,7 +368,9 @@ void Font::drawString(gpu::Batch& batch, float x, float y, const QString& str, c setupGPU(); batch.setPipeline(((*color).a < 1.0f || layered) ? _transparentPipeline : _pipeline); - batch.setResourceTexture(_fontLoc, _texture); + if (_fontLoc >= 0) { + batch.setResourceTexture(_fontLoc, _texture); + } if (_outlineLoc >= 0) { batch._glUniform1i(_outlineLoc, (effectType == OUTLINE_EFFECT)); } diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index f175bab99a..f6d02e1e96 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -29,7 +29,6 @@ public: TRANSLUCENT, LIGHTMAP, TANGENTS, - SPECULAR, UNLIT, SKINNED, DUAL_QUAT_SKINNED, @@ -78,7 +77,6 @@ public: Builder& withTranslucent() { _flags.set(TRANSLUCENT); return (*this); } Builder& withLightmap() { _flags.set(LIGHTMAP); return (*this); } Builder& withTangents() { _flags.set(TANGENTS); return (*this); } - Builder& withSpecular() { _flags.set(SPECULAR); return (*this); } Builder& withUnlit() { _flags.set(UNLIT); return (*this); } Builder& withSkinned() { _flags.set(SKINNED); return (*this); } Builder& withDualQuatSkinned() { _flags.set(DUAL_QUAT_SKINNED); return (*this); } @@ -126,9 +124,6 @@ public: Builder& withTangents() { _flags.set(TANGENTS); _mask.set(TANGENTS); return (*this); } Builder& withoutTangents() { _flags.reset(TANGENTS); _mask.set(TANGENTS); return (*this); } - Builder& withSpecular() { _flags.set(SPECULAR); _mask.set(SPECULAR); return (*this); } - Builder& withoutSpecular() { _flags.reset(SPECULAR); _mask.set(SPECULAR); return (*this); } - Builder& withUnlit() { _flags.set(UNLIT); _mask.set(UNLIT); return (*this); } Builder& withoutUnlit() { _flags.reset(UNLIT); _mask.set(UNLIT); return (*this); } @@ -172,7 +167,6 @@ public: bool useMaterial() const { return _flags[MATERIAL]; } bool hasLightmap() const { return _flags[LIGHTMAP]; } bool hasTangents() const { return _flags[TANGENTS]; } - bool hasSpecular() const { return _flags[SPECULAR]; } bool isUnlit() const { return _flags[UNLIT]; } bool isTranslucent() const { return _flags[TRANSLUCENT]; } bool isSkinned() const { return _flags[SKINNED]; } @@ -212,7 +206,6 @@ inline QDebug operator<<(QDebug debug, const ShapeKey& key) { << "useMaterial:" << key.useMaterial() << "hasLightmap:" << key.hasLightmap() << "hasTangents:" << key.hasTangents() - << "hasSpecular:" << key.hasSpecular() << "isUnlit:" << key.isUnlit() << "isTranslucent:" << key.isTranslucent() << "isSkinned:" << key.isSkinned() diff --git a/libraries/shared/src/shared/FileUtils.cpp b/libraries/shared/src/shared/FileUtils.cpp index 7b88321e99..9bdd65bf11 100644 --- a/libraries/shared/src/shared/FileUtils.cpp +++ b/libraries/shared/src/shared/FileUtils.cpp @@ -38,6 +38,16 @@ const QStringList& FileUtils::getFileSelectors() { } +QString FileUtils::selectFile(const QString& path) { + QFileSelector fileSelector; + fileSelector.setExtraSelectors(FileUtils::getFileSelectors()); + QString result = fileSelector.select(path); + if (path != result) { + qDebug() << "Using" << result << "instead of" << path; + } + return result; +} + QString FileUtils::readFile(const QString& filename) { QFile file(filename); @@ -51,7 +61,7 @@ QStringList FileUtils::readLines(const QString& filename, QString::SplitBehavior return readFile(filename).split(QRegularExpression("[\\r\\n]"), QString::SkipEmptyParts); } -void FileUtils::locateFile(QString filePath) { +void FileUtils::locateFile(const QString& filePath) { // adapted from // http://stackoverflow.com/questions/3490336/how-to-reveal-in-finder-or-show-in-explorer-with-qt diff --git a/libraries/shared/src/shared/FileUtils.h b/libraries/shared/src/shared/FileUtils.h index 9a5e2d5aba..2f5e11f005 100644 --- a/libraries/shared/src/shared/FileUtils.h +++ b/libraries/shared/src/shared/FileUtils.h @@ -18,7 +18,8 @@ class FileUtils { public: static const QStringList& getFileSelectors(); - static void locateFile(QString fileName); + static QString selectFile(const QString& fileName); + static void locateFile(const QString& fileName); static QString standardPath(QString subfolder); static QString readFile(const QString& filename); static QStringList readLines(const QString& filename, QString::SplitBehavior splitBehavior = QString::KeepEmptyParts); diff --git a/libraries/ui/src/QmlFragmentClass.cpp b/libraries/ui/src/QmlFragmentClass.cpp new file mode 100644 index 0000000000..c4cac73b2d --- /dev/null +++ b/libraries/ui/src/QmlFragmentClass.cpp @@ -0,0 +1,87 @@ +// +// Created by Gabriel Calero & Cristian Duarte on Aug 25, 2017 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "QmlFragmentClass.h" + +#include +#include +#include + +#include + +#include "OffscreenUi.h" + + +std::mutex QmlFragmentClass::_mutex; +std::map QmlFragmentClass::_fragments; + +QmlFragmentClass::QmlFragmentClass(QString id) : qml(id) { } + +// Method called by Qt scripts to create a new bottom menu bar in Android +QScriptValue QmlFragmentClass::constructor(QScriptContext* context, QScriptEngine* engine) { + + std::lock_guard guard(_mutex); + auto qml = context->argument(0).toVariant().toMap().value("qml"); + if (qml.isValid()) { + // look up tabletId in the map. + auto iter = _fragments.find(qml.toString()); + if (iter != _fragments.end()) { + //qDebug() << "[QML-ANDROID] QmlFragmentClass menu already exists"; + return iter->second; + } + } else { + qWarning() << "QmlFragmentClass could not build instance " << qml; + return QScriptValue(); + } + + auto properties = parseArguments(context); + auto offscreenUi = DependencyManager::get(); + QmlFragmentClass* retVal = new QmlFragmentClass(qml.toString()); + Q_ASSERT(retVal); + if (QThread::currentThread() != qApp->thread()) { + retVal->moveToThread(qApp->thread()); + BLOCKING_INVOKE_METHOD(retVal, "initQml", Q_ARG(QVariantMap, properties)); + } else { + retVal->initQml(properties); + } + connect(engine, &QScriptEngine::destroyed, retVal, &QmlWindowClass::deleteLater); + QScriptValue scriptObject = engine->newQObject(retVal); + _fragments[qml.toString()] = scriptObject; + return scriptObject; +} + +void QmlFragmentClass::close() { + QmlWindowClass::close(); + _fragments.erase(qml); +} + +QObject* QmlFragmentClass::addButton(const QVariant& properties) { + QVariant resultVar; + Qt::ConnectionType connectionType = Qt::AutoConnection; + + if (QThread::currentThread() != _qmlWindow->thread()) { + connectionType = Qt::BlockingQueuedConnection; + } + bool hasResult = QMetaObject::invokeMethod(_qmlWindow, "addButton", connectionType, + Q_RETURN_ARG(QVariant, resultVar), Q_ARG(QVariant, properties)); + if (!hasResult) { + qWarning() << "QmlFragmentClass addButton has no result"; + return NULL; + } + + QObject* qmlButton = qvariant_cast(resultVar); + if (!qmlButton) { + qWarning() << "QmlFragmentClass addButton result not a QObject"; + return NULL; + } + + return qmlButton; +} + +void QmlFragmentClass::removeButton(QObject* button) { +} diff --git a/libraries/ui/src/QmlFragmentClass.h b/libraries/ui/src/QmlFragmentClass.h new file mode 100644 index 0000000000..87c18a49ad --- /dev/null +++ b/libraries/ui/src/QmlFragmentClass.h @@ -0,0 +1,45 @@ +// +// Created by Gabriel Calero & Cristian Duarte on Aug 25, 2017 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_ui_QmlFragmentClass_h +#define hifi_ui_QmlFragmentClass_h + +#include "QmlWindowClass.h" + +class QmlFragmentClass : public QmlWindowClass { + Q_OBJECT +public: + QmlFragmentClass(QString id); + static QScriptValue constructor(QScriptContext* context, QScriptEngine* engine); + + /**jsdoc + * Creates a new button, adds it to this and returns it. + * @function QmlFragmentClass#addButton + * @param properties {Object} button properties + * @returns {TabletButtonProxy} + */ + Q_INVOKABLE QObject* addButton(const QVariant& properties); + + /* + * TODO - not yet implemented + */ + Q_INVOKABLE void removeButton(QObject* tabletButtonProxy); +public slots: + Q_INVOKABLE void close(); + +protected: + QString qmlSource() const override { return qml; } + + static std::mutex _mutex; + static std::map _fragments; +private: + QString qml; + +}; + +#endif diff --git a/libraries/ui/src/VirtualPadManager.cpp b/libraries/ui/src/VirtualPadManager.cpp new file mode 100644 index 0000000000..4c3e6ff728 --- /dev/null +++ b/libraries/ui/src/VirtualPadManager.cpp @@ -0,0 +1,58 @@ +// +// Created by Gabriel Calero & Cristian Duarte on 01/16/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "VirtualPadManager.h" + +namespace VirtualPad { + + bool Instance::isBeingTouched() { + return _isBeingTouched; + } + + void Instance::setBeingTouched(bool touched) { + _isBeingTouched = touched; + } + + void Instance::setFirstTouch(glm::vec2 point) { + _firstTouch = point; + } + + glm::vec2 Instance::getFirstTouch() { + return _firstTouch; + } + + void Instance::setCurrentTouch(glm::vec2 point) { + _currentTouch = point; + } + + glm::vec2 Instance::getCurrentTouch() { + return _currentTouch; + } + + Manager::Manager() { + + } + + Manager& Manager::instance() { + static QSharedPointer instance = DependencyManager::get(); + return *instance; + } + + void Manager::enable(bool enable) { + _enabled = enable; + } + + bool Manager::isEnabled() { + return _enabled; + } + + Instance* Manager::getLeftVirtualPad() { + return &_leftVPadInstance; + } + +} diff --git a/libraries/ui/src/VirtualPadManager.h b/libraries/ui/src/VirtualPadManager.h new file mode 100644 index 0000000000..599954989f --- /dev/null +++ b/libraries/ui/src/VirtualPadManager.h @@ -0,0 +1,46 @@ +// +// Created by Gabriel Calero & Cristian Duarte on 01/16/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#pragma once +#include +#include + +#include + +namespace VirtualPad { + class Instance { + public: + virtual bool isBeingTouched(); + virtual void setBeingTouched(bool touched); + virtual void setFirstTouch(glm::vec2 point); + virtual glm::vec2 getFirstTouch(); + virtual void setCurrentTouch(glm::vec2 point); + virtual glm::vec2 getCurrentTouch(); + private: + bool _isBeingTouched; + glm::vec2 _firstTouch; + glm::vec2 _currentTouch; + }; + + class Manager : public QObject, public Dependency { + SINGLETON_DEPENDENCY + + Manager(); + Manager(const Manager& other) = delete; + public: + static Manager& instance(); + Instance* getLeftVirtualPad(); + bool isEnabled(); + void enable(bool enable); + private: + Instance _leftVPadInstance; + bool _enabled; + }; +} + + diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index 749a60a578..73d82c6b89 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -28,7 +28,7 @@ #include #include #include - +#include #include #include #include diff --git a/scripts/+android/defaultScripts.js b/scripts/+android/defaultScripts.js index a115e498da..a8f6bf42a1 100644 --- a/scripts/+android/defaultScripts.js +++ b/scripts/+android/defaultScripts.js @@ -12,7 +12,11 @@ // var DEFAULT_SCRIPTS_COMBINED = [ - "system/progress.js"/*, + "system/progress.js", + "system/+android/touchscreenvirtualpad.js", + "system/+android/bottombar.js", + "system/+android/audio.js" , + "system/+android/modes.js"/*, "system/away.js", "system/controllers/controllerDisplayManager.js", "system/controllers/handControllerGrabAndroid.js", diff --git a/scripts/system/+android/audio.js b/scripts/system/+android/audio.js new file mode 100644 index 0000000000..b4f156d4bf --- /dev/null +++ b/scripts/system/+android/audio.js @@ -0,0 +1,67 @@ +"use strict"; +// +// audio.js +// scripts/system/ +// +// Created by Gabriel Calero & Cristian Duarte on Jan 16, 2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function() { // BEGIN LOCAL_SCOPE + +var audiobar; +var audioButton; + +var logEnabled = true; + +function printd(str) { + if (logEnabled) + print("[audio.js] " + str); +} + +function init() { + audiobar = new QmlFragment({ + qml: "hifi/AudioBar.qml" + }); + + audioButton = audiobar.addButton({ + icon: "icons/mic-unmute-a.svg", + activeIcon: "icons/mic-mute-a.svg", + text: "", + bgOpacity: 0.0, + activeBgOpacity: 0.0, + bgColor: "#FFFFFF" + }); + + onMuteToggled(); + + audioButton.clicked.connect(onMuteClicked); + Audio.mutedChanged.connect(onMuteToggled); +} + +function onMuteClicked() { + printd("On Mute Clicked"); + //Menu.setIsOptionChecked("Mute Microphone", !Menu.isOptionChecked("Mute Microphone")); + Audio.muted = !Audio.muted; + onMuteToggled(); +} + +function onMuteToggled() { + printd("On Mute Toggled"); + audioButton.isActive = Audio.muted; // Menu.isOptionChecked("Mute Microphone") + printd("Audio button is active: " + audioButton.isActive); +} + +Script.scriptEnding.connect(function () { + if(audioButton) { + audioButton.clicked.disconnect(onMuteClicked); + Audio.mutedChanged.connect(onMuteToggled); + } +}); + +init(); + +}()); // END LOCAL_SCOPE diff --git a/scripts/system/+android/bottombar.js b/scripts/system/+android/bottombar.js new file mode 100644 index 0000000000..e58840ad6f --- /dev/null +++ b/scripts/system/+android/bottombar.js @@ -0,0 +1,159 @@ +"use strict"; +// +// bottombar.js +// scripts/system/ +// +// Created by Gabriel Calero & Cristian Duarte on Jan 18, 2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +(function() { // BEGIN LOCAL_SCOPE + +var bottombar; +var bottomHudOptionsBar; +var gotoBtn; + +var gotoScript = Script.require('./goto.js'); + +var logEnabled = false; + +function printd(str) { + if (logEnabled) { + print("[bottombar.js] " + str); + } +} + +function init() { + gotoScript.init(); + gotoScript.setOnShownChange(function (shown) { + if (shown) { + showAddressBar(); + } else { + hideAddressBar(); + } + }); + + setupBottomBar(); + setupBottomHudOptionsBar(); + + raiseBottomBar(); + +} + +function shutdown() { +} + +function setupBottomBar() { + bottombar = new QmlFragment({ + qml: "hifi/bottombar.qml" + }); + + bottombar.fromQml.connect(function(message) { + switch (message.method) { + case 'hide': + lowerBottomBar(); + break; + default: + print('[bottombar.js] Unrecognized message from bottomHud.qml:', JSON.stringify(message)); + } + }); + + + gotoBtn = bottombar.addButton({ + icon: "icons/goto-i.svg", + activeIcon: "icons/goto-a.svg", + bgOpacity: 0, + hoverBgOpacity: 0, + activeBgOpacity: 0, + activeHoverBgOpacity: 0, + height: 240, + width: 300, + iconSize: 108, + textSize: 45, + text: "GO TO" + }); + + gotoBtn.clicked.connect(function() { + if (!gotoScript.isVisible()) { + showAddressBar(); + } else { + hideAddressBar(); + } + }); + + // TODO: setup all the buttons or provide a dynamic interface + + raiseBottomBar(); + + +} + +var setupBottomHudOptionsBar = function() { + var bottomHud = new QmlFragment({ + qml: "hifi/bottomHudOptions.qml" + }); + + bottomHudOptionsBar = { + show: function() { + bottomHud.setVisible(true); + }, + hide: function() { + bottomHud.setVisible(false); + }, + qmlFragment: bottomHud + }; + bottomHud.fromQml.connect( + function(message) { + switch (message.method) { + case 'showUpBar': + printd('[bottombar.js] showUpBar message from bottomHudOptions.qml: ', JSON.stringify(message)); + raiseBottomBar(); + break; + default: + print('[bottombar.js] Unrecognized message from bottomHudOptions.qml:', JSON.stringify(message)); + } + } + ); +} + +function lowerBottomBar() { + if (bottombar) { + bottombar.setVisible(false); + } + if (bottomHudOptionsBar) { + bottomHudOptionsBar.show(); + } +} + +function raiseBottomBar() { + print('[bottombar.js] raiseBottomBar begin'); + if (bottombar) { + bottombar.setVisible(true); + } + if (bottomHudOptionsBar) { + bottomHudOptionsBar.hide(); + } + print('[bottombar.js] raiseBottomBar end'); +} + +function showAddressBar() { + gotoScript.show(); + gotoBtn.isActive = true; +} + +function hideAddressBar() { + gotoScript.hide(); + gotoBtn.isActive = false; +} + + + +Script.scriptEnding.connect(function () { + shutdown(); +}); + +init(); + +}()); // END LOCAL_SCOPE diff --git a/scripts/system/+android/goto.js b/scripts/system/+android/goto.js new file mode 100644 index 0000000000..e917455128 --- /dev/null +++ b/scripts/system/+android/goto.js @@ -0,0 +1,96 @@ +"use strict"; +// +// goto-android.js +// scripts/system/ +// +// Created by Gabriel Calero & Cristian Duarte on 12 Sep 2017 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var window; + + +var logEnabled = false; +function printd(str) { + if (logEnabled) + print("[goto-android.js] " + str); +} + +function init() { +} + +function fromQml(message) { // messages are {method, params}, like json-rpc. See also sendToQml. + switch (message.method) { + case 'shownChanged': + if (notifyShownChange) { + notifyShownChange(message.params.shown); + } ; + break; + case 'hide': + module.exports.hide(); + module.exports.onHidden(); + break; + default: + print('[goto-android.js] Unrecognized message from AddressBarDialog.qml:', JSON.stringify(message)); + } +} + +function sendToQml(message) { + window.sendToQml(message); +} + +var isVisible = false; +var notifyShownChange; +module.exports = { + init: function() { + window = new QmlFragment({ + qml: "AddressBarDialog.qml", + visible: false + }); + }, + show: function() { + Controller.setVPadEnabled(false); + if (window) { + window.fromQml.connect(fromQml); + window.setVisible(true); + isVisible = true; + } + }, + hide: function() { + Controller.setVPadEnabled(true); + if (window) { + window.fromQml.disconnect(fromQml); + window.setVisible(false); + } + isVisible = false; + }, + destroy: function() { + if (window) { + window.close(); + window = null; + } + }, + isVisible: function() { + return isVisible; + }, + width: function() { + return window ? window.size.x : 0; + }, + height: function() { + return window ? window.size.y : 0; + }, + position: function() { + return window && isVisible ? window.position : null; + }, + setOnShownChange: function(f) { + notifyShownChange = f; + }, + onHidden: function() { } + + +}; + +init(); diff --git a/scripts/system/+android/modes.js b/scripts/system/+android/modes.js new file mode 100644 index 0000000000..b29548094f --- /dev/null +++ b/scripts/system/+android/modes.js @@ -0,0 +1,220 @@ +"use strict"; +// +// modes.js +// scripts/system/ +// +// Created by Gabriel Calero & Cristian Duarte on Jan 23, 2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +(function() { // BEGIN LOCAL_SCOPE + +var modesbar; +var modesButtons; +var currentSelectedBtn; + +var SETTING_CURRENT_MODE_KEY = 'Android/Mode'; +var MODE_VR = "VR", MODE_RADAR = "RADAR", MODE_MY_VIEW = "MY VIEW"; +var DEFAULT_MODE = MODE_RADAR; +var logEnabled = true; + +var radar = Script.require('./radar.js'); +var uniqueColor = Script.require('./uniqueColor.js'); + +function printd(str) { + if (logEnabled) { + print("[modes.js] " + str); + } +} + +function init() { + radar.setUniqueColor(uniqueColor); + radar.init(); + setupModesBar(); + radar.isTouchValid = isRadarModeValidTouch; +} + +function shutdown() { + +} + +function setupModesBar() { + + var bar = new QmlFragment({ + qml: "hifi/modesbar.qml" + }); + var buttonRadarMode = bar.addButton({ + icon: "icons/radar-i.svg", + activeIcon: "icons/radar-a.svg", + hoverIcon: "icons/radar-a.svg", + activeBgOpacity: 0.0, + hoverBgOpacity: 0.0, + activeHoverBgOpacity: 0.0, + text: "RADAR", + height:240, + bottomMargin: 6, + textSize: 45 + }); + var buttonMyViewMode = bar.addButton({ + icon: "icons/myview-i.svg", + activeIcon: "icons/myview-a.svg", + hoverIcon: "icons/myview-a.svg", + activeBgOpacity: 0.0, + hoverBgOpacity: 0.0, + activeHoverBgOpacity: 0.0, + text: "MY VIEW", + height: 240, + bottomMargin: 6, + textSize: 45 + }); + + modesButtons = [buttonRadarMode, buttonMyViewMode]; + + var mode = getCurrentModeSetting(); + + var buttonsRevealed = false; + bar.sendToQml({type: "inactiveButtonsHidden"}); + + modesbar = { + restoreMyViewButton: function() { + switchModeButtons(buttonMyViewMode); + saveCurrentModeSetting(MODE_MY_VIEW); + }, + sendToQml: function(o) { bar.sendToQml(o); }, + qmlFragment: bar + }; + + buttonRadarMode.clicked.connect(function() { + //if (connections.isVisible()) return; + saveCurrentModeSetting(MODE_RADAR); + printd("Radar clicked"); + onButtonClicked(buttonRadarMode, function() { + radar.startRadarMode(); + }); + }); + buttonMyViewMode.clicked.connect(function() { + //if (connections.isVisible()) return; + saveCurrentModeSetting(MODE_MY_VIEW); + printd("My View clicked"); + onButtonClicked(buttonMyViewMode, function() { + if (currentSelectedBtn == buttonRadarMode) { + radar.endRadarMode(); + } + }); + }); + + var savedButton; + if (mode == MODE_MY_VIEW) { + savedButton = buttonMyViewMode; + } else { + savedButton = buttonRadarMode; + } + printd("[MODE] previous mode " + mode); + + savedButton.clicked(); +} + +function saveCurrentModeSetting(mode) { + Settings.setValue(SETTING_CURRENT_MODE_KEY, mode); +} + +function getCurrentModeSetting(mode) { + return Settings.getValue(SETTING_CURRENT_MODE_KEY, DEFAULT_MODE); +} + +function showAllButtons() { + for (var i=0; i= aQmlFrag.position.x * 3 && coords.x <= aQmlFrag.position.x * 3 + aQmlFrag.size.x * 3 && + coords.y >= aQmlFrag.position.y * 3 && coords.y <= aQmlFrag.position.y * 3 + aQmlFrag.size.y * 3 + ) { + printd("godViewModeTouchValid- false because of qmlFragments!? idx " + i); + return false; + } + } + + for (var i=0; i < windows.length; i++) { + var aWin = windows[i]; + if (aWin != null && aWin.position() != null && + coords.x >= aWin.position().x * 3 && coords.x <= aWin.position().x * 3 + aWin.width() * 3 && + coords.y >= aWin.position().y * 3 && coords.y <= aWin.position().y * 3 + aWin.height() * 3 + ) { + printd("godViewModeTouchValid- false because of windows!?"); + return false; + } + } + printd("godViewModeTouchValid- true by default "); + return true; +} + +Script.scriptEnding.connect(function () { + shutdown(); +}); + +init(); + +}()); // END LOCAL_SCOPE \ No newline at end of file diff --git a/scripts/system/+android/radar.js b/scripts/system/+android/radar.js new file mode 100644 index 0000000000..9b9bd9c473 --- /dev/null +++ b/scripts/system/+android/radar.js @@ -0,0 +1,1503 @@ +"use strict"; +// +// radar.js +// scripts/system/+android/ +// +// Created by Cristian Duarte & Gabriel Calero on 31 Jan 2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or +// http://www.apache.org/licenses/LICENSE-2.0.html +// + +var radarModeInterface = {}; + +var logEnabled = true; +function printd(str) { + if (logEnabled) { + print("[radar.js] " + str); + } +} + +var radar = false; +var radarHeight = 10; // camera position meters above the avatar +var tablet; + +var RADAR_CAMERA_OFFSET = -1; // 1 meter below the avatar +var ABOVE_GROUND_DROP = 2; +var MOVE_BY = 1; + +// Swipe/Drag vars +var PINCH_INCREMENT_FIRST = 0.4; // 0.1 meters zoom in - out +var PINCH_INCREMENT = 0.4; // 0.1 meters zoom in - out +var RADAR_HEIGHT_MAX_PLUS_AVATAR = 40; +var RADAR_HEIGHT_MIN_PLUS_AVATAR = 2; +var RADAR_CAMERA_DISTANCE_TO_ICONS = 0.5; // Icons are near the camera to + // prevent the LOD manager + // dismissing them +var RADAR_ICONS_APPARENT_DISTANCE_TO_AVATAR_BASE = 1; // How much above the + // avatar base should + // the icon appear +var AVATAR_DISPLAY_NAME_HEIGHT = 38; +var AVATAR_DISPLAY_NAME_CHAR_WIDTH = 18; +var lastDragAt; +var lastDeltaDrag; + +var uniqueColor; + +function moveTo(position) { + if (radar) { + MyAvatar.position = position; + Camera.position = Vec3.sum(MyAvatar.position, { + x : 0, + y : radarHeight, + z : 0 + }); + } +} + +function keyPressEvent(event) { + if (radar) { + switch (event.text) { + case "UP": + moveTo(Vec3.sum(MyAvatar.position, { + x : 0.0, + y : 0, + z : -1 * MOVE_BY + })); + break; + case "DOWN": + moveTo(Vec3.sum(MyAvatar.position, { + x : 0, + y : 0, + z : MOVE_BY + })); + break; + case "LEFT": + moveTo(Vec3.sum(MyAvatar.position, { + x : -1 * MOVE_BY, + y : 0, + z : 0 + })); + break; + case "RIGHT": + moveTo(Vec3.sum(MyAvatar.position, { + x : MOVE_BY, + y : 0, + z : 0 + })); + break; + } + } +} + +function actionOnObjectFromEvent(event) { + var rayIntersection = findRayIntersection(Camera.computePickRay(event.x, + event.y)); + if (rayIntersection && rayIntersection.intersects + && rayIntersection.overlayID) { + printd("found overlayID touched " + rayIntersection.overlayID); + if (entitiesByOverlayID[rayIntersection.overlayID]) { + var entity = Entities.getEntityProperties( + entitiesByOverlayID[rayIntersection.overlayID], + [ "sourceUrl" ]); + App.openUrl(entity.sourceUrl); + return true; + } + } + if (rayIntersection && rayIntersection.intersects + && rayIntersection.entityID && rayIntersection.properties) { + printd("found " + rayIntersection.entityID + " of type " + + rayIntersection.properties.type); + if (rayIntersection.properties.type == "Web") { + printd("found web element to " + + rayIntersection.properties.sourceUrl); + App.openUrl(rayIntersection.properties.sourceUrl); + return true; + } + } + return false; +} + +function mousePress(event) { + if (!isTouchValid(coords)) { + currentTouchIsValid = false; + return; + } else { + currentTouchIsValid = true; + } + mousePressOrTouchEnd(event); +} + +function mousePressOrTouchEnd(event) { + if (!currentTouchIsValid) { + return; + } + if (radar) { + if (actionOnObjectFromEvent(event)) { + return; + } + } +} + +function toggleRadarMode() { + if (radar) { + endRadar(); + } else { + startRadar(); + } +} + +function fakeDoubleTap(event) { + // CLD - temporarily disable toggling mode through double tap + // * As we have a new UI for toggling between modes, it may be discarded + // completely in the future. + // toggleRadarMode(); + teleporter.dragTeleportUpdate(event); + teleporter.dragTeleportRelease(event); +} + +var currentTouchIsValid = false; // Currently used to know if touch hasn't + // started on a UI overlay + +var DOUBLE_TAP_TIME = 300; +var fakeDoubleTapStart = Date.now(); +var touchEndCount = 0; + +/* + * Counts touchEnds and if there were 2 in the DOUBLE_TAP_TIME lapse, it + * triggers a fakeDoubleTap and returns true. Otherwise, returns false (no + * double tap yet) + */ +function analyzeDoubleTap(event) { + var fakeDoubleTapEnd = Date.now(); + var elapsed = fakeDoubleTapEnd - fakeDoubleTapStart; + if (elapsed > DOUBLE_TAP_TIME) { + touchEndCount = 0; + } + + // if this is our first "up" then record time so we can + // later determine if second "up" is a double tap + if (touchEndCount == 0) { + fakeDoubleTapStart = Date.now(); + } + touchEndCount++; + + if (touchEndCount >= 2) { + var fakeDoubleTapEnd = Date.now(); + var elapsed = fakeDoubleTapEnd - fakeDoubleTapStart; + printd("-- fakeDoubleTapEnd:" + fakeDoubleTapEnd + "-- elapsed:" + + elapsed) + if (elapsed <= DOUBLE_TAP_TIME) { + touchEndCount = 0; + fakeDoubleTap(event); + return true; // don't do the normal touch end processing + } + + touchEndCount = 0; + } + return false; +} + +function touchEnd(event) { + printd("touchEnd received " + JSON.stringify(event)); + // Clean up touch variables + lastDragAt = null; + lastDeltaDrag = null; + touchStartingCoordinates = null; // maybe in special cases it should be + // setup later? + startedDraggingCamera = false; + prevTouchPinchRadius = null; + draggingCamera = false; + + if (movingCamera) { + // if camera was indeed moving, we should not further process, it was + // just dragging + movingCamera = false; + dragModeFunc = null; + return; + } + + // teleport release analysis + if (teleporter && teleporter.dragTeleportUpdate == dragModeFunc) { + teleporter.dragTeleportRelease(event); + dragModeFunc = null; + return; + } + dragModeFunc = null; + + // if pinching or moving is still detected, cancel + if (event.isPinching) { + printd("touchEnd fail because isPinching"); + return; + } + if (event.isPinchOpening) { + printd("touchEnd fail because isPinchingOpening"); + return; + } + if (event.isMoved) { + printd("touchEnd fail because isMoved"); + return; + } + + // if touch is invalid, cancel + if (!currentTouchIsValid) { + printd("touchEnd fail because !currentTouchIsValid"); + return; + } + + if (analyzeDoubleTap(event)) + return; // double tap detected, finish + + if (radar) { + mousePressOrTouchEnd(event); + } +} + +/** + * Polyfill for sign(x) + */ +if (!Math.sign) { + Math.sign = function(x) { + // If x is NaN, the result is NaN. + // If x is -0, the result is -0. + // If x is +0, the result is +0. + // If x is negative and not -0, the result is -1. + // If x is positive and not +0, the result is +1. + x = +x; // convert to a number + if (x === 0 || isNaN(x)) { + return Number(x); + } + return x > 0 ? 1 : -1; + }; +} + +/******************************************************************************* + * Line and Plane intersection methods + ******************************************************************************/ + +/** + * findLinePlaneIntersection Given points p {x: y: z:} and q that define a line, + * and the plane of formula ax+by+cz+d = 0, returns the intersection point or + * null if none. + */ +function findLinePlaneIntersection(p, q, a, b, c, d) { + return findLinePlaneIntersectionCoords(p.x, p.y, p.z, q.x, q.y, q.z, a, b, + c, d); +} + +/** + * findLineToHeightIntersection Given points p {x: y: z:} and q that define a + * line, and a planeY value that defines a plane paralel to 'the floor' xz + * plane, returns the intersection to that plane or null if none. + */ +function findLineToHeightIntersection(p, q, planeY) { + return findLinePlaneIntersection(p, q, 0, 1, 0, -planeY); +} + +/** + * findLinePlaneIntersectionCoords (to avoid requiring unnecessary + * instantiation) Given points p with px py pz and q that define a line, and the + * plane of formula ax+by+cz+d = 0, returns the intersection point or null if + * none. + */ +function findLinePlaneIntersectionCoords(px, py, pz, qx, qy, qz, a, b, c, d) { + var tDenom = a * (qx - px) + b * (qy - py) + c * (qz - pz); + if (tDenom == 0) + return null; + + var t = -(a * px + b * py + c * pz + d) / tDenom; + + return { + x : (px + t * (qx - px)), + y : (py + t * (qy - py)), + z : (pz + t * (qz - pz)) + }; +} + +/** + * findLineToHeightIntersection Given points p with px py pz and q that define a + * line, and a planeY value that defines a plane paralel to 'the floor' xz + * plane, returns the intersection to that plane or null if none. + */ +function findLineToHeightIntersectionCoords(px, py, pz, qx, qy, qz, planeY) { + return findLinePlaneIntersectionCoords(px, py, pz, qx, qy, qz, 0, 1, 0, + -planeY); +} + +function findRayIntersection(pickRay) { + // Check 3D overlays and entities. Argument is an object with origin and + // direction. + var result = Overlays.findRayIntersection(pickRay); + if (!result.intersects) { + result = Entities.findRayIntersection(pickRay, true); + } + return result; +} + +/** + * Given a 2d point (x,y) this function returns the intersection (x, y, z) of + * the computedPickRay for that point with the plane y = py + */ +function computePointAtPlaneY(x, y, py) { + var ray = Camera.computePickRay(x, y); + var p1 = ray.origin; + var p2 = Vec3.sum(p1, Vec3.multiply(ray.direction, 1)); + return findLineToHeightIntersectionCoords(p1.x, p1.y, p1.z, p2.x, p2.y, + p2.z, py); +} + +/******************************************************************************* + * + ******************************************************************************/ + +function isTouchValid(coords) { + // TODO: Extend to the detection of touches on new menu bars + var radarModeTouchValid = radarModeInterface.isTouchValid(coords); + + // getItemAtPoint does not exist anymore, look for another way to know if we + // are touching buttons + // is it still needed? + return /* !tablet.getItemAtPoint(coords) && */radarModeTouchValid; +} + +/******************************************************************************* + * + ******************************************************************************/ + +var touchStartingCoordinates = null; + +var KEEP_PRESSED_FOR_TELEPORT_MODE_TIME = 750; +var touchBeginTime; + +function touchBegin(event) { + var coords = { + x : event.x, + y : event.y + }; + if (!isTouchValid(coords)) { + printd("analyze touch - RADAR_TOUCH - INVALID"); + currentTouchIsValid = false; + touchStartingCoordinates = null; + } else { + printd("analyze touch - RADAR_TOUCH - ok"); + currentTouchIsValid = true; + touchStartingCoordinates = coords; + touchBeginTime = Date.now(); + } +} + +var startedDraggingCamera = false; // first time +var draggingCamera = false; // is trying +var movingCamera = false; // definitive + +var MIN_DRAG_DISTANCE_TO_CONSIDER = 100; // distance by axis, not real + // distance + +var prevTouchPinchRadius = null; + +function pinchUpdate(event) { + if (!event.isMoved) + return; + if (event.radius <= 0) + return; + + // pinch management + var avatarY = MyAvatar.position.y; + var pinchIncrement; + if (!!prevTouchPinchRadius) { + // no prev value + pinchIncrement = PINCH_INCREMENT + * Math.abs(event.radius - prevTouchPinchRadius) * 0.1; + } else { + pinchIncrement = PINCH_INCREMENT_FIRST; + } + + if (event.isPinching) { + if (radarHeight + pinchIncrement > RADAR_HEIGHT_MAX_PLUS_AVATAR + + avatarY) { + radarHeight = RADAR_HEIGHT_MAX_PLUS_AVATAR + avatarY; + } else { + radarHeight += pinchIncrement; + } + } else if (event.isPinchOpening) { + if (radarHeight - pinchIncrement < RADAR_HEIGHT_MIN_PLUS_AVATAR + + avatarY) { + radarHeight = RADAR_HEIGHT_MIN_PLUS_AVATAR + avatarY; + } else { + radarHeight -= pinchIncrement; + } + } + var deltaHeight = avatarY + radarHeight - Camera.position.y; + Camera.position = Vec3.sum(Camera.position, { + x : 0, + y : deltaHeight, + z : 0 + }); + if (!draggingCamera) { + startedDraggingCamera = true; + draggingCamera = true; + } + + prevTouchPinchRadius = event.radius; +} + +function isInsideSquare(coords0, coords1, halfside) { + return Math.abs(coords0.x - coords1.x) <= halfside + && Math.abs(coords0.y - coords1.y) <= halfside; +} + +function dragScrollUpdate(event) { + if (!event.isMoved) + return; + + // drag management + var pickRay = Camera.computePickRay(event.x, event.y); + var dragAt = Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction, + radarHeight)); + + if (lastDragAt === undefined || lastDragAt === null) { + lastDragAt = dragAt; + return; + } + + var deltaDrag = { + x : (lastDragAt.x - dragAt.x), + y : 0, + z : (lastDragAt.z - dragAt.z) + }; + + lastDragAt = dragAt; + if (lastDeltaDrag === undefined || lastDeltaDrag === null) { + lastDeltaDrag = deltaDrag; + return; + } + + if (!draggingCamera) { + startedDraggingCamera = true; + draggingCamera = true; + } else { + if (!movingCamera) { + if (!isInsideSquare(touchStartingCoordinates, event, + MIN_DRAG_DISTANCE_TO_CONSIDER)) { + movingCamera = true; + } + } + + if (movingCamera) { + if (Math.sign(deltaDrag.x) == Math.sign(lastDeltaDrag.x) + && Math.sign(deltaDrag.z) == Math.sign(lastDeltaDrag.z)) { + // Process movement if direction of the movement is the same + // than the previous frame + // process delta + var moveCameraTo = Vec3.sum(Camera.position, deltaDrag); + // move camera + Camera.position = moveCameraTo; + } else { + // Do not move camera if it's changing direction in this case, + // wait until the next direction confirmation.. + } + lastDeltaDrag = deltaDrag; // save last + } + } +} + +/******************************************************************************* + * Teleport feature + ******************************************************************************/ + +function Teleporter() { + + var SURFACE_DETECTION_FOR_TELEPORT = true; // true if uses teleport.js + // similar logic to detect + // surfaces. false if uses plain + // teleport to avatar same + // height. + + var TELEPORT_TARGET_MODEL_URL = Script + .resolvePath("../assets/models/teleport-destination.fbx"); + var TELEPORT_TOO_CLOSE_MODEL_URL = Script + .resolvePath("../assets/models/teleport-cancel.fbx"); + + var TELEPORT_MODEL_DEFAULT_DIMENSIONS = { + x : 0.10, + y : 0.00001, + z : 0.10 + }; + + var teleportOverlay = Overlays.addOverlay("model", { + url : TELEPORT_TARGET_MODEL_URL, + dimensions : TELEPORT_MODEL_DEFAULT_DIMENSIONS, + orientation : Quat.fromPitchYawRollDegrees(0, 180, 0), + visible : false + }); + + var teleportCancelOverlay = Overlays.addOverlay("model", { + url : TELEPORT_TOO_CLOSE_MODEL_URL, + dimensions : TELEPORT_MODEL_DEFAULT_DIMENSIONS, + orientation : Quat.fromPitchYawRollDegrees(0, 180, 0), + visible : false + }); + + var TELEPORT_COLOR = { + red : 0, + green : 255, + blue : 255 + }; + var TELEPORT_CANCEL_COLOR = { + red : 255, + green : 255, + blue : 0 + }; + + var teleportLine = Overlays.addOverlay("line3d", { + start : { + x : 0, + y : 0, + z : 0 + }, + end : { + x : 0, + y : 0, + z : 0 + }, + color : TELEPORT_COLOR, + alpha : 1, + lineWidth : 2, + dashed : false, + visible : false + }); + + // code from teleport.js + var TELEPORT_TARGET = { + NONE : 'none', // Not currently targetting anything + INVISIBLE : 'invisible', // The current target is an invvsible + // surface + INVALID : 'invalid', // The current target is invalid (wall, ceiling, + // etc.) + SURFACE : 'surface', // The current target is a valid surface + SEAT : 'seat', // The current target is a seat + } + + var TELEPORT_CANCEL_RANGE = 1; + var teleportTargetType = TELEPORT_TARGET.NONE; + + function parseJSON(json) { + try { + return JSON.parse(json); + } catch (e) { + return undefined; + } + } + + /* + * Enhanced with intersection with terrain instead of using current avatar y + * position if SURFACE_DETECTION_FOR_TELEPORT is true + */ + function computeDestination(touchEventPos, avatarPosition, cameraPosition, + radarH) { + if (SURFACE_DETECTION_FOR_TELEPORT) { + var pickRay = Camera.computePickRay(touchEventPos.x, + touchEventPos.y); + printd("newTeleportDetect - pickRay " + JSON.stringify(pickRay)); + var destination = Entities.findRayIntersection(pickRay, true, [], + [], false, true); + printd("newTeleportDetect - destination " + + JSON.stringify(destination)); + return destination; + } else { + var pickRay = Camera.computePickRay(touchEventPos.x, + touchEventPos.y); + var pointingAt = Vec3.sum(pickRay.origin, Vec3.multiply( + pickRay.direction, radarH)); + var destination = { + x : pointingAt.x, + y : avatarPosition.y, + z : pointingAt.z + }; + return destination; + } + } + + function renderTeleportOverlays(destination) { + var overlayPosition = findLineToHeightIntersection(destination, + Camera.position, Camera.position.y + - RADAR_CAMERA_DISTANCE_TO_ICONS); + printd("[newTeleport] TELEPORT ! render overlay at " + + JSON.stringify(overlayPosition)); + + // CLD note Oct 11, 2017 + // Version of teleport.js 3c109f294f88ba7573bd1221f907f2605893c509 + // doesn't allow invisible surfaces, let's allow it for now + if (teleportTargetType == TELEPORT_TARGET.SURFACE + || teleportTargetType == TELEPORT_TARGET.INVISIBLE) { + Overlays.editOverlay(teleportOverlay, { + visible : true, + position : overlayPosition + }); + Overlays.editOverlay(teleportCancelOverlay, { + visible : false + }); + Overlays.editOverlay(teleportLine, { + start : MyAvatar.position, + end : destination, + color : TELEPORT_COLOR, + visible : true + }); + } else if (teleportTargetType == TELEPORT_TARGET.INVALID) { + Overlays.editOverlay(teleportOverlay, { + visible : false + }); + Overlays.editOverlay(teleportCancelOverlay, { + visible : true, + position : overlayPosition + }); + Overlays.editOverlay(teleportLine, { + start : MyAvatar.position, + end : destination, + color : TELEPORT_CANCEL_COLOR, + visible : true + }); + } else { // TELEPORT_TARGET:NONE? + Overlays.editOverlay(teleportOverlay, { + visible : false + }); + Overlays.editOverlay(teleportCancelOverlay, { + visible : false + }); + Overlays.editOverlay(teleportLine, { + visible : false + }); + } + } + + var BORDER_DISTANCE_PX = 100; + var border_top = 0; + var border_left = 0; + var border_right = Window.innerWidth; + var border_bottom = Window.innerHeight; + + function moveOnBorders(event) { + var xDelta = 0; + var zDelta = 0; + + if (event.y <= border_top + BORDER_DISTANCE_PX) { + zDelta = -0.1; + } else if (event.y >= border_bottom - BORDER_DISTANCE_PX) { + zDelta = 0.1; + } + if (event.x <= border_left + BORDER_DISTANCE_PX) { + xDelta = -0.1; + } else if (event.x >= border_right - BORDER_DISTANCE_PX) { + xDelta = 0.1; + } + if (xDelta == 0 && zDelta == 0) { + draggingCamera = false; + return; + } + + Camera.position = Vec3.sum(Camera.position, { + x : xDelta, + y : 0, + z : zDelta + }); + draggingCamera = true; + } + + // When determininig whether you can teleport to a location, the normal of + // the + // point that is being intersected with is looked at. If this normal is more + // than MAX_ANGLE_FROM_UP_TO_TELEPORT degrees from <0, 1, 0> (straight up), + // then + // you can't teleport there. + const MAX_ANGLE_FROM_UP_TO_TELEPORT = 70; + function getTeleportTargetType(intersection) { + if (SURFACE_DETECTION_FOR_TELEPORT) { + if (!intersection.intersects) { + return TELEPORT_TARGET.NONE; + } + var props = Entities.getEntityProperties(intersection.entityID, [ + 'userData', 'visible' ]); + var data = parseJSON(props.userData); + if (data !== undefined && data.seat !== undefined) { + return TELEPORT_TARGET.SEAT; + } + + if (!props.visible) { + return TELEPORT_TARGET.INVISIBLE; + } + + var surfaceNormal = intersection.surfaceNormal; + var adj = Math.sqrt(surfaceNormal.x * surfaceNormal.x + + surfaceNormal.z * surfaceNormal.z); + var angleUp = Math.atan2(surfaceNormal.y, adj) * (180 / Math.PI); + + if (angleUp < (90 - MAX_ANGLE_FROM_UP_TO_TELEPORT) + || angleUp > (90 + MAX_ANGLE_FROM_UP_TO_TELEPORT) + || Vec3.distance(MyAvatar.position, + intersection.intersection) <= TELEPORT_CANCEL_RANGE) { + return TELEPORT_TARGET.INVALID; + } else { + return TELEPORT_TARGET.SURFACE; + } + } else { + var destination = intersection; + if (Vec3.distance(MyAvatar.position, destination) <= TELEPORT_CANCEL_RANGE) { + return TELEPORT_TARGET.INVALID; + } else { + return TELEPORT_TARGET.SURFACE; + } + } + } + ; + + function moveToFromEvent(event) { + var destination = computeDestination(event, MyAvatar.position, + Camera.position, radarHeight); + moveTo(SURFACE_DETECTION_FOR_TELEPORT ? Vec3.sum( + destination.intersection, { + y : 1 + }) : destination); + return true; + } + + return { + dragTeleportBegin : function(event) { + printd("[newTeleport] TELEPORT began"); + var overlayDimensions = entityIconModelDimensions(); + // var destination = computeDestination(event, MyAvatar.position, + // Camera.position, radarHeight); + // Dimension teleport and cancel overlays (not show them yet) + Overlays.editOverlay(teleportOverlay, { + dimensions : overlayDimensions + }); + Overlays.editOverlay(teleportCancelOverlay, { + dimensions : overlayDimensions + }); + // Position line + Overlays.editOverlay(teleportLine, { + visible : true, + start : 0, + end : 0 + }); + }, + + dragTeleportUpdate : function(event) { + // if in border, move camera + moveOnBorders(event); + + var destination = computeDestination(event, MyAvatar.position, + Camera.position, radarHeight); + + teleportTargetType = getTeleportTargetType(destination); + renderTeleportOverlays(SURFACE_DETECTION_FOR_TELEPORT ? destination.intersection + : destination); + }, + + dragTeleportRelease : function(event) { + printd("[newTeleport] TELEPORT released at " + + JSON.stringify(event)); + // CLD note Oct 11, 2017 + // Version of teleport.js 3c109f294f88ba7573bd1221f907f2605893c509 + // doesn't allow invisible surfaces, let's allow it for now + if (teleportTargetType == TELEPORT_TARGET.SURFACE + || teleportTargetType == TELEPORT_TARGET.INVISIBLE) { + moveToFromEvent(event); + } + teleportTargetType = TELEPORT_TARGET.NONE; + + Overlays.editOverlay(teleportOverlay, { + visible : false + }); + Overlays.editOverlay(teleportLine, { + visible : false + }); + Overlays.editOverlay(teleportCancelOverlay, { + visible : false + }); + } + }; + +} + +var teleporter = Teleporter(); + +/******************************************************************************* + * + ******************************************************************************/ + +var dragModeFunc = null; // by default is nothing + +function oneFingerTouchUpdate(event) { + if (dragModeFunc) { + dragModeFunc(event); + } else { + if (!isInsideSquare(touchStartingCoordinates, event, + MIN_DRAG_DISTANCE_TO_CONSIDER)) { + dragModeFunc = dragScrollUpdate; + dragModeFunc(event); + } else { + var now = Date.now(); // check time + if (now - touchBeginTime >= KEEP_PRESSED_FOR_TELEPORT_MODE_TIME) { + teleporter.dragTeleportBegin(event); + dragModeFunc = teleporter.dragTeleportUpdate; + dragModeFunc(event); + } else { + // not defined yet, let's wait for time or movement to happen + } + } + } +} + +function touchUpdate(event) { + if (!currentTouchIsValid) { + return; // avoid moving and zooming when tap is over UI entities + } + if (event.isPinching || event.isPinchOpening) { + pinchUpdate(event); + } else { + oneFingerTouchUpdate(event); + } +} + +/******************************************************************************* + * Avatar cache structure for showing avatars markers + ******************************************************************************/ + +// by QUuid +var avatarsData = {}; +var avatarsIcons = []; // a parallel list of icons (overlays) to easily run + // through +var avatarsNames = []; // a parallel list of names (overlays) to easily run + // through + +function getAvatarIconForUser(uid) { + var color = uniqueColor.getColor(uid); + if (color.charAt(0) == '#') { + color = color.substring(1, color.length); + } + // FIXME: this is a temporary solution until we can use circle3d with + // lineWidth + return Script.resolvePath("assets/images/circle-" + color + ".svg"); +} + +var avatarIconDimensionsVal = { + x : 0, + y : 0, + z : 0.00001 +}; +function avatarIconPlaneDimensions() { + // given the current height, give a size + var xy = -0.003531 * radarHeight + 0.1; + avatarIconDimensionsVal.x = Math.abs(xy); + avatarIconDimensionsVal.y = Math.abs(xy); + // reuse object + return avatarIconDimensionsVal; +} + +function currentOverlayIconForAvatar(QUuid) { + if (avatarsData[QUuid] != undefined) { + return avatarsData[QUuid].icon; + } else { + return null; + } +} + +function currentOverlayNameForAvatar(QUuid) { + if (avatarsData[QUuid] != undefined) { + return avatarsData[QUuid].name; + } else { + return null; + } +} + +function saveAvatarData(QUuid) { + if (QUuid == null) + return; + var avat = AvatarList.getAvatar(QUuid); + printd("avatar added save avatar " + QUuid); + + if (!avat) + return; + + if (avatarsData[QUuid] != undefined) { + avatarsData[QUuid].position = avat.position; + } else { + var avatarIcon = Overlays.addOverlay("image3d", { + subImage : { + x : 0, + y : 0, + width : 150, + height : 142 + }, + url : getAvatarIconForUser(QUuid), + dimensions : ICON_ENTITY_DEFAULT_DIMENSIONS, + visible : false, + ignoreRayIntersection : false, + orientation : Quat.fromPitchYawRollDegrees(-90, 0, 0) + }); + + var needRefresh = !avat || !avat.displayName; + var displayName = avat && avat.displayName ? avat.displayName + : "Unknown"; + var textWidth = displayName.length * AVATAR_DISPLAY_NAME_CHAR_WIDTH; + var avatarName = Overlays.addOverlay("text", { + width : textWidth, + height : AVATAR_DISPLAY_NAME_HEIGHT, + color : { + red : 255, + green : 255, + blue : 255 + }, + backgroundAlpha : 0.0, + textRaiseColor : { + red : 0, + green : 0, + blue : 0 + }, + font : { + size : 68, + bold : true + }, + visible : false, + text : displayName, + textAlignCenter : true + }); + avatarsIcons.push(avatarIcon); + avatarsNames.push(avatarName); + avatarsData[QUuid] = { + position : avat.position, + icon : avatarIcon, + name : avatarName, + textWidth : textWidth, + needRefresh : needRefresh + }; + } +} + +function removeAvatarData(QUuid) { + if (QUuid == null) + return; + + var itsOverlay = currentOverlayIconForAvatar(QUuid); + if (itsOverlay != null) { + Overlays.deleteOverlay(itsOverlay); + } + var itsNameOverlay = currentOverlayNameForAvatar(QUuid); + if (itsNameOverlay != null) { + Overlays.deleteOverlay(itsNameOverlay); + } + + var idx = avatarsIcons.indexOf(itsOverlay); + avatarsIcons.splice(idx, 1); + idx = avatarsNames.indexOf(itsNameOverlay); + avatarsNames.splice(idx, 1); + + delete avatarsData[QUuid]; +} + +function saveAllOthersAvatarsData() { + var avatarIds = AvatarList.getAvatarIdentifiers(); + var len = avatarIds.length; + for (var i = 0; i < len; i++) { + if (avatarIds[i]) { + saveAvatarData(avatarIds[i]); + } + } +} + +function avatarAdded(QUuid) { + printd("avatar added " + QUuid);// + " at " + + // JSON.stringify(AvatarList.getAvatar(QUuid).position)); + saveAvatarData(QUuid); +} + +function avatarRemoved(QUuid) { + printd("avatar removed " + QUuid); + removeAvatarData(QUuid); +} + +/******************************************************************************* + * Avatar Icon/Markers rendering + ******************************************************************************/ +var myAvatarIcon; +var myAvatarName; + +function renderMyAvatarIcon() { + var iconPos = findLineToHeightIntersectionCoords(MyAvatar.position.x, + MyAvatar.position.y + RADAR_ICONS_APPARENT_DISTANCE_TO_AVATAR_BASE, + MyAvatar.position.z, Camera.position.x, Camera.position.y, + Camera.position.z, Camera.position.y + - RADAR_CAMERA_DISTANCE_TO_ICONS); + if (!iconPos) { + printd("avatarmy icon pos null"); + return; + } + var iconDimensions = avatarIconPlaneDimensions(); + + var avatarPos = MyAvatar.position; + var cameraPos = Camera.position; + var commonY = Camera.position.y - RADAR_CAMERA_DISTANCE_TO_ICONS; + var borderPoints = [ + computePointAtPlaneY(0, 0, commonY), + computePointAtPlaneY(Window.innerWidth, Window.innerHeight, commonY) ]; + + var p1 = findLineToHeightIntersectionCoords(avatarPos.x, avatarPos.y, + avatarPos.z, cameraPos.x, cameraPos.y, cameraPos.z, commonY); + var x = (p1.x - borderPoints[0].x) * (Window.innerWidth) + / (borderPoints[1].x - borderPoints[0].x); + var y = (p1.z - borderPoints[0].z) * (Window.innerHeight) + / (borderPoints[1].z - borderPoints[0].z); + + if (!myAvatarIcon && MyAvatar.sessionUUID) { + myAvatarIcon = Overlays.addOverlay("image3d", { + subImage : { + x : 0, + y : 0, + width : 150, + height : 142 + }, + url : getAvatarIconForUser(MyAvatar.sessionUUID), + dimensions : ICON_ENTITY_DEFAULT_DIMENSIONS, + visible : false, + ignoreRayIntersection : false, + orientation : Quat.fromPitchYawRollDegrees(-90, 0, 0) + }); + } + + if (!myAvatarName) { + myAvatarName = Overlays.addOverlay("text", { + width : 40, + height : AVATAR_DISPLAY_NAME_HEIGHT, + textAlignCenter : true, + color : { + red : 255, + green : 255, + blue : 255 + }, + backgroundAlpha : 0.0, + font : { + size : 68, + bold : true + }, + textRaiseColor : { + red : 0, + green : 0, + blue : 0 + }, + visible : false, + text : "Me" + }); + } + + if (myAvatarIcon) { + Overlays.editOverlay(myAvatarIcon, { + visible : true, + dimensions : iconDimensions, + position : iconPos + }); + + } + var textSize = (14 + (iconDimensions.y - 0.03) * 15 / 0.06); + + Overlays.editOverlay(myAvatarName, { + visible : true, + x : x - 18 + (iconDimensions.y - 0.03) * 2 / 0.06, + y : y + iconDimensions.y * 550, + font : { + size : textSize, + bold : true + }, + }); + +} + +function hideAllAvatarIcons() { + var len = avatarsIcons.length; + for (var i = 0; i < len; i++) { + Overlays.editOverlay(avatarsIcons[i], { + visible : false + }); + } + len = avatarsNames.length; + for (var j = 0; j < len; j++) { + Overlays.editOverlay(avatarsNames[j], { + visible : false + }); + } + if (myAvatarIcon) { + Overlays.editOverlay(myAvatarIcon, { + visible : false + }); + } + Overlays.editOverlay(myAvatarName, { + visible : false + }) +} + +function renderAllOthersAvatarIcons() { + var avatarPos; + var iconDimensions = avatarIconPlaneDimensions(); + var commonY = Camera.position.y - RADAR_CAMERA_DISTANCE_TO_ICONS; + var borderPoints = [ + computePointAtPlaneY(0, 0, commonY), + computePointAtPlaneY(Window.innerWidth, Window.innerHeight, commonY) ]; + + for ( var QUuid in avatarsData) { + if (avatarsData.hasOwnProperty(QUuid)) { + if (AvatarList.getAvatar(QUuid) != null) { + avatarPos = AvatarList.getAvatar(QUuid).position; + + var cameraPos = Camera.position; + var p1 = findLineToHeightIntersectionCoords(avatarPos.x, + avatarPos.y, avatarPos.z, cameraPos.x, cameraPos.y, + cameraPos.z, commonY); + + var x = (p1.x - borderPoints[0].x) * (Window.innerWidth) + / (borderPoints[1].x - borderPoints[0].x); + var y = (p1.z - borderPoints[0].z) * (Window.innerHeight) + / (borderPoints[1].z - borderPoints[0].z); + + if (avatarsData[QUuid].icon != undefined) { + var iconPos = findLineToHeightIntersectionCoords( + avatarPos.x, + avatarPos.y + + RADAR_ICONS_APPARENT_DISTANCE_TO_AVATAR_BASE, + avatarPos.z, Camera.position.x, Camera.position.y, + Camera.position.z, Camera.position.y + - RADAR_CAMERA_DISTANCE_TO_ICONS); + if (!iconPos) { + print("avatar icon pos bad for " + QUuid); + continue; + } + if (avatarsData[QUuid].needRefresh) { + var avat = AvatarList.getAvatar(QUuid); + if (avat && avat.displayName) { + Overlays.editOverlay(avatarsData[QUuid].name, { + width : avat.displayName.length + * AVATAR_DISPLAY_NAME_CHAR_WIDTH, + text : avat.displayName, + textAlignCenter : true + }); + avatarsData[QUuid].needRefresh = false; + } + } + var textSize = (14 + (iconDimensions.y - 0.03) * 15 / 0.06); + Overlays.editOverlay(avatarsData[QUuid].icon, { + visible : true, + dimensions : iconDimensions, + position : iconPos + }); + Overlays.editOverlay(avatarsData[QUuid].name, { + visible : true, + x : x - avatarsData[QUuid].textWidth * 0.5, + y : y + iconDimensions.y * 550, + font : { + size : textSize, + bold : true + } + }); + } + } + } + } +} + +function entityAdded(entityID) { + printd("Entity added " + entityID); + var props = Entities.getEntityProperties(entityID, [ "type" ]); + printd("Entity added " + entityID + " PROPS " + JSON.stringify(props)); + if (props && props.type == "Web") { + printd("Entity Web added " + entityID); + saveEntityData(entityID, true); + } +} + +function entityRemoved(entityID) { + printd("Entity removed " + entityID); + var props = Entities.getEntityProperties(entityID, [ "type" ]); + if (props && props.type == "Web") { + print("Entity Web removed " + entityID); + removeEntityData(entityID); + } +} + +/******************************************************************************* + * Entities (to remark) cache structure for showing entities markers + ******************************************************************************/ + +var entitiesData = {}; // by entityID +var entitiesByOverlayID = {}; // by overlayID +var entitiesIcons = []; // a parallel list of icons (overlays) to easily run + // through + +var ICON_ENTITY_WEB_MODEL_URL = Script.resolvePath("../assets/images/web.svg"); +var ICON_ENTITY_IMG_MODEL_URL = Script + .resolvePath("../assets/models/teleport-cancel.fbx"); // FIXME - use + // correct + // model&texture +var ICON_ENTITY_DEFAULT_DIMENSIONS = { + x : 0.10, + y : 0.00001, + z : 0.10 +}; + +var entityIconModelDimensionsVal = { + x : 0, + y : 0.00001, + z : 0 +}; +function entityIconModelDimensions() { + // given the current height, give a size + var xz = -0.002831 * radarHeight + 0.1; + entityIconModelDimensionsVal.x = xz; + entityIconModelDimensionsVal.z = xz; + // reuse object + return entityIconModelDimensionsVal; +} +/* + * entityIconPlaneDimensions: similar to entityIconModelDimensions but using xy + * plane + */ +function entityIconPlaneDimensions() { + var dim = entityIconModelDimensions(); + var z = dim.z; + dim.z = dim.y; + dim.y = z; + return dim; +} + +function currentOverlayForEntity(QUuid) { + if (entitiesData[QUuid] != undefined) { + return entitiesData[QUuid].icon; + } else { + return null; + } +} + +function saveEntityData(QUuid, planar) { + if (QUuid == null) + return; + var entity = Entities.getEntityProperties(QUuid, [ "position" ]); + printd("entity added save entity " + QUuid); + if (entitiesData[QUuid] != undefined) { + entitiesData[QUuid].position = entity.position; + } else { + var entityIcon = Overlays.addOverlay("image3d", { + subImage : { + x : 0, + y : 0, + width : 150, + height : 150 + }, + url : ICON_ENTITY_WEB_MODEL_URL, + dimensions : ICON_ENTITY_DEFAULT_DIMENSIONS, + visible : false, + ignoreRayIntersection : false, + orientation : Quat.fromPitchYawRollDegrees(-90, 0, 0) + }); + + entitiesIcons.push(entityIcon); + entitiesData[QUuid] = { + position : entity.position, + icon : entityIcon + }; + entitiesByOverlayID[entityIcon] = QUuid; + } +} + +function removeEntityData(QUuid) { + if (QUuid == null) + return; + + var itsOverlay = currentOverlayForEntity(QUuid); + if (itsOverlay != null) { + Overlays.deleteOverlay(itsOverlay); + delete entitiesByOverlayID[itsOverlay]; + } + var idx = entitiesIcons.indexOf(itsOverlay); + entitiesIcons.splice(idx, 1); + + delete entitiesData[QUuid]; +} + +/******************************************************************************* + * Entities to remark Icon/Markers rendering + ******************************************************************************/ + +function hideAllEntitiesIcons() { + var len = entitiesIcons.length; + for (var i = 0; i < len; i++) { + Overlays.editOverlay(entitiesIcons[i], { + visible : false + }); + } +} + +function renderAllEntitiesIcons() { + var entityPos; + var entityProps; + var iconDimensions = entityIconModelDimensions(); + var planeDimensions = entityIconPlaneDimensions(); // plane overlays uses + // xy instead of xz + for ( var QUuid in entitiesData) { + if (entitiesData.hasOwnProperty(QUuid)) { + entityProps = Entities.getEntityProperties(QUuid, [ "position", + "visible" ]); + if (entityProps != null) { + entityPos = entityProps.position; + if (entitiesData[QUuid].icon != undefined && entityPos) { + var iconPos = findLineToHeightIntersectionCoords( + entityPos.x, + entityPos.y + + RADAR_ICONS_APPARENT_DISTANCE_TO_AVATAR_BASE, + entityPos.z, Camera.position.x, Camera.position.y, + Camera.position.z, Camera.position.y + - RADAR_CAMERA_DISTANCE_TO_ICONS); + if (!iconPos) { + printd("entity icon pos bad for " + QUuid); + continue; + } + var dimensions = entitiesData[QUuid].planar ? planeDimensions + : iconDimensions; + Overlays.editOverlay(entitiesData[QUuid].icon, { + visible : entityProps.visible, + dimensions : dimensions, + position : iconPos + }); + } + } + } + } +} + +/******************************************************************************* + * + ******************************************************************************/ + +function startRadar() { + printd("avatar added my avatar is " + MyAvatar.sessionUUID); + saveAllOthersAvatarsData(); + Camera.mode = "independent"; + + Camera.position = Vec3.sum(MyAvatar.position, { + x : 0, + y : radarHeight, + z : 0 + }); + Camera.orientation = Quat.fromPitchYawRollDegrees(-90, 0, 0); + radar = true; + + connectRadarModeEvents(); +} + +function endRadar() { + printd("-- endRadar"); + Camera.mode = "first person"; + radar = false; + + disconnectRadarModeEvents(); + hideAllEntitiesIcons(); + hideAllAvatarIcons(); +} + +function onRadarModeClicked() { + startRadar(); +} + +function onMyViewModeClicked() { + endRadar(); +} + +radarModeInterface.startRadarMode = function() { + startRadar(); +}; + +radarModeInterface.endRadarMode = function() { + endRadar(); +}; + +radarModeInterface.init = function() { + init(); +} + +radarModeInterface.setUniqueColor = function(c) { + uniqueColor = c; +}; + +module.exports = radarModeInterface; + +function updateRadar() { + // Update avatar icons + if (startedDraggingCamera) { + hideAllAvatarIcons(); + hideAllEntitiesIcons(); + startedDraggingCamera = false; + } else if (!draggingCamera) { + renderMyAvatarIcon(); + renderAllOthersAvatarIcons(); + renderAllEntitiesIcons(); + } +} + +function valueIfDefined(value) { + return value !== undefined ? value : ""; +} + +function entitiesAnalysis() { + var ids = Entities.findEntitiesInFrustum(Camera.frustum); + var entities = []; + for (var i = 0; i < ids.length; i++) { + var id = ids[i]; + var properties = Entities.getEntityProperties(id); + entities.push({ + id : id, + name : properties.name, + type : properties.type, + url : properties.type == "Model" ? properties.modelURL : "", + sourceUrl : properties.sourceUrl, + locked : properties.locked, + visible : properties.visible, + drawCalls : valueIfDefined(properties.renderInfo.drawCalls), + hasScript : properties.script !== "" + }); + } +} + +function connectRadarModeEvents() { + Script.update.connect(updateRadar); // 60Hz loop + Controller.keyPressEvent.connect(keyPressEvent); + Controller.mousePressEvent.connect(mousePress); // single click/touch + Controller.touchUpdateEvent.connect(touchUpdate); + MyAvatar.positionGoneTo.connect(positionGoneTo); +} + +function positionGoneTo() { + Camera.position = Vec3.sum(MyAvatar.position, { + x : 0, + y : radarHeight, + z : 0 + }); +} + +function disconnectRadarModeEvents() { + Script.update.disconnect(updateRadar); + Controller.keyPressEvent.disconnect(keyPressEvent); + Controller.mousePressEvent.disconnect(mousePress); + Controller.touchUpdateEvent.disconnect(touchUpdate); + MyAvatar.positionGoneTo.disconnect(positionGoneTo); +} + +function init() { + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + + Controller.touchBeginEvent.connect(touchBegin); + Controller.touchEndEvent.connect(touchEnd); + + AvatarList.avatarAddedEvent.connect(avatarAdded); + AvatarList.avatarRemovedEvent.connect(avatarRemoved); + + Entities.addingEntity.connect(entityAdded); + Entities.deletingEntity.connect(entityRemoved); +} diff --git a/scripts/system/+android/touchscreenvirtualpad.js b/scripts/system/+android/touchscreenvirtualpad.js new file mode 100644 index 0000000000..fa41a2b5e0 --- /dev/null +++ b/scripts/system/+android/touchscreenvirtualpad.js @@ -0,0 +1,21 @@ +"use strict"; +// +// touchscreenvirtualpad.js +// scripts/system/ +// +// Created by Gabriel Calero & Cristian Duarte on Jan 16, 2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function() { // BEGIN LOCAL_SCOPE + +function init() { + Controller.setVPadEnabled(true); +} + +init(); + +}()); // END LOCAL_SCOPE diff --git a/scripts/system/+android/uniqueColor.js b/scripts/system/+android/uniqueColor.js new file mode 100644 index 0000000000..c296b6c87d --- /dev/null +++ b/scripts/system/+android/uniqueColor.js @@ -0,0 +1,46 @@ +"use strict"; +// +// uniqueColor.js +// scripts/system/ +// +// Created by Gabriel Calero & Cristian Duarte on 17 Oct 2017 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var colorsMap = {}; +var colorsCount = 0; + // 'red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'magenta' +var baseColors = [ '#EB3345', '#F0851F', '#FFCD29', '#94C338', '#11A6C5', '#294C9F', '#C01D84' ]; + +function getNextColor(n) { + var N = baseColors.length; + /*if (n < baseColors.length) { + return baseColors[n]; + } else { + var baseColor = baseColors[n % N]; + var d = (n / N) % 10; + var c2 = "" + Qt.lighter(baseColor, 1 + d / 10); + return c2; + }*/ + return baseColors[n%N]; +} + +function getColorForId(uuid) { + if (colorsMap == undefined) { + colorsMap = {}; + } + if (!colorsMap.hasOwnProperty(uuid)) { + colorsMap[uuid] = getNextColor(colorsCount); + colorsCount = colorsCount + 1; + } + return colorsMap[uuid]; +} + +module.exports = { + getColor: function(id) { + return getColorForId(id); + } +}; diff --git a/server-console/package-lock.json b/server-console/package-lock.json index ba8ef3c720..e25fd3cded 100644 --- a/server-console/package-lock.json +++ b/server-console/package-lock.json @@ -151,7 +151,8 @@ "balanced-match": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.3.0.tgz", - "integrity": "sha1-qRzdHr7xqGZZ5w/03vAWJfwtZ1Y=" + "integrity": "sha1-qRzdHr7xqGZZ5w/03vAWJfwtZ1Y=", + "dev": true }, "base64-js": { "version": "1.2.0", @@ -220,6 +221,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.3.tgz", "integrity": "sha1-Rr/1ARXUf8mriYVKu4fZgHihCZE=", + "dev": true, "requires": { "balanced-match": "0.3.0", "concat-map": "0.0.1" @@ -345,7 +347,8 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "concat-stream": { "version": "1.5.0", @@ -886,17 +889,21 @@ } }, "fs-extra": { - "version": "0.26.7", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz", - "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", + "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", "requires": { "graceful-fs": "4.1.3", "jsonfile": "2.2.3", - "klaw": "1.1.3", - "path-is-absolute": "1.0.0", - "rimraf": "2.5.2" + "klaw": "1.3.1" } }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, "generate-function": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", @@ -1003,15 +1010,44 @@ "dev": true }, "glob": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.3.tgz", - "integrity": "sha1-CqI1kxpKlqwT1g/6wvuHe9btT1g=", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, "requires": { + "fs.realpath": "1.0.0", "inflight": "1.0.4", "inherits": "2.0.1", - "minimatch": "3.0.0", + "minimatch": "3.0.4", "once": "1.3.3", "path-is-absolute": "1.0.0" + }, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + } } }, "graceful-fs": { @@ -1144,6 +1180,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz", "integrity": "sha1-bLtFIevVHODsCpNr/XZX736bFyo=", + "dev": true, "requires": { "once": "1.3.3", "wrappy": "1.0.1" @@ -1303,9 +1340,20 @@ } }, "klaw": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.1.3.tgz", - "integrity": "sha1-faM8a0L5s9yc7ADRfxOvAX/MJyE=" + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "requires": { + "graceful-fs": "4.1.11" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "optional": true + } + } }, "lcid": { "version": "1.0.0", @@ -1417,6 +1465,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.0.tgz", "integrity": "sha1-UjYVelHk8ATBd/s8Un/33Xjw74M=", + "dev": true, "requires": { "brace-expansion": "1.1.3" } @@ -1529,6 +1578,19 @@ "mime-types": "2.1.17" } }, + "fs-extra": { + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz", + "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=", + "dev": true, + "requires": { + "graceful-fs": "4.1.3", + "jsonfile": "2.2.3", + "klaw": "1.3.1", + "path-is-absolute": "1.0.0", + "rimraf": "2.6.2" + } + }, "har-validator": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", @@ -1912,7 +1974,8 @@ "path-is-absolute": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz", - "integrity": "sha1-Jj2tpmqz8vsQv3+dJN2PPlcO+RI=" + "integrity": "sha1-Jj2tpmqz8vsQv3+dJN2PPlcO+RI=", + "dev": true }, "path-parse": { "version": "1.0.5", @@ -2184,11 +2247,12 @@ } }, "rimraf": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.2.tgz", - "integrity": "sha1-YrqUf6TAtDY4Oa7+zU8PutYFlyY=", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, "requires": { - "glob": "7.0.3" + "glob": "7.1.2" } }, "safe-buffer": { diff --git a/server-console/package.json b/server-console/package.json index 9f47d0e4cc..0b13eeb2a8 100644 --- a/server-console/package.json +++ b/server-console/package.json @@ -26,7 +26,7 @@ "always-tail": "0.2.0", "cheerio": "^0.19.0", "extend": "^3.0.0", - "fs-extra": "^0.26.4", + "fs-extra": "^1.0.0", "node-notifier": "^5.2.1", "os-homedir": "^1.0.1", "request": "^2.67.0", diff --git a/tests/animation/src/AnimInverseKinematicsTests.cpp b/tests/animation/src/AnimInverseKinematicsTests.cpp index f36b8891ff..eba74726bb 100644 --- a/tests/animation/src/AnimInverseKinematicsTests.cpp +++ b/tests/animation/src/AnimInverseKinematicsTests.cpp @@ -93,6 +93,9 @@ void makeTestFBXJoints(FBXGeometry& geometry) { } void AnimInverseKinematicsTests::testSingleChain() { + + AnimContext context(false, false, false, glm::mat4(), glm::mat4()); + FBXGeometry geometry; makeTestFBXJoints(geometry); @@ -108,14 +111,14 @@ void AnimInverseKinematicsTests::testSingleChain() { // // A------>B------>C------>D AnimPose pose; - pose.scale = glm::vec3(1.0f); - pose.rot = identity; - pose.trans = origin; + pose.scale() = glm::vec3(1.0f); + pose.rot() = identity; + pose.trans() = origin; AnimPoseVec poses; poses.push_back(pose); - pose.trans = xAxis; + pose.trans() = xAxis; for (int i = 1; i < (int)geometry.joints.size(); ++i) { poses.push_back(pose); } @@ -133,8 +136,13 @@ void AnimInverseKinematicsTests::testSingleChain() { AnimVariantMap varMap; varMap.set("positionD", targetPosition); varMap.set("rotationD", targetRotation); - varMap.set("targetType", (int)IKTarget::Type::RotationAndPosition); - ikDoll.setTargetVars(QString("D"), QString("positionD"), QString("rotationD"), QString("targetType")); + varMap.set("targetTypeD", (int)IKTarget::Type::RotationAndPosition); + varMap.set("poleVectorEnabledD", false); + + std::vector flexCoefficients = {1.0f, 1.0f, 1.0f, 1.0f}; + ikDoll.setTargetVars(QString("D"), QString("positionD"), QString("rotationD"), QString("targetTypeD"), + QString("weightD"), 1.0f, flexCoefficients, QString("poleVectorEnabledD"), + QString("poleReferenceVectorD"), QString("poleVectorD")); AnimNode::Triggers triggers; // the IK solution should be: @@ -147,14 +155,12 @@ void AnimInverseKinematicsTests::testSingleChain() { // iterate several times float dt = 1.0f; - ikDoll.overlay(varMap, dt, triggers, poses); - ikDoll.overlay(varMap, dt, triggers, poses); - ikDoll.overlay(varMap, dt, triggers, poses); - ikDoll.overlay(varMap, dt, triggers, poses); - ikDoll.overlay(varMap, dt, triggers, poses); - ikDoll.overlay(varMap, dt, triggers, poses); - const AnimPoseVec& relativePoses = ikDoll.overlay(varMap, dt, triggers, poses); + const int NUM_FRAMES = 10; + for (int i = 0; i < NUM_FRAMES; i++) { + poses = ikDoll.overlay(varMap, context, dt, triggers, poses); + } + const AnimPoseVec& relativePoses = ikDoll.overlay(varMap, context, dt, triggers, poses); // verify absolute results // NOTE: since we expect this solution to converge very quickly (one loop) @@ -164,28 +170,30 @@ void AnimInverseKinematicsTests::testSingleChain() { absolutePoses.push_back(pose); } ikDoll.computeAbsolutePoses(absolutePoses); + const float acceptableAngleError = 0.001f; - QCOMPARE_QUATS(absolutePoses[0].rot, identity, acceptableAngleError); - QCOMPARE_QUATS(absolutePoses[1].rot, identity, acceptableAngleError); - QCOMPARE_QUATS(absolutePoses[2].rot, quaterTurnAroundZ, acceptableAngleError); - QCOMPARE_QUATS(absolutePoses[3].rot, quaterTurnAroundZ, acceptableAngleError); + QCOMPARE_QUATS(absolutePoses[0].rot(), identity, acceptableAngleError); + QCOMPARE_QUATS(absolutePoses[1].rot(), identity, acceptableAngleError); + QCOMPARE_QUATS(absolutePoses[2].rot(), quaterTurnAroundZ, acceptableAngleError); + QCOMPARE_QUATS(absolutePoses[3].rot(), quaterTurnAroundZ, acceptableAngleError); const float acceptableTranslationError = 0.025f; - QCOMPARE_WITH_ABS_ERROR(absolutePoses[0].trans, origin, acceptableTranslationError); - QCOMPARE_WITH_ABS_ERROR(absolutePoses[1].trans, xAxis, acceptableTranslationError); - QCOMPARE_WITH_ABS_ERROR(absolutePoses[2].trans, 2.0f * xAxis, acceptableTranslationError); - QCOMPARE_WITH_ABS_ERROR(absolutePoses[3].trans, targetPosition, acceptableTranslationError); + QCOMPARE_WITH_ABS_ERROR(absolutePoses[0].trans(), origin, acceptableTranslationError); + QCOMPARE_WITH_ABS_ERROR(absolutePoses[1].trans(), xAxis, acceptableTranslationError); + QCOMPARE_WITH_ABS_ERROR(absolutePoses[2].trans(), 2.0f * xAxis, acceptableTranslationError); + QCOMPARE_WITH_ABS_ERROR(absolutePoses[3].trans(), targetPosition, acceptableTranslationError); // verify relative results - QCOMPARE_QUATS(relativePoses[0].rot, identity, acceptableAngleError); - QCOMPARE_QUATS(relativePoses[1].rot, identity, acceptableAngleError); - QCOMPARE_QUATS(relativePoses[2].rot, quaterTurnAroundZ, acceptableAngleError); - QCOMPARE_QUATS(relativePoses[3].rot, identity, acceptableAngleError); + QCOMPARE_QUATS(relativePoses[0].rot(), identity, acceptableAngleError); + QCOMPARE_QUATS(relativePoses[1].rot(), identity, acceptableAngleError); + QCOMPARE_QUATS(relativePoses[2].rot(), quaterTurnAroundZ, acceptableAngleError); + QCOMPARE_QUATS(relativePoses[3].rot(), identity, acceptableAngleError); + + QCOMPARE_WITH_ABS_ERROR(relativePoses[0].trans(), origin, acceptableTranslationError); + QCOMPARE_WITH_ABS_ERROR(relativePoses[1].trans(), xAxis, acceptableTranslationError); + QCOMPARE_WITH_ABS_ERROR(relativePoses[2].trans(), xAxis, acceptableTranslationError); + QCOMPARE_WITH_ABS_ERROR(relativePoses[3].trans(), xAxis, acceptableTranslationError); - QCOMPARE_WITH_ABS_ERROR(relativePoses[0].trans, origin, acceptableTranslationError); - QCOMPARE_WITH_ABS_ERROR(relativePoses[1].trans, xAxis, acceptableTranslationError); - QCOMPARE_WITH_ABS_ERROR(relativePoses[2].trans, xAxis, acceptableTranslationError); - QCOMPARE_WITH_ABS_ERROR(relativePoses[3].trans, xAxis, acceptableTranslationError); } { // hard test IK of joint C // load intial poses that look like this: @@ -196,15 +204,15 @@ void AnimInverseKinematicsTests::testSingleChain() { // A------>B // AnimPose pose; - pose.scale = glm::vec3(1.0f); - pose.rot = identity; - pose.trans = origin; + pose.scale() = glm::vec3(1.0f); + pose.rot() = identity; + pose.trans() = origin; AnimPoseVec poses; poses.push_back(pose); - pose.trans = xAxis; + pose.trans() = xAxis; - pose.rot = quaterTurnAroundZ; + pose.rot() = quaterTurnAroundZ; poses.push_back(pose); poses.push_back(pose); poses.push_back(pose); @@ -222,8 +230,12 @@ void AnimInverseKinematicsTests::testSingleChain() { AnimVariantMap varMap; varMap.set("positionD", targetPosition); varMap.set("rotationD", targetRotation); - varMap.set("targetType", (int)IKTarget::Type::RotationAndPosition); - ikDoll.setTargetVars(QString("D"), QString("positionD"), QString("rotationD"), QString("targetType")); + varMap.set("targetTypeD", (int)IKTarget::Type::RotationAndPosition); + varMap.set("poleVectorEnabledD", false); + std::vector flexCoefficients = {1.0f, 1.0f, 1.0f, 1.0f}; + ikDoll.setTargetVars(QString("D"), QString("positionD"), QString("rotationD"), QString("targetTypeD"), + QString("weightD"), 1.0f, flexCoefficients, QString("poleVectorEnabledD"), + QString("poleReferenceVectorD"), QString("poleVectorD")); AnimNode::Triggers triggers; // the IK solution should be: @@ -233,15 +245,11 @@ void AnimInverseKinematicsTests::testSingleChain() { // iterate several times float dt = 1.0f; - ikDoll.overlay(varMap, dt, triggers, poses); - ikDoll.overlay(varMap, dt, triggers, poses); - ikDoll.overlay(varMap, dt, triggers, poses); - ikDoll.overlay(varMap, dt, triggers, poses); - ikDoll.overlay(varMap, dt, triggers, poses); - ikDoll.overlay(varMap, dt, triggers, poses); - ikDoll.overlay(varMap, dt, triggers, poses); - ikDoll.overlay(varMap, dt, triggers, poses); - const AnimPoseVec& relativePoses = ikDoll.overlay(varMap, dt, triggers, poses); + const int NUM_FRAMES = 50; + for (int i = 0; i < NUM_FRAMES; i++) { + poses = ikDoll.overlay(varMap, context, dt, triggers, poses); + } + const AnimPoseVec& relativePoses = ikDoll.overlay(varMap, context, dt, triggers, poses); // verify absolute results // NOTE: the IK algorithm doesn't converge very fast for full-reach targets, @@ -255,28 +263,29 @@ void AnimInverseKinematicsTests::testSingleChain() { absolutePoses.push_back(pose); } ikDoll.computeAbsolutePoses(absolutePoses); - float acceptableAngle = 0.01f; // radians - QCOMPARE_QUATS(absolutePoses[0].rot, identity, acceptableAngle); - QCOMPARE_QUATS(absolutePoses[1].rot, identity, acceptableAngle); - QCOMPARE_QUATS(absolutePoses[2].rot, identity, acceptableAngle); - QCOMPARE_QUATS(absolutePoses[3].rot, identity, acceptableAngle); - float acceptableDistance = 0.03f; - QCOMPARE_WITH_ABS_ERROR(absolutePoses[0].trans, origin, acceptableDistance); - QCOMPARE_WITH_ABS_ERROR(absolutePoses[1].trans, xAxis, acceptableDistance); - QCOMPARE_WITH_ABS_ERROR(absolutePoses[2].trans, 2.0f * xAxis, acceptableDistance); - QCOMPARE_WITH_ABS_ERROR(absolutePoses[3].trans, 3.0f * xAxis, acceptableDistance); + float acceptableAngle = 0.01f; // radians + QCOMPARE_QUATS(absolutePoses[0].rot(), identity, acceptableAngle); + QCOMPARE_QUATS(absolutePoses[1].rot(), identity, acceptableAngle); + QCOMPARE_QUATS(absolutePoses[2].rot(), identity, acceptableAngle); + QCOMPARE_QUATS(absolutePoses[3].rot(), identity, acceptableAngle); + + float acceptableDistance = 0.1f; + QCOMPARE_WITH_ABS_ERROR(absolutePoses[0].trans(), origin, acceptableDistance); + QCOMPARE_WITH_ABS_ERROR(absolutePoses[1].trans(), xAxis, acceptableDistance); + QCOMPARE_WITH_ABS_ERROR(absolutePoses[2].trans(), 2.0f * xAxis, acceptableDistance); + QCOMPARE_WITH_ABS_ERROR(absolutePoses[3].trans(), 3.0f * xAxis, acceptableDistance); // verify relative results - QCOMPARE_QUATS(relativePoses[0].rot, identity, acceptableAngle); - QCOMPARE_QUATS(relativePoses[1].rot, identity, acceptableAngle); - QCOMPARE_QUATS(relativePoses[2].rot, identity, acceptableAngle); - QCOMPARE_QUATS(relativePoses[3].rot, identity, acceptableAngle); + QCOMPARE_QUATS(relativePoses[0].rot(), identity, acceptableAngle); + QCOMPARE_QUATS(relativePoses[1].rot(), identity, acceptableAngle); + QCOMPARE_QUATS(relativePoses[2].rot(), identity, acceptableAngle); + QCOMPARE_QUATS(relativePoses[3].rot(), identity, acceptableAngle); - QCOMPARE_WITH_ABS_ERROR(relativePoses[0].trans, origin, acceptableDistance); - QCOMPARE_WITH_ABS_ERROR(relativePoses[1].trans, xAxis, acceptableDistance); - QCOMPARE_WITH_ABS_ERROR(relativePoses[2].trans, xAxis, acceptableDistance); - QCOMPARE_WITH_ABS_ERROR(relativePoses[3].trans, xAxis, acceptableDistance); + QCOMPARE_WITH_ABS_ERROR(relativePoses[0].trans(), origin, acceptableDistance); + QCOMPARE_WITH_ABS_ERROR(relativePoses[1].trans(), xAxis, acceptableDistance); + QCOMPARE_WITH_ABS_ERROR(relativePoses[2].trans(), xAxis, acceptableDistance); + QCOMPARE_WITH_ABS_ERROR(relativePoses[3].trans(), xAxis, acceptableDistance); } } @@ -293,6 +302,6 @@ void AnimInverseKinematicsTests::testBar() { AnimPose poseC = poseA * poseB; glm::vec3 expectedTransC = transA + transB; - QCOMPARE_WITH_ABS_ERROR(expectedTransC, poseC.trans, EPSILON); + QCOMPARE_WITH_ABS_ERROR(expectedTransC, poseC.trans(), EPSILON); } diff --git a/tests/animation/src/AnimTests.cpp b/tests/animation/src/AnimTests.cpp index 8e67bda2d3..fe54ac3781 100644 --- a/tests/animation/src/AnimTests.cpp +++ b/tests/animation/src/AnimTests.cpp @@ -15,7 +15,11 @@ #include #include #include - +#include +#include +#include +#include +#include #include <../QTestExtensions.h> QTEST_MAIN(AnimTests) @@ -23,12 +27,18 @@ QTEST_MAIN(AnimTests) const float EPSILON = 0.001f; void AnimTests::initTestCase() { - auto animationCache = DependencyManager::set(); - auto resourceCacheSharedItems = DependencyManager::set(); + DependencyManager::registerInheritance(); + DependencyManager::set(); + DependencyManager::set(); + DependencyManager::set(NodeType::Agent); + DependencyManager::set(); + DependencyManager::set(); + DependencyManager::set(); + DependencyManager::set(); } void AnimTests::cleanupTestCase() { - DependencyManager::destroy(); + //DependencyManager::destroy(); } void AnimTests::testClipInternalState() { @@ -59,6 +69,7 @@ static float framesToSec(float secs) { } void AnimTests::testClipEvaulate() { + AnimContext context(false, false, false, glm::mat4(), glm::mat4()); QString id = "myClipNode"; QString url = "https://hifi-public.s3.amazonaws.com/ozan/support/FightClubBotTest1/Animations/standard_idle.fbx"; float startFrame = 2.0f; @@ -73,12 +84,12 @@ void AnimTests::testClipEvaulate() { AnimClip clip(id, url, startFrame, endFrame, timeScale, loopFlag, mirrorFlag); AnimNode::Triggers triggers; - clip.evaluate(vars, framesToSec(10.0f), triggers); + clip.evaluate(vars, context, framesToSec(10.0f), triggers); QCOMPARE_WITH_ABS_ERROR(clip._frame, 12.0f, EPSILON); // does it loop? triggers.clear(); - clip.evaluate(vars, framesToSec(12.0f), triggers); + clip.evaluate(vars, context, framesToSec(12.0f), triggers); QCOMPARE_WITH_ABS_ERROR(clip._frame, 3.0f, EPSILON); // Note: frame 3 and not 4, because extra frame between start and end. // did we receive a loop trigger? @@ -87,7 +98,7 @@ void AnimTests::testClipEvaulate() { // does it pause at end? triggers.clear(); clip.setLoopFlagVar("FalseVar"); - clip.evaluate(vars, framesToSec(20.0f), triggers); + clip.evaluate(vars, context, framesToSec(20.0f), triggers); QCOMPARE_WITH_ABS_ERROR(clip._frame, 22.0f, EPSILON); // did we receive a done trigger? @@ -95,6 +106,7 @@ void AnimTests::testClipEvaulate() { } void AnimTests::testClipEvaulateWithVars() { + AnimContext context(false, false, false, glm::mat4(), glm::mat4()); QString id = "myClipNode"; QString url = "https://hifi-public.s3.amazonaws.com/ozan/support/FightClubBotTest1/Animations/standard_idle.fbx"; float startFrame = 2.0f; @@ -121,7 +133,7 @@ void AnimTests::testClipEvaulateWithVars() { clip.setLoopFlagVar("loopFlag2"); AnimNode::Triggers triggers; - clip.evaluate(vars, framesToSec(0.1f), triggers); + clip.evaluate(vars, context, framesToSec(0.1f), triggers); // verify that the values from the AnimVariantMap made it into the clipNode's // internal state @@ -132,7 +144,7 @@ void AnimTests::testClipEvaulateWithVars() { } void AnimTests::testLoader() { - auto url = QUrl("https://gist.githubusercontent.com/hyperlogic/857129fe04567cbe670f/raw/0c54500f480fd7314a5aeb147c45a8a707edcc2e/test.json"); + auto url = QUrl("https://gist.githubusercontent.com/hyperlogic/756e6b7018c96c9778dba4ffb959c3c7/raw/4b37f10c9d2636608916208ba7b415c1a3f842ff/test.json"); // NOTE: This will warn about missing "test01.fbx", "test02.fbx", etc. if the resource loading code doesn't handle relative pathnames! // However, the test will proceed. AnimNodeLoader loader(url); @@ -173,14 +185,22 @@ void AnimTests::testLoader() { QVERIFY(nodes[2]->getChildCount() == 0); auto test01 = std::static_pointer_cast(nodes[0]); - QVERIFY(test01->_url == "test01.fbx"); + + QUrl relativeUrl01("test01.fbx"); + QString url01 = url.resolved(relativeUrl01).toString(); + + QVERIFY(test01->_url == url01); QVERIFY(test01->_startFrame == 1.0f); QVERIFY(test01->_endFrame == 20.0f); QVERIFY(test01->_timeScale == 1.0f); QVERIFY(test01->_loopFlag == false); auto test02 = std::static_pointer_cast(nodes[1]); - QVERIFY(test02->_url == "test02.fbx"); + + QUrl relativeUrl02("test02.fbx"); + QString url02 = url.resolved(relativeUrl02).toString(); + + QVERIFY(test02->_url == url02); QVERIFY(test02->_startFrame == 2.0f); QVERIFY(test02->_endFrame == 21.0f); QVERIFY(test02->_timeScale == 0.9f); diff --git a/tests/animation/src/RigTests.cpp b/tests/animation/src/RigTests.cpp deleted file mode 100644 index d5de9226c0..0000000000 --- a/tests/animation/src/RigTests.cpp +++ /dev/null @@ -1,101 +0,0 @@ -// -// RigTests.cpp -// tests/rig/src -// -// Created by Howard Stearns on 6/16/15 -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -/* FIXME/TBD: - - The following lower level functionality might be separated out into a separate class, covered by a separate test case class: - - With no input, initial pose is standing, arms at side - - Some single animation produces correct results at a given keyframe time. - - Some single animation produces correct results at a given interpolated time. - - Blend between two animations, started at separate times, produces correct result at a given interpolated time. - - Head orientation can be overridden to produce change that doesn't come from the playing animation. - - Hand position/orientation can be overridden to produce change that doesn't come from the playing animation. - - Hand position/orientation can be overrridden to produce elbow change that doesn't come from the playing animation. - - Respect scaling? (e.g., so that MyAvatar.increase/decreaseSize can alter rig, such that anti-scating and footfalls-on-stairs works) - - Higher level functionality: - - start/stopAnimation adds the animation to that which is playing, blending/fading as needed. - - thrust causes walk role animation to be used. - - turning causes turn role animation to be used. (two tests, correctly symmetric left & right) - - walk/turn do not skate (footfalls match over-ground velocity) - - (Later?) walk up stairs / hills have proper footfall for terrain - - absence of above causes return to idle role animation to be used - - (later?) The lower-level head/hand placements respect previous state. E.g., actual hand movement can be slower than requested. - - (later) The lower-level head/hand placements can move whole skeleton. E.g., turning head past a limit may turn whole body. Reaching up can move shoulders and hips. - - Backward-compatability operations. We should think of this behavior as deprecated: - - clearJointData return to standing. TBD: presumably with idle and all other animations NOT playing, until explicitly reenabled with a new TBD method? - - setJointData applies the given data. Same TBD. - These can be defined true or false, but the tests document the behavior and tells us if something's changed: - - An external change to the original skeleton IS/ISN'T seen by the rig. - - An external change to the original skeleton's head orientation IS/ISN'T seen by the rig. - - An external change to the original skeleton's hand orientiation IS/ISN'T seen by the rig. - */ - -#include - -#include "FBXReader.h" -#include "OBJReader.h" - -#include -#include "RigTests.h" - -static void reportJoint(const Rig& rig, int index) { // Handy for debugging - std::cout << "\n"; - std::cout << index << " " << rig->getAnimSkeleton()->getJointName(index).toUtf8().data() << "\n"; - glm::vec3 pos; - rig->getJointPosition(index, pos); - glm::quat rot; - rig->getJointRotation(index, rot); - std::cout << " pos:" << pos << "\n"; - std::cout << " rot:" << safeEulerAngles(rot) << "\n"; - std::cout << "\n"; -} -static void reportByName(const Rig& rig, const QString& name) { - int jointIndex = rig->indexOfJoint(name); - reportJoint(rig, jointIndex); -} -static void reportAll(const Rig& rig) { - for (int i = 0; i < rig->getJointStateCount(); i++) { - reportJoint(rig, i); - } -} -static void reportSome(const Rig& rig) { - QString names[] = {"Head", "Neck", "RightShoulder", "RightArm", "RightForeArm", "RightHand", "Spine2", "Spine1", "Spine", "Hips", "RightUpLeg", "RightLeg", "RightFoot", "RightToeBase", "RightToe_End"}; - for (auto name : names) { - reportByName(rig, name); - } -} - -QTEST_MAIN(RigTests) - -void RigTests::initTestCase() { -//#define FROM_FILE "/Users/howardstearns/howardHiFi/Zack.fbx" -#ifdef FROM_FILE - QFile file(FROM_FILE); - QCOMPARE(file.open(QIODevice::ReadOnly), true); - FBXGeometry* geometry = readFBX(file.readAll(), QVariantHash()); -#else - QUrl fbxUrl("https://s3.amazonaws.com/hifi-public/models/skeletons/Zack/Zack.fbx"); - QNetworkReply* reply = OBJReader().request(fbxUrl, false); // Just a convenience hack for synchronoud http request - auto fbxHttpCode = !reply->isFinished() ? -1 : reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - QCOMPARE(fbxHttpCode, 200); - FBXGeometry* geometry = readFBX(reply->readAll(), QVariantHash()); -#endif - QVERIFY((bool)geometry); - - _rig.initJointStates(*geometry, glm::mat4()); - std::cout << "Rig is ready " << geometry->joints.count() << " joints " << std::endl; - reportAll(_rig); -} - -void RigTests::initialPoseArmsDown() { - reportSome(_rig); -} diff --git a/tests/animation/src/RigTests.h b/tests/animation/src/RigTests.h deleted file mode 100644 index 3242c27b99..0000000000 --- a/tests/animation/src/RigTests.h +++ /dev/null @@ -1,55 +0,0 @@ -// -// RigTests.h -// tests/rig/src -// -// Created by Howard Stearns on 6/16/15 -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_RigTests_h -#define hifi_RigTests_h - -#include -#include - -//#include "../QTestExtensions.h" - - -// The QTest terminology is not consistent with itself or with industry: -// The whole directory, and the rig-tests target, doesn't seem to be a QTest concept, an corresponds roughly to a toplevel suite of suites. -// The directory can contain any number of classes like this one. (Don't forget to wipe your build dir, and rerun cmake when you add one.): -// QTest doc (http://doc.qt.io/qt-5/qtest-overview.html) calls this a "test case". -// The output of QTest's 'ctest' runner calls this a "test" when run in the whole directory (e.g., when reporting success/failure counts). -// The test case (like this class) can contain any number of test slots: -// QTest doc calls these "test functions" -// When you run a single test case executable (e.g., "rig-RigTests"), the (unlabeled) count includes these test functions and also the before method, which is auto generated as initTestCase. - -// To build and run via make: -// make help | grep tests # shows all test targets, including all-tests and rig-tests. -// make all-tests # will compile and then die as soon as any test case dies, even if its not in your directory -// make rig-tests # will compile and run `ctest .` in the tests/rig directory, running all the test cases found there. -// Alas, only summary output is shown on stdout. The real results, including any stdout that your code does, is in tests/rig/Testing/Temporary/LastTest.log, or... -// tests/rig/rig-RigTests (or the executable corresponding to any test case you define here) will run just that case and give output directly. -// -// To build and run via Xcode: -// On some machines, xcode can't find cmake on the path it uses. I did, effectively: sudo ln -s `which cmake` /usr/bin -// Note the above make instructions. -// all-tests, rig-tests, and rig-RigTests are all targets: -// The first two of these show no output at all, but if there's a failure you can see it by clicking on the red failure in the "issue navigator" (or by externally viewing the .log above). -// The last (or any other individual test case executable) does show output in the Xcode output display. - -class RigTests : public QObject { - Q_OBJECT - - private slots: - void initTestCase(); - void initialPoseArmsDown(); - - private: - Rig _rig; -}; - -#endif // hifi_RigTests_h diff --git a/tests/shaders/src/main.cpp b/tests/shaders/src/main.cpp index a3b4196031..cce5b0678b 100644 --- a/tests/shaders/src/main.cpp +++ b/tests/shaders/src/main.cpp @@ -50,12 +50,8 @@ #include #include #include -#include -#include #include #include -#include -#include #include #include @@ -180,19 +176,13 @@ void QTestWindow::draw() { testShaderBuild(model_vert::getSource(), model_frag::getSource()); testShaderBuild(model_normal_map_vert::getSource(), model_normal_map_frag::getSource()); - testShaderBuild(model_vert::getSource(), model_specular_map_frag::getSource()); - testShaderBuild(model_normal_map_vert::getSource(), model_normal_specular_map_frag::getSource()); testShaderBuild(model_vert::getSource(), model_translucent_frag::getSource()); testShaderBuild(model_normal_map_vert::getSource(), model_translucent_frag::getSource()); testShaderBuild(model_lightmap_vert::getSource(), model_lightmap_frag::getSource()); testShaderBuild(model_lightmap_normal_map_vert::getSource(), model_lightmap_normal_map_frag::getSource()); - testShaderBuild(model_lightmap_vert::getSource(), model_lightmap_specular_map_frag::getSource()); - testShaderBuild(model_lightmap_normal_map_vert::getSource(), model_lightmap_normal_specular_map_frag::getSource()); testShaderBuild(skin_model_vert::getSource(), model_frag::getSource()); testShaderBuild(skin_model_normal_map_vert::getSource(), model_normal_map_frag::getSource()); - testShaderBuild(skin_model_vert::getSource(), model_specular_map_frag::getSource()); - testShaderBuild(skin_model_normal_map_vert::getSource(), model_normal_specular_map_frag::getSource()); testShaderBuild(skin_model_vert::getSource(), model_translucent_frag::getSource()); testShaderBuild(skin_model_normal_map_vert::getSource(), model_translucent_frag::getSource()); diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 53d7fc2836..1c36306410 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -18,6 +18,9 @@ if (BUILD_TOOLS) add_subdirectory(ice-client) set_target_properties(ice-client PROPERTIES FOLDER "Tools") + add_subdirectory(ktx-tool) + set_target_properties(ktx-tool PROPERTIES FOLDER "Tools") + add_subdirectory(ac-client) set_target_properties(ac-client PROPERTIES FOLDER "Tools") diff --git a/tools/ktx-tool/CMakeLists.txt b/tools/ktx-tool/CMakeLists.txt new file mode 100644 index 0000000000..9daf8e0a1a --- /dev/null +++ b/tools/ktx-tool/CMakeLists.txt @@ -0,0 +1,14 @@ +set(TARGET_NAME ktx-tool) + +setup_hifi_project(Quick Gui Concurrent) + +link_hifi_libraries(shared networking image gl gpu ktx) + +target_gli() + +setup_memory_debugger() + +if (WIN32) + package_libraries_for_deployment() +endif() + diff --git a/tools/ktx-tool/src/main.cpp b/tools/ktx-tool/src/main.cpp new file mode 100644 index 0000000000..803b08c115 --- /dev/null +++ b/tools/ktx-tool/src/main.cpp @@ -0,0 +1,125 @@ +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + + + + +void stripKtxKeyValues(const std::string& sourceFile, const std::string& destFile) { + auto sourceStorage = std::make_shared(sourceFile.c_str()); + auto ktx = ktx::KTX::create(sourceStorage); + auto newStorageSize = ktx::KTX::evalStorageSize(ktx->_header, ktx->_images); + storage::FileStorage::create(destFile.c_str(), newStorageSize, nullptr); + storage::FileStorage destStorage(destFile.c_str()); + ktx::KTX::write(destStorage.mutableData(), newStorageSize, ktx->_header, ktx->_images); +} + +#if DEV_BUILD +const QDir SOURCE_FOLDER{ PathUtils::projectRootPath() + "/interface/resources/meshes/mannequin" }; +const QDir DEST_FOLDER{ PathUtils::projectRootPath() + "/interface/resources/meshes/mannequin/+gles" }; +#else +const QDir SOURCE_FOLDER{ PathUtils::resourcesPath() + "/interface/resources/meshes/mannequin" }; +const QDir DEST_FOLDER{ PathUtils::resourcesPath() + "/interface/resources/meshes/mannequin/+gles" }; +#endif + + +void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { +#ifdef Q_OS_WIN + OutputDebugStringA(message.toStdString().c_str()); + OutputDebugStringA("\n"); +#endif + std::cout << message.toStdString() << std::endl; +} + +void processKtxFile(const QFileInfo& inputFileInfo) { + const QString inputFileName = inputFileInfo.absoluteFilePath(); + const QString compressedFileName = DEST_FOLDER.absoluteFilePath(inputFileInfo.fileName()); + const QString finalFilename = compressedFileName + ".new.ktx"; + if (QFileInfo(finalFilename).exists()) { + return; + } + qDebug() << inputFileName; + qDebug() << compressedFileName; + auto uncomrpessedKtx = ktx::KTX::create(std::make_shared(compressedFileName)); + if (!uncomrpessedKtx) { + throw std::runtime_error("Unable to load texture using hifi::ktx"); + } + + auto compressedKtx = ktx::KTX::create(std::make_shared(inputFileName)); + if (!compressedKtx) { + throw std::runtime_error("Unable to load texture using hifi::ktx"); + } + + + auto outputKtx = ktx::KTX::create(uncomrpessedKtx->getHeader(), uncomrpessedKtx->_images, compressedKtx->_keyValues); + auto outputStorage = outputKtx->getStorage(); + + storage::FileStorage::create(finalFilename, outputStorage->size(), outputStorage->data()); +} + +void scanDir(const QDir& dir) { + + auto entries = dir.entryInfoList(); + for (const auto& entry : entries) { + if (entry.isDir()) { + scanDir(QDir(entry.absoluteFilePath())); + } else { + qDebug() << entry.absoluteFilePath(); + } + } +} + +int main(int argc, char** argv) { + qInstallMessageHandler(messageHandler); + { + QDir destFolder(DEST_FOLDER); + if (!destFolder.exists() && !destFolder.mkpath(".")) { + throw std::runtime_error("failed to create output directory"); + } + for (const auto ktxFile : SOURCE_FOLDER.entryInfoList(QStringList() << "*.ktx")) { + processKtxFile(ktxFile); + } + qDebug() << "Done"; + } + + return 0; +}