mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 18:16:08 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi
This commit is contained in:
commit
054e12a315
39 changed files with 1120 additions and 829 deletions
|
@ -18,4 +18,5 @@ Script.load("users.js");
|
|||
Script.load("grab.js");
|
||||
Script.load("pointer.js");
|
||||
Script.load("directory.js");
|
||||
Script.load("mouseLook.js");
|
||||
Script.load("dialTone.js");
|
||||
|
|
200
examples/mouseLook.js
Normal file
200
examples/mouseLook.js
Normal file
|
@ -0,0 +1,200 @@
|
|||
//
|
||||
// mouseLook.js
|
||||
// examples
|
||||
//
|
||||
// Created by Sam Gondelman 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
|
||||
//
|
||||
|
||||
var lastX = Window.getCursorPositionX();
|
||||
var lastY = Window.getCursorPositionY();
|
||||
var yawFromMouse = 0;
|
||||
var pitchFromMouse = 0;
|
||||
|
||||
var yawSpeed = 0;
|
||||
var pitchSpeed = 0;
|
||||
|
||||
var DEFAULT_PARAMETERS = {
|
||||
MOUSE_YAW_SCALE: -0.125,
|
||||
MOUSE_PITCH_SCALE: -0.125,
|
||||
MOUSE_SENSITIVITY: 0.5,
|
||||
|
||||
// Damping frequency, adjust to change mouse look behavior
|
||||
W: 10,
|
||||
}
|
||||
|
||||
var movementParameters = DEFAULT_PARAMETERS;
|
||||
|
||||
var mouseLook = (function () {
|
||||
|
||||
var BUTTON_WIDTH = 50,
|
||||
BUTTON_HEIGHT = 50,
|
||||
BUTTON_ALPHA = 0.9,
|
||||
BUTTON_MARGIN = 8,
|
||||
active = false,
|
||||
keyboardID = 0;
|
||||
|
||||
function onKeyPressEvent(event) {
|
||||
if (event.text == 'm' && event.isMeta) {
|
||||
active = !active;
|
||||
updateMapping();
|
||||
}
|
||||
}
|
||||
|
||||
function findInput(name) {
|
||||
var availableInputs = Controller.getAvailableInputs(keyboardID);
|
||||
for (i = 0; i < availableInputs.length; i++) {
|
||||
if (availableInputs[i].inputName == name) {
|
||||
return availableInputs[i].input;
|
||||
}
|
||||
}
|
||||
// If the input isn't found, it will default to the first available input
|
||||
return availableInputs[0].input;
|
||||
}
|
||||
|
||||
function findAction(name) {
|
||||
var actions = Controller.getAllActions();
|
||||
for (var i = 0; i < actions.length; i++) {
|
||||
if (actions[i].actionName == name) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
// If the action isn't found, it will default to the first available action
|
||||
return 0;
|
||||
}
|
||||
|
||||
function updateMapping() {
|
||||
if (keyboardID != 0) {
|
||||
if (active) {
|
||||
// Turn mouselook on
|
||||
yawFromMouse = 0;
|
||||
pitchFromMouse = 0;
|
||||
yawSpeed = 0;
|
||||
pitchSpeed = 0;
|
||||
|
||||
var a = findInput("A").channel;
|
||||
var d = findInput("D").channel;
|
||||
var left = findInput("Left").channel;
|
||||
var right = findInput("Right").channel;
|
||||
var shift = findInput("Shift").channel;
|
||||
|
||||
for (var i = findAction("YAW_LEFT"); i <= findAction("YAW_RIGHT"); i++) {
|
||||
var inputChannels = Controller.getAllActions()[i].inputChannels;
|
||||
for (var j = 0; j < inputChannels.length; j++) {
|
||||
var inputChannel = inputChannels[j];
|
||||
// make a, d, left, and right strafe
|
||||
if ((inputChannel.input.channel == a || inputChannel.input.channel == left) && inputChannel.modifier.device == 0) {
|
||||
Controller.removeInputChannel(inputChannel);
|
||||
inputChannel.action = findAction("LATERAL_LEFT");
|
||||
Controller.addInputChannel(inputChannel);
|
||||
} else if ((inputChannel.input.channel == d || inputChannel.input.channel == right) && inputChannel.modifier.device == 0) {
|
||||
Controller.removeInputChannel(inputChannel);
|
||||
inputChannel.action = findAction("LATERAL_RIGHT");
|
||||
Controller.addInputChannel(inputChannel);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var i = findAction("LATERAL_LEFT"); i <= findAction("LATERAL_RIGHT"); i++) {
|
||||
var inputChannels = Controller.getAllActions()[i].inputChannels;
|
||||
for (var j = 0; j < inputChannels.length; j++) {
|
||||
var inputChannel = inputChannels[j];
|
||||
// make shift + a/d/left/right change yaw/pitch
|
||||
if ((inputChannel.input.channel == a || inputChannel.input.channel == left) && inputChannel.modifier.channel == shift) {
|
||||
Controller.removeInputChannel(inputChannel);
|
||||
inputChannel.action = findAction("YAW_LEFT");
|
||||
Controller.addInputChannel(inputChannel);
|
||||
} else if ((inputChannel.input.channel == d || inputChannel.input.channel == right) && inputChannel.modifier.channel == shift) {
|
||||
Controller.removeInputChannel(inputChannel);
|
||||
inputChannel.action = findAction("YAW_RIGHT");
|
||||
Controller.addInputChannel(inputChannel);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Controller.resetDevice(keyboardID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onScriptUpdate(dt) {
|
||||
if (active && Window.hasFocus()) {
|
||||
var x = Window.getCursorPositionX();
|
||||
// I'm not sure why this + 0.5 is necessary?
|
||||
var y = Window.getCursorPositionY() + 0.5;
|
||||
|
||||
yawFromMouse += ((x - lastX) * movementParameters.MOUSE_YAW_SCALE * movementParameters.MOUSE_SENSITIVITY);
|
||||
pitchFromMouse += ((y - lastY) * movementParameters.MOUSE_PITCH_SCALE * movementParameters.MOUSE_SENSITIVITY);
|
||||
pitchFromMouse = Math.max(-180, Math.min(180, pitchFromMouse));
|
||||
|
||||
resetCursorPosition();
|
||||
|
||||
// Here we use a linear damping model - http://en.wikipedia.org/wiki/Damping#Linear_damping
|
||||
// Because we are using a critically damped model (no oscillation), ζ = 1 and
|
||||
// so we derive the formula: acceleration = -(2 * w0 * v) - (w0^2 * x)
|
||||
var W = movementParameters.W;
|
||||
yawAccel = (W * W * yawFromMouse) - (2 * W * yawSpeed);
|
||||
pitchAccel = (W * W * pitchFromMouse) - (2 * W * pitchSpeed);
|
||||
|
||||
yawSpeed += yawAccel * dt;
|
||||
var yawMove = yawSpeed * dt;
|
||||
var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees( { x: 0, y: yawMove, z: 0 } ));
|
||||
MyAvatar.orientation = newOrientation;
|
||||
yawFromMouse -= yawMove;
|
||||
|
||||
pitchSpeed += pitchAccel * dt;
|
||||
var pitchMove = pitchSpeed * dt;
|
||||
var newPitch = MyAvatar.headPitch + pitchMove;
|
||||
MyAvatar.headPitch = newPitch;
|
||||
pitchFromMouse -= pitchMove;
|
||||
}
|
||||
}
|
||||
|
||||
function resetCursorPosition() {
|
||||
var newX = Window.x + Window.innerWidth / 2.0;
|
||||
var newY = Window.y + Window.innerHeight / 2.0;
|
||||
Window.setCursorPosition(newX, newY);
|
||||
lastX = newX;
|
||||
lastY = newY;
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
keyboardID = Controller.findDevice("Keyboard");
|
||||
|
||||
Controller.keyPressEvent.connect(onKeyPressEvent);
|
||||
|
||||
Menu.menuItemEvent.connect(handleMenuEvent);
|
||||
|
||||
Script.update.connect(onScriptUpdate);
|
||||
}
|
||||
|
||||
function setupMenu() {
|
||||
Menu.addMenuItem({ menuName: "View", menuItemName: "Mouselook Mode", shortcutKey: "META+M",
|
||||
afterItem: "Mirror", isCheckable: true, isChecked: false });
|
||||
}
|
||||
|
||||
setupMenu();
|
||||
|
||||
function cleanupMenu() {
|
||||
Menu.removeMenuItem("View", "Mouselook Mode");
|
||||
}
|
||||
|
||||
function handleMenuEvent(menuItem) {
|
||||
if (menuItem == "Mouselook Mode") {
|
||||
active = !active;
|
||||
updateMapping();
|
||||
}
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
if (keyboardID != 0) {
|
||||
Controller.resetDevice(keyboardID);
|
||||
}
|
||||
cleanupMenu();
|
||||
}
|
||||
|
||||
setUp();
|
||||
Script.scriptEnding.connect(tearDown);
|
||||
}());
|
|
@ -22,10 +22,12 @@ Script.setTimeout(function() {
|
|||
type: "Model",
|
||||
modelURL: "https://hifi-public.s3.amazonaws.com/eric/models/stick.fbx",
|
||||
compoundShapeURL: "https://hifi-public.s3.amazonaws.com/eric/models/stick.obj",
|
||||
dimensions: {x: .11, y: .11, z: .59},
|
||||
dimensions: {x: .11, y: .11, z: 1.0},
|
||||
position: MyAvatar.getRightPalmPosition(), // initial position doesn't matter, as long as it's close
|
||||
rotation: MyAvatar.orientation,
|
||||
damping: .1,
|
||||
collisionSoundURL: "http://public.highfidelity.io/sounds/Collisions-hitsandslaps/67LCollision07.wav",
|
||||
restitution: 0.01,
|
||||
collisionsWillMove: true
|
||||
});
|
||||
actionID = Entities.addAction("hold", stickID, {relativePosition: {x: 0.0, y: 0.0, z: -0.9},
|
||||
|
|
|
@ -120,6 +120,23 @@ Slider = function(x,y,width,thumbSize) {
|
|||
|
||||
this.onValueChanged = function(value) {};
|
||||
|
||||
this.setMaxValue = function(maxValue) {
|
||||
if (this.maxValue == maxValue) {
|
||||
return;
|
||||
}
|
||||
var currentVal = this.getValue();
|
||||
this.maxValue = maxValue;
|
||||
this.setValue(currentVal);
|
||||
}
|
||||
this.setMinValue = function(minValue) {
|
||||
if (this.minValue == minValue) {
|
||||
return;
|
||||
}
|
||||
var currentVal = this.getValue();
|
||||
this.minValue = minValue;
|
||||
this.setValue(currentVal);
|
||||
}
|
||||
|
||||
this.destroy = function() {
|
||||
Overlays.deleteOverlay(this.background);
|
||||
Overlays.deleteOverlay(this.thumb);
|
||||
|
@ -613,6 +630,14 @@ Panel = function(x, y) {
|
|||
return null;
|
||||
}
|
||||
|
||||
this.getWidget = function(name) {
|
||||
var item = this.items[name];
|
||||
if (item != null) {
|
||||
return item.widget;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
this.update = function(name) {
|
||||
var item = this.items[name];
|
||||
if (item != null) {
|
||||
|
|
|
@ -10,25 +10,7 @@
|
|||
|
||||
Script.include("cookies.js");
|
||||
|
||||
var panel = new Panel(10, 400);
|
||||
|
||||
panel.newCheckbox("Enable Cull Opaque",
|
||||
function(value) { Scene.setEngineCullOpaque((value != 0)); },
|
||||
function() { return Scene.doEngineCullOpaque(); },
|
||||
function(value) { return (value); }
|
||||
);
|
||||
|
||||
panel.newCheckbox("Enable Sort Opaque",
|
||||
function(value) { Scene.setEngineSortOpaque((value != 0)); },
|
||||
function() { return Scene.doEngineSortOpaque(); },
|
||||
function(value) { return (value); }
|
||||
);
|
||||
|
||||
panel.newCheckbox("Enable Render Opaque",
|
||||
function(value) { Scene.setEngineRenderOpaque((value != 0)); },
|
||||
function() { return Scene.doEngineRenderOpaque(); },
|
||||
function(value) { return (value); }
|
||||
);
|
||||
var panel = new Panel(10, 800);
|
||||
|
||||
panel.newSlider("Num Feed Opaques", 0, 1000,
|
||||
function(value) { },
|
||||
|
@ -48,24 +30,6 @@ panel.newSlider("Max Drawn Opaques", -1, 1000,
|
|||
function(value) { return (value); }
|
||||
);
|
||||
|
||||
panel.newCheckbox("Enable Cull Transparent",
|
||||
function(value) { Scene.setEngineCullTransparent((value != 0)); },
|
||||
function() { return Scene.doEngineCullTransparent(); },
|
||||
function(value) { return (value); }
|
||||
);
|
||||
|
||||
panel.newCheckbox("Enable Sort Transparent",
|
||||
function(value) { Scene.setEngineSortTransparent((value != 0)); },
|
||||
function() { return Scene.doEngineSortTransparent(); },
|
||||
function(value) { return (value); }
|
||||
);
|
||||
|
||||
panel.newCheckbox("Enable Render Transparent",
|
||||
function(value) { Scene.setEngineRenderTransparent((value != 0)); },
|
||||
function() { return Scene.doEngineRenderTransparent(); },
|
||||
function(value) { return (value); }
|
||||
);
|
||||
|
||||
panel.newSlider("Num Feed Transparents", 0, 100,
|
||||
function(value) { },
|
||||
function() { return Scene.getEngineNumFeedTransparentItems(); },
|
||||
|
@ -84,13 +48,52 @@ panel.newSlider("Max Drawn Transparents", -1, 100,
|
|||
function(value) { return (value); }
|
||||
);
|
||||
|
||||
panel.newSlider("Num Feed Overlay3Ds", 0, 100,
|
||||
function(value) { },
|
||||
function() { return Scene.getEngineNumFeedOverlay3DItems(); },
|
||||
function(value) { return (value); }
|
||||
);
|
||||
|
||||
panel.newSlider("Num Drawn Overlay3Ds", 0, 100,
|
||||
function(value) { },
|
||||
function() { return Scene.getEngineNumDrawnOverlay3DItems(); },
|
||||
function(value) { return (value); }
|
||||
);
|
||||
|
||||
panel.newSlider("Max Drawn Overlay3Ds", -1, 100,
|
||||
function(value) { Scene.setEngineMaxDrawnOverlay3DItems(value); },
|
||||
function() { return Scene.getEngineMaxDrawnOverlay3DItems(); },
|
||||
function(value) { return (value); }
|
||||
);
|
||||
|
||||
var tickTackPeriod = 500;
|
||||
|
||||
function updateCounters() {
|
||||
panel.set("Num Feed Opaques", panel.get("Num Feed Opaques"));
|
||||
panel.set("Num Drawn Opaques", panel.get("Num Drawn Opaques"));
|
||||
panel.set("Num Feed Transparents", panel.get("Num Feed Transparents"));
|
||||
panel.set("Num Drawn Transparents", panel.get("Num Drawn Transparents"));
|
||||
var numFeedOpaques = panel.get("Num Feed Opaques");
|
||||
var numFeedTransparents = panel.get("Num Feed Transparents");
|
||||
var numFeedOverlay3Ds = panel.get("Num Feed Overlay3Ds");
|
||||
|
||||
panel.set("Num Feed Opaques", numFeedOpaques);
|
||||
panel.set("Num Drawn Opaques", panel.get("Num Drawn Opaques"));
|
||||
panel.set("Num Feed Transparents", numFeedTransparents);
|
||||
panel.set("Num Drawn Transparents", panel.get("Num Drawn Transparents"));
|
||||
panel.set("Num Feed Overlay3Ds", numFeedOverlay3Ds);
|
||||
panel.set("Num Drawn Overlay3Ds", panel.get("Num Drawn Overlay3Ds"));
|
||||
|
||||
var numMax = Math.max(numFeedOpaques * 1.2, 1);
|
||||
panel.getWidget("Num Feed Opaques").setMaxValue(numMax);
|
||||
panel.getWidget("Num Drawn Opaques").setMaxValue(numMax);
|
||||
panel.getWidget("Max Drawn Opaques").setMaxValue(numMax);
|
||||
|
||||
numMax = Math.max(numFeedTransparents * 1.2, 1);
|
||||
panel.getWidget("Num Feed Transparents").setMaxValue(numMax);
|
||||
panel.getWidget("Num Drawn Transparents").setMaxValue(numMax);
|
||||
panel.getWidget("Max Drawn Transparents").setMaxValue(numMax);
|
||||
|
||||
numMax = Math.max(numFeedOverlay3Ds * 1.2, 1);
|
||||
panel.getWidget("Num Feed Overlay3Ds").setMaxValue(numMax);
|
||||
panel.getWidget("Num Drawn Overlay3Ds").setMaxValue(numMax);
|
||||
panel.getWidget("Max Drawn Overlay3Ds").setMaxValue(numMax);
|
||||
}
|
||||
Script.setInterval(updateCounters, tickTackPeriod);
|
||||
|
||||
|
|
|
@ -909,13 +909,18 @@ void Application::paintGL() {
|
|||
}
|
||||
|
||||
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
||||
_myCamera.setPosition(_myAvatar->getDefaultEyePosition() +
|
||||
_myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, 1.0f) * _myAvatar->getBoomLength() * _myAvatar->getScale());
|
||||
if (OculusManager::isConnected()) {
|
||||
_myCamera.setRotation(_myAvatar->getWorldAlignedOrientation());
|
||||
} else {
|
||||
_myCamera.setRotation(_myAvatar->getHead()->getOrientation());
|
||||
}
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::CenterPlayerInView)) {
|
||||
_myCamera.setPosition(_myAvatar->getDefaultEyePosition() +
|
||||
_myCamera.getRotation() * glm::vec3(0.0f, 0.0f, 1.0f) * _myAvatar->getBoomLength() * _myAvatar->getScale());
|
||||
} else {
|
||||
_myCamera.setPosition(_myAvatar->getDefaultEyePosition() +
|
||||
_myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, 1.0f) * _myAvatar->getBoomLength() * _myAvatar->getScale());
|
||||
}
|
||||
|
||||
} else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
||||
_myCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
|
||||
|
@ -2418,6 +2423,12 @@ void Application::cameraMenuChanged() {
|
|||
}
|
||||
}
|
||||
|
||||
void Application::rotationModeChanged() {
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::CenterPlayerInView)) {
|
||||
_myAvatar->setHeadPitch(0);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::updateCamera(float deltaTime) {
|
||||
PerformanceTimer perfTimer("updateCamera");
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
|
@ -3530,6 +3541,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
|
|||
|
||||
renderContext._maxDrawnOpaqueItems = sceneInterface->getEngineMaxDrawnOpaqueItems();
|
||||
renderContext._maxDrawnTransparentItems = sceneInterface->getEngineMaxDrawnTransparentItems();
|
||||
renderContext._maxDrawnOverlay3DItems = sceneInterface->getEngineMaxDrawnOverlay3DItems();
|
||||
|
||||
renderArgs->_shouldRender = LODManager::shouldRender;
|
||||
|
||||
|
@ -3546,7 +3558,9 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
|
|||
|
||||
sceneInterface->setEngineFeedTransparentItems(engineRC->_numFeedTransparentItems);
|
||||
sceneInterface->setEngineDrawnTransparentItems(engineRC->_numDrawnTransparentItems);
|
||||
|
||||
|
||||
sceneInterface->setEngineFeedOverlay3DItems(engineRC->_numFeedOverlay3DItems);
|
||||
sceneInterface->setEngineDrawnOverlay3DItems(engineRC->_numDrawnOverlay3DItems);
|
||||
}
|
||||
//Render the sixense lasers
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)) {
|
||||
|
|
|
@ -450,6 +450,7 @@ private slots:
|
|||
void setEnable3DTVMode(bool enable3DTVMode);
|
||||
void setEnableVRMode(bool enableVRMode);
|
||||
void cameraMenuChanged();
|
||||
void rotationModeChanged();
|
||||
|
||||
glm::vec2 getScaledScreenPoint(glm::vec2 projectedPoint);
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
|
||||
#include <avatar/AvatarActionHold.h>
|
||||
#include <ObjectActionPullToPoint.h>
|
||||
#include <ObjectActionOffset.h>
|
||||
#include <ObjectActionSpring.h>
|
||||
|
||||
#include "InterfaceActionFactory.h"
|
||||
|
@ -27,8 +27,8 @@ EntityActionPointer InterfaceActionFactory::factory(EntitySimulation* simulation
|
|||
switch (type) {
|
||||
case ACTION_TYPE_NONE:
|
||||
return nullptr;
|
||||
case ACTION_TYPE_PULL_TO_POINT:
|
||||
action = (EntityActionPointer) new ObjectActionPullToPoint(id, ownerEntity);
|
||||
case ACTION_TYPE_OFFSET:
|
||||
action = (EntityActionPointer) new ObjectActionOffset(id, ownerEntity);
|
||||
break;
|
||||
case ACTION_TYPE_SPRING:
|
||||
action = (EntityActionPointer) new ObjectActionSpring(id, ownerEntity);
|
||||
|
|
|
@ -277,6 +277,9 @@ Menu::Menu() {
|
|||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FullscreenMirror,
|
||||
0, // QML Qt::Key_H,
|
||||
false, qApp, SLOT(cameraMenuChanged()));
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::CenterPlayerInView,
|
||||
0, false, qApp, SLOT(rotationModeChanged()));
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::HMDTools,
|
||||
#ifdef Q_OS_MAC
|
||||
|
|
|
@ -199,6 +199,7 @@ namespace MenuOption {
|
|||
const QString FrameTimer = "Show Timer";
|
||||
const QString Fullscreen = "Fullscreen";
|
||||
const QString FullscreenMirror = "Fullscreen Mirror";
|
||||
const QString CenterPlayerInView = "Center Player In View";
|
||||
const QString GlowWhenSpeaking = "Glow When Speaking";
|
||||
const QString NamesAboveHeads = "Names Above Heads";
|
||||
const QString HMDTools = "HMD Tools";
|
||||
|
|
|
@ -29,6 +29,12 @@ AvatarActionHold::~AvatarActionHold() {
|
|||
|
||||
void AvatarActionHold::updateActionWorker(float deltaTimeStep) {
|
||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
|
||||
if (!tryLockForRead()) {
|
||||
// don't risk hanging the thread running the physics simulation
|
||||
return;
|
||||
}
|
||||
|
||||
glm::vec3 palmPosition;
|
||||
if (_hand == "right") {
|
||||
palmPosition = myAvatar->getRightPalmPosition();
|
||||
|
@ -40,8 +46,11 @@ void AvatarActionHold::updateActionWorker(float deltaTimeStep) {
|
|||
auto offset = rotation * _relativePosition;
|
||||
auto position = palmPosition + offset;
|
||||
rotation *= _relativeRotation;
|
||||
unlock();
|
||||
|
||||
lockForWrite();
|
||||
if (!tryLockForWrite()) {
|
||||
return;
|
||||
}
|
||||
_positionalTarget = position;
|
||||
_rotationalTarget = rotation;
|
||||
unlock();
|
||||
|
|
|
@ -242,8 +242,6 @@ void KeyboardMouseDevice::assignDefaultInputMapping(UserInputMapper& mapper) {
|
|||
mapper.addInputChannel(UserInputMapper::VERTICAL_DOWN, makeInput(Qt::Key_PageDown), BUTTON_MOVE_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::VERTICAL_UP, makeInput(Qt::Key_PageUp), BUTTON_MOVE_SPEED);
|
||||
|
||||
mapper.addInputChannel(UserInputMapper::BOOM_IN, makeInput(Qt::Key_Up), makeInput(Qt::Key_Shift), BUTTON_BOOM_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::BOOM_OUT, makeInput(Qt::Key_Down), makeInput(Qt::Key_Shift), BUTTON_BOOM_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::LATERAL_LEFT, makeInput(Qt::Key_Left), makeInput(Qt::RightButton), BUTTON_YAW_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::LATERAL_RIGHT, makeInput(Qt::Key_Right), makeInput(Qt::RightButton), BUTTON_YAW_SPEED);
|
||||
mapper.addInputChannel(UserInputMapper::LATERAL_LEFT, makeInput(Qt::Key_Left), makeInput(Qt::Key_Shift), BUTTON_YAW_SPEED);
|
||||
|
|
|
@ -457,6 +457,14 @@ void ControllerScriptingInterface::resetAllDeviceBindings() {
|
|||
Application::getUserInputMapper()->resetAllDeviceBindings();
|
||||
}
|
||||
|
||||
void ControllerScriptingInterface::resetDevice(unsigned int device) {
|
||||
Application::getUserInputMapper()->resetDevice(device);
|
||||
}
|
||||
|
||||
int ControllerScriptingInterface::findDevice(QString name) {
|
||||
return Application::getUserInputMapper()->findDevice(name);
|
||||
}
|
||||
|
||||
InputController::InputController(int deviceTrackerId, int subTrackerId, QObject* parent) :
|
||||
AbstractInputController(),
|
||||
_deviceTrackerId(deviceTrackerId),
|
||||
|
|
|
@ -91,6 +91,8 @@ public slots:
|
|||
Q_INVOKABLE virtual bool removeInputChannel(UserInputMapper::InputChannel inputChannel);
|
||||
Q_INVOKABLE virtual QVector<UserInputMapper::InputPair> getAvailableInputs(unsigned int device);
|
||||
Q_INVOKABLE virtual void resetAllDeviceBindings();
|
||||
Q_INVOKABLE virtual void resetDevice(unsigned int device);
|
||||
Q_INVOKABLE virtual int findDevice(QString name);
|
||||
virtual bool isPrimaryButtonPressed() const;
|
||||
virtual glm::vec2 getPrimaryJoystickPosition() const;
|
||||
|
||||
|
|
|
@ -41,6 +41,22 @@ void UserInputMapper::resetAllDeviceBindings() {
|
|||
}
|
||||
}
|
||||
|
||||
void UserInputMapper::resetDevice(uint16 deviceID) {
|
||||
auto device = _registeredDevices.find(deviceID);
|
||||
if (device != _registeredDevices.end()) {
|
||||
device->second->resetDeviceBindings();
|
||||
}
|
||||
}
|
||||
|
||||
int UserInputMapper::findDevice(QString name) {
|
||||
for (auto device : _registeredDevices) {
|
||||
if (device.second->_name.split(" (")[0] == name) {
|
||||
return device.first;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool UserInputMapper::addInputChannel(Action action, const Input& input, float scale) {
|
||||
return addInputChannel(action, input, Input(), scale);
|
||||
}
|
||||
|
|
|
@ -116,6 +116,8 @@ public:
|
|||
QString getDeviceName(uint16 deviceID) { return _registeredDevices[deviceID]->_name; }
|
||||
QVector<InputPair> getAvailableInputs(uint16 deviceID) { return _registeredDevices[deviceID]->getAvailabeInputs(); }
|
||||
void resetAllDeviceBindings();
|
||||
void resetDevice(uint16 deviceID);
|
||||
int findDevice(QString name);
|
||||
|
||||
// Actions are the output channels of the Mapper, that's what the InputChannel map to
|
||||
// For now the Actions are hardcoded, this is bad, but we will fix that in the near future
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <DeferredLightingEffect.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <GlowEffect.h>
|
||||
#include <SharedUtil.h>
|
||||
|
@ -101,206 +102,185 @@ void Circle3DOverlay::render(RenderArgs* args) {
|
|||
bool colorChanged = colorX.red != _lastColor.red || colorX.green != _lastColor.green || colorX.blue != _lastColor.blue;
|
||||
_lastColor = colorX;
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
glm::vec3 position = getPosition();
|
||||
glm::vec3 center = getCenter();
|
||||
glm::vec2 dimensions = getDimensions();
|
||||
glm::quat rotation = getRotation();
|
||||
|
||||
float glowLevel = getGlowLevel();
|
||||
Glower* glower = NULL;
|
||||
if (glowLevel > 0.0f) {
|
||||
glower = new Glower(glowLevel);
|
||||
}
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
glm::vec3 axis = glm::axis(rotation);
|
||||
glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z);
|
||||
glPushMatrix();
|
||||
glm::vec3 positionToCenter = center - position;
|
||||
glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z);
|
||||
glScalef(dimensions.x / 2.0f, dimensions.y / 2.0f, 1.0f);
|
||||
|
||||
glLineWidth(_lineWidth);
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
|
||||
// for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise
|
||||
// we just draw a line...
|
||||
if (getIsSolid()) {
|
||||
if (_quadVerticesID == GeometryCache::UNKNOWN_ID) {
|
||||
_quadVerticesID = geometryCache->allocateID();
|
||||
}
|
||||
|
||||
if (geometryChanged || colorChanged) {
|
||||
|
||||
QVector<glm::vec2> points;
|
||||
|
||||
float angle = startAt;
|
||||
float angleInRadians = glm::radians(angle);
|
||||
glm::vec2 firstInnerPoint(cosf(angleInRadians) * innerRadius, sinf(angleInRadians) * innerRadius);
|
||||
glm::vec2 firstOuterPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
|
||||
|
||||
points << firstInnerPoint << firstOuterPoint;
|
||||
|
||||
while (angle < endAt) {
|
||||
angleInRadians = glm::radians(angle);
|
||||
glm::vec2 thisInnerPoint(cosf(angleInRadians) * innerRadius, sinf(angleInRadians) * innerRadius);
|
||||
glm::vec2 thisOuterPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
|
||||
|
||||
points << thisOuterPoint << thisInnerPoint;
|
||||
|
||||
angle += SLICE_ANGLE;
|
||||
}
|
||||
|
||||
// get the last slice portion....
|
||||
angle = endAt;
|
||||
angleInRadians = glm::radians(angle);
|
||||
glm::vec2 lastInnerPoint(cosf(angleInRadians) * innerRadius, sinf(angleInRadians) * innerRadius);
|
||||
glm::vec2 lastOuterPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
|
||||
|
||||
points << lastOuterPoint << lastInnerPoint;
|
||||
|
||||
geometryCache->updateVertices(_quadVerticesID, points, color);
|
||||
}
|
||||
|
||||
geometryCache->renderVertices(gpu::QUAD_STRIP, _quadVerticesID);
|
||||
|
||||
} else {
|
||||
if (_lineVerticesID == GeometryCache::UNKNOWN_ID) {
|
||||
_lineVerticesID = geometryCache->allocateID();
|
||||
}
|
||||
|
||||
if (geometryChanged || colorChanged) {
|
||||
QVector<glm::vec2> points;
|
||||
|
||||
float angle = startAt;
|
||||
float angleInRadians = glm::radians(angle);
|
||||
glm::vec2 firstPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
|
||||
points << firstPoint;
|
||||
|
||||
while (angle < endAt) {
|
||||
angle += SLICE_ANGLE;
|
||||
angleInRadians = glm::radians(angle);
|
||||
glm::vec2 thisPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
|
||||
points << thisPoint;
|
||||
|
||||
if (getIsDashedLine()) {
|
||||
angle += SLICE_ANGLE / 2.0f; // short gap
|
||||
angleInRadians = glm::radians(angle);
|
||||
glm::vec2 dashStartPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
|
||||
points << dashStartPoint;
|
||||
}
|
||||
}
|
||||
|
||||
// get the last slice portion....
|
||||
angle = endAt;
|
||||
angleInRadians = glm::radians(angle);
|
||||
glm::vec2 lastPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
|
||||
points << lastPoint;
|
||||
|
||||
geometryCache->updateVertices(_lineVerticesID, points, color);
|
||||
}
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
|
||||
Transform transform;
|
||||
transform.setTranslation(getCenter());
|
||||
transform.setRotation(getRotation());
|
||||
transform.setScale(glm::vec3(getDimensions(), 0.01f));
|
||||
|
||||
|
||||
auto& batch = *args->_batch;
|
||||
batch._glLineWidth(_lineWidth);
|
||||
batch.setModelTransform(transform);
|
||||
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, false, false);
|
||||
|
||||
// for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise
|
||||
// we just draw a line...
|
||||
if (getIsSolid()) {
|
||||
if (_quadVerticesID == GeometryCache::UNKNOWN_ID) {
|
||||
_quadVerticesID = geometryCache->allocateID();
|
||||
}
|
||||
|
||||
if (geometryChanged || colorChanged) {
|
||||
|
||||
QVector<glm::vec2> points;
|
||||
|
||||
float angle = startAt;
|
||||
float angleInRadians = glm::radians(angle);
|
||||
glm::vec2 firstInnerPoint(cosf(angleInRadians) * innerRadius, sinf(angleInRadians) * innerRadius);
|
||||
glm::vec2 firstOuterPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
|
||||
|
||||
points << firstInnerPoint << firstOuterPoint;
|
||||
|
||||
while (angle < endAt) {
|
||||
angleInRadians = glm::radians(angle);
|
||||
glm::vec2 thisInnerPoint(cosf(angleInRadians) * innerRadius, sinf(angleInRadians) * innerRadius);
|
||||
glm::vec2 thisOuterPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
|
||||
|
||||
points << thisOuterPoint << thisInnerPoint;
|
||||
|
||||
angle += SLICE_ANGLE;
|
||||
}
|
||||
|
||||
// get the last slice portion....
|
||||
angle = endAt;
|
||||
angleInRadians = glm::radians(angle);
|
||||
glm::vec2 lastInnerPoint(cosf(angleInRadians) * innerRadius, sinf(angleInRadians) * innerRadius);
|
||||
glm::vec2 lastOuterPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
|
||||
|
||||
points << lastOuterPoint << lastInnerPoint;
|
||||
|
||||
geometryCache->updateVertices(_quadVerticesID, points, color);
|
||||
}
|
||||
|
||||
geometryCache->renderVertices(batch, gpu::QUAD_STRIP, _quadVerticesID);
|
||||
|
||||
} else {
|
||||
if (_lineVerticesID == GeometryCache::UNKNOWN_ID) {
|
||||
_lineVerticesID = geometryCache->allocateID();
|
||||
}
|
||||
|
||||
if (geometryChanged || colorChanged) {
|
||||
QVector<glm::vec2> points;
|
||||
|
||||
float angle = startAt;
|
||||
float angleInRadians = glm::radians(angle);
|
||||
glm::vec2 firstPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
|
||||
points << firstPoint;
|
||||
|
||||
while (angle < endAt) {
|
||||
angle += SLICE_ANGLE;
|
||||
angleInRadians = glm::radians(angle);
|
||||
glm::vec2 thisPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
|
||||
points << thisPoint;
|
||||
|
||||
if (getIsDashedLine()) {
|
||||
geometryCache->renderVertices(gpu::LINES, _lineVerticesID);
|
||||
} else {
|
||||
geometryCache->renderVertices(gpu::LINE_STRIP, _lineVerticesID);
|
||||
angle += SLICE_ANGLE / 2.0f; // short gap
|
||||
angleInRadians = glm::radians(angle);
|
||||
glm::vec2 dashStartPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
|
||||
points << dashStartPoint;
|
||||
}
|
||||
}
|
||||
|
||||
// draw our tick marks
|
||||
// for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise
|
||||
// we just draw a line...
|
||||
if (getHasTickMarks()) {
|
||||
|
||||
if (_majorTicksVerticesID == GeometryCache::UNKNOWN_ID) {
|
||||
_majorTicksVerticesID = geometryCache->allocateID();
|
||||
|
||||
// get the last slice portion....
|
||||
angle = endAt;
|
||||
angleInRadians = glm::radians(angle);
|
||||
glm::vec2 lastPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
|
||||
points << lastPoint;
|
||||
|
||||
geometryCache->updateVertices(_lineVerticesID, points, color);
|
||||
}
|
||||
|
||||
if (getIsDashedLine()) {
|
||||
geometryCache->renderVertices(batch, gpu::LINES, _lineVerticesID);
|
||||
} else {
|
||||
geometryCache->renderVertices(batch, gpu::LINE_STRIP, _lineVerticesID);
|
||||
}
|
||||
}
|
||||
|
||||
// draw our tick marks
|
||||
// for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise
|
||||
// we just draw a line...
|
||||
if (getHasTickMarks()) {
|
||||
|
||||
if (_majorTicksVerticesID == GeometryCache::UNKNOWN_ID) {
|
||||
_majorTicksVerticesID = geometryCache->allocateID();
|
||||
}
|
||||
if (_minorTicksVerticesID == GeometryCache::UNKNOWN_ID) {
|
||||
_minorTicksVerticesID = geometryCache->allocateID();
|
||||
}
|
||||
|
||||
if (geometryChanged) {
|
||||
QVector<glm::vec2> majorPoints;
|
||||
QVector<glm::vec2> minorPoints;
|
||||
|
||||
// draw our major tick marks
|
||||
if (getMajorTickMarksAngle() > 0.0f && getMajorTickMarksLength() != 0.0f) {
|
||||
|
||||
float tickMarkAngle = getMajorTickMarksAngle();
|
||||
float angle = startAt - fmodf(startAt, tickMarkAngle) + tickMarkAngle;
|
||||
float angleInRadians = glm::radians(angle);
|
||||
float tickMarkLength = getMajorTickMarksLength();
|
||||
float startRadius = (tickMarkLength > 0.0f) ? innerRadius : outerRadius;
|
||||
float endRadius = startRadius + tickMarkLength;
|
||||
|
||||
while (angle <= endAt) {
|
||||
angleInRadians = glm::radians(angle);
|
||||
|
||||
glm::vec2 thisPointA(cosf(angleInRadians) * startRadius, sinf(angleInRadians) * startRadius);
|
||||
glm::vec2 thisPointB(cosf(angleInRadians) * endRadius, sinf(angleInRadians) * endRadius);
|
||||
|
||||
majorPoints << thisPointA << thisPointB;
|
||||
|
||||
angle += tickMarkAngle;
|
||||
}
|
||||
if (_minorTicksVerticesID == GeometryCache::UNKNOWN_ID) {
|
||||
_minorTicksVerticesID = geometryCache->allocateID();
|
||||
}
|
||||
|
||||
if (geometryChanged) {
|
||||
QVector<glm::vec2> majorPoints;
|
||||
QVector<glm::vec2> minorPoints;
|
||||
|
||||
// draw our major tick marks
|
||||
if (getMajorTickMarksAngle() > 0.0f && getMajorTickMarksLength() != 0.0f) {
|
||||
|
||||
float tickMarkAngle = getMajorTickMarksAngle();
|
||||
float angle = startAt - fmodf(startAt, tickMarkAngle) + tickMarkAngle;
|
||||
float angleInRadians = glm::radians(angle);
|
||||
float tickMarkLength = getMajorTickMarksLength();
|
||||
float startRadius = (tickMarkLength > 0.0f) ? innerRadius : outerRadius;
|
||||
float endRadius = startRadius + tickMarkLength;
|
||||
|
||||
while (angle <= endAt) {
|
||||
angleInRadians = glm::radians(angle);
|
||||
|
||||
glm::vec2 thisPointA(cosf(angleInRadians) * startRadius, sinf(angleInRadians) * startRadius);
|
||||
glm::vec2 thisPointB(cosf(angleInRadians) * endRadius, sinf(angleInRadians) * endRadius);
|
||||
|
||||
majorPoints << thisPointA << thisPointB;
|
||||
|
||||
angle += tickMarkAngle;
|
||||
}
|
||||
}
|
||||
|
||||
// draw our minor tick marks
|
||||
if (getMinorTickMarksAngle() > 0.0f && getMinorTickMarksLength() != 0.0f) {
|
||||
|
||||
float tickMarkAngle = getMinorTickMarksAngle();
|
||||
float angle = startAt - fmodf(startAt, tickMarkAngle) + tickMarkAngle;
|
||||
float angleInRadians = glm::radians(angle);
|
||||
float tickMarkLength = getMinorTickMarksLength();
|
||||
float startRadius = (tickMarkLength > 0.0f) ? innerRadius : outerRadius;
|
||||
float endRadius = startRadius + tickMarkLength;
|
||||
|
||||
while (angle <= endAt) {
|
||||
angleInRadians = glm::radians(angle);
|
||||
|
||||
glm::vec2 thisPointA(cosf(angleInRadians) * startRadius, sinf(angleInRadians) * startRadius);
|
||||
glm::vec2 thisPointB(cosf(angleInRadians) * endRadius, sinf(angleInRadians) * endRadius);
|
||||
|
||||
minorPoints << thisPointA << thisPointB;
|
||||
|
||||
angle += tickMarkAngle;
|
||||
}
|
||||
}
|
||||
|
||||
xColor majorColorX = getMajorTickMarksColor();
|
||||
glm::vec4 majorColor(majorColorX.red / MAX_COLOR, majorColorX.green / MAX_COLOR, majorColorX.blue / MAX_COLOR, alpha);
|
||||
|
||||
geometryCache->updateVertices(_majorTicksVerticesID, majorPoints, majorColor);
|
||||
|
||||
xColor minorColorX = getMinorTickMarksColor();
|
||||
glm::vec4 minorColor(minorColorX.red / MAX_COLOR, minorColorX.green / MAX_COLOR, minorColorX.blue / MAX_COLOR, alpha);
|
||||
|
||||
geometryCache->updateVertices(_minorTicksVerticesID, minorPoints, minorColor);
|
||||
}
|
||||
|
||||
geometryCache->renderVertices(gpu::LINES, _majorTicksVerticesID);
|
||||
|
||||
geometryCache->renderVertices(gpu::LINES, _minorTicksVerticesID);
|
||||
}
|
||||
|
||||
|
||||
glPopMatrix();
|
||||
glPopMatrix();
|
||||
|
||||
|
||||
// draw our minor tick marks
|
||||
if (getMinorTickMarksAngle() > 0.0f && getMinorTickMarksLength() != 0.0f) {
|
||||
|
||||
float tickMarkAngle = getMinorTickMarksAngle();
|
||||
float angle = startAt - fmodf(startAt, tickMarkAngle) + tickMarkAngle;
|
||||
float angleInRadians = glm::radians(angle);
|
||||
float tickMarkLength = getMinorTickMarksLength();
|
||||
float startRadius = (tickMarkLength > 0.0f) ? innerRadius : outerRadius;
|
||||
float endRadius = startRadius + tickMarkLength;
|
||||
|
||||
while (angle <= endAt) {
|
||||
angleInRadians = glm::radians(angle);
|
||||
|
||||
glm::vec2 thisPointA(cosf(angleInRadians) * startRadius, sinf(angleInRadians) * startRadius);
|
||||
glm::vec2 thisPointB(cosf(angleInRadians) * endRadius, sinf(angleInRadians) * endRadius);
|
||||
|
||||
minorPoints << thisPointA << thisPointB;
|
||||
|
||||
angle += tickMarkAngle;
|
||||
}
|
||||
}
|
||||
|
||||
xColor majorColorX = getMajorTickMarksColor();
|
||||
glm::vec4 majorColor(majorColorX.red / MAX_COLOR, majorColorX.green / MAX_COLOR, majorColorX.blue / MAX_COLOR, alpha);
|
||||
|
||||
geometryCache->updateVertices(_majorTicksVerticesID, majorPoints, majorColor);
|
||||
|
||||
xColor minorColorX = getMinorTickMarksColor();
|
||||
glm::vec4 minorColor(minorColorX.red / MAX_COLOR, minorColorX.green / MAX_COLOR, minorColorX.blue / MAX_COLOR, alpha);
|
||||
|
||||
geometryCache->updateVertices(_minorTicksVerticesID, minorPoints, minorColor);
|
||||
}
|
||||
|
||||
geometryCache->renderVertices(batch, gpu::LINES, _majorTicksVerticesID);
|
||||
|
||||
geometryCache->renderVertices(batch, gpu::LINES, _minorTicksVerticesID);
|
||||
}
|
||||
|
||||
if (geometryChanged) {
|
||||
_lastStartAt = startAt;
|
||||
_lastEndAt = endAt;
|
||||
_lastInnerRadius = innerRadius;
|
||||
_lastOuterRadius = outerRadius;
|
||||
}
|
||||
|
||||
if (glower) {
|
||||
delete glower;
|
||||
}
|
||||
}
|
||||
|
||||
void Circle3DOverlay::setProperties(const QScriptValue &properties) {
|
||||
|
|
|
@ -19,8 +19,8 @@ EntityActionType EntityActionInterface::actionTypeFromString(QString actionTypeS
|
|||
if (normalizedActionTypeString == "none") {
|
||||
return ACTION_TYPE_NONE;
|
||||
}
|
||||
if (normalizedActionTypeString == "pulltopoint") {
|
||||
return ACTION_TYPE_PULL_TO_POINT;
|
||||
if (normalizedActionTypeString == "offset") {
|
||||
return ACTION_TYPE_OFFSET;
|
||||
}
|
||||
if (normalizedActionTypeString == "spring") {
|
||||
return ACTION_TYPE_SPRING;
|
||||
|
@ -37,8 +37,8 @@ QString EntityActionInterface::actionTypeToString(EntityActionType actionType) {
|
|||
switch(actionType) {
|
||||
case ACTION_TYPE_NONE:
|
||||
return "none";
|
||||
case ACTION_TYPE_PULL_TO_POINT:
|
||||
return "pullToPoint";
|
||||
case ACTION_TYPE_OFFSET:
|
||||
return "offset";
|
||||
case ACTION_TYPE_SPRING:
|
||||
return "spring";
|
||||
case ACTION_TYPE_HOLD:
|
||||
|
|
|
@ -21,7 +21,7 @@ class EntitySimulation;
|
|||
enum EntityActionType {
|
||||
// keep these synchronized with actionTypeFromString and actionTypeToString
|
||||
ACTION_TYPE_NONE,
|
||||
ACTION_TYPE_PULL_TO_POINT,
|
||||
ACTION_TYPE_OFFSET,
|
||||
ACTION_TYPE_SPRING,
|
||||
ACTION_TYPE_HOLD
|
||||
};
|
||||
|
|
|
@ -506,7 +506,7 @@ FBXNode parseFBX(QIODevice* device) {
|
|||
|
||||
QVector<glm::vec4> createVec4Vector(const QVector<double>& doubleVector) {
|
||||
QVector<glm::vec4> values;
|
||||
for (const double* it = doubleVector.constData(), *end = it + (doubleVector.size() / 4 * 4); it != end; ) {
|
||||
for (const double* it = doubleVector.constData(), *end = it + ((doubleVector.size() / 4) * 4); it != end; ) {
|
||||
float x = *it++;
|
||||
float y = *it++;
|
||||
float z = *it++;
|
||||
|
@ -516,9 +516,27 @@ QVector<glm::vec4> createVec4Vector(const QVector<double>& doubleVector) {
|
|||
return values;
|
||||
}
|
||||
|
||||
|
||||
QVector<glm::vec4> createVec4VectorRGBA(const QVector<double>& doubleVector, glm::vec4& average) {
|
||||
QVector<glm::vec4> values;
|
||||
for (const double* it = doubleVector.constData(), *end = it + ((doubleVector.size() / 4) * 4); it != end; ) {
|
||||
float x = *it++;
|
||||
float y = *it++;
|
||||
float z = *it++;
|
||||
float w = *it++;
|
||||
auto val = glm::vec4(x, y, z, w);
|
||||
values.append(val);
|
||||
average += val;
|
||||
}
|
||||
if (!values.isEmpty()) {
|
||||
average *= (1.0f / float(values.size()));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
QVector<glm::vec3> createVec3Vector(const QVector<double>& doubleVector) {
|
||||
QVector<glm::vec3> values;
|
||||
for (const double* it = doubleVector.constData(), *end = it + (doubleVector.size() / 3 * 3); it != end; ) {
|
||||
for (const double* it = doubleVector.constData(), *end = it + ((doubleVector.size() / 3) * 3); it != end; ) {
|
||||
float x = *it++;
|
||||
float y = *it++;
|
||||
float z = *it++;
|
||||
|
@ -529,7 +547,7 @@ QVector<glm::vec3> createVec3Vector(const QVector<double>& doubleVector) {
|
|||
|
||||
QVector<glm::vec2> createVec2Vector(const QVector<double>& doubleVector) {
|
||||
QVector<glm::vec2> values;
|
||||
for (const double* it = doubleVector.constData(), *end = it + (doubleVector.size() / 2 * 2); it != end; ) {
|
||||
for (const double* it = doubleVector.constData(), *end = it + ((doubleVector.size() / 2) * 2); it != end; ) {
|
||||
float s = *it++;
|
||||
float t = *it++;
|
||||
values.append(glm::vec2(s, -t));
|
||||
|
@ -799,6 +817,7 @@ public:
|
|||
QVector<int> normalIndices;
|
||||
|
||||
bool colorsByVertex;
|
||||
glm::vec4 averageColor{1.0f, 1.0f, 1.0f, 1.0f};
|
||||
QVector<glm::vec4> colors;
|
||||
QVector<int> colorIndices;
|
||||
|
||||
|
@ -940,8 +959,7 @@ ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex) {
|
|||
bool indexToDirect = false;
|
||||
foreach (const FBXNode& subdata, child.children) {
|
||||
if (subdata.name == "Colors") {
|
||||
data.colors = createVec4Vector(getDoubleVector(subdata));
|
||||
|
||||
data.colors = createVec4VectorRGBA(getDoubleVector(subdata), data.averageColor);
|
||||
} else if (subdata.name == "ColorsIndex") {
|
||||
data.colorIndices = getIntVector(subdata);
|
||||
|
||||
|
@ -956,6 +974,19 @@ ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex) {
|
|||
// hack to work around wacky Makehuman exports
|
||||
data.colorsByVertex = true;
|
||||
}
|
||||
|
||||
#if defined(FBXREADER_KILL_BLACK_COLOR_ATTRIBUTE)
|
||||
// Potential feature where we decide to kill the color attribute is to dark?
|
||||
// Tested with the model:
|
||||
// https://hifi-public.s3.amazonaws.com/ryan/gardenLight2.fbx
|
||||
// let's check if we did have true data ?
|
||||
if (glm::all(glm::lessThanEqual(data.averageColor, glm::vec4(0.09f)))) {
|
||||
data.colors.clear();
|
||||
data.colorIndices.clear();
|
||||
data.colorsByVertex = false;
|
||||
qCDebug(modelformat) << "LayerElementColor has an average value of 0.0f... let's forget it.";
|
||||
}
|
||||
#endif
|
||||
|
||||
} else if (child.name == "LayerElementUV") {
|
||||
if (child.properties.at(0).toInt() == 0) {
|
||||
|
|
|
@ -450,6 +450,7 @@ void GLBackend::do_glUniform1i(Batch& batch, uint32 paramOffset) {
|
|||
// because these uniform setters are deprecated and we don;t want to create side effect
|
||||
return;
|
||||
}
|
||||
updatePipeline();
|
||||
glUniform1f(
|
||||
batch._params[paramOffset + 1]._int,
|
||||
batch._params[paramOffset + 0]._int);
|
||||
|
@ -472,6 +473,8 @@ void GLBackend::do_glUniform1f(Batch& batch, uint32 paramOffset) {
|
|||
// because these uniform setters are deprecated and we don;t want to create side effect
|
||||
return;
|
||||
}
|
||||
updatePipeline();
|
||||
|
||||
glUniform1f(
|
||||
batch._params[paramOffset + 1]._int,
|
||||
batch._params[paramOffset + 0]._float);
|
||||
|
@ -494,6 +497,7 @@ void GLBackend::do_glUniform2f(Batch& batch, uint32 paramOffset) {
|
|||
// because these uniform setters are deprecated and we don;t want to create side effect
|
||||
return;
|
||||
}
|
||||
updatePipeline();
|
||||
glUniform2f(
|
||||
batch._params[paramOffset + 2]._int,
|
||||
batch._params[paramOffset + 1]._float,
|
||||
|
@ -518,6 +522,7 @@ void GLBackend::do_glUniform3f(Batch& batch, uint32 paramOffset) {
|
|||
// because these uniform setters are deprecated and we don;t want to create side effect
|
||||
return;
|
||||
}
|
||||
updatePipeline();
|
||||
glUniform3f(
|
||||
batch._params[paramOffset + 3]._int,
|
||||
batch._params[paramOffset + 2]._float,
|
||||
|
@ -542,6 +547,7 @@ void GLBackend::do_glUniform3fv(Batch& batch, uint32 paramOffset) {
|
|||
// because these uniform setters are deprecated and we don;t want to create side effect
|
||||
return;
|
||||
}
|
||||
updatePipeline();
|
||||
glUniform3fv(
|
||||
batch._params[paramOffset + 2]._int,
|
||||
batch._params[paramOffset + 1]._uint,
|
||||
|
@ -567,6 +573,7 @@ void GLBackend::do_glUniform4fv(Batch& batch, uint32 paramOffset) {
|
|||
// because these uniform setters are deprecated and we don;t want to create side effect
|
||||
return;
|
||||
}
|
||||
updatePipeline();
|
||||
glUniform4fv(
|
||||
batch._params[paramOffset + 2]._int,
|
||||
batch._params[paramOffset + 1]._uint,
|
||||
|
@ -592,6 +599,7 @@ void GLBackend::do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset) {
|
|||
// because these uniform setters are deprecated and we don;t want to create side effect
|
||||
return;
|
||||
}
|
||||
updatePipeline();
|
||||
glUniformMatrix4fv(
|
||||
batch._params[paramOffset + 3]._int,
|
||||
batch._params[paramOffset + 2]._uint,
|
||||
|
|
|
@ -343,10 +343,10 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) {
|
|||
if (bytes && texture.isAutogenerateMips()) {
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
} else {
|
||||
}/* else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
}
|
||||
}*/
|
||||
|
||||
object->_target = GL_TEXTURE_2D;
|
||||
|
||||
|
|
|
@ -245,7 +245,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
|||
|
||||
float dx2 = glm::distance2(position, _serverPosition);
|
||||
|
||||
const float MAX_POSITION_ERROR_SQUARED = 0.001f; // 0.001 m^2 ~~> 0.03 m
|
||||
const float MAX_POSITION_ERROR_SQUARED = 0.000004f; // Sqrt() - corresponds to 2 millimeters
|
||||
if (dx2 > MAX_POSITION_ERROR_SQUARED) {
|
||||
|
||||
#ifdef WANT_DEBUG
|
||||
|
@ -270,7 +270,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
|||
_serverRotation = glm::normalize(computeBulletRotationStep(_serverAngularVelocity, PHYSICS_ENGINE_FIXED_SUBSTEP) * _serverRotation);
|
||||
}
|
||||
}
|
||||
const float MIN_ROTATION_DOT = 0.99f; // 0.99 dot threshold coresponds to about 16 degrees of slop
|
||||
const float MIN_ROTATION_DOT = 0.99999f; // This corresponds to about 0.5 degrees of rotation
|
||||
glm::quat actualRotation = bulletToGLM(worldTrans.getRotation());
|
||||
|
||||
#ifdef WANT_DEBUG
|
||||
|
|
|
@ -28,7 +28,7 @@ void ObjectAction::updateAction(btCollisionWorld* collisionWorld, btScalar delta
|
|||
return;
|
||||
}
|
||||
if (!_ownerEntity) {
|
||||
qDebug() << "ObjectActionPullToPoint::updateAction no owner entity";
|
||||
qDebug() << "ObjectAction::updateAction no owner entity";
|
||||
return;
|
||||
}
|
||||
updateActionWorker(deltaTimeStep);
|
||||
|
|
|
@ -59,6 +59,7 @@ protected:
|
|||
|
||||
bool tryLockForRead() { return _lock.tryLockForRead(); }
|
||||
void lockForWrite() { _lock.lockForWrite(); }
|
||||
bool tryLockForWrite() { return _lock.tryLockForWrite(); }
|
||||
void unlock() { _lock.unlock(); }
|
||||
|
||||
bool _active;
|
||||
|
|
109
libraries/physics/src/ObjectActionOffset.cpp
Normal file
109
libraries/physics/src/ObjectActionOffset.cpp
Normal file
|
@ -0,0 +1,109 @@
|
|||
//
|
||||
// ObjectActionOffset.cpp
|
||||
// libraries/physics/src
|
||||
//
|
||||
// Created by Seth Alves 2015-6-17
|
||||
// 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
|
||||
//
|
||||
|
||||
#include "ObjectActionOffset.h"
|
||||
|
||||
ObjectActionOffset::ObjectActionOffset(QUuid id, EntityItemPointer ownerEntity) :
|
||||
ObjectAction(id, ownerEntity) {
|
||||
#if WANT_DEBUG
|
||||
qDebug() << "ObjectActionOffset::ObjectActionOffset";
|
||||
#endif
|
||||
}
|
||||
|
||||
ObjectActionOffset::~ObjectActionOffset() {
|
||||
#if WANT_DEBUG
|
||||
qDebug() << "ObjectActionOffset::~ObjectActionOffset";
|
||||
#endif
|
||||
}
|
||||
|
||||
void ObjectActionOffset::updateActionWorker(btScalar deltaTimeStep) {
|
||||
if (!tryLockForRead()) {
|
||||
// don't risk hanging the thread running the physics simulation
|
||||
return;
|
||||
}
|
||||
|
||||
void* physicsInfo = _ownerEntity->getPhysicsInfo();
|
||||
if (!physicsInfo) {
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(physicsInfo);
|
||||
btRigidBody* rigidBody = motionState->getRigidBody();
|
||||
if (!rigidBody) {
|
||||
unlock();
|
||||
qDebug() << "ObjectActionOffset::updateActionWorker no rigidBody";
|
||||
return;
|
||||
}
|
||||
|
||||
if (_positionalTargetSet) {
|
||||
glm::vec3 offset = _pointToOffsetFrom - bulletToGLM(rigidBody->getCenterOfMassPosition());
|
||||
float offsetLength = glm::length(offset);
|
||||
float offsetError = _linearDistance - offsetLength;
|
||||
|
||||
// if (glm::abs(offsetError) > IGNORE_POSITION_DELTA) {
|
||||
if (glm::abs(offsetError) > 0.0f) {
|
||||
float offsetErrorAbs = glm::abs(offsetError);
|
||||
float offsetErrorDirection = - offsetError / offsetErrorAbs;
|
||||
glm::vec3 previousVelocity = bulletToGLM(rigidBody->getLinearVelocity());
|
||||
|
||||
glm::vec3 velocityAdjustment = glm::normalize(offset) * offsetErrorDirection * offsetErrorAbs / _linearTimeScale;
|
||||
rigidBody->setLinearVelocity(glmToBullet(previousVelocity + velocityAdjustment));
|
||||
// rigidBody->setLinearVelocity(glmToBullet(velocityAdjustment));
|
||||
rigidBody->activate();
|
||||
}
|
||||
}
|
||||
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
||||
bool ObjectActionOffset::updateArguments(QVariantMap arguments) {
|
||||
bool pOk0 = true;
|
||||
glm::vec3 pointToOffsetFrom =
|
||||
EntityActionInterface::extractVec3Argument("offset action", arguments, "pointToOffsetFrom", pOk0, true);
|
||||
|
||||
bool pOk1 = true;
|
||||
float linearTimeScale =
|
||||
EntityActionInterface::extractFloatArgument("offset action", arguments, "linearTimeScale", pOk1, false);
|
||||
|
||||
bool pOk2 = true;
|
||||
float linearDistance =
|
||||
EntityActionInterface::extractFloatArgument("offset action", arguments, "linearDistance", pOk2, false);
|
||||
|
||||
if (!pOk0) {
|
||||
return false;
|
||||
}
|
||||
if (pOk1 && linearTimeScale <= 0.0f) {
|
||||
qDebug() << "offset action -- linearTimeScale must be greater than zero.";
|
||||
return false;
|
||||
}
|
||||
|
||||
lockForWrite();
|
||||
|
||||
_pointToOffsetFrom = pointToOffsetFrom;
|
||||
_positionalTargetSet = true;
|
||||
|
||||
if (pOk1) {
|
||||
_linearTimeScale = linearTimeScale;
|
||||
} else {
|
||||
_linearTimeScale = 0.1f;
|
||||
}
|
||||
|
||||
if (pOk2) {
|
||||
_linearDistance = linearDistance;
|
||||
} else {
|
||||
_linearDistance = 1.0f;
|
||||
}
|
||||
|
||||
_active = true;
|
||||
unlock();
|
||||
return true;
|
||||
}
|
35
libraries/physics/src/ObjectActionOffset.h
Normal file
35
libraries/physics/src/ObjectActionOffset.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// ObjectActionOffset.h
|
||||
// libraries/physics/src
|
||||
//
|
||||
// Created by Seth Alves 2015-6-17
|
||||
// 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_ObjectActionOffset_h
|
||||
#define hifi_ObjectActionOffset_h
|
||||
|
||||
#include <QUuid>
|
||||
|
||||
#include <EntityItem.h>
|
||||
#include "ObjectAction.h"
|
||||
|
||||
class ObjectActionOffset : public ObjectAction {
|
||||
public:
|
||||
ObjectActionOffset(QUuid id, EntityItemPointer ownerEntity);
|
||||
virtual ~ObjectActionOffset();
|
||||
|
||||
virtual bool updateArguments(QVariantMap arguments);
|
||||
virtual void updateActionWorker(float deltaTimeStep);
|
||||
|
||||
private:
|
||||
glm::vec3 _pointToOffsetFrom;
|
||||
float _linearDistance;
|
||||
float _linearTimeScale;
|
||||
bool _positionalTargetSet;
|
||||
};
|
||||
|
||||
#endif // hifi_ObjectActionOffset_h
|
|
@ -1,72 +0,0 @@
|
|||
//
|
||||
// ObjectActionPullToPoint.cpp
|
||||
// libraries/physics/src
|
||||
//
|
||||
// Created by Seth Alves 2015-6-2
|
||||
// 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
|
||||
//
|
||||
|
||||
#include "ObjectActionPullToPoint.h"
|
||||
|
||||
ObjectActionPullToPoint::ObjectActionPullToPoint(QUuid id, EntityItemPointer ownerEntity) :
|
||||
ObjectAction(id, ownerEntity) {
|
||||
#if WANT_DEBUG
|
||||
qDebug() << "ObjectActionPullToPoint::ObjectActionPullToPoint";
|
||||
#endif
|
||||
}
|
||||
|
||||
ObjectActionPullToPoint::~ObjectActionPullToPoint() {
|
||||
#if WANT_DEBUG
|
||||
qDebug() << "ObjectActionPullToPoint::~ObjectActionPullToPoint";
|
||||
#endif
|
||||
}
|
||||
|
||||
void ObjectActionPullToPoint::updateActionWorker(btScalar deltaTimeStep) {
|
||||
if (!tryLockForRead()) {
|
||||
// don't risk hanging the thread running the physics simulation
|
||||
return;
|
||||
}
|
||||
|
||||
void* physicsInfo = _ownerEntity->getPhysicsInfo();
|
||||
if (!physicsInfo) {
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(physicsInfo);
|
||||
btRigidBody* rigidBody = motionState->getRigidBody();
|
||||
if (!rigidBody) {
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
glm::vec3 offset = _target - bulletToGLM(rigidBody->getCenterOfMassPosition());
|
||||
float offsetLength = glm::length(offset);
|
||||
if (offsetLength > IGNORE_POSITION_DELTA) {
|
||||
glm::vec3 newVelocity = glm::normalize(offset) * _speed;
|
||||
rigidBody->setLinearVelocity(glmToBullet(newVelocity));
|
||||
rigidBody->activate();
|
||||
} else {
|
||||
rigidBody->setLinearVelocity(glmToBullet(glm::vec3()));
|
||||
}
|
||||
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
||||
bool ObjectActionPullToPoint::updateArguments(QVariantMap arguments) {
|
||||
bool ok = true;
|
||||
glm::vec3 target = EntityActionInterface::extractVec3Argument("pull-to-point action", arguments, "target", ok);
|
||||
float speed = EntityActionInterface::extractFloatArgument("pull-to-point action", arguments, "speed", ok);
|
||||
if (ok) {
|
||||
lockForWrite();
|
||||
_target = target;
|
||||
_speed = speed;
|
||||
_active = true;
|
||||
unlock();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
//
|
||||
// ObjectActionPullToPoint.h
|
||||
// libraries/physics/src
|
||||
//
|
||||
// Created by Seth Alves 2015-6-3
|
||||
// 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_ObjectActionPullToPoint_h
|
||||
#define hifi_ObjectActionPullToPoint_h
|
||||
|
||||
#include <QUuid>
|
||||
|
||||
#include <EntityItem.h>
|
||||
#include "ObjectAction.h"
|
||||
|
||||
class ObjectActionPullToPoint : public ObjectAction {
|
||||
public:
|
||||
ObjectActionPullToPoint(QUuid id, EntityItemPointer ownerEntity);
|
||||
virtual ~ObjectActionPullToPoint();
|
||||
|
||||
virtual bool updateArguments(QVariantMap arguments);
|
||||
virtual void updateActionWorker(float deltaTimeStep);
|
||||
|
||||
private:
|
||||
|
||||
glm::vec3 _target;
|
||||
float _speed;
|
||||
};
|
||||
|
||||
#endif // hifi_ObjectActionPullToPoint_h
|
|
@ -61,15 +61,26 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) {
|
|||
gpu::Shader::BindingSet slotBindings;
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
gpu::Shader::makeProgram(*programTextured, slotBindings);
|
||||
|
||||
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setCullMode(gpu::State::CULL_BACK);
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
state->setBlendFunction(false,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
|
||||
|
||||
gpu::StatePointer stateCullNone = gpu::StatePointer(new gpu::State());
|
||||
stateCullNone->setCullMode(gpu::State::CULL_NONE);
|
||||
stateCullNone->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
stateCullNone->setBlendFunction(false,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
|
||||
_simpleProgram = gpu::PipelinePointer(gpu::Pipeline::create(program, state));
|
||||
_simpleProgramCullNone = gpu::PipelinePointer(gpu::Pipeline::create(program, stateCullNone));
|
||||
_simpleProgramTextured = gpu::PipelinePointer(gpu::Pipeline::create(programTextured, state));
|
||||
_simpleProgramTexturedCullNone = gpu::PipelinePointer(gpu::Pipeline::create(programTextured, stateCullNone));
|
||||
|
||||
_viewState = viewState;
|
||||
loadLightProgram(directional_light_frag, false, _directionalLight, _directionalLightLocations);
|
||||
|
@ -106,13 +117,21 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) {
|
|||
lp->setAmbientSpherePreset(gpu::SphericalHarmonics::Preset(_ambientLightMode % gpu::SphericalHarmonics::NUM_PRESET));
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch, bool textured) {
|
||||
void DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled) {
|
||||
// DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(batch, true, true, true);
|
||||
|
||||
if (textured) {
|
||||
batch.setPipeline(_simpleProgramTextured);
|
||||
if (culled) {
|
||||
batch.setPipeline(_simpleProgramTextured);
|
||||
} else {
|
||||
batch.setPipeline(_simpleProgramTexturedCullNone);
|
||||
}
|
||||
} else {
|
||||
batch.setPipeline(_simpleProgram);
|
||||
if (culled) {
|
||||
batch.setPipeline(_simpleProgram);
|
||||
} else {
|
||||
batch.setPipeline(_simpleProgramCullNone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,7 +210,7 @@ void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radiu
|
|||
}
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::prepare() {
|
||||
void DeferredLightingEffect::prepare(RenderArgs* args) {
|
||||
// clear the normal and specular buffers
|
||||
auto textureCache = DependencyManager::get<TextureCache>();
|
||||
textureCache->setPrimaryDrawBuffers(false, true, false);
|
||||
|
@ -205,7 +224,7 @@ void DeferredLightingEffect::prepare() {
|
|||
textureCache->setPrimaryDrawBuffers(true, false, false);
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::render() {
|
||||
void DeferredLightingEffect::render(RenderArgs* args) {
|
||||
// perform deferred lighting, rendering to free fbo
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
|
|
@ -34,7 +34,7 @@ public:
|
|||
void init(AbstractViewStateInterface* viewState);
|
||||
|
||||
/// Sets up the state necessary to render static untextured geometry with the simple program.
|
||||
void bindSimpleProgram(gpu::Batch& batch, bool textured = false);
|
||||
void bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true);
|
||||
|
||||
/// Tears down the state necessary to render static untextured geometry with the simple program.
|
||||
void releaseSimpleProgram(gpu::Batch& batch);
|
||||
|
@ -66,8 +66,8 @@ public:
|
|||
void addSpotLight(const glm::vec3& position, float radius, const glm::vec3& color = glm::vec3(1.0f, 1.0f, 1.0f),
|
||||
float intensity = 0.5f, const glm::quat& orientation = glm::quat(), float exponent = 0.0f, float cutoff = PI);
|
||||
|
||||
void prepare();
|
||||
void render();
|
||||
void prepare(RenderArgs* args);
|
||||
void render(RenderArgs* args);
|
||||
void copyBack(RenderArgs* args);
|
||||
|
||||
void setupTransparent(RenderArgs* args, int lightBufferUnit);
|
||||
|
@ -100,7 +100,9 @@ private:
|
|||
static void loadLightProgram(const char* fragSource, bool limited, ProgramObject& program, LightLocations& locations);
|
||||
|
||||
gpu::PipelinePointer _simpleProgram;
|
||||
gpu::PipelinePointer _simpleProgramCullNone;
|
||||
gpu::PipelinePointer _simpleProgramTextured;
|
||||
gpu::PipelinePointer _simpleProgramTexturedCullNone;
|
||||
|
||||
ProgramObject _directionalSkyboxLight;
|
||||
LightLocations _directionalSkyboxLightLocations;
|
||||
|
|
|
@ -1804,6 +1804,7 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) {
|
|||
}
|
||||
|
||||
void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool translucent) {
|
||||
PerformanceTimer perfTimer("Model::renderPart");
|
||||
if (!_readyWhenAdded) {
|
||||
return; // bail asap
|
||||
}
|
||||
|
|
|
@ -19,42 +19,54 @@
|
|||
|
||||
#include <PerfStat.h>
|
||||
|
||||
#include "overlay3D_vert.h"
|
||||
#include "overlay3D_vert.h"
|
||||
#include "overlay3D_frag.h"
|
||||
|
||||
using namespace render;
|
||||
|
||||
template <> void render::jobRun(const PrepareDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
PerformanceTimer perfTimer("PrepareDeferred");
|
||||
DependencyManager::get<DeferredLightingEffect>()->prepare();
|
||||
void PrepareDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
DependencyManager::get<DeferredLightingEffect>()->prepare(renderContext->args);
|
||||
}
|
||||
|
||||
template <> void render::jobRun(const RenderDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
PerformanceTimer perfTimer("RenderDeferred");
|
||||
DependencyManager::get<DeferredLightingEffect>()->render();
|
||||
// renderContext->args->_context->syncCache();
|
||||
void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
DependencyManager::get<DeferredLightingEffect>()->render(renderContext->args);
|
||||
}
|
||||
|
||||
template <> void render::jobRun(const ResolveDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
void ResolveDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
PerformanceTimer perfTimer("ResolveDeferred");
|
||||
DependencyManager::get<DeferredLightingEffect>()->copyBack(renderContext->args);
|
||||
renderContext->args->_context->syncCache();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
RenderDeferredTask::RenderDeferredTask() : Task() {
|
||||
_jobs.push_back(Job(PrepareDeferred()));
|
||||
_jobs.push_back(Job(DrawBackground()));
|
||||
_jobs.push_back(Job(DrawOpaqueDeferred()));
|
||||
_jobs.push_back(Job(DrawLight()));
|
||||
_jobs.push_back(Job(ResetGLState()));
|
||||
_jobs.push_back(Job(RenderDeferred()));
|
||||
_jobs.push_back(Job(ResolveDeferred()));
|
||||
_jobs.push_back(Job(DrawTransparentDeferred()));
|
||||
_jobs.push_back(Job(DrawOverlay3D()));
|
||||
_jobs.push_back(Job(ResetGLState()));
|
||||
_jobs.push_back(Job(new PrepareDeferred::JobModel("PrepareDeferred")));
|
||||
_jobs.push_back(Job(new DrawBackground::JobModel("DrawBackground")));
|
||||
_jobs.push_back(Job(new FetchItems::JobModel("FetchOpaque",
|
||||
FetchItems(
|
||||
[] (const RenderContextPointer& context, int count) {
|
||||
context->_numFeedOpaqueItems = count;
|
||||
}
|
||||
)
|
||||
)));
|
||||
_jobs.push_back(Job(new CullItems::JobModel("CullOpaque", _jobs.back().getOutput())));
|
||||
_jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortOpaque", _jobs.back().getOutput())));
|
||||
_jobs.push_back(Job(new DrawOpaqueDeferred::JobModel("DrawOpaqueDeferred", _jobs.back().getOutput())));
|
||||
_jobs.push_back(Job(new DrawLight::JobModel("DrawLight")));
|
||||
_jobs.push_back(Job(new ResetGLState::JobModel()));
|
||||
_jobs.push_back(Job(new RenderDeferred::JobModel("RenderDeferred")));
|
||||
_jobs.push_back(Job(new ResolveDeferred::JobModel("ResolveDeferred")));
|
||||
_jobs.push_back(Job(new FetchItems::JobModel("FetchTransparent",
|
||||
FetchItems(
|
||||
ItemFilter::Builder::transparentShape().withoutLayered(),
|
||||
[] (const RenderContextPointer& context, int count) {
|
||||
context->_numFeedTransparentItems = count;
|
||||
}
|
||||
)
|
||||
)));
|
||||
_jobs.push_back(Job(new CullItems::JobModel("CullTransparent", _jobs.back().getOutput())));
|
||||
_jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortTransparent", _jobs.back().getOutput(), DepthSortItems(false))));
|
||||
_jobs.push_back(Job(new DrawTransparentDeferred::JobModel("TransparentDeferred", _jobs.back().getOutput())));
|
||||
_jobs.push_back(Job(new DrawOverlay3D::JobModel("DrawOverlay3D")));
|
||||
_jobs.push_back(Job(new ResetGLState::JobModel()));
|
||||
}
|
||||
|
||||
RenderDeferredTask::~RenderDeferredTask() {
|
||||
|
@ -80,181 +92,104 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <> void render::jobRun(const DrawOpaqueDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
PerformanceTimer perfTimer("DrawOpaqueDeferred");
|
||||
void DrawOpaqueDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
|
||||
// render opaques
|
||||
auto& scene = sceneContext->_scene;
|
||||
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape().withoutLayered());
|
||||
auto& renderDetails = renderContext->args->_details;
|
||||
RenderArgs* args = renderContext->args;
|
||||
gpu::Batch batch;
|
||||
args->_batch = &batch;
|
||||
|
||||
ItemIDsBounds inItems;
|
||||
inItems.reserve(items.size());
|
||||
for (auto id : items) {
|
||||
inItems.emplace_back(ItemIDAndBounds(id));
|
||||
renderContext->_numDrawnOpaqueItems = inItems.size();
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
||||
args->_viewFrustum->evalViewTransform(viewMat);
|
||||
if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) {
|
||||
viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
ItemIDsBounds& renderedItems = inItems;
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
|
||||
renderContext->_numFeedOpaqueItems = renderedItems.size();
|
||||
|
||||
ItemIDsBounds culledItems;
|
||||
culledItems.reserve(inItems.size());
|
||||
if (renderContext->_cullOpaque) {
|
||||
renderDetails.pointTo(RenderDetails::OPAQUE_ITEM);
|
||||
cullItems(sceneContext, renderContext, renderedItems, culledItems);
|
||||
renderDetails.pointTo(RenderDetails::OTHER_ITEM);
|
||||
renderedItems = culledItems;
|
||||
{
|
||||
GLenum buffers[3];
|
||||
int bufferCount = 0;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
|
||||
batch._glDrawBuffers(bufferCount, buffers);
|
||||
const float OPAQUE_ALPHA_THRESHOLD = 0.5f;
|
||||
args->_alphaThreshold = OPAQUE_ALPHA_THRESHOLD;
|
||||
}
|
||||
|
||||
renderContext->_numDrawnOpaqueItems = renderedItems.size();
|
||||
renderItems(sceneContext, renderContext, inItems, renderContext->_maxDrawnOpaqueItems);
|
||||
|
||||
|
||||
ItemIDsBounds sortedItems;
|
||||
sortedItems.reserve(culledItems.size());
|
||||
if (renderContext->_sortOpaque) {
|
||||
depthSortItems(sceneContext, renderContext, true, renderedItems, sortedItems); // Sort Front to back opaque items!
|
||||
renderedItems = sortedItems;
|
||||
}
|
||||
|
||||
// ItemIDsBounds sortedItems;
|
||||
/* ItemMaterialBucketMap stateSortedItems;
|
||||
stateSortedItems.allocateStandardMaterialBuckets();
|
||||
if (true) {
|
||||
for (auto& itemIDAndBound : renderedItems) {
|
||||
stateSortedItems.insert(itemIDAndBound.id, scene->getItem(itemIDAndBound.id).getMaterialKey());
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (renderContext->_renderOpaque) {
|
||||
RenderArgs* args = renderContext->args;
|
||||
gpu::Batch batch;
|
||||
args->_batch = &batch;
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
||||
args->_viewFrustum->evalViewTransform(viewMat);
|
||||
if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) {
|
||||
viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
|
||||
{
|
||||
GLenum buffers[3];
|
||||
int bufferCount = 0;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
|
||||
batch._glDrawBuffers(bufferCount, buffers);
|
||||
}
|
||||
|
||||
renderItems(sceneContext, renderContext, renderedItems, renderContext->_maxDrawnOpaqueItems);
|
||||
|
||||
args->_context->render((*args->_batch));
|
||||
args->_batch = nullptr;
|
||||
}
|
||||
// Before rendering the batch make sure we re in sync with gl state
|
||||
args->_context->syncCache();
|
||||
renderContext->args->_context->syncCache();
|
||||
args->_context->render((*args->_batch));
|
||||
args->_batch = nullptr;
|
||||
}
|
||||
|
||||
|
||||
template <> void render::jobRun(const DrawTransparentDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
PerformanceTimer perfTimer("DrawTransparentDeferred");
|
||||
void DrawTransparentDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
|
||||
// render transparents
|
||||
auto& scene = sceneContext->_scene;
|
||||
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::transparentShape().withoutLayered());
|
||||
auto& renderDetails = renderContext->args->_details;
|
||||
|
||||
RenderArgs* args = renderContext->args;
|
||||
gpu::Batch batch;
|
||||
args->_batch = &batch;
|
||||
|
||||
ItemIDsBounds inItems;
|
||||
inItems.reserve(items.size());
|
||||
for (auto id : items) {
|
||||
inItems.push_back(id);
|
||||
renderContext->_numDrawnTransparentItems = inItems.size();
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
||||
args->_viewFrustum->evalViewTransform(viewMat);
|
||||
if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) {
|
||||
viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
ItemIDsBounds& renderedItems = inItems;
|
||||
|
||||
renderContext->_numFeedTransparentItems = renderedItems.size();
|
||||
|
||||
ItemIDsBounds culledItems;
|
||||
if (renderContext->_cullTransparent) {
|
||||
renderDetails.pointTo(RenderDetails::TRANSLUCENT_ITEM);
|
||||
cullItems(sceneContext, renderContext, inItems, culledItems);
|
||||
renderDetails.pointTo(RenderDetails::OTHER_ITEM);
|
||||
renderedItems = culledItems;
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
const float TRANSPARENT_ALPHA_THRESHOLD = 0.0f;
|
||||
|
||||
{
|
||||
GLenum buffers[3];
|
||||
int bufferCount = 0;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
|
||||
batch._glDrawBuffers(bufferCount, buffers);
|
||||
args->_alphaThreshold = TRANSPARENT_ALPHA_THRESHOLD;
|
||||
}
|
||||
|
||||
renderContext->_numDrawnTransparentItems = renderedItems.size();
|
||||
|
||||
ItemIDsBounds sortedItems;
|
||||
if (renderContext->_sortTransparent) {
|
||||
depthSortItems(sceneContext, renderContext, false, renderedItems, sortedItems); // Sort Back to front transparent items!
|
||||
renderedItems = sortedItems;
|
||||
}
|
||||
|
||||
if (renderContext->_renderTransparent) {
|
||||
RenderArgs* args = renderContext->args;
|
||||
gpu::Batch batch;
|
||||
args->_batch = &batch;
|
||||
|
||||
renderItems(sceneContext, renderContext, inItems, renderContext->_maxDrawnTransparentItems);
|
||||
|
||||
// Before rendering the batch make sure we re in sync with gl state
|
||||
args->_context->syncCache();
|
||||
args->_context->render((*args->_batch));
|
||||
args->_batch = nullptr;
|
||||
|
||||
// reset blend function to standard...
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
|
||||
}
|
||||
|
||||
const gpu::PipelinePointer& DrawOverlay3D::getOpaquePipeline() const {
|
||||
if (!_opaquePipeline) {
|
||||
auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(overlay3D_vert)));
|
||||
auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(overlay3D_frag)));
|
||||
|
||||
auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps));
|
||||
|
||||
auto state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
||||
args->_viewFrustum->evalViewTransform(viewMat);
|
||||
if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) {
|
||||
viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
|
||||
const float TRANSPARENT_ALPHA_THRESHOLD = 0.0f;
|
||||
|
||||
{
|
||||
GLenum buffers[3];
|
||||
int bufferCount = 0;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
|
||||
batch._glDrawBuffers(bufferCount, buffers);
|
||||
args->_alphaThreshold = TRANSPARENT_ALPHA_THRESHOLD;
|
||||
}
|
||||
|
||||
|
||||
renderItems(sceneContext, renderContext, renderedItems, renderContext->_maxDrawnTransparentItems);
|
||||
|
||||
// Before rendering the batch make sure we re in sync with gl state
|
||||
args->_context->syncCache();
|
||||
args->_context->render((*args->_batch));
|
||||
args->_batch = nullptr;
|
||||
|
||||
// reset blend function to standard...
|
||||
// glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
|
||||
_opaquePipeline.reset(gpu::Pipeline::create(program, state));
|
||||
}
|
||||
return _opaquePipeline;
|
||||
}
|
||||
|
||||
const gpu::PipelinePointer& DrawOverlay3D::getOpaquePipeline() const {
|
||||
if (!_opaquePipeline) {
|
||||
auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(overlay3D_vert)));
|
||||
auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(overlay3D_frag)));
|
||||
|
||||
auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps));
|
||||
|
||||
auto state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
|
||||
_opaquePipeline.reset(gpu::Pipeline::create(program, state));
|
||||
}
|
||||
return _opaquePipeline;
|
||||
}
|
||||
|
||||
template <> void render::jobRun(const DrawOverlay3D& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
PerformanceTimer perfTimer("DrawOverlay3D");
|
||||
void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
|
||||
|
@ -271,13 +206,14 @@ template <> void render::jobRun(const DrawOverlay3D& job, const SceneContextPoin
|
|||
inItems.emplace_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
renderContext->_numFeedOverlay3DItems = inItems.size();
|
||||
renderContext->_numDrawnOverlay3DItems = inItems.size();
|
||||
|
||||
RenderArgs* args = renderContext->args;
|
||||
gpu::Batch batch;
|
||||
args->_batch = &batch;
|
||||
args->_whiteTexture = DependencyManager::get<TextureCache>()->getWhiteTexture();
|
||||
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
||||
|
@ -287,12 +223,13 @@ template <> void render::jobRun(const DrawOverlay3D& job, const SceneContextPoin
|
|||
}
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
batch.setPipeline(job.getOpaquePipeline());
|
||||
|
||||
batch.setPipeline(getOpaquePipeline());
|
||||
batch.setUniformTexture(0, args->_whiteTexture);
|
||||
|
||||
if (!inItems.empty()) {
|
||||
batch.clearFramebuffer(gpu::Framebuffer::BUFFER_DEPTH, glm::vec4(), 1.f, 0);
|
||||
renderItems(sceneContext, renderContext, inItems);
|
||||
batch.clearFramebuffer(gpu::Framebuffer::BUFFER_DEPTH, glm::vec4(), 1.f, 0);
|
||||
renderItems(sceneContext, renderContext, inItems, renderContext->_maxDrawnOverlay3DItems);
|
||||
}
|
||||
|
||||
// Before rendering the batch make sure we re in sync with gl state
|
||||
|
@ -301,3 +238,4 @@ template <> void render::jobRun(const DrawOverlay3D& job, const SceneContextPoin
|
|||
args->_batch = nullptr;
|
||||
args->_whiteTexture.reset();
|
||||
}
|
||||
|
||||
|
|
|
@ -18,48 +18,49 @@
|
|||
|
||||
class PrepareDeferred {
|
||||
public:
|
||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||
|
||||
typedef render::Job::Model<PrepareDeferred> JobModel;
|
||||
};
|
||||
namespace render {
|
||||
template <> void jobRun(const PrepareDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
|
||||
}
|
||||
|
||||
|
||||
class RenderDeferred {
|
||||
public:
|
||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||
|
||||
typedef render::Job::Model<RenderDeferred> JobModel;
|
||||
};
|
||||
namespace render {
|
||||
template <> void jobRun(const RenderDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
|
||||
}
|
||||
|
||||
class ResolveDeferred {
|
||||
public:
|
||||
};
|
||||
namespace render {
|
||||
template <> void jobRun(const ResolveDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
|
||||
}
|
||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||
|
||||
typedef render::Job::Model<ResolveDeferred> JobModel;
|
||||
};
|
||||
|
||||
class DrawOpaqueDeferred {
|
||||
public:
|
||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems);
|
||||
|
||||
typedef render::Job::ModelI<DrawOpaqueDeferred, render::ItemIDsBounds> JobModel;
|
||||
};
|
||||
namespace render {
|
||||
template <> void jobRun(const DrawOpaqueDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
|
||||
}
|
||||
|
||||
class DrawTransparentDeferred {
|
||||
public:
|
||||
};
|
||||
namespace render {
|
||||
template <> void jobRun(const DrawTransparentDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
|
||||
}
|
||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems);
|
||||
|
||||
class DrawOverlay3D {
|
||||
mutable gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable
|
||||
public:
|
||||
const gpu::PipelinePointer& getOpaquePipeline() const;
|
||||
typedef render::Job::ModelI<DrawTransparentDeferred, render::ItemIDsBounds> JobModel;
|
||||
};
|
||||
|
||||
class DrawOverlay3D {
|
||||
mutable gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable
|
||||
public:
|
||||
const gpu::PipelinePointer& getOpaquePipeline() const;
|
||||
|
||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||
|
||||
typedef render::Job::Model<DrawOverlay3D> JobModel;
|
||||
};
|
||||
namespace render {
|
||||
template <> void jobRun(const DrawOverlay3D& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
|
||||
}
|
||||
|
||||
class RenderDeferredTask : public render::Task {
|
||||
public:
|
||||
|
|
|
@ -25,11 +25,6 @@
|
|||
using namespace render;
|
||||
|
||||
DrawSceneTask::DrawSceneTask() : Task() {
|
||||
|
||||
_jobs.push_back(Job(DrawOpaque()));
|
||||
_jobs.push_back(Job(DrawLight()));
|
||||
_jobs.push_back(Job(DrawTransparent()));
|
||||
_jobs.push_back(Job(ResetGLState()));
|
||||
}
|
||||
|
||||
DrawSceneTask::~DrawSceneTask() {
|
||||
|
@ -56,8 +51,11 @@ void DrawSceneTask::run(const SceneContextPointer& sceneContext, const RenderCon
|
|||
Job::~Job() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void render::cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) {
|
||||
PerformanceTimer perfTimer("cullItems");
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
|
||||
|
@ -68,17 +66,9 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont
|
|||
renderDetails->_considered += inItems.size();
|
||||
|
||||
// Culling / LOD
|
||||
for (auto itemDetails : inItems) {
|
||||
auto item = scene->getItem(itemDetails.id);
|
||||
AABox bound;
|
||||
{
|
||||
PerformanceTimer perfTimer("getBound");
|
||||
|
||||
bound = item.getBound();
|
||||
}
|
||||
|
||||
if (bound.isNull()) {
|
||||
outItems.emplace_back(ItemIDAndBounds(itemDetails.id)); // One more Item to render
|
||||
for (auto item : inItems) {
|
||||
if (item.bounds.isNull()) {
|
||||
outItems.emplace_back(item); // One more Item to render
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -87,16 +77,16 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont
|
|||
bool outOfView;
|
||||
{
|
||||
PerformanceTimer perfTimer("boxInFrustum");
|
||||
outOfView = args->_viewFrustum->boxInFrustum(bound) == ViewFrustum::OUTSIDE;
|
||||
outOfView = args->_viewFrustum->boxInFrustum(item.bounds) == ViewFrustum::OUTSIDE;
|
||||
}
|
||||
if (!outOfView) {
|
||||
bool bigEnoughToRender;
|
||||
{
|
||||
PerformanceTimer perfTimer("shouldRender");
|
||||
bigEnoughToRender = (args->_shouldRender) ? args->_shouldRender(args, bound) : true;
|
||||
bigEnoughToRender = (args->_shouldRender) ? args->_shouldRender(args, item.bounds) : true;
|
||||
}
|
||||
if (bigEnoughToRender) {
|
||||
outItems.emplace_back(ItemIDAndBounds(itemDetails.id, bound)); // One more Item to render
|
||||
outItems.emplace_back(item); // One more Item to render
|
||||
} else {
|
||||
renderDetails->_tooSmall++;
|
||||
}
|
||||
|
@ -107,6 +97,32 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont
|
|||
renderDetails->_rendered += outItems.size();
|
||||
}
|
||||
|
||||
|
||||
void FetchItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemIDsBounds& outItems) {
|
||||
auto& scene = sceneContext->_scene;
|
||||
auto& items = scene->getMasterBucket().at(_filter);
|
||||
auto& renderDetails = renderContext->args->_details;
|
||||
|
||||
outItems.clear();
|
||||
outItems.reserve(items.size());
|
||||
for (auto id : items) {
|
||||
auto& item = scene->getItem(id);
|
||||
outItems.emplace_back(ItemIDAndBounds(id, item.getBound()));
|
||||
}
|
||||
|
||||
if (_probeNumItems) {
|
||||
_probeNumItems(renderContext, outItems.size());
|
||||
}
|
||||
}
|
||||
|
||||
void CullItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) {
|
||||
|
||||
outItems.clear();
|
||||
outItems.reserve(inItems.size());
|
||||
cullItems(sceneContext, renderContext, inItems, outItems);
|
||||
}
|
||||
|
||||
|
||||
struct ItemBound {
|
||||
float _centerDepth = 0.0f;
|
||||
float _nearDepth = 0.0f;
|
||||
|
@ -130,7 +146,6 @@ struct BackToFrontSort {
|
|||
};
|
||||
|
||||
void render::depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) {
|
||||
PerformanceTimer perfTimer("depthSortItems");
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
|
||||
|
@ -139,9 +154,10 @@ void render::depthSortItems(const SceneContextPointer& sceneContext, const Rende
|
|||
|
||||
|
||||
// Allocate and simply copy
|
||||
outItems.clear();
|
||||
outItems.reserve(inItems.size());
|
||||
|
||||
|
||||
|
||||
// Make a local dataset of the center distance and closest point distance
|
||||
std::vector<ItemBound> itemBounds;
|
||||
itemBounds.reserve(outItems.size());
|
||||
|
@ -169,8 +185,14 @@ void render::depthSortItems(const SceneContextPointer& sceneContext, const Rende
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void DepthSortItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) {
|
||||
outItems.clear();
|
||||
outItems.reserve(inItems.size());
|
||||
depthSortItems(sceneContext, renderContext, _frontToBack, inItems, outItems);
|
||||
}
|
||||
|
||||
void render::renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, int maxDrawnItems) {
|
||||
PerformanceTimer perfTimer("renderItems");
|
||||
auto& scene = sceneContext->_scene;
|
||||
RenderArgs* args = renderContext->args;
|
||||
// render
|
||||
|
@ -183,6 +205,10 @@ void render::renderItems(const SceneContextPointer& sceneContext, const RenderCo
|
|||
int numItems = 0;
|
||||
for (auto itemDetails : inItems) {
|
||||
auto item = scene->getItem(itemDetails.id);
|
||||
if (numItems + 1 >= maxDrawnItems) {
|
||||
item.render(args);
|
||||
return;
|
||||
}
|
||||
item.render(args);
|
||||
numItems++;
|
||||
if (numItems >= maxDrawnItems) {
|
||||
|
@ -224,8 +250,7 @@ void addClearStateCommands(gpu::Batch& batch) {
|
|||
// Back to no program
|
||||
batch._glUseProgram(0);
|
||||
}
|
||||
|
||||
template <> void render::jobRun(const ResetGLState& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
void ResetGLState::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
|
||||
gpu::Batch theBatch;
|
||||
addClearStateCommands(theBatch);
|
||||
|
@ -233,160 +258,7 @@ template <> void render::jobRun(const ResetGLState& job, const SceneContextPoint
|
|||
renderContext->args->_context->render(theBatch);
|
||||
}
|
||||
|
||||
template <> void render::jobRun(const DrawOpaque& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
PerformanceTimer perfTimer("DrawOpaque");
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
|
||||
// render opaques
|
||||
auto& scene = sceneContext->_scene;
|
||||
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape());
|
||||
auto& renderDetails = renderContext->args->_details;
|
||||
|
||||
ItemIDsBounds inItems;
|
||||
inItems.reserve(items.size());
|
||||
for (auto id : items) {
|
||||
inItems.emplace_back(ItemIDAndBounds(id));
|
||||
}
|
||||
ItemIDsBounds& renderedItems = inItems;
|
||||
|
||||
renderContext->_numFeedOpaqueItems = renderedItems.size();
|
||||
|
||||
ItemIDsBounds culledItems;
|
||||
culledItems.reserve(inItems.size());
|
||||
if (renderContext->_cullOpaque) {
|
||||
renderDetails.pointTo(RenderDetails::OPAQUE_ITEM);
|
||||
cullItems(sceneContext, renderContext, renderedItems, culledItems);
|
||||
renderDetails.pointTo(RenderDetails::OTHER_ITEM);
|
||||
renderedItems = culledItems;
|
||||
}
|
||||
|
||||
renderContext->_numDrawnOpaqueItems = renderedItems.size();
|
||||
|
||||
ItemIDsBounds sortedItems;
|
||||
sortedItems.reserve(culledItems.size());
|
||||
if (renderContext->_sortOpaque) {
|
||||
depthSortItems(sceneContext, renderContext, true, renderedItems, sortedItems); // Sort Front to back opaque items!
|
||||
renderedItems = sortedItems;
|
||||
}
|
||||
|
||||
if (renderContext->_renderOpaque) {
|
||||
RenderArgs* args = renderContext->args;
|
||||
gpu::Batch batch;
|
||||
args->_batch = &batch;
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
||||
args->_viewFrustum->evalViewTransform(viewMat);
|
||||
if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) {
|
||||
viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
|
||||
{
|
||||
GLenum buffers[3];
|
||||
int bufferCount = 0;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
|
||||
batch._glDrawBuffers(bufferCount, buffers);
|
||||
}
|
||||
|
||||
renderItems(sceneContext, renderContext, renderedItems, renderContext->_maxDrawnOpaqueItems);
|
||||
|
||||
args->_context->render((*args->_batch));
|
||||
args->_batch = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <> void render::jobRun(const DrawTransparent& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
PerformanceTimer perfTimer("DrawTransparent");
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
|
||||
// render transparents
|
||||
auto& scene = sceneContext->_scene;
|
||||
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::transparentShape());
|
||||
auto& renderDetails = renderContext->args->_details;
|
||||
|
||||
ItemIDsBounds inItems;
|
||||
inItems.reserve(items.size());
|
||||
for (auto id : items) {
|
||||
inItems.emplace_back(id);
|
||||
}
|
||||
ItemIDsBounds& renderedItems = inItems;
|
||||
|
||||
renderContext->_numFeedTransparentItems = renderedItems.size();
|
||||
|
||||
ItemIDsBounds culledItems;
|
||||
culledItems.reserve(inItems.size());
|
||||
if (renderContext->_cullTransparent) {
|
||||
renderDetails.pointTo(RenderDetails::TRANSLUCENT_ITEM);
|
||||
cullItems(sceneContext, renderContext, inItems, culledItems);
|
||||
renderDetails.pointTo(RenderDetails::OTHER_ITEM);
|
||||
renderedItems = culledItems;
|
||||
}
|
||||
|
||||
renderContext->_numDrawnTransparentItems = renderedItems.size();
|
||||
|
||||
ItemIDsBounds sortedItems;
|
||||
sortedItems.reserve(culledItems.size());
|
||||
if (renderContext->_sortTransparent) {
|
||||
depthSortItems(sceneContext, renderContext, false, renderedItems, sortedItems); // Sort Back to front transparent items!
|
||||
renderedItems = sortedItems;
|
||||
}
|
||||
|
||||
if (renderContext->_renderTransparent) {
|
||||
RenderArgs* args = renderContext->args;
|
||||
gpu::Batch batch;
|
||||
args->_batch = &batch;
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
||||
args->_viewFrustum->evalViewTransform(viewMat);
|
||||
if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) {
|
||||
viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
|
||||
const float MOSTLY_OPAQUE_THRESHOLD = 0.75f;
|
||||
const float TRANSPARENT_ALPHA_THRESHOLD = 0.0f;
|
||||
|
||||
// render translucent meshes afterwards
|
||||
{
|
||||
GLenum buffers[2];
|
||||
int bufferCount = 0;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
|
||||
batch._glDrawBuffers(bufferCount, buffers);
|
||||
args->_alphaThreshold = MOSTLY_OPAQUE_THRESHOLD;
|
||||
}
|
||||
|
||||
renderItems(sceneContext, renderContext, renderedItems, renderContext->_maxDrawnTransparentItems);
|
||||
|
||||
{
|
||||
GLenum buffers[3];
|
||||
int bufferCount = 0;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
|
||||
batch._glDrawBuffers(bufferCount, buffers);
|
||||
args->_alphaThreshold = TRANSPARENT_ALPHA_THRESHOLD;
|
||||
}
|
||||
|
||||
|
||||
renderItems(sceneContext, renderContext, renderedItems, renderContext->_maxDrawnTransparentItems);
|
||||
|
||||
args->_context->render((*args->_batch));
|
||||
args->_batch = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template <> void render::jobRun(const DrawLight& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
PerformanceTimer perfTimer("DrawLight");
|
||||
void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
|
||||
|
@ -398,7 +270,8 @@ template <> void render::jobRun(const DrawLight& job, const SceneContextPointer&
|
|||
ItemIDsBounds inItems;
|
||||
inItems.reserve(items.size());
|
||||
for (auto id : items) {
|
||||
inItems.emplace_back(id);
|
||||
auto item = scene->getItem(id);
|
||||
inItems.emplace_back(ItemIDAndBounds(id, item.getBound()));
|
||||
}
|
||||
|
||||
ItemIDsBounds culledItems;
|
||||
|
@ -413,8 +286,7 @@ template <> void render::jobRun(const DrawLight& job, const SceneContextPointer&
|
|||
args->_batch = nullptr;
|
||||
}
|
||||
|
||||
template <> void render::jobRun(const DrawBackground& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
PerformanceTimer perfTimer("DrawBackground");
|
||||
void DrawBackground::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
|
||||
|
@ -450,53 +322,6 @@ template <> void render::jobRun(const DrawBackground& job, const SceneContextPoi
|
|||
args->_context->syncCache();
|
||||
}
|
||||
|
||||
template <> void render::jobRun(const DrawPostLayered& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
PerformanceTimer perfTimer("DrawPostLayered");
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
|
||||
// render backgrounds
|
||||
auto& scene = sceneContext->_scene;
|
||||
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape().withLayered());
|
||||
|
||||
|
||||
ItemIDsBounds inItems;
|
||||
inItems.reserve(items.size());
|
||||
for (auto id : items) {
|
||||
auto& item = scene->getItem(id);
|
||||
if (item.getKey().isVisible() && (item.getLayer() > 0)) {
|
||||
inItems.emplace_back(id);
|
||||
}
|
||||
}
|
||||
if (inItems.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RenderArgs* args = renderContext->args;
|
||||
gpu::Batch batch;
|
||||
args->_batch = &batch;
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
||||
args->_viewFrustum->evalViewTransform(viewMat);
|
||||
if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) {
|
||||
viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
|
||||
batch.clearFramebuffer(gpu::Framebuffer::BUFFER_DEPTH, glm::vec4(), 1.f, 0);
|
||||
|
||||
renderItems(sceneContext, renderContext, inItems);
|
||||
args->_context->render((*args->_batch));
|
||||
args->_batch = nullptr;
|
||||
|
||||
// Force the context sync
|
||||
args->_context->syncCache();
|
||||
}
|
||||
|
||||
|
||||
void ItemMaterialBucketMap::insert(const ItemID& id, const model::MaterialKey& key) {
|
||||
// Insert the itemID in every bucket where it filters true
|
||||
for (auto& bucket : (*this)) {
|
||||
|
|
|
@ -13,42 +13,173 @@
|
|||
#define hifi_render_Task_h
|
||||
|
||||
#include "Engine.h"
|
||||
#include "gpu/Batch.h"
|
||||
#include <PerfStat.h>
|
||||
|
||||
|
||||
namespace render {
|
||||
|
||||
template <class T> void jobRun(const T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { }
|
||||
template <class T> void jobRun(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
jobModel.run(sceneContext, renderContext);
|
||||
}
|
||||
template <class T, class I> void jobRunI(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input) {
|
||||
jobModel.run(sceneContext, renderContext, input);
|
||||
}
|
||||
template <class T, class O> void jobRunO(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, O& output) {
|
||||
jobModel.run(sceneContext, renderContext, output);
|
||||
}
|
||||
template <class T, class I, class O> void jobRunIO(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input, O& output) {
|
||||
jobModel.run(sceneContext, renderContext, input, output);
|
||||
}
|
||||
|
||||
class Job {
|
||||
public:
|
||||
|
||||
template <class T>
|
||||
Job(T data) : _concept(new Model<T>(data)) {}
|
||||
// Varying represent a varying piece of data
|
||||
class Varying {
|
||||
public:
|
||||
|
||||
Varying(const Varying& var): _concept(var._concept) {}
|
||||
|
||||
Varying() {}
|
||||
template <class T>
|
||||
Varying(const T& data) : _concept(new Job::Varying::Model<T>(data)) {}
|
||||
|
||||
// Access the _data contained win the concept explicitely
|
||||
template <class T> T& edit() { return (static_cast<Model<T>*> (_concept.get())->_data); }
|
||||
template <class T> const T& get() const { return (static_cast<const Model<T>*> (_concept.get())->_data); }
|
||||
|
||||
protected:
|
||||
friend class Job;
|
||||
|
||||
std::vector<std::weak_ptr<Job>> _consumerJobs;
|
||||
|
||||
void addJobConsumer(const std::shared_ptr<Job>& job) {
|
||||
_consumerJobs.push_back(job);
|
||||
}
|
||||
|
||||
class Concept {
|
||||
public:
|
||||
virtual ~Concept() = default;
|
||||
};
|
||||
template <class T> class Model : public Concept {
|
||||
public:
|
||||
typedef T Data;
|
||||
Data _data;
|
||||
Model(const Model& source): _data(source.data) {}
|
||||
Model(const Data& data): _data(data) {}
|
||||
virtual ~Model() {}
|
||||
};
|
||||
|
||||
std::shared_ptr<Concept> _concept;
|
||||
};
|
||||
|
||||
Job(const Job& other) : _concept(other._concept) {}
|
||||
~Job();
|
||||
|
||||
virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
if (_concept) {
|
||||
_concept->run(sceneContext, renderContext);
|
||||
}
|
||||
const std::string& getName() const { return _concept->getName(); }
|
||||
const Varying getInput() const { return _concept->getInput(); }
|
||||
const Varying getOutput() const { return _concept->getOutput(); }
|
||||
|
||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
PerformanceTimer perfTimer(getName().c_str());
|
||||
PROFILE_RANGE(getName().c_str());
|
||||
_concept->run(sceneContext, renderContext);
|
||||
}
|
||||
|
||||
protected:
|
||||
public:
|
||||
|
||||
class Concept {
|
||||
std::string _name;
|
||||
public:
|
||||
Concept() : _name() {}
|
||||
Concept(const std::string& name) : _name(name) {}
|
||||
virtual ~Concept() = default;
|
||||
|
||||
void setName(const std::string& name) { _name = name; }
|
||||
const std::string& getName() const { return _name; }
|
||||
|
||||
virtual const Varying getInput() const { return Varying(); }
|
||||
virtual const Varying getOutput() const { return Varying(); }
|
||||
virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) = 0;
|
||||
};
|
||||
|
||||
Job(Concept* concept) : _concept(concept) {}
|
||||
|
||||
public:
|
||||
template <class T> class Model : public Concept {
|
||||
public:
|
||||
typedef T Data;
|
||||
|
||||
|
||||
Data _data;
|
||||
|
||||
Model() {}
|
||||
Model(const std::string& name): Concept(name) {}
|
||||
Model(Data data): _data(data) {}
|
||||
Model(Data data, const std::string& name): Concept(name), _data(data) {}
|
||||
|
||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { jobRun(_data, sceneContext, renderContext); }
|
||||
};
|
||||
|
||||
template <class T, class I> class ModelI : public Concept {
|
||||
public:
|
||||
typedef T Data;
|
||||
typedef I Input;
|
||||
|
||||
Data _data;
|
||||
Varying _input;
|
||||
|
||||
const Varying getInput() const { return _input; }
|
||||
|
||||
ModelI(const std::string& name, const Varying& input): Concept(name), _input(input) {}
|
||||
ModelI(const std::string& name, Data data): Concept(name), _data(data) {}
|
||||
|
||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { jobRunI(_data, sceneContext, renderContext, _input.get<I>()); }
|
||||
};
|
||||
|
||||
template <class T, class O> class ModelO : public Concept {
|
||||
public:
|
||||
typedef T Data;
|
||||
typedef O Output;
|
||||
|
||||
Data _data;
|
||||
Varying _output;
|
||||
|
||||
const Varying getOutput() const { return _output; }
|
||||
|
||||
ModelO(const std::string& name): Concept(name), _output(Output()) {
|
||||
|
||||
}
|
||||
|
||||
ModelO(const std::string& name, Data data): Concept(name), _data(data), _output(Output()) {}
|
||||
|
||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
jobRunO(_data, sceneContext, renderContext, _output.edit<O>());
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class I, class O> class ModelIO : public Concept {
|
||||
public:
|
||||
typedef T Data;
|
||||
typedef I Input;
|
||||
typedef O Output;
|
||||
|
||||
Data _data;
|
||||
Varying _input;
|
||||
Varying _output;
|
||||
|
||||
const Varying getInput() const { return _input; }
|
||||
const Varying getOutput() const { return _output; }
|
||||
|
||||
ModelIO(const std::string& name, const Varying& input, Data data = Data()): Concept(name), _data(data), _input(input), _output(Output()) {}
|
||||
ModelIO(const std::string& name, Data data, Output output): Concept(name), _data(data), _output(output) {}
|
||||
|
||||
void setInput(const Varying& input) { _input = input; }
|
||||
|
||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { jobRunIO(_data, sceneContext, renderContext, _input.get<I>(), _output.edit<O>()); }
|
||||
};
|
||||
|
||||
std::shared_ptr<Concept> _concept;
|
||||
};
|
||||
|
||||
|
@ -62,43 +193,59 @@ void depthSortItems(const SceneContextPointer& sceneContext, const RenderContext
|
|||
void renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, int maxDrawnItems = -1);
|
||||
|
||||
|
||||
|
||||
void materialSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems);
|
||||
|
||||
|
||||
class DrawOpaque {
|
||||
class FetchItems {
|
||||
public:
|
||||
typedef std::function<void (const RenderContextPointer& context, int count)> ProbeNumItems;
|
||||
FetchItems(const ProbeNumItems& probe): _probeNumItems(probe) {}
|
||||
FetchItems(const ItemFilter& filter, const ProbeNumItems& probe): _filter(filter), _probeNumItems(probe) {}
|
||||
|
||||
ItemFilter _filter = ItemFilter::Builder::opaqueShape().withoutLayered();
|
||||
ProbeNumItems _probeNumItems;
|
||||
|
||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemIDsBounds& outItems);
|
||||
|
||||
typedef Job::ModelO<FetchItems, ItemIDsBounds> JobModel;
|
||||
};
|
||||
template <> void jobRun(const DrawOpaque& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
|
||||
|
||||
|
||||
class DrawTransparent {
|
||||
class CullItems {
|
||||
public:
|
||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems);
|
||||
|
||||
typedef Job::ModelIO<CullItems, ItemIDsBounds, ItemIDsBounds> JobModel;
|
||||
};
|
||||
|
||||
class DepthSortItems {
|
||||
public:
|
||||
bool _frontToBack = true;
|
||||
|
||||
DepthSortItems(bool frontToBack = true) : _frontToBack(frontToBack) {}
|
||||
|
||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outITems);
|
||||
|
||||
typedef Job::ModelIO<DepthSortItems, ItemIDsBounds, ItemIDsBounds> JobModel;
|
||||
};
|
||||
template <> void jobRun(const DrawTransparent& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
|
||||
|
||||
class DrawLight {
|
||||
public:
|
||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
|
||||
|
||||
typedef Job::Model<DrawLight> JobModel;
|
||||
};
|
||||
template <> void jobRun(const DrawLight& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
|
||||
|
||||
class DrawBackground {
|
||||
public:
|
||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
|
||||
|
||||
typedef Job::Model<DrawBackground> JobModel;
|
||||
};
|
||||
template <> void jobRun(const DrawBackground& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
|
||||
|
||||
|
||||
class DrawPostLayered {
|
||||
public:
|
||||
};
|
||||
template <> void jobRun(const DrawPostLayered& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
|
||||
|
||||
|
||||
|
||||
class ResetGLState {
|
||||
public:
|
||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
|
||||
|
||||
typedef Job::Model<ResetGLState> JobModel;
|
||||
};
|
||||
template <> void jobRun(const ResetGLState& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
|
||||
|
||||
|
||||
|
||||
class DrawSceneTask : public Task {
|
||||
|
@ -126,6 +273,7 @@ public:
|
|||
// standard builders allocating the main buckets
|
||||
void allocateStandardMaterialBuckets();
|
||||
};
|
||||
void materialSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,10 @@ public:
|
|||
int _numDrawnTransparentItems = 0;
|
||||
int _maxDrawnTransparentItems = -1;
|
||||
|
||||
int _numFeedOverlay3DItems = 0;
|
||||
int _numDrawnOverlay3DItems = 0;
|
||||
int _maxDrawnOverlay3DItems = -1;
|
||||
|
||||
RenderContext() {}
|
||||
};
|
||||
typedef std::shared_ptr<RenderContext> RenderContextPointer;
|
||||
|
|
|
@ -159,4 +159,6 @@ void SceneScriptingInterface::clearEngineCounters() {
|
|||
_numDrawnOpaqueItems = 0;
|
||||
_numFeedTransparentItems = 0;
|
||||
_numDrawnTransparentItems = 0;
|
||||
_numFeedOverlay3DItems = 0;
|
||||
_numDrawnOverlay3DItems = 0;
|
||||
}
|
||||
|
|
|
@ -90,17 +90,22 @@ public:
|
|||
Q_INVOKABLE int getEngineNumDrawnOpaqueItems() { return _numDrawnOpaqueItems; }
|
||||
void setEngineDrawnTransparentItems(int count) { _numDrawnTransparentItems = count; }
|
||||
Q_INVOKABLE int getEngineNumDrawnTransparentItems() { return _numDrawnTransparentItems; }
|
||||
void setEngineDrawnOverlay3DItems(int count) { _numDrawnOverlay3DItems = count; }
|
||||
Q_INVOKABLE int getEngineNumDrawnOverlay3DItems() { return _numDrawnOverlay3DItems; }
|
||||
|
||||
void setEngineFeedOpaqueItems(int count) { _numFeedOpaqueItems = count; }
|
||||
Q_INVOKABLE int getEngineNumFeedOpaqueItems() { return _numFeedOpaqueItems; }
|
||||
void setEngineFeedTransparentItems(int count) { _numFeedTransparentItems = count; }
|
||||
Q_INVOKABLE int getEngineNumFeedTransparentItems() { return _numFeedTransparentItems; }
|
||||
void setEngineFeedOverlay3DItems(int count) { _numFeedOverlay3DItems = count; }
|
||||
Q_INVOKABLE int getEngineNumFeedOverlay3DItems() { return _numFeedOverlay3DItems; }
|
||||
|
||||
Q_INVOKABLE void setEngineMaxDrawnOpaqueItems(int count) { _maxDrawnOpaqueItems = count; }
|
||||
Q_INVOKABLE int getEngineMaxDrawnOpaqueItems() { return _maxDrawnOpaqueItems; }
|
||||
Q_INVOKABLE void setEngineMaxDrawnTransparentItems(int count) { _maxDrawnTransparentItems = count; }
|
||||
Q_INVOKABLE int getEngineMaxDrawnTransparentItems() { return _maxDrawnTransparentItems; }
|
||||
|
||||
Q_INVOKABLE void setEngineMaxDrawnOverlay3DItems(int count) { _maxDrawnOverlay3DItems = count; }
|
||||
Q_INVOKABLE int getEngineMaxDrawnOverlay3DItems() { return _maxDrawnOverlay3DItems; }
|
||||
signals:
|
||||
void shouldRenderAvatarsChanged(bool shouldRenderAvatars);
|
||||
void shouldRenderEntitiesChanged(bool shouldRenderEntities);
|
||||
|
@ -124,9 +129,12 @@ protected:
|
|||
int _numDrawnOpaqueItems = 0;
|
||||
int _numFeedTransparentItems = 0;
|
||||
int _numDrawnTransparentItems = 0;
|
||||
int _numFeedOverlay3DItems = 0;
|
||||
int _numDrawnOverlay3DItems = 0;
|
||||
|
||||
int _maxDrawnOpaqueItems = -1;
|
||||
int _maxDrawnTransparentItems = -1;
|
||||
int _maxDrawnOverlay3DItems = -1;
|
||||
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue