Merge branch 'android_new' into android

This commit is contained in:
Brad Davis 2018-01-23 14:46:23 -08:00
commit 4d6538edf7
44 changed files with 1071 additions and 169 deletions

View file

@ -0,0 +1,15 @@
{
"name": "TouchscreenVirtualPad to Actions",
"channels": [
{ "from": "TouchscreenVirtualPad.LY", "when": "Application.CameraFirstPerson", "filters": { "type": "deadZone", "min": 0.05 }, "to": "Actions.TranslateZ" },
{ "from": "TouchscreenVirtualPad.LX", "when": "Application.CameraFirstPerson", "filters": { "type": "deadZone", "min": 0.05 }, "to": "Actions.TranslateX" },
{ "from": "TouchscreenVirtualPad.RX", "when": "Application.CameraFirstPerson", "filters": { "type": "deadZone", "min": 0.05 }, "to": "Actions.Yaw" },
{ "from": "TouchscreenVirtualPad.RY",
"when": "Application.CameraFirstPerson",
"to": "Actions.Pitch"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 645 KiB

Binary file not shown.

View file

@ -69,6 +69,7 @@
#include <AudioInjectorManager.h>
#include <AvatarBookmarks.h>
#include <CursorManager.h>
#include <VirtualPadManager.h>
#include <DebugDraw.h>
#include <DeferredLightingEffect.h>
#include <EntityScriptClient.h>
@ -693,6 +694,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
DependencyManager::set<PointerScriptingInterface>();
DependencyManager::set<PickScriptingInterface>();
DependencyManager::set<Cursor::Manager>();
DependencyManager::set<VirtualPad::Manager>();
DependencyManager::set<DesktopPreviewProvider>();
DependencyManager::set<AccountManager>(std::bind(&Application::getUserAgent, qApp));
DependencyManager::set<StatTracker>();
@ -1429,12 +1431,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
return DependencyManager::get<OffscreenUi>()->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());
}
// force the model the look at the correct directory (weird order of operations issue)
scriptEngines->setScriptsLocation(scriptEngines->getScriptsLocation());
@ -2503,6 +2508,9 @@ void Application::initializeUi() {
if (TouchscreenDevice::NAME == inputPlugin->getName()) {
_touchscreenDevice = std::dynamic_pointer_cast<TouchscreenDevice>(inputPlugin);
}
if (TouchscreenVirtualPadDevice::NAME == inputPlugin->getName()) {
_touchscreenVirtualPadDevice = std::dynamic_pointer_cast<TouchscreenVirtualPadDevice>(inputPlugin);
}
}
_window->setMenuBar(new Menu());
@ -3591,6 +3599,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) {
@ -3612,6 +3623,9 @@ void Application::touchBeginEvent(QTouchEvent* event) {
if (_touchscreenDevice && _touchscreenDevice->isActive()) {
_touchscreenDevice->touchBeginEvent(event);
}
if (_touchscreenVirtualPadDevice && _touchscreenVirtualPadDevice->isActive()) {
_touchscreenVirtualPadDevice->touchBeginEvent(event);
}
}
@ -3632,7 +3646,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..
}
@ -3640,6 +3656,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 {

View file

@ -33,6 +33,7 @@
#include <FileScriptingInterface.h>
#include <input-plugins/KeyboardMouseDevice.h>
#include <input-plugins/TouchscreenDevice.h>
#include <input-plugins/TouchscreenVirtualPadDevice.h>
#include <OctreeQuery.h>
#include <PhysicalEntitySimulation.h>
#include <PhysicsEngine.h>
@ -545,6 +546,7 @@ private:
std::shared_ptr<controller::StateController> _applicationStateDevice; // Default ApplicationDevice reflecting the state of different properties of the session
std::shared_ptr<KeyboardMouseDevice> _keyboardMouseDevice; // Default input device, the good old keyboard mouse and maybe touchpad
std::shared_ptr<TouchscreenDevice> _touchscreenDevice; // the good old touchscreen
std::shared_ptr<TouchscreenVirtualPadDevice> _touchscreenVirtualPadDevice;
SimpleMovingAverage _avatarSimsPerSecond {10};
int _avatarSimsPerSecondReport {0};
quint64 _lastAvatarSimsPerSecondUpdate {0};

View file

@ -16,6 +16,7 @@
#include <plugins/PluginManager.h>
#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)); }

View file

@ -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);

View file

@ -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 <mutex>
@ -14,11 +16,60 @@
#include <QtWidgets/QAction>
#include <ui-plugins/PluginContainer.h>
#include <PathUtils.h>
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();
_container->addMenuItem(PluginType::DISPLAY_PLUGIN, MENU_PATH(), FULLSCREEN,
@ -33,6 +84,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<CompositorHelper>()->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<CompositorHelper>()->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 {

View file

@ -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;
};

View file

@ -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());

View file

@ -92,6 +92,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; }

View file

@ -14,9 +14,12 @@
#include <QDebug>
#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);
}

View file

@ -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")

View file

@ -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
};

View file

@ -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 <QtGui/QTouchEvent>
#include <QGestureEvent>
#include <QGuiApplication>
#include <QWindow>
#include <QScreen>
#include <controllers/UserInputMapper.h>
#include <PathUtils.h>
#include <NumericalConstants.h>
#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<controller::UserInputMapper>();
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<QTouchEvent::TouchPoint>& tPoints = event->touchPoints();
QVector<glm::vec2> 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<QTouchEvent::TouchPoint>& 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<QPinchGesture*>(gesture);
_pinchScale = pinch->totalScaleFactor();
}
}
controller::Input::NamedVector TouchscreenVirtualPadDevice::InputDevice::getAvailableInputs() const {
using namespace controller;
QVector<Input::NamedPair> 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;
}

View file

@ -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 <controllers/InputDevice.h>
#include "InputPlugin.h"
#include <QtGui/qtouchdevice.h>
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<InputDevice>& 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> _inputDevice { std::make_shared<InputDevice>() };
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

View file

@ -37,7 +37,7 @@
#include <NumericalConstants.h>
#include <shared/NsightHelpers.h>
#include <shared/FileUtils.h>
#include <Finally.h>
#include <Profile.h>
@ -50,10 +50,8 @@ 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" };
#endif
static const QString RESOURCE_SCHEME = "resource";
static const QUrl SPECTATOR_CAMERA_FRAME_URL("resource://spectatorCameraFrame");
@ -62,9 +60,12 @@ static const QUrl HMD_PREVIEW_FRAME_URL("resource://hmdPreviewFrame");
static const float SKYBOX_LOAD_PRIORITY { 10.0f }; // Make sure skybox loads first
static const float HIGH_MIPS_LOAD_PRIORITY { 9.0f }; // Make sure high mips loads after skybox but before models
#pragma optimize("", off)
TextureCache::TextureCache() {
#if !defined(DISABLE_KTX_CACHE)
_ktxCache->initialize();
#if defined(DISABLE_KTX_CACHE)
_ktxCache->wipe();
#endif
setUnusedResourceCacheSize(0);
setObjectName("TextureCache");
@ -294,6 +295,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),
@ -387,6 +392,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<NetworkTexture*>(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() } });
@ -435,6 +455,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<storage::FileStorage>(path);
std::unique_ptr<ktx::KTX> ktxFile;
if (storage) {
ktxFile = ktx::KTX::create(storage);
}
std::shared_ptr<ktx::KTXDescriptor> ktxDescriptor;
if (ktxFile) {
ktxDescriptor = std::make_shared<ktx::KTXDescriptor>(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<const char*>(found->_value.data()), gpu::SOURCE_HASH_BYTES);
hash = binaryHash.toHex().toStdString();
}
auto textureCache = DependencyManager::get<TextureCache>();
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();
@ -750,7 +838,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) {
@ -763,9 +850,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";
@ -778,7 +864,6 @@ void NetworkTexture::handleFinishedInitialLoad() {
// Move ktx to file
const char* data = reinterpret_cast<const char*>(memKtx->_storage->data());
#if !defined(DISABLE_KTX_CACHE)
size_t length = memKtx->_storage->size();
cache::FilePointer file;
auto& ktxCache = textureCache->_ktxCache;
@ -790,14 +875,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;
@ -940,7 +1022,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);
@ -953,7 +1034,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.
@ -989,7 +1069,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
@ -1006,7 +1085,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

View file

@ -70,6 +70,7 @@ public slots:
protected:
void makeRequest() override;
void makeLocalRequest();
virtual bool isCacheable() const override { return _loaded; }
@ -194,12 +195,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<cache::FileCache> _ktxCache { std::make_shared<KTXCache>(KTX_DIRNAME, KTX_EXT) };
#endif
// Map from image hashes to texture weak pointers
std::unordered_map<std::string, std::weak_ptr<gpu::Texture>> _texturesByHashes;
std::mutex _texturesByHashesMutex;

View file

@ -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://dev-android"), LookupTrigger::StartupFromSettings);
#else
if (lookupString.isEmpty()) {
handleUrl(currentAddressHandle.get(), LookupTrigger::StartupFromSettings);
} else {
handleUrl(lookupString, LookupTrigger::StartupFromSettings);
}
#endif
}
void AddressManager::goBack() {

View file

@ -18,6 +18,7 @@
#include <StatTracker.h>
#include <shared/FileUtils.h>
#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;

View file

@ -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;
}

View file

@ -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);
}
};
}

View file

@ -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,11 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu
color += directionalDiffuse;
color += directionalSpecular;
// 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 +171,7 @@ vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscur
<@include Haze.slh@>
<@func declareEvalGlobalLightingAlphaBlended()@>
@ -198,6 +202,46 @@ 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
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@>

View file

@ -46,7 +46,7 @@ vec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface) {
float levels = getLightAmbientMapNumMips(ambient);
float m = 12.0 / (1.0+11.0*surface.roughness);
float lod = levels - m;
lod = max(lod, 0);
lod = max(lod, 0.0);
specularLight = evalSkyboxLight(lightDir, lod).xyz;
}
<@endif@>

View file

@ -64,6 +64,7 @@
#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"
@ -451,6 +452,7 @@ void initForwardPipelines(ShapePlumber& plumber, const render::ShapePipeline::Ba
auto modelSpecularMapPixel = gpu::Shader::createPixel(std::string(forward_model_specular_map_frag));
auto modelNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(forward_model_normal_specular_map_frag));
auto modelNormalMapFadePixel = gpu::Shader::createPixel(std::string(model_normal_map_fade_frag));
auto modelTranslucentPixel = gpu::Shader::createPixel(std::string(forward_model_translucent_frag));
using Key = render::ShapeKey;
auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3, _4, _5);
@ -486,7 +488,25 @@ void initForwardPipelines(ShapePlumber& plumber, const render::ShapePipeline::Ba
addPipeline(
Key::Builder().withMaterial().withSkinned().withTangents().withFade(),
skinModelNormalMapFadeVertex, modelNormalMapFadePixel, batchSetter, itemSetter, nullptr, nullptr);
// Translucents
addPipeline(
Key::Builder().withMaterial().withTranslucent(),
modelVertex, modelTranslucentPixel, batchSetter, itemSetter, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withTranslucent().withTangents(),
modelNormalMapVertex, modelTranslucentPixel, batchSetter, itemSetter, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withTranslucent().withSpecular(),
modelVertex, modelTranslucentPixel, batchSetter, itemSetter, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withTranslucent().withTangents().withSpecular(),
modelNormalMapVertex, modelTranslucentPixel, batchSetter, itemSetter, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents(),
skinModelNormalMapVertex, modelTranslucentPixel, batchSetter, itemSetter, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withSkinned().withTranslucent(),
skinModelVertex, modelTranslucentPixel, batchSetter, itemSetter, nullptr, nullptr);
}
void addPlumberPipeline(ShapePlumber& plumber,

View file

@ -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));
}

View file

@ -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

View file

@ -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);

View file

@ -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<Manager> instance = DependencyManager::get<VirtualPad::Manager>();
return *instance;
}
void Manager::enable(bool enable) {
_enabled = enable;
}
bool Manager::isEnabled() {
return _enabled;
}
Instance* Manager::getLeftVirtualPad() {
return &_leftVPadInstance;
}
}

View file

@ -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 <stdint.h>
#include <DependencyManager.h>
#include <GLMHelpers.h>
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;
};
}

View file

@ -12,7 +12,8 @@
//
var DEFAULT_SCRIPTS_COMBINED = [
"system/progress.js"/*,
"system/progress.js",
"system/touchscreenvirtualpad.js"/*,
"system/away.js",
"system/controllers/controllerDisplayManager.js",
"system/controllers/handControllerGrabAndroid.js",

View file

@ -0,0 +1,21 @@
"use strict";
//
// android.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

View file

@ -12,6 +12,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")

View file

@ -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()

209
tools/ktx-tool/src/main.cpp Normal file
View file

@ -0,0 +1,209 @@
#include <unordered_map>
#include <memory>
#include <cstdio>
#include <string>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <gli/gli.hpp>
#include <gli/convert.hpp>
#include <gli/generate_mipmaps.hpp>
#include <gli/load.hpp>
#include <gli/save.hpp>
#include <QtGlobal>
#include <QtCore/QTime>
#include <QtCore/QTimer>
#include <QtCore/QDir>
#include <QtCore/QElapsedTimer>
#include <QtCore/QFile>
#include <QtCore/QLoggingCategory>
#include <QtCore/QResource>
#include <QtGui/QResizeEvent>
#include <QtGui/QWindow>
#include <QtGui/QGuiApplication>
#include <QtGui/QImage>
#include <gl/Config.h>
#include <gpu/Context.h>
#include <gpu/Batch.h>
#include <gpu/Stream.h>
#include <GLMHelpers.h>
#include <PathUtils.h>
#include <NumericalConstants.h>
#include <PerfStat.h>
#include <PathUtils.h>
#include <ViewFrustum.h>
#include <gpu/Pipeline.h>
#include <gpu/Context.h>
#include <gpu/Texture.h>
#include <ktx/KTX.h>
void stripKtxKeyValues(const std::string& sourceFile, const std::string& destFile) {
auto sourceStorage = std::make_shared<storage::FileStorage>(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());
auto writtenSize = ktx::KTX::write(destStorage.mutableData(), newStorageSize, ktx->_header, ktx->_images);
}
const QDir SOURCE_FOLDER{ PathUtils::projectRootPath() + "/interface/resources/meshes/mannequin" };
const QDir DEST_FOLDER{ PathUtils::projectRootPath() + "/interface/resources/meshes/mannequin/+gles" };
const gli::gl GL(gli::gl::PROFILE_GL33);
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;
}
static inline glm::uvec2 evalMipDimension(uint32_t mipLevel, const glm::uvec2& dims) {
return glm::uvec2{
std::max(dims.x >> mipLevel, 1U),
std::max(dims.y >> mipLevel, 1U),
};
}
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<storage::FileStorage>(compressedFileName));
if (!uncomrpessedKtx) {
throw std::runtime_error("Unable to load texture using hifi::ktx");
}
auto compressedKtx = ktx::KTX::create(std::make_shared<storage::FileStorage>(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());
#if 0
const auto& header = inputKtx->getHeader();
detexTexture **input_textures;
int nu_levels;
if (!detexLoadTextureFileWithMipmaps(inputFileName.toStdString().c_str(), 32, &input_textures, &nu_levels)) {
return;
//throw std::runtime_error(detexGetErrorMessage());
}
switch (header.glInternalFormat) {
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
outputHeader.glFormat = GL_RGBA;
outputHeader.glInternalFormat = GL_RGBA8;
break;
case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
outputHeader.glFormat = GL_RG;
outputHeader.glInternalFormat = GL_RG8;
qWarning() << "Unsupported";
return;
break;
case GL_COMPRESSED_RED_RGTC1_EXT:
outputHeader.glFormat = GL_RED;
outputHeader.glInternalFormat = GL_R8;
qWarning() << "Unsupported";
return;
break;
default:
qWarning() << "Unsupported";
return;
}
auto outputKtx = ktx::KTX::createBare(outputHeader, ktx->_keyValues);
auto outputDescriptor = outputKtx->toDescriptor();
auto outputStorage = outputKtx->getStorage();
auto outputPointer = outputStorage->mutableData();
auto outputSize = outputStorage->size();
glm::uvec2 dimensions{ header.pixelWidth, header.pixelHeight };
for (uint16_t mip = 0; mip < header.numberOfMipmapLevels; ++mip) {
auto mipDimensions = evalMipDimension(mip, dimensions);
for (uint8_t face = 0; face < header.numberOfFaces; ++face) {
auto faceSize = outputDescriptor.getMipFaceTexelsSize(mip, face);
auto faceOffset = outputDescriptor.getMipFaceTexelsOffset(mip, face);
assert(faceOffset + faceSize <= outputSize);
auto mipFace = ktx->getMipFaceTexelsData(mip, face);
auto outputMipFace = outputKtx->getMipFaceTexelsData();
if (header.glInternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) {
BlockDecompressImageDXT5(mipDimensions.x, mipDimensions.y, mipFace->data(), (unsigned long*)(outputPointer + faceOffset));
} else if (header.glInternalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT) {
BlockDecompressImageDXT1(mipDimensions.x, mipDimensions.y, mipFace->data(), (unsigned long*)(outputPointer + faceOffset));
} else {
qWarning() << "Unsupported";
return;
}
}
}
storage::FileStorage::create(outputFileName, outputStorage->size(), outputStorage->data());
#endif
//if (gliTexture.empty()) {
// throw std::runtime_error("Unable to load texture using GLI");
//}
//gli::texture2d gliTextureConverted = gli::convert(gliTexture, gli::FORMAT_RGBA8_UNORM_PACK8);
}
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;
}