mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 20:25:00 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into dressing-room
This commit is contained in:
commit
56679c6a1d
50 changed files with 844 additions and 550 deletions
|
@ -551,7 +551,9 @@ void AudioMixer::handleNodeAudioPacket(QSharedPointer<ReceivedMessage> message,
|
||||||
void AudioMixer::handleMuteEnvironmentPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
|
void AudioMixer::handleMuteEnvironmentPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
|
||||||
if (sendingNode->getCanAdjustLocks()) {
|
if (sendingNode->isAllowedEditor()) {
|
||||||
|
qDebug() << "Received a mute environment packet of" << message->getSize() << "bytes";
|
||||||
|
|
||||||
auto newPacket = NLPacket::create(PacketType::MuteEnvironment, message->getSize());
|
auto newPacket = NLPacket::create(PacketType::MuteEnvironment, message->getSize());
|
||||||
// Copy payload
|
// Copy payload
|
||||||
newPacket->write(message->getRawMessage(), message->getSize());
|
newPacket->write(message->getRawMessage(), message->getSize());
|
||||||
|
|
|
@ -155,7 +155,7 @@ SharedNodePointer DomainGatekeeper::processAssignmentConnectRequest(const NodeCo
|
||||||
_pendingAssignedNodes.erase(it);
|
_pendingAssignedNodes.erase(it);
|
||||||
|
|
||||||
// always allow assignment clients to create and destroy entities
|
// always allow assignment clients to create and destroy entities
|
||||||
newNode->setCanAdjustLocks(true);
|
newNode->setIsAllowedEditor(true);
|
||||||
newNode->setCanRez(true);
|
newNode->setCanRez(true);
|
||||||
|
|
||||||
return newNode;
|
return newNode;
|
||||||
|
@ -219,13 +219,13 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if this user is in the editors list (or if the editors list is empty) set the user's node's canAdjustLocks to true
|
// if this user is in the editors list (or if the editors list is empty) set the user's node's isAllowedEditor to true
|
||||||
const QVariant* allowedEditorsVariant =
|
const QVariant* allowedEditorsVariant =
|
||||||
valueForKeyPath(_server->_settingsManager.getSettingsMap(), ALLOWED_EDITORS_SETTINGS_KEYPATH);
|
valueForKeyPath(_server->_settingsManager.getSettingsMap(), ALLOWED_EDITORS_SETTINGS_KEYPATH);
|
||||||
QStringList allowedEditors = allowedEditorsVariant ? allowedEditorsVariant->toStringList() : QStringList();
|
QStringList allowedEditors = allowedEditorsVariant ? allowedEditorsVariant->toStringList() : QStringList();
|
||||||
|
|
||||||
// if the allowed editors list is empty then everyone can adjust locks
|
// if the allowed editors list is empty then everyone can adjust locks
|
||||||
bool canAdjustLocks = allowedEditors.empty();
|
bool isAllowedEditor = allowedEditors.empty();
|
||||||
|
|
||||||
if (allowedEditors.contains(username, Qt::CaseInsensitive)) {
|
if (allowedEditors.contains(username, Qt::CaseInsensitive)) {
|
||||||
// we have a non-empty allowed editors list - check if this user is verified to be in it
|
// we have a non-empty allowed editors list - check if this user is verified to be in it
|
||||||
|
@ -238,10 +238,10 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
|
||||||
<< "will be given edit rights to avoid a thrasing of public key requests and connect requests.";
|
<< "will be given edit rights to avoid a thrasing of public key requests and connect requests.";
|
||||||
}
|
}
|
||||||
|
|
||||||
canAdjustLocks = true;
|
isAllowedEditor = true;
|
||||||
} else {
|
} else {
|
||||||
// already verified this user and they are in the allowed editors list
|
// already verified this user and they are in the allowed editors list
|
||||||
canAdjustLocks = true;
|
isAllowedEditor = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,14 +256,14 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
|
||||||
|
|
||||||
bool canRez = true;
|
bool canRez = true;
|
||||||
if (onlyEditorsAreRezzers) {
|
if (onlyEditorsAreRezzers) {
|
||||||
canRez = canAdjustLocks;
|
canRez = isAllowedEditor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the new node
|
// add the new node
|
||||||
SharedNodePointer newNode = addVerifiedNodeFromConnectRequest(nodeConnection);
|
SharedNodePointer newNode = addVerifiedNodeFromConnectRequest(nodeConnection);
|
||||||
|
|
||||||
// set the edit rights for this user
|
// set the edit rights for this user
|
||||||
newNode->setCanAdjustLocks(canAdjustLocks);
|
newNode->setIsAllowedEditor(isAllowedEditor);
|
||||||
newNode->setCanRez(canRez);
|
newNode->setCanRez(canRez);
|
||||||
|
|
||||||
// grab the linked data for our new node so we can set the username
|
// grab the linked data for our new node so we can set the username
|
||||||
|
|
|
@ -744,7 +744,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
|
||||||
|
|
||||||
extendedHeaderStream << limitedNodeList->getSessionUUID();
|
extendedHeaderStream << limitedNodeList->getSessionUUID();
|
||||||
extendedHeaderStream << node->getUUID();
|
extendedHeaderStream << node->getUUID();
|
||||||
extendedHeaderStream << (quint8) node->getCanAdjustLocks();
|
extendedHeaderStream << (quint8) node->isAllowedEditor();
|
||||||
extendedHeaderStream << (quint8) node->getCanRez();
|
extendedHeaderStream << (quint8) node->getCanRez();
|
||||||
|
|
||||||
auto domainListPackets = NLPacketList::create(PacketType::DomainList, extendedHeader);
|
auto domainListPackets = NLPacketList::create(PacketType::DomainList, extendedHeader);
|
||||||
|
|
|
@ -22,41 +22,44 @@ var MINIMUM_DROP_DISTANCE_FROM_JOINT = 0.8;
|
||||||
var ATTACHED_ENTITY_SEARCH_DISTANCE = 10.0;
|
var ATTACHED_ENTITY_SEARCH_DISTANCE = 10.0;
|
||||||
var ATTACHED_ENTITIES_SETTINGS_KEY = "ATTACHED_ENTITIES";
|
var ATTACHED_ENTITIES_SETTINGS_KEY = "ATTACHED_ENTITIES";
|
||||||
var DRESSING_ROOM_DISTANCE = 2.0;
|
var DRESSING_ROOM_DISTANCE = 2.0;
|
||||||
|
var SHOW_TOOL_BAR = false;
|
||||||
|
|
||||||
// tool bar
|
// tool bar
|
||||||
|
|
||||||
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
if (SHOW_TOOL_BAR) {
|
||||||
var BUTTON_SIZE = 32;
|
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
||||||
var PADDING = 3;
|
var BUTTON_SIZE = 32;
|
||||||
Script.include(["libraries/toolBars.js"]);
|
var PADDING = 3;
|
||||||
var toolBar = new ToolBar(0, 0, ToolBar.VERTICAL, "highfidelity.attachedEntities.toolbar", function(screenSize) {
|
Script.include(["libraries/toolBars.js"]);
|
||||||
return {
|
var toolBar = new ToolBar(0, 0, ToolBar.VERTICAL, "highfidelity.attachedEntities.toolbar", function(screenSize) {
|
||||||
x: (BUTTON_SIZE + PADDING),
|
return {
|
||||||
y: (screenSize.y / 2 - BUTTON_SIZE * 2 + PADDING)
|
x: (BUTTON_SIZE + PADDING),
|
||||||
};
|
y: (screenSize.y / 2 - BUTTON_SIZE * 2 + PADDING)
|
||||||
});
|
};
|
||||||
var saveButton = toolBar.addOverlay("image", {
|
});
|
||||||
width: BUTTON_SIZE,
|
var saveButton = toolBar.addOverlay("image", {
|
||||||
height: BUTTON_SIZE,
|
width: BUTTON_SIZE,
|
||||||
imageURL: "http://headache.hungry.com/~seth/hifi/save.png",
|
height: BUTTON_SIZE,
|
||||||
color: {
|
imageURL: ".../save.png",
|
||||||
red: 255,
|
color: {
|
||||||
green: 255,
|
red: 255,
|
||||||
blue: 255
|
green: 255,
|
||||||
},
|
blue: 255
|
||||||
alpha: 1
|
},
|
||||||
});
|
alpha: 1
|
||||||
var loadButton = toolBar.addOverlay("image", {
|
});
|
||||||
width: BUTTON_SIZE,
|
var loadButton = toolBar.addOverlay("image", {
|
||||||
height: BUTTON_SIZE,
|
width: BUTTON_SIZE,
|
||||||
imageURL: "http://headache.hungry.com/~seth/hifi/load.png",
|
height: BUTTON_SIZE,
|
||||||
color: {
|
imageURL: ".../load.png",
|
||||||
red: 255,
|
color: {
|
||||||
green: 255,
|
red: 255,
|
||||||
blue: 255
|
green: 255,
|
||||||
},
|
blue: 255
|
||||||
alpha: 1
|
},
|
||||||
});
|
alpha: 1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function mousePressEvent(event) {
|
function mousePressEvent(event) {
|
||||||
|
@ -73,10 +76,14 @@ function mousePressEvent(event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function scriptEnding() {
|
function scriptEnding() {
|
||||||
toolBar.cleanup();
|
if (SHOW_TOOL_BAR) {
|
||||||
|
toolBar.cleanup();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.mousePressEvent.connect(mousePressEvent);
|
if (SHOW_TOOL_BAR) {
|
||||||
|
Controller.mousePressEvent.connect(mousePressEvent);
|
||||||
|
}
|
||||||
Script.scriptEnding.connect(scriptEnding);
|
Script.scriptEnding.connect(scriptEnding);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1266,6 +1266,7 @@ function MyController(hand) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.getPresetPosition = function() {
|
this.getPresetPosition = function() {
|
||||||
|
|
|
@ -21,3 +21,4 @@ Script.load("controllers/squeezeHands.js");
|
||||||
Script.load("grab.js");
|
Script.load("grab.js");
|
||||||
Script.load("directory.js");
|
Script.load("directory.js");
|
||||||
Script.load("dialTone.js");
|
Script.load("dialTone.js");
|
||||||
|
Script.load("attachedEntitiesManager.js");
|
||||||
|
|
|
@ -39,10 +39,10 @@ var lightOverlayManager = new LightOverlayManager();
|
||||||
var cameraManager = new CameraManager();
|
var cameraManager = new CameraManager();
|
||||||
|
|
||||||
var grid = Grid();
|
var grid = Grid();
|
||||||
gridTool = GridTool({
|
// gridTool = GridTool({
|
||||||
horizontalGrid: grid
|
// horizontalGrid: grid
|
||||||
});
|
// });
|
||||||
gridTool.setVisible(false);
|
// gridTool.setVisible(false);
|
||||||
|
|
||||||
var entityListTool = EntityListTool();
|
var entityListTool = EntityListTool();
|
||||||
|
|
||||||
|
@ -336,7 +336,7 @@ var toolBar = (function() {
|
||||||
isActive = active;
|
isActive = active;
|
||||||
if (!isActive) {
|
if (!isActive) {
|
||||||
entityListTool.setVisible(false);
|
entityListTool.setVisible(false);
|
||||||
gridTool.setVisible(false);
|
// gridTool.setVisible(false);
|
||||||
grid.setEnabled(false);
|
grid.setEnabled(false);
|
||||||
propertiesTool.setVisible(false);
|
propertiesTool.setVisible(false);
|
||||||
selectionManager.clearSelections();
|
selectionManager.clearSelections();
|
||||||
|
@ -344,7 +344,7 @@ var toolBar = (function() {
|
||||||
} else {
|
} else {
|
||||||
hasShownPropertiesTool = false;
|
hasShownPropertiesTool = false;
|
||||||
entityListTool.setVisible(true);
|
entityListTool.setVisible(true);
|
||||||
gridTool.setVisible(true);
|
// gridTool.setVisible(true);
|
||||||
grid.setEnabled(true);
|
grid.setEnabled(true);
|
||||||
propertiesTool.setVisible(true);
|
propertiesTool.setVisible(true);
|
||||||
Window.setFocus();
|
Window.setFocus();
|
||||||
|
|
|
@ -235,7 +235,12 @@ var usersWindow = (function () {
|
||||||
FRIENDS_BUTTON_HEIGHT = FRIENDS_BUTTON_SVG_HEIGHT,
|
FRIENDS_BUTTON_HEIGHT = FRIENDS_BUTTON_SVG_HEIGHT,
|
||||||
FRIENDS_BUTTON_COLOR = { red: 225, green: 225, blue: 225 },
|
FRIENDS_BUTTON_COLOR = { red: 225, green: 225, blue: 225 },
|
||||||
FRIENDS_BUTTON_ALPHA = 0.95,
|
FRIENDS_BUTTON_ALPHA = 0.95,
|
||||||
|
FRIENDS_WINDOW_URL = "https://metaverse.highfidelity.com/user/friends",
|
||||||
|
FRIENDS_WINDOW_WIDTH = 290,
|
||||||
|
FRIENDS_WINDOW_HEIGHT = 500,
|
||||||
|
FRIENDS_WINDOW_TITLE = "Add/Remove Friends",
|
||||||
friendsButton,
|
friendsButton,
|
||||||
|
friendsWindow,
|
||||||
|
|
||||||
OPTION_BACKGROUND_COLOR = { red: 60, green: 60, blue: 60 },
|
OPTION_BACKGROUND_COLOR = { red: 60, green: 60, blue: 60 },
|
||||||
OPTION_BACKGROUND_ALPHA = 0.1,
|
OPTION_BACKGROUND_ALPHA = 0.1,
|
||||||
|
@ -643,7 +648,17 @@ var usersWindow = (function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clickedOverlay === friendsButton) {
|
if (clickedOverlay === friendsButton) {
|
||||||
GlobalServices.editFriends();
|
if (!friendsWindow) {
|
||||||
|
friendsWindow = new OverlayWebWindow({
|
||||||
|
title: FRIENDS_WINDOW_TITLE,
|
||||||
|
width: FRIENDS_WINDOW_WIDTH,
|
||||||
|
height: FRIENDS_WINDOW_HEIGHT,
|
||||||
|
visible: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
friendsWindow.setURL(FRIENDS_WINDOW_URL);
|
||||||
|
friendsWindow.setVisible(true);
|
||||||
|
friendsWindow.raise();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -247,7 +247,9 @@
|
||||||
{ "var": "isTurningRight", "state": "turnRight" },
|
{ "var": "isTurningRight", "state": "turnRight" },
|
||||||
{ "var": "isTurningLeft", "state": "turnLeft" },
|
{ "var": "isTurningLeft", "state": "turnLeft" },
|
||||||
{ "var": "isAway", "state": "awayIntro" },
|
{ "var": "isAway", "state": "awayIntro" },
|
||||||
{ "var": "isFlying", "state": "fly" }
|
{ "var": "isFlying", "state": "fly" },
|
||||||
|
{ "var": "isTakeoff", "state": "takeoff" },
|
||||||
|
{ "var": "isInAir", "state": "inAir" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -263,7 +265,9 @@
|
||||||
{ "var": "isTurningRight", "state": "turnRight" },
|
{ "var": "isTurningRight", "state": "turnRight" },
|
||||||
{ "var": "isTurningLeft", "state": "turnLeft" },
|
{ "var": "isTurningLeft", "state": "turnLeft" },
|
||||||
{ "var": "isAway", "state": "awayIntro" },
|
{ "var": "isAway", "state": "awayIntro" },
|
||||||
{ "var": "isFlying", "state": "fly" }
|
{ "var": "isFlying", "state": "fly" },
|
||||||
|
{ "var": "isTakeoff", "state": "takeoff" },
|
||||||
|
{ "var": "isInAir", "state": "inAir" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -278,7 +282,9 @@
|
||||||
{ "var": "isTurningRight", "state": "turnRight" },
|
{ "var": "isTurningRight", "state": "turnRight" },
|
||||||
{ "var": "isTurningLeft", "state": "turnLeft" },
|
{ "var": "isTurningLeft", "state": "turnLeft" },
|
||||||
{ "var": "isAway", "state": "awayIntro" },
|
{ "var": "isAway", "state": "awayIntro" },
|
||||||
{ "var": "isFlying", "state": "fly" }
|
{ "var": "isFlying", "state": "fly" },
|
||||||
|
{ "var": "isTakeoff", "state": "takeoff" },
|
||||||
|
{ "var": "isInAir", "state": "inAir" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -293,7 +299,9 @@
|
||||||
{ "var": "isTurningRight", "state": "turnRight" },
|
{ "var": "isTurningRight", "state": "turnRight" },
|
||||||
{ "var": "isTurningLeft", "state": "turnLeft" },
|
{ "var": "isTurningLeft", "state": "turnLeft" },
|
||||||
{ "var": "isAway", "state": "awayIntro" },
|
{ "var": "isAway", "state": "awayIntro" },
|
||||||
{ "var": "isFlying", "state": "fly" }
|
{ "var": "isFlying", "state": "fly" },
|
||||||
|
{ "var": "isTakeoff", "state": "takeoff" },
|
||||||
|
{ "var": "isInAir", "state": "inAir" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -308,7 +316,9 @@
|
||||||
{ "var": "isTurningRight", "state": "turnRight" },
|
{ "var": "isTurningRight", "state": "turnRight" },
|
||||||
{ "var": "isTurningLeft", "state": "turnLeft" },
|
{ "var": "isTurningLeft", "state": "turnLeft" },
|
||||||
{ "var": "isAway", "state": "awayIntro" },
|
{ "var": "isAway", "state": "awayIntro" },
|
||||||
{ "var": "isFlying", "state": "fly" }
|
{ "var": "isFlying", "state": "fly" },
|
||||||
|
{ "var": "isTakeoff", "state": "takeoff" },
|
||||||
|
{ "var": "isInAir", "state": "inAir" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -323,7 +333,9 @@
|
||||||
{ "var": "isTurningRight", "state": "turnRight" },
|
{ "var": "isTurningRight", "state": "turnRight" },
|
||||||
{ "var": "isTurningLeft", "state": "turnLeft" },
|
{ "var": "isTurningLeft", "state": "turnLeft" },
|
||||||
{ "var": "isAway", "state": "awayIntro" },
|
{ "var": "isAway", "state": "awayIntro" },
|
||||||
{ "var": "isFlying", "state": "fly" }
|
{ "var": "isFlying", "state": "fly" },
|
||||||
|
{ "var": "isTakeoff", "state": "takeoff" },
|
||||||
|
{ "var": "isInAir", "state": "inAir" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -338,7 +350,9 @@
|
||||||
{ "var": "isMovingLeft", "state": "strafeLeft" },
|
{ "var": "isMovingLeft", "state": "strafeLeft" },
|
||||||
{ "var": "isTurningLeft", "state": "turnLeft" },
|
{ "var": "isTurningLeft", "state": "turnLeft" },
|
||||||
{ "var": "isAway", "state": "awayIntro" },
|
{ "var": "isAway", "state": "awayIntro" },
|
||||||
{ "var": "isFlying", "state": "fly" }
|
{ "var": "isFlying", "state": "fly" },
|
||||||
|
{ "var": "isTakeoff", "state": "takeoff" },
|
||||||
|
{ "var": "isInAir", "state": "inAir" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -353,7 +367,9 @@
|
||||||
{ "var": "isMovingLeft", "state": "strafeLeft" },
|
{ "var": "isMovingLeft", "state": "strafeLeft" },
|
||||||
{ "var": "isTurningRight", "state": "turnRight" },
|
{ "var": "isTurningRight", "state": "turnRight" },
|
||||||
{ "var": "isAway", "state": "awayIntro" },
|
{ "var": "isAway", "state": "awayIntro" },
|
||||||
{ "var": "isFlying", "state": "fly" }
|
{ "var": "isFlying", "state": "fly" },
|
||||||
|
{ "var": "isTakeoff", "state": "takeoff" },
|
||||||
|
{ "var": "isInAir", "state": "inAir" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -361,6 +377,7 @@
|
||||||
"interpTarget": 30,
|
"interpTarget": 30,
|
||||||
"interpDuration": 30,
|
"interpDuration": 30,
|
||||||
"transitions": [
|
"transitions": [
|
||||||
|
{ "var": "isNotAway", "state": "awayOutro" },
|
||||||
{ "var": "awayIntroOnDone", "state": "away"}
|
{ "var": "awayIntroOnDone", "state": "away"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -385,8 +402,27 @@
|
||||||
"interpTarget": 6,
|
"interpTarget": 6,
|
||||||
"interpDuration": 6,
|
"interpDuration": 6,
|
||||||
"transitions": [
|
"transitions": [
|
||||||
|
{ "var": "isAway", "state": "awayIntro" },
|
||||||
{ "var": "isNotFlying", "state": "idle" }
|
{ "var": "isNotFlying", "state": "idle" }
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "takeoff",
|
||||||
|
"interpTarget": 0,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "isAway", "state": "awayIntro" },
|
||||||
|
{ "var": "isNotTakeoff", "state": "inAir" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "inAir",
|
||||||
|
"interpTarget": 0,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "isAway", "state": "awayIntro" },
|
||||||
|
{ "var": "isNotInAir", "state": "idle" }
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -685,6 +721,64 @@
|
||||||
"loopFlag": true
|
"loopFlag": true
|
||||||
},
|
},
|
||||||
"children": []
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "takeoff",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "https://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/jump_takeoff.fbx",
|
||||||
|
"startFrame": 1.0,
|
||||||
|
"endFrame": 2.5,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": false
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "inAir",
|
||||||
|
"type": "blendLinear",
|
||||||
|
"data": {
|
||||||
|
"alpha": 0.0,
|
||||||
|
"alphaVar": "inAirAlpha"
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "inAirPreApex",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "https://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/jump_in_air.fbx",
|
||||||
|
"startFrame": 0.0,
|
||||||
|
"endFrame": 0.0,
|
||||||
|
"timeScale": 0.0,
|
||||||
|
"loopFlag": false
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "inAirApex",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "https://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/jump_in_air.fbx",
|
||||||
|
"startFrame": 6.0,
|
||||||
|
"endFrame": 6.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": false
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "inAirPostApex",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "https://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/jump_in_air.fbx",
|
||||||
|
"startFrame": 11.0,
|
||||||
|
"endFrame": 11.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": false
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
import QtQuick.Controls 1.4
|
import QtQuick.Controls 1.4
|
||||||
|
import QtWebEngine 1.1;
|
||||||
|
|
||||||
import "../desktop"
|
import "../desktop"
|
||||||
import ".."
|
import ".."
|
||||||
|
@ -7,6 +8,13 @@ import ".."
|
||||||
Desktop {
|
Desktop {
|
||||||
id: desktop
|
id: desktop
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
WebEngine.settings.javascriptCanOpenWindows = false;
|
||||||
|
WebEngine.settings.javascriptCanAccessClipboard = false;
|
||||||
|
WebEngine.settings.spatialNavigationEnabled = true;
|
||||||
|
WebEngine.settings.localContentCanAccessRemoteUrls = true;
|
||||||
|
}
|
||||||
|
|
||||||
// The tool window, one instance
|
// The tool window, one instance
|
||||||
property alias toolWindow: toolWindow
|
property alias toolWindow: toolWindow
|
||||||
ToolWindow { id: toolWindow }
|
ToolWindow { id: toolWindow }
|
||||||
|
|
|
@ -6,8 +6,10 @@ import "../controls"
|
||||||
Frame {
|
Frame {
|
||||||
id: frame
|
id: frame
|
||||||
|
|
||||||
|
property bool wideTopMargin: (window && (window.closable || window.title));
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors { margins: -iconSize; topMargin: -iconSize * ((window && window.closable) ? 2 : 1); }
|
anchors { margins: -iconSize; topMargin: -iconSize * (wideTopMargin ? 2 : 1); }
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
color: "#7f7f7f7f";
|
color: "#7f7f7f7f";
|
||||||
radius: 3;
|
radius: 3;
|
||||||
|
|
|
@ -1362,6 +1362,9 @@ void Application::paintGL() {
|
||||||
renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE;
|
renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE;
|
||||||
renderArgs._blitFramebuffer = DependencyManager::get<FramebufferCache>()->getSelfieFramebuffer();
|
renderArgs._blitFramebuffer = DependencyManager::get<FramebufferCache>()->getSelfieFramebuffer();
|
||||||
|
|
||||||
|
auto inputs = AvatarInputs::getInstance();
|
||||||
|
_mirrorViewRect.moveTo(inputs->x(), inputs->y());
|
||||||
|
|
||||||
renderRearViewMirror(&renderArgs, _mirrorViewRect);
|
renderRearViewMirror(&renderArgs, _mirrorViewRect);
|
||||||
|
|
||||||
renderArgs._blitFramebuffer.reset();
|
renderArgs._blitFramebuffer.reset();
|
||||||
|
@ -4612,22 +4615,6 @@ void Application::activeChanged(Qt::ApplicationState state) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Application::showFriendsWindow() {
|
|
||||||
const QString FRIENDS_WINDOW_OBJECT_NAME = "FriendsWindow";
|
|
||||||
const QString FRIENDS_WINDOW_TITLE = "Add/Remove Friends";
|
|
||||||
const QString FRIENDS_WINDOW_URL = "https://metaverse.highfidelity.com/user/friends";
|
|
||||||
const int FRIENDS_WINDOW_WIDTH = 290;
|
|
||||||
const int FRIENDS_WINDOW_HEIGHT = 500;
|
|
||||||
auto webWindowClass = _window->findChildren<WebWindowClass>(FRIENDS_WINDOW_OBJECT_NAME);
|
|
||||||
if (webWindowClass.empty()) {
|
|
||||||
auto friendsWindow = new WebWindowClass(FRIENDS_WINDOW_TITLE, FRIENDS_WINDOW_URL, FRIENDS_WINDOW_WIDTH,
|
|
||||||
FRIENDS_WINDOW_HEIGHT);
|
|
||||||
friendsWindow->setParent(_window);
|
|
||||||
friendsWindow->setObjectName(FRIENDS_WINDOW_OBJECT_NAME);
|
|
||||||
connect(friendsWindow, &WebWindowClass::closed, &WebWindowClass::deleteLater);
|
|
||||||
friendsWindow->setVisible(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::postLambdaEvent(std::function<void()> f) {
|
void Application::postLambdaEvent(std::function<void()> f) {
|
||||||
if (this->thread() == QThread::currentThread()) {
|
if (this->thread() == QThread::currentThread()) {
|
||||||
|
|
|
@ -167,11 +167,11 @@ public:
|
||||||
virtual controller::ScriptingInterface* getControllerScriptingInterface() { return _controllerScriptingInterface; }
|
virtual controller::ScriptingInterface* getControllerScriptingInterface() { return _controllerScriptingInterface; }
|
||||||
virtual void registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) override;
|
virtual void registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) override;
|
||||||
|
|
||||||
virtual ViewFrustum* getCurrentViewFrustum() { return getDisplayViewFrustum(); }
|
virtual ViewFrustum* getCurrentViewFrustum() override { return getDisplayViewFrustum(); }
|
||||||
virtual QThread* getMainThread() { return thread(); }
|
virtual QThread* getMainThread() override { return thread(); }
|
||||||
virtual PickRay computePickRay(float x, float y) const;
|
virtual PickRay computePickRay(float x, float y) const override;
|
||||||
virtual glm::vec3 getAvatarPosition() const;
|
virtual glm::vec3 getAvatarPosition() const override;
|
||||||
virtual qreal getDevicePixelRatio();
|
virtual qreal getDevicePixelRatio() override;
|
||||||
|
|
||||||
void setActiveDisplayPlugin(const QString& pluginName);
|
void setActiveDisplayPlugin(const QString& pluginName);
|
||||||
|
|
||||||
|
@ -245,8 +245,6 @@ public slots:
|
||||||
void handleLocalServerConnection();
|
void handleLocalServerConnection();
|
||||||
void readArgumentsFromLocalSocket();
|
void readArgumentsFromLocalSocket();
|
||||||
|
|
||||||
void showFriendsWindow();
|
|
||||||
|
|
||||||
void packageModel();
|
void packageModel();
|
||||||
|
|
||||||
void openUrl(const QUrl& url);
|
void openUrl(const QUrl& url);
|
||||||
|
|
|
@ -164,10 +164,10 @@ public:
|
||||||
virtual void setOrientation(const glm::quat& orientation) override;
|
virtual void setOrientation(const glm::quat& orientation) override;
|
||||||
|
|
||||||
// these call through to the SpatiallyNestable versions, but they are here to expose these to javascript.
|
// these call through to the SpatiallyNestable versions, but they are here to expose these to javascript.
|
||||||
Q_INVOKABLE virtual const QUuid getParentID() const { return SpatiallyNestable::getParentID(); }
|
Q_INVOKABLE virtual const QUuid getParentID() const override { return SpatiallyNestable::getParentID(); }
|
||||||
Q_INVOKABLE virtual void setParentID(const QUuid& parentID);
|
Q_INVOKABLE virtual void setParentID(const QUuid& parentID) override;
|
||||||
Q_INVOKABLE virtual quint16 getParentJointIndex() const { return SpatiallyNestable::getParentJointIndex(); }
|
Q_INVOKABLE virtual quint16 getParentJointIndex() const override { return SpatiallyNestable::getParentJointIndex(); }
|
||||||
Q_INVOKABLE virtual void setParentJointIndex(quint16 parentJointIndex);
|
Q_INVOKABLE virtual void setParentJointIndex(quint16 parentJointIndex) override;
|
||||||
|
|
||||||
// NOT thread safe, must be called on main thread.
|
// NOT thread safe, must be called on main thread.
|
||||||
glm::vec3 getUncachedLeftPalmPosition() const;
|
glm::vec3 getUncachedLeftPalmPosition() const;
|
||||||
|
|
|
@ -61,7 +61,7 @@ public:
|
||||||
|
|
||||||
void addDirtyFlags(uint32_t flags) { _dirtyFlags |= flags; }
|
void addDirtyFlags(uint32_t flags) { _dirtyFlags |= flags; }
|
||||||
|
|
||||||
virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const;
|
virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const override;
|
||||||
|
|
||||||
friend class AvatarManager;
|
friend class AvatarManager;
|
||||||
friend class Avatar;
|
friend class Avatar;
|
||||||
|
@ -72,7 +72,7 @@ protected:
|
||||||
~AvatarMotionState();
|
~AvatarMotionState();
|
||||||
|
|
||||||
virtual bool isReadyToComputeShape() const override { return true; }
|
virtual bool isReadyToComputeShape() const override { return true; }
|
||||||
virtual btCollisionShape* computeNewShape();
|
virtual btCollisionShape* computeNewShape() override;
|
||||||
|
|
||||||
// The AvatarMotionState keeps a RAW backpointer to its Avatar because all AvatarMotionState
|
// The AvatarMotionState keeps a RAW backpointer to its Avatar because all AvatarMotionState
|
||||||
// instances are "owned" by their corresponding Avatar instance and are deleted in the Avatar dtor.
|
// instances are "owned" by their corresponding Avatar instance and are deleted in the Avatar dtor.
|
||||||
|
|
|
@ -1311,21 +1311,22 @@ void MyAvatar::preRender(RenderArgs* renderArgs) {
|
||||||
_prevShouldDrawHead = shouldDrawHead;
|
_prevShouldDrawHead = shouldDrawHead;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float RENDER_HEAD_CUTOFF_DISTANCE = 0.50f;
|
const float RENDER_HEAD_CUTOFF_DISTANCE = 0.5f;
|
||||||
|
|
||||||
bool MyAvatar::cameraInsideHead() const {
|
bool MyAvatar::cameraInsideHead() const {
|
||||||
const Head* head = getHead();
|
|
||||||
const glm::vec3 cameraPosition = qApp->getCamera()->getPosition();
|
const glm::vec3 cameraPosition = qApp->getCamera()->getPosition();
|
||||||
return glm::length(cameraPosition - head->getEyePosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * getUniformScale());
|
return glm::length(cameraPosition - getDefaultEyePosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * getUniformScale());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const {
|
bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const {
|
||||||
return ((renderArgs->_renderMode != RenderArgs::DEFAULT_RENDER_MODE) ||
|
bool defaultMode = renderArgs->_renderMode == RenderArgs::DEFAULT_RENDER_MODE;
|
||||||
(qApp->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON) ||
|
bool firstPerson = qApp->getCamera()->getMode() == CAMERA_MODE_FIRST_PERSON;
|
||||||
!cameraInsideHead());
|
bool insideHead = cameraInsideHead();
|
||||||
|
return !defaultMode || !firstPerson || !insideHead;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::updateOrientation(float deltaTime) {
|
void MyAvatar::updateOrientation(float deltaTime) {
|
||||||
|
|
||||||
// Smoothly rotate body with arrow keys
|
// Smoothly rotate body with arrow keys
|
||||||
float targetSpeed = _driveKeys[YAW] * _yawSpeed;
|
float targetSpeed = _driveKeys[YAW] * _yawSpeed;
|
||||||
if (targetSpeed != 0.0f) {
|
if (targetSpeed != 0.0f) {
|
||||||
|
@ -1510,7 +1511,8 @@ void MyAvatar::updatePosition(float deltaTime) {
|
||||||
// rotate velocity into camera frame
|
// rotate velocity into camera frame
|
||||||
glm::quat rotation = getHead()->getCameraOrientation();
|
glm::quat rotation = getHead()->getCameraOrientation();
|
||||||
glm::vec3 localVelocity = glm::inverse(rotation) * _targetVelocity;
|
glm::vec3 localVelocity = glm::inverse(rotation) * _targetVelocity;
|
||||||
glm::vec3 newLocalVelocity = applyKeyboardMotor(deltaTime, localVelocity, isHovering());
|
bool isHovering = _characterController.getState() == CharacterController::State::Hover;
|
||||||
|
glm::vec3 newLocalVelocity = applyKeyboardMotor(deltaTime, localVelocity, isHovering);
|
||||||
newLocalVelocity = applyScriptedMotor(deltaTime, newLocalVelocity);
|
newLocalVelocity = applyScriptedMotor(deltaTime, newLocalVelocity);
|
||||||
|
|
||||||
// rotate back into world-frame
|
// rotate back into world-frame
|
||||||
|
@ -1579,10 +1581,6 @@ bool findAvatarAvatarPenetration(const glm::vec3 positionA, float radiusA, float
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MyAvatar::isHovering() const {
|
|
||||||
return _characterController.isHovering();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyAvatar::increaseSize() {
|
void MyAvatar::increaseSize() {
|
||||||
if ((1.0f + SCALING_RATIO) * _targetScale < MAX_AVATAR_SCALE) {
|
if ((1.0f + SCALING_RATIO) * _targetScale < MAX_AVATAR_SCALE) {
|
||||||
_targetScale *= (1.0f + SCALING_RATIO);
|
_targetScale *= (1.0f + SCALING_RATIO);
|
||||||
|
|
|
@ -239,8 +239,6 @@ public:
|
||||||
glm::quat getCustomListenOrientation() { return _customListenOrientation; }
|
glm::quat getCustomListenOrientation() { return _customListenOrientation; }
|
||||||
void setCustomListenOrientation(glm::quat customListenOrientation) { _customListenOrientation = customListenOrientation; }
|
void setCustomListenOrientation(glm::quat customListenOrientation) { _customListenOrientation = customListenOrientation; }
|
||||||
|
|
||||||
bool isHovering() const;
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void increaseSize();
|
void increaseSize();
|
||||||
void decreaseSize();
|
void decreaseSize();
|
||||||
|
|
|
@ -67,7 +67,7 @@ void MyCharacterController::updateShapeIfNecessary() {
|
||||||
_rigidBody->setAngularFactor(0.0f);
|
_rigidBody->setAngularFactor(0.0f);
|
||||||
_rigidBody->setWorldTransform(btTransform(glmToBullet(_avatar->getOrientation()),
|
_rigidBody->setWorldTransform(btTransform(glmToBullet(_avatar->getOrientation()),
|
||||||
glmToBullet(_avatar->getPosition())));
|
glmToBullet(_avatar->getPosition())));
|
||||||
if (_isHovering) {
|
if (_state == State::Hover) {
|
||||||
_rigidBody->setGravity(btVector3(0.0f, 0.0f, 0.0f));
|
_rigidBody->setGravity(btVector3(0.0f, 0.0f, 0.0f));
|
||||||
} else {
|
} else {
|
||||||
_rigidBody->setGravity(DEFAULT_CHARACTER_GRAVITY * _currentUp);
|
_rigidBody->setGravity(DEFAULT_CHARACTER_GRAVITY * _currentUp);
|
||||||
|
|
|
@ -72,6 +72,20 @@ void SkeletonModel::initJointStates() {
|
||||||
emit skeletonLoaded();
|
emit skeletonLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rig::CharacterControllerState convertCharacterControllerState(CharacterController::State state) {
|
||||||
|
switch (state) {
|
||||||
|
default:
|
||||||
|
case CharacterController::State::Ground:
|
||||||
|
return Rig::CharacterControllerState::Ground;
|
||||||
|
case CharacterController::State::Takeoff:
|
||||||
|
return Rig::CharacterControllerState::Takeoff;
|
||||||
|
case CharacterController::State::InAir:
|
||||||
|
return Rig::CharacterControllerState::InAir;
|
||||||
|
case CharacterController::State::Hover:
|
||||||
|
return Rig::CharacterControllerState::Hover;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Called within Model::simulate call, below.
|
// Called within Model::simulate call, below.
|
||||||
void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||||
Head* head = _owningAvatar->getHead();
|
Head* head = _owningAvatar->getHead();
|
||||||
|
@ -133,7 +147,8 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||||
|
|
||||||
_rig->updateFromHandParameters(handParams, deltaTime);
|
_rig->updateFromHandParameters(handParams, deltaTime);
|
||||||
|
|
||||||
_rig->computeMotionAnimationState(deltaTime, _owningAvatar->getPosition(), _owningAvatar->getVelocity(), _owningAvatar->getOrientation(), myAvatar->isHovering());
|
Rig::CharacterControllerState ccState = convertCharacterControllerState(myAvatar->getCharacterController()->getState());
|
||||||
|
_rig->computeMotionAnimationState(deltaTime, _owningAvatar->getPosition(), _owningAvatar->getVelocity(), _owningAvatar->getOrientation(), ccState);
|
||||||
|
|
||||||
// evaluate AnimGraph animation and update jointStates.
|
// evaluate AnimGraph animation and update jointStates.
|
||||||
Model::updateRig(deltaTime, parentTransform);
|
Model::updateRig(deltaTime, parentTransform);
|
||||||
|
|
|
@ -144,6 +144,3 @@ void GlobalServicesScriptingInterface::updateDownloadInfo() {
|
||||||
emit downloadInfoChanged(getDownloadInfo());
|
emit downloadInfoChanged(getDownloadInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlobalServicesScriptingInterface::editFriends() {
|
|
||||||
QMetaObject::invokeMethod(qApp, "showFriendsWindow");
|
|
||||||
}
|
|
||||||
|
|
|
@ -45,8 +45,7 @@ public:
|
||||||
public slots:
|
public slots:
|
||||||
DownloadInfoResult getDownloadInfo();
|
DownloadInfoResult getDownloadInfo();
|
||||||
void updateDownloadInfo();
|
void updateDownloadInfo();
|
||||||
void editFriends();
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void loggedOut();
|
void loggedOut();
|
||||||
void checkDownloadInfo();
|
void checkDownloadInfo();
|
||||||
|
|
|
@ -20,7 +20,7 @@ class ImageOverlay : public QmlOverlay {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static QString const TYPE;
|
static QString const TYPE;
|
||||||
virtual QString getType() const { return TYPE; }
|
virtual QString getType() const override { return TYPE; }
|
||||||
static QUrl const URL;
|
static QUrl const URL;
|
||||||
|
|
||||||
ImageOverlay();
|
ImageOverlay();
|
||||||
|
|
|
@ -30,7 +30,7 @@ public:
|
||||||
void setText(const QString& text);
|
void setText(const QString& text);
|
||||||
|
|
||||||
|
|
||||||
TextOverlay* createClone() const;
|
TextOverlay* createClone() const override;
|
||||||
QSizeF textSize(const QString& text) const; // Pixels
|
QSizeF textSize(const QString& text) const; // Pixels
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -504,7 +504,7 @@ static const std::vector<float> FORWARD_SPEEDS = { 0.4f, 1.4f, 4.5f }; // m/s
|
||||||
static const std::vector<float> BACKWARD_SPEEDS = { 0.6f, 1.45f }; // m/s
|
static const std::vector<float> BACKWARD_SPEEDS = { 0.6f, 1.45f }; // m/s
|
||||||
static const std::vector<float> LATERAL_SPEEDS = { 0.2f, 0.65f }; // m/s
|
static const std::vector<float> LATERAL_SPEEDS = { 0.2f, 0.65f }; // m/s
|
||||||
|
|
||||||
void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPosition, const glm::vec3& worldVelocity, const glm::quat& worldRotation, bool isHovering) {
|
void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPosition, const glm::vec3& worldVelocity, const glm::quat& worldRotation, CharacterControllerState ccState) {
|
||||||
|
|
||||||
glm::vec3 front = worldRotation * IDENTITY_FRONT;
|
glm::vec3 front = worldRotation * IDENTITY_FRONT;
|
||||||
|
|
||||||
|
@ -572,11 +572,21 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
|
||||||
const float TURN_ENTER_SPEED_THRESHOLD = 0.5f; // rad/sec
|
const float TURN_ENTER_SPEED_THRESHOLD = 0.5f; // rad/sec
|
||||||
const float TURN_EXIT_SPEED_THRESHOLD = 0.2f; // rad/sec
|
const float TURN_EXIT_SPEED_THRESHOLD = 0.2f; // rad/sec
|
||||||
|
|
||||||
if (isHovering) {
|
if (ccState == CharacterControllerState::Hover) {
|
||||||
if (_desiredState != RigRole::Hover) {
|
if (_desiredState != RigRole::Hover) {
|
||||||
_desiredStateAge = 0.0f;
|
_desiredStateAge = 0.0f;
|
||||||
}
|
}
|
||||||
_desiredState = RigRole::Hover;
|
_desiredState = RigRole::Hover;
|
||||||
|
} else if (ccState == CharacterControllerState::InAir) {
|
||||||
|
if (_desiredState != RigRole::InAir) {
|
||||||
|
_desiredStateAge = 0.0f;
|
||||||
|
}
|
||||||
|
_desiredState = RigRole::InAir;
|
||||||
|
} else if (ccState == CharacterControllerState::Takeoff) {
|
||||||
|
if (_desiredState != RigRole::Takeoff) {
|
||||||
|
_desiredStateAge = 0.0f;
|
||||||
|
}
|
||||||
|
_desiredState = RigRole::Takeoff;
|
||||||
} else {
|
} else {
|
||||||
float moveThresh;
|
float moveThresh;
|
||||||
if (_state != RigRole::Move) {
|
if (_state != RigRole::Move) {
|
||||||
|
@ -614,6 +624,13 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
|
||||||
|
|
||||||
const float STATE_CHANGE_HYSTERESIS_TIMER = 0.1f;
|
const float STATE_CHANGE_HYSTERESIS_TIMER = 0.1f;
|
||||||
|
|
||||||
|
// Skip hystersis timer for jump transitions.
|
||||||
|
if (_desiredState == RigRole::Takeoff) {
|
||||||
|
_desiredStateAge = STATE_CHANGE_HYSTERESIS_TIMER;
|
||||||
|
} else if (_state == RigRole::InAir && _desiredState != RigRole::InAir) {
|
||||||
|
_desiredStateAge = STATE_CHANGE_HYSTERESIS_TIMER;
|
||||||
|
}
|
||||||
|
|
||||||
if ((_desiredStateAge >= STATE_CHANGE_HYSTERESIS_TIMER) && _desiredState != _state) {
|
if ((_desiredStateAge >= STATE_CHANGE_HYSTERESIS_TIMER) && _desiredState != _state) {
|
||||||
_state = _desiredState;
|
_state = _desiredState;
|
||||||
_desiredStateAge = 0.0f;
|
_desiredStateAge = 0.0f;
|
||||||
|
@ -662,6 +679,10 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
|
||||||
_animVars.set("isNotTurning", true);
|
_animVars.set("isNotTurning", true);
|
||||||
_animVars.set("isFlying", false);
|
_animVars.set("isFlying", false);
|
||||||
_animVars.set("isNotFlying", true);
|
_animVars.set("isNotFlying", true);
|
||||||
|
_animVars.set("isTakeoff", false);
|
||||||
|
_animVars.set("isNotTakeoff", true);
|
||||||
|
_animVars.set("isInAir", false);
|
||||||
|
_animVars.set("isNotInAir", true);
|
||||||
}
|
}
|
||||||
} else if (_state == RigRole::Turn) {
|
} else if (_state == RigRole::Turn) {
|
||||||
if (turningSpeed > 0.0f) {
|
if (turningSpeed > 0.0f) {
|
||||||
|
@ -682,6 +703,11 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
|
||||||
_animVars.set("isNotMoving", true);
|
_animVars.set("isNotMoving", true);
|
||||||
_animVars.set("isFlying", false);
|
_animVars.set("isFlying", false);
|
||||||
_animVars.set("isNotFlying", true);
|
_animVars.set("isNotFlying", true);
|
||||||
|
_animVars.set("isTakeoff", false);
|
||||||
|
_animVars.set("isNotTakeoff", true);
|
||||||
|
_animVars.set("isInAir", false);
|
||||||
|
_animVars.set("isNotInAir", true);
|
||||||
|
|
||||||
} else if (_state == RigRole::Idle ) {
|
} else if (_state == RigRole::Idle ) {
|
||||||
// default anim vars to notMoving and notTurning
|
// default anim vars to notMoving and notTurning
|
||||||
_animVars.set("isMovingForward", false);
|
_animVars.set("isMovingForward", false);
|
||||||
|
@ -694,7 +720,12 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
|
||||||
_animVars.set("isNotTurning", true);
|
_animVars.set("isNotTurning", true);
|
||||||
_animVars.set("isFlying", false);
|
_animVars.set("isFlying", false);
|
||||||
_animVars.set("isNotFlying", true);
|
_animVars.set("isNotFlying", true);
|
||||||
} else {
|
_animVars.set("isTakeoff", false);
|
||||||
|
_animVars.set("isNotTakeoff", true);
|
||||||
|
_animVars.set("isInAir", false);
|
||||||
|
_animVars.set("isNotInAir", true);
|
||||||
|
|
||||||
|
} else if (_state == RigRole::Hover) {
|
||||||
// flying.
|
// flying.
|
||||||
_animVars.set("isMovingForward", false);
|
_animVars.set("isMovingForward", false);
|
||||||
_animVars.set("isMovingBackward", false);
|
_animVars.set("isMovingBackward", false);
|
||||||
|
@ -706,15 +737,61 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
|
||||||
_animVars.set("isNotTurning", true);
|
_animVars.set("isNotTurning", true);
|
||||||
_animVars.set("isFlying", true);
|
_animVars.set("isFlying", true);
|
||||||
_animVars.set("isNotFlying", false);
|
_animVars.set("isNotFlying", false);
|
||||||
|
_animVars.set("isTakeoff", false);
|
||||||
|
_animVars.set("isNotTakeoff", true);
|
||||||
|
_animVars.set("isInAir", false);
|
||||||
|
_animVars.set("isNotInAir", true);
|
||||||
|
|
||||||
|
} else if (_state == RigRole::Takeoff) {
|
||||||
|
// jumping in-air
|
||||||
|
_animVars.set("isMovingForward", false);
|
||||||
|
_animVars.set("isMovingBackward", false);
|
||||||
|
_animVars.set("isMovingLeft", false);
|
||||||
|
_animVars.set("isMovingRight", false);
|
||||||
|
_animVars.set("isNotMoving", true);
|
||||||
|
_animVars.set("isTurningLeft", false);
|
||||||
|
_animVars.set("isTurningRight", false);
|
||||||
|
_animVars.set("isNotTurning", true);
|
||||||
|
_animVars.set("isFlying", false);
|
||||||
|
_animVars.set("isNotFlying", true);
|
||||||
|
_animVars.set("isTakeoff", true);
|
||||||
|
_animVars.set("isNotTakeoff", false);
|
||||||
|
_animVars.set("isInAir", true);
|
||||||
|
_animVars.set("isNotInAir", false);
|
||||||
|
|
||||||
|
} else if (_state == RigRole::InAir) {
|
||||||
|
// jumping in-air
|
||||||
|
_animVars.set("isMovingForward", false);
|
||||||
|
_animVars.set("isMovingBackward", false);
|
||||||
|
_animVars.set("isMovingLeft", false);
|
||||||
|
_animVars.set("isMovingRight", false);
|
||||||
|
_animVars.set("isNotMoving", true);
|
||||||
|
_animVars.set("isTurningLeft", false);
|
||||||
|
_animVars.set("isTurningRight", false);
|
||||||
|
_animVars.set("isNotTurning", true);
|
||||||
|
_animVars.set("isFlying", false);
|
||||||
|
_animVars.set("isNotFlying", true);
|
||||||
|
_animVars.set("isTakeoff", false);
|
||||||
|
_animVars.set("isNotTakeoff", true);
|
||||||
|
_animVars.set("isInAir", true);
|
||||||
|
_animVars.set("isNotInAir", false);
|
||||||
|
|
||||||
|
// compute blend based on velocity
|
||||||
|
const float JUMP_SPEED = 3.5f;
|
||||||
|
float alpha = glm::clamp(-worldVelocity.y / JUMP_SPEED, -1.0f, 1.0f) + 1.0f;
|
||||||
|
_animVars.set("inAirAlpha", alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
t += deltaTime;
|
t += deltaTime;
|
||||||
|
|
||||||
if (_enableInverseKinematics) {
|
if (_enableInverseKinematics != _lastEnableInverseKinematics) {
|
||||||
_animVars.set("ikOverlayAlpha", 1.0f);
|
if (_enableInverseKinematics) {
|
||||||
} else {
|
_animVars.set("ikOverlayAlpha", 1.0f);
|
||||||
_animVars.set("ikOverlayAlpha", 0.0f);
|
} else {
|
||||||
|
_animVars.set("ikOverlayAlpha", 0.0f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
_lastEnableInverseKinematics = _enableInverseKinematics;
|
||||||
}
|
}
|
||||||
|
|
||||||
_lastFront = front;
|
_lastFront = front;
|
||||||
|
|
|
@ -73,6 +73,13 @@ public:
|
||||||
glm::quat rightOrientation = glm::quat(); // rig space (z forward)
|
glm::quat rightOrientation = glm::quat(); // rig space (z forward)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class CharacterControllerState {
|
||||||
|
Ground = 0,
|
||||||
|
Takeoff,
|
||||||
|
InAir,
|
||||||
|
Hover
|
||||||
|
};
|
||||||
|
|
||||||
virtual ~Rig() {}
|
virtual ~Rig() {}
|
||||||
|
|
||||||
void destroyAnimGraph();
|
void destroyAnimGraph();
|
||||||
|
@ -141,7 +148,7 @@ public:
|
||||||
glm::mat4 getJointTransform(int jointIndex) const;
|
glm::mat4 getJointTransform(int jointIndex) const;
|
||||||
|
|
||||||
// Start or stop animations as needed.
|
// Start or stop animations as needed.
|
||||||
void computeMotionAnimationState(float deltaTime, const glm::vec3& worldPosition, const glm::vec3& worldVelocity, const glm::quat& worldRotation, bool isHovering);
|
void computeMotionAnimationState(float deltaTime, const glm::vec3& worldPosition, const glm::vec3& worldVelocity, const glm::quat& worldRotation, CharacterControllerState ccState);
|
||||||
|
|
||||||
// Regardless of who started the animations or how many, update the joints.
|
// Regardless of who started the animations or how many, update the joints.
|
||||||
void updateAnimations(float deltaTime, glm::mat4 rootTransform);
|
void updateAnimations(float deltaTime, glm::mat4 rootTransform);
|
||||||
|
@ -271,7 +278,9 @@ public:
|
||||||
Idle = 0,
|
Idle = 0,
|
||||||
Turn,
|
Turn,
|
||||||
Move,
|
Move,
|
||||||
Hover
|
Hover,
|
||||||
|
Takeoff,
|
||||||
|
InAir
|
||||||
};
|
};
|
||||||
RigRole _state { RigRole::Idle };
|
RigRole _state { RigRole::Idle };
|
||||||
RigRole _desiredState { RigRole::Idle };
|
RigRole _desiredState { RigRole::Idle };
|
||||||
|
@ -292,6 +301,7 @@ public:
|
||||||
std::map<QString, AnimNode::Pointer> _origRoleAnimations;
|
std::map<QString, AnimNode::Pointer> _origRoleAnimations;
|
||||||
std::vector<AnimNode::Pointer> _prefetchedAnimations;
|
std::vector<AnimNode::Pointer> _prefetchedAnimations;
|
||||||
|
|
||||||
|
bool _lastEnableInverseKinematics { false };
|
||||||
bool _enableInverseKinematics { true };
|
bool _enableInverseKinematics { true };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -51,7 +51,7 @@ public:
|
||||||
virtual bool apply(glm::quat& rotation) const override;
|
virtual bool apply(glm::quat& rotation) const override;
|
||||||
|
|
||||||
void setLowerSpine(bool lowerSpine) { _lowerSpine = lowerSpine; }
|
void setLowerSpine(bool lowerSpine) { _lowerSpine = lowerSpine; }
|
||||||
virtual bool isLowerSpine() const { return _lowerSpine; }
|
virtual bool isLowerSpine() const override { return _lowerSpine; }
|
||||||
|
|
||||||
// SwingLimitFunction is an implementation of the constraint check described in the paper:
|
// SwingLimitFunction is an implementation of the constraint check described in the paper:
|
||||||
// "The Parameterization of Joint Rotation with the Unit Quaternion" by Quang Liu and Edmond C. Prakash
|
// "The Parameterization of Joint Rotation with the Unit Quaternion" by Quang Liu and Edmond C. Prakash
|
||||||
|
|
|
@ -22,8 +22,8 @@ public:
|
||||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||||
RenderableBoxEntityItem(const EntityItemID& entityItemID) : BoxEntityItem(entityItemID) { }
|
RenderableBoxEntityItem(const EntityItemID& entityItemID) : BoxEntityItem(entityItemID) { }
|
||||||
|
|
||||||
virtual void render(RenderArgs* args);
|
virtual void render(RenderArgs* args) override;
|
||||||
virtual void setUserData(const QString& value);
|
virtual void setUserData(const QString& value) override;
|
||||||
|
|
||||||
SIMPLE_RENDERABLE()
|
SIMPLE_RENDERABLE()
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -20,12 +20,12 @@ public:
|
||||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||||
RenderableLightEntityItem(const EntityItemID& entityItemID) : LightEntityItem(entityItemID) { }
|
RenderableLightEntityItem(const EntityItemID& entityItemID) : LightEntityItem(entityItemID) { }
|
||||||
|
|
||||||
virtual void render(RenderArgs* args);
|
virtual void render(RenderArgs* args) override;
|
||||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
virtual bool supportsDetailedRayIntersection() const override { return true; }
|
||||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||||
BoxFace& face, glm::vec3& surfaceNormal,
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
void** intersectedObject, bool precisionPicking) const;
|
void** intersectedObject, bool precisionPicking) const override;
|
||||||
|
|
||||||
SIMPLE_RENDERABLE();
|
SIMPLE_RENDERABLE();
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,7 +24,7 @@ public:
|
||||||
_lineVerticesID(GeometryCache::UNKNOWN_ID)
|
_lineVerticesID(GeometryCache::UNKNOWN_ID)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual void render(RenderArgs* args);
|
virtual void render(RenderArgs* args) override;
|
||||||
|
|
||||||
SIMPLE_RENDERABLE();
|
SIMPLE_RENDERABLE();
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,8 @@ public:
|
||||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||||
RenderableSphereEntityItem(const EntityItemID& entityItemID) : SphereEntityItem(entityItemID) { }
|
RenderableSphereEntityItem(const EntityItemID& entityItemID) : SphereEntityItem(entityItemID) { }
|
||||||
|
|
||||||
virtual void render(RenderArgs* args);
|
virtual void render(RenderArgs* args) override;
|
||||||
virtual void setUserData(const QString& value);
|
virtual void setUserData(const QString& value) override;
|
||||||
|
|
||||||
SIMPLE_RENDERABLE();
|
SIMPLE_RENDERABLE();
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ public:
|
||||||
RenderableTextEntityItem(const EntityItemID& entityItemID) : TextEntityItem(entityItemID) { }
|
RenderableTextEntityItem(const EntityItemID& entityItemID) : TextEntityItem(entityItemID) { }
|
||||||
~RenderableTextEntityItem() { delete _textRenderer; }
|
~RenderableTextEntityItem() { delete _textRenderer; }
|
||||||
|
|
||||||
virtual void render(RenderArgs* args);
|
virtual void render(RenderArgs* args) override;
|
||||||
|
|
||||||
SIMPLE_RENDERABLE();
|
SIMPLE_RENDERABLE();
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,8 @@ public:
|
||||||
RenderableWebEntityItem(const EntityItemID& entityItemID);
|
RenderableWebEntityItem(const EntityItemID& entityItemID);
|
||||||
~RenderableWebEntityItem();
|
~RenderableWebEntityItem();
|
||||||
|
|
||||||
virtual void render(RenderArgs* args);
|
virtual void render(RenderArgs* args) override;
|
||||||
virtual void setSourceUrl(const QString& value);
|
virtual void setSourceUrl(const QString& value) override;
|
||||||
|
|
||||||
void setProxyWindow(QWindow* proxyWindow);
|
void setProxyWindow(QWindow* proxyWindow);
|
||||||
QObject* getEventHandler();
|
QObject* getEventHandler();
|
||||||
|
|
|
@ -29,7 +29,7 @@ EntityScriptingInterface::EntityScriptingInterface() :
|
||||||
_entityTree(NULL)
|
_entityTree(NULL)
|
||||||
{
|
{
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
connect(nodeList.data(), &NodeList::canAdjustLocksChanged, this, &EntityScriptingInterface::canAdjustLocksChanged);
|
connect(nodeList.data(), &NodeList::isAllowedEditorChanged, this, &EntityScriptingInterface::canAdjustLocksChanged);
|
||||||
connect(nodeList.data(), &NodeList::canRezChanged, this, &EntityScriptingInterface::canRezChanged);
|
connect(nodeList.data(), &NodeList::canRezChanged, this, &EntityScriptingInterface::canRezChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ void EntityScriptingInterface::queueEntityMessage(PacketType packetType,
|
||||||
|
|
||||||
bool EntityScriptingInterface::canAdjustLocks() {
|
bool EntityScriptingInterface::canAdjustLocks() {
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
return nodeList->getThisNodeCanAdjustLocks();
|
return nodeList->isAllowedEditor();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityScriptingInterface::canRez() {
|
bool EntityScriptingInterface::canRez() {
|
||||||
|
|
|
@ -124,10 +124,10 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
|
||||||
QUuid senderID;
|
QUuid senderID;
|
||||||
if (senderNode.isNull()) {
|
if (senderNode.isNull()) {
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
allowLockChange = nodeList->getThisNodeCanAdjustLocks();
|
allowLockChange = nodeList->isAllowedEditor();
|
||||||
senderID = nodeList->getSessionUUID();
|
senderID = nodeList->getSessionUUID();
|
||||||
} else {
|
} else {
|
||||||
allowLockChange = senderNode->getCanAdjustLocks();
|
allowLockChange = senderNode->isAllowedEditor();
|
||||||
senderID = senderNode->getUUID();
|
senderID = senderNode->getUUID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,6 @@ LimitedNodeList::LimitedNodeList(unsigned short socketListenPort, unsigned short
|
||||||
_numCollectedPackets(0),
|
_numCollectedPackets(0),
|
||||||
_numCollectedBytes(0),
|
_numCollectedBytes(0),
|
||||||
_packetStatTimer(),
|
_packetStatTimer(),
|
||||||
_thisNodeCanAdjustLocks(false),
|
|
||||||
_thisNodeCanRez(true)
|
_thisNodeCanRez(true)
|
||||||
{
|
{
|
||||||
static bool firstCall = true;
|
static bool firstCall = true;
|
||||||
|
@ -131,10 +130,10 @@ void LimitedNodeList::setSessionUUID(const QUuid& sessionUUID) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LimitedNodeList::setThisNodeCanAdjustLocks(bool canAdjustLocks) {
|
void LimitedNodeList::setIsAllowedEditor(bool isAllowedEditor) {
|
||||||
if (_thisNodeCanAdjustLocks != canAdjustLocks) {
|
if (_isAllowedEditor != isAllowedEditor) {
|
||||||
_thisNodeCanAdjustLocks = canAdjustLocks;
|
_isAllowedEditor = isAllowedEditor;
|
||||||
emit canAdjustLocksChanged(canAdjustLocks);
|
emit isAllowedEditorChanged(isAllowedEditor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,7 +514,7 @@ void LimitedNodeList::handleNodeKill(const SharedNodePointer& node) {
|
||||||
|
|
||||||
SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType,
|
SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType,
|
||||||
const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket,
|
const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket,
|
||||||
bool canAdjustLocks, bool canRez,
|
bool isAllowedEditor, bool canRez,
|
||||||
const QUuid& connectionSecret) {
|
const QUuid& connectionSecret) {
|
||||||
NodeHash::const_iterator it = _nodeHash.find(uuid);
|
NodeHash::const_iterator it = _nodeHash.find(uuid);
|
||||||
|
|
||||||
|
@ -524,14 +523,14 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t
|
||||||
|
|
||||||
matchingNode->setPublicSocket(publicSocket);
|
matchingNode->setPublicSocket(publicSocket);
|
||||||
matchingNode->setLocalSocket(localSocket);
|
matchingNode->setLocalSocket(localSocket);
|
||||||
matchingNode->setCanAdjustLocks(canAdjustLocks);
|
matchingNode->setIsAllowedEditor(isAllowedEditor);
|
||||||
matchingNode->setCanRez(canRez);
|
matchingNode->setCanRez(canRez);
|
||||||
matchingNode->setConnectionSecret(connectionSecret);
|
matchingNode->setConnectionSecret(connectionSecret);
|
||||||
|
|
||||||
return matchingNode;
|
return matchingNode;
|
||||||
} else {
|
} else {
|
||||||
// we didn't have this node, so add them
|
// we didn't have this node, so add them
|
||||||
Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket, canAdjustLocks, canRez, connectionSecret, this);
|
Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket, isAllowedEditor, canRez, connectionSecret, this);
|
||||||
|
|
||||||
if (nodeType == NodeType::AudioMixer) {
|
if (nodeType == NodeType::AudioMixer) {
|
||||||
LimitedNodeList::flagTimeForConnectionStep(LimitedNodeList::AddedAudioMixer);
|
LimitedNodeList::flagTimeForConnectionStep(LimitedNodeList::AddedAudioMixer);
|
||||||
|
|
|
@ -104,8 +104,8 @@ public:
|
||||||
const QUuid& getSessionUUID() const { return _sessionUUID; }
|
const QUuid& getSessionUUID() const { return _sessionUUID; }
|
||||||
void setSessionUUID(const QUuid& sessionUUID);
|
void setSessionUUID(const QUuid& sessionUUID);
|
||||||
|
|
||||||
bool getThisNodeCanAdjustLocks() const { return _thisNodeCanAdjustLocks; }
|
bool isAllowedEditor() const { return _isAllowedEditor; }
|
||||||
void setThisNodeCanAdjustLocks(bool canAdjustLocks);
|
void setIsAllowedEditor(bool isAllowedEditor);
|
||||||
|
|
||||||
bool getThisNodeCanRez() const { return _thisNodeCanRez; }
|
bool getThisNodeCanRez() const { return _thisNodeCanRez; }
|
||||||
void setThisNodeCanRez(bool canRez);
|
void setThisNodeCanRez(bool canRez);
|
||||||
|
@ -137,7 +137,7 @@ public:
|
||||||
|
|
||||||
SharedNodePointer addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType,
|
SharedNodePointer addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType,
|
||||||
const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket,
|
const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket,
|
||||||
bool canAdjustLocks = false, bool canRez = false,
|
bool isAllowedEditor = false, bool canRez = false,
|
||||||
const QUuid& connectionSecret = QUuid());
|
const QUuid& connectionSecret = QUuid());
|
||||||
|
|
||||||
bool hasCompletedInitialSTUN() const { return _hasCompletedInitialSTUN; }
|
bool hasCompletedInitialSTUN() const { return _hasCompletedInitialSTUN; }
|
||||||
|
@ -244,7 +244,7 @@ signals:
|
||||||
void localSockAddrChanged(const HifiSockAddr& localSockAddr);
|
void localSockAddrChanged(const HifiSockAddr& localSockAddr);
|
||||||
void publicSockAddrChanged(const HifiSockAddr& publicSockAddr);
|
void publicSockAddrChanged(const HifiSockAddr& publicSockAddr);
|
||||||
|
|
||||||
void canAdjustLocksChanged(bool canAdjustLocks);
|
void isAllowedEditorChanged(bool isAllowedEditor);
|
||||||
void canRezChanged(bool canRez);
|
void canRezChanged(bool canRez);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -289,7 +289,7 @@ protected:
|
||||||
int _numCollectedBytes;
|
int _numCollectedBytes;
|
||||||
|
|
||||||
QElapsedTimer _packetStatTimer;
|
QElapsedTimer _packetStatTimer;
|
||||||
bool _thisNodeCanAdjustLocks;
|
bool _isAllowedEditor { false };
|
||||||
bool _thisNodeCanRez;
|
bool _thisNodeCanRez;
|
||||||
|
|
||||||
QPointer<QTimer> _initialSTUNTimer;
|
QPointer<QTimer> _initialSTUNTimer;
|
||||||
|
|
|
@ -47,7 +47,7 @@ const QString& NodeType::getNodeTypeName(NodeType_t nodeType) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Node::Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket,
|
Node::Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket,
|
||||||
const HifiSockAddr& localSocket, bool canAdjustLocks, bool canRez, const QUuid& connectionSecret,
|
const HifiSockAddr& localSocket, bool isAllowedEditor, bool canRez, const QUuid& connectionSecret,
|
||||||
QObject* parent) :
|
QObject* parent) :
|
||||||
NetworkPeer(uuid, publicSocket, localSocket, parent),
|
NetworkPeer(uuid, publicSocket, localSocket, parent),
|
||||||
_type(type),
|
_type(type),
|
||||||
|
@ -57,7 +57,7 @@ Node::Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket,
|
||||||
_clockSkewUsec(0),
|
_clockSkewUsec(0),
|
||||||
_mutex(),
|
_mutex(),
|
||||||
_clockSkewMovingPercentile(30, 0.8f), // moving 80th percentile of 30 samples
|
_clockSkewMovingPercentile(30, 0.8f), // moving 80th percentile of 30 samples
|
||||||
_canAdjustLocks(canAdjustLocks),
|
_isAllowedEditor(isAllowedEditor),
|
||||||
_canRez(canRez)
|
_canRez(canRez)
|
||||||
{
|
{
|
||||||
// Update socket's object name
|
// Update socket's object name
|
||||||
|
@ -84,7 +84,7 @@ QDataStream& operator<<(QDataStream& out, const Node& node) {
|
||||||
out << node._uuid;
|
out << node._uuid;
|
||||||
out << node._publicSocket;
|
out << node._publicSocket;
|
||||||
out << node._localSocket;
|
out << node._localSocket;
|
||||||
out << node._canAdjustLocks;
|
out << node._isAllowedEditor;
|
||||||
out << node._canRez;
|
out << node._canRez;
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
@ -95,7 +95,7 @@ QDataStream& operator>>(QDataStream& in, Node& node) {
|
||||||
in >> node._uuid;
|
in >> node._uuid;
|
||||||
in >> node._publicSocket;
|
in >> node._publicSocket;
|
||||||
in >> node._localSocket;
|
in >> node._localSocket;
|
||||||
in >> node._canAdjustLocks;
|
in >> node._isAllowedEditor;
|
||||||
in >> node._canRez;
|
in >> node._canRez;
|
||||||
|
|
||||||
return in;
|
return in;
|
||||||
|
|
|
@ -33,7 +33,7 @@ class Node : public NetworkPeer {
|
||||||
public:
|
public:
|
||||||
Node(const QUuid& uuid, NodeType_t type,
|
Node(const QUuid& uuid, NodeType_t type,
|
||||||
const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket,
|
const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket,
|
||||||
bool canAdjustLocks, bool canRez, const QUuid& connectionSecret = QUuid(),
|
bool isAllowedEditor, bool canRez, const QUuid& connectionSecret = QUuid(),
|
||||||
QObject* parent = 0);
|
QObject* parent = 0);
|
||||||
|
|
||||||
bool operator==(const Node& otherNode) const { return _uuid == otherNode._uuid; }
|
bool operator==(const Node& otherNode) const { return _uuid == otherNode._uuid; }
|
||||||
|
@ -58,8 +58,8 @@ public:
|
||||||
void updateClockSkewUsec(int clockSkewSample);
|
void updateClockSkewUsec(int clockSkewSample);
|
||||||
QMutex& getMutex() { return _mutex; }
|
QMutex& getMutex() { return _mutex; }
|
||||||
|
|
||||||
void setCanAdjustLocks(bool canAdjustLocks) { _canAdjustLocks = canAdjustLocks; }
|
void setIsAllowedEditor(bool isAllowedEditor) { _isAllowedEditor = isAllowedEditor; }
|
||||||
bool getCanAdjustLocks() { return _canAdjustLocks; }
|
bool isAllowedEditor() { return _isAllowedEditor; }
|
||||||
|
|
||||||
void setCanRez(bool canRez) { _canRez = canRez; }
|
void setCanRez(bool canRez) { _canRez = canRez; }
|
||||||
bool getCanRez() { return _canRez; }
|
bool getCanRez() { return _canRez; }
|
||||||
|
@ -81,7 +81,7 @@ private:
|
||||||
int _clockSkewUsec;
|
int _clockSkewUsec;
|
||||||
QMutex _mutex;
|
QMutex _mutex;
|
||||||
MovingPercentile _clockSkewMovingPercentile;
|
MovingPercentile _clockSkewMovingPercentile;
|
||||||
bool _canAdjustLocks;
|
bool _isAllowedEditor;
|
||||||
bool _canRez;
|
bool _canRez;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -512,9 +512,9 @@ void NodeList::processDomainServerList(QSharedPointer<ReceivedMessage> message)
|
||||||
packetStream >> newUUID;
|
packetStream >> newUUID;
|
||||||
setSessionUUID(newUUID);
|
setSessionUUID(newUUID);
|
||||||
|
|
||||||
quint8 thisNodeCanAdjustLocks;
|
quint8 isAllowedEditor;
|
||||||
packetStream >> thisNodeCanAdjustLocks;
|
packetStream >> isAllowedEditor;
|
||||||
setThisNodeCanAdjustLocks((bool) thisNodeCanAdjustLocks);
|
setIsAllowedEditor((bool) isAllowedEditor);
|
||||||
|
|
||||||
quint8 thisNodeCanRez;
|
quint8 thisNodeCanRez;
|
||||||
packetStream >> thisNodeCanRez;
|
packetStream >> thisNodeCanRez;
|
||||||
|
@ -546,10 +546,10 @@ void NodeList::parseNodeFromPacketStream(QDataStream& packetStream) {
|
||||||
qint8 nodeType;
|
qint8 nodeType;
|
||||||
QUuid nodeUUID, connectionUUID;
|
QUuid nodeUUID, connectionUUID;
|
||||||
HifiSockAddr nodePublicSocket, nodeLocalSocket;
|
HifiSockAddr nodePublicSocket, nodeLocalSocket;
|
||||||
bool canAdjustLocks;
|
bool isAllowedEditor;
|
||||||
bool canRez;
|
bool canRez;
|
||||||
|
|
||||||
packetStream >> nodeType >> nodeUUID >> nodePublicSocket >> nodeLocalSocket >> canAdjustLocks >> canRez;
|
packetStream >> nodeType >> nodeUUID >> nodePublicSocket >> nodeLocalSocket >> isAllowedEditor >> canRez;
|
||||||
|
|
||||||
// if the public socket address is 0 then it's reachable at the same IP
|
// if the public socket address is 0 then it's reachable at the same IP
|
||||||
// as the domain server
|
// as the domain server
|
||||||
|
@ -560,7 +560,7 @@ void NodeList::parseNodeFromPacketStream(QDataStream& packetStream) {
|
||||||
packetStream >> connectionUUID;
|
packetStream >> connectionUUID;
|
||||||
|
|
||||||
SharedNodePointer node = addOrUpdateNode(nodeUUID, nodeType, nodePublicSocket,
|
SharedNodePointer node = addOrUpdateNode(nodeUUID, nodeType, nodePublicSocket,
|
||||||
nodeLocalSocket, canAdjustLocks, canRez,
|
nodeLocalSocket, isAllowedEditor, canRez,
|
||||||
connectionUUID);
|
connectionUUID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,11 +15,18 @@
|
||||||
|
|
||||||
#include "PhysicsCollisionGroups.h"
|
#include "PhysicsCollisionGroups.h"
|
||||||
#include "ObjectMotionState.h"
|
#include "ObjectMotionState.h"
|
||||||
|
#include "PhysicsLogging.h"
|
||||||
|
|
||||||
const btVector3 LOCAL_UP_AXIS(0.0f, 1.0f, 0.0f);
|
const btVector3 LOCAL_UP_AXIS(0.0f, 1.0f, 0.0f);
|
||||||
const float JUMP_SPEED = 3.5f;
|
const float JUMP_SPEED = 3.5f;
|
||||||
const float MAX_FALL_HEIGHT = 20.0f;
|
const float MAX_FALL_HEIGHT = 20.0f;
|
||||||
|
|
||||||
|
#ifdef DEBUG_STATE_CHANGE
|
||||||
|
#define SET_STATE(desiredState, reason) setState(desiredState, reason)
|
||||||
|
#else
|
||||||
|
#define SET_STATE(desiredState, reason) setState(desiredState)
|
||||||
|
#endif
|
||||||
|
|
||||||
// helper class for simple ray-traces from character
|
// helper class for simple ray-traces from character
|
||||||
class ClosestNotMe : public btCollisionWorld::ClosestRayResultCallback {
|
class ClosestNotMe : public btCollisionWorld::ClosestRayResultCallback {
|
||||||
public:
|
public:
|
||||||
|
@ -51,19 +58,17 @@ CharacterController::CharacterController() {
|
||||||
_followDesiredBodyTransform.setIdentity();
|
_followDesiredBodyTransform.setIdentity();
|
||||||
_followTimeRemaining = 0.0f;
|
_followTimeRemaining = 0.0f;
|
||||||
_jumpSpeed = JUMP_SPEED;
|
_jumpSpeed = JUMP_SPEED;
|
||||||
_isOnGround = false;
|
_state = State::Hover;
|
||||||
_isJumping = false;
|
|
||||||
_isFalling = false;
|
|
||||||
_isHovering = true;
|
|
||||||
_isPushingUp = false;
|
_isPushingUp = false;
|
||||||
_jumpToHoverStart = 0;
|
_jumpButtonDownStart = 0;
|
||||||
|
_jumpButtonDownCount = 0;
|
||||||
|
_takeoffToInAirStart = 0;
|
||||||
_followTime = 0.0f;
|
_followTime = 0.0f;
|
||||||
_followLinearDisplacement = btVector3(0, 0, 0);
|
_followLinearDisplacement = btVector3(0, 0, 0);
|
||||||
_followAngularDisplacement = btQuaternion::getIdentity();
|
_followAngularDisplacement = btQuaternion::getIdentity();
|
||||||
_hasSupport = false;
|
_hasSupport = false;
|
||||||
|
|
||||||
_pendingFlags = PENDING_FLAG_UPDATE_SHAPE;
|
_pendingFlags = PENDING_FLAG_UPDATE_SHAPE;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CharacterController::needsRemoval() const {
|
bool CharacterController::needsRemoval() const {
|
||||||
|
@ -107,6 +112,8 @@ void CharacterController::setDynamicsWorld(btDynamicsWorld* world) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const float COS_PI_OVER_THREE = cosf(PI / 3.0f);
|
||||||
|
|
||||||
bool CharacterController::checkForSupport(btCollisionWorld* collisionWorld) const {
|
bool CharacterController::checkForSupport(btCollisionWorld* collisionWorld) const {
|
||||||
int numManifolds = collisionWorld->getDispatcher()->getNumManifolds();
|
int numManifolds = collisionWorld->getDispatcher()->getNumManifolds();
|
||||||
for (int i = 0; i < numManifolds; i++) {
|
for (int i = 0; i < numManifolds; i++) {
|
||||||
|
@ -119,8 +126,10 @@ bool CharacterController::checkForSupport(btCollisionWorld* collisionWorld) cons
|
||||||
btManifoldPoint& pt = contactManifold->getContactPoint(j);
|
btManifoldPoint& pt = contactManifold->getContactPoint(j);
|
||||||
|
|
||||||
// check to see if contact point is touching the bottom sphere of the capsule.
|
// check to see if contact point is touching the bottom sphere of the capsule.
|
||||||
|
// and the contact normal is not slanted too much.
|
||||||
float contactPointY = (obA == _rigidBody) ? pt.m_localPointA.getY() : pt.m_localPointB.getY();
|
float contactPointY = (obA == _rigidBody) ? pt.m_localPointA.getY() : pt.m_localPointB.getY();
|
||||||
if (contactPointY < -_halfHeight) {
|
btVector3 normal = (obA == _rigidBody) ? pt.m_normalWorldOnB : -pt.m_normalWorldOnB;
|
||||||
|
if (contactPointY < -_halfHeight && normal.dot(_currentUp) > COS_PI_OVER_THREE) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,72 +162,61 @@ void CharacterController::preStep(btCollisionWorld* collisionWorld) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterController::playerStep(btCollisionWorld* dynaWorld, btScalar dt) {
|
void CharacterController::playerStep(btCollisionWorld* dynaWorld, btScalar dt) {
|
||||||
btVector3 actualVelocity = _rigidBody->getLinearVelocity();
|
|
||||||
btScalar actualSpeed = actualVelocity.length();
|
|
||||||
|
|
||||||
btVector3 desiredVelocity = _walkVelocity;
|
|
||||||
btScalar desiredSpeed = desiredVelocity.length();
|
|
||||||
|
|
||||||
const btScalar MIN_UP_PUSH = 0.1f;
|
|
||||||
if (desiredVelocity.dot(_currentUp) < MIN_UP_PUSH) {
|
|
||||||
_isPushingUp = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const btScalar MIN_SPEED = 0.001f;
|
const btScalar MIN_SPEED = 0.001f;
|
||||||
if (_isHovering) {
|
|
||||||
if (desiredSpeed < MIN_SPEED) {
|
btVector3 actualVelocity = _rigidBody->getLinearVelocity();
|
||||||
if (actualSpeed < MIN_SPEED) {
|
if (actualVelocity.length() < MIN_SPEED) {
|
||||||
_rigidBody->setLinearVelocity(btVector3(0.0f, 0.0f, 0.0f));
|
actualVelocity = btVector3(0.0f, 0.0f, 0.0f);
|
||||||
} else {
|
}
|
||||||
const btScalar HOVER_BRAKING_TIMESCALE = 0.1f;
|
|
||||||
btScalar tau = glm::max(dt / HOVER_BRAKING_TIMESCALE, 1.0f);
|
btVector3 desiredVelocity = _walkVelocity;
|
||||||
_rigidBody->setLinearVelocity((1.0f - tau) * actualVelocity);
|
if (desiredVelocity.length() < MIN_SPEED) {
|
||||||
}
|
desiredVelocity = btVector3(0.0f, 0.0f, 0.0f);
|
||||||
} else {
|
}
|
||||||
const btScalar HOVER_ACCELERATION_TIMESCALE = 0.1f;
|
|
||||||
btScalar tau = dt / HOVER_ACCELERATION_TIMESCALE;
|
// decompose into horizontal and vertical components.
|
||||||
_rigidBody->setLinearVelocity(actualVelocity - tau * (actualVelocity - desiredVelocity));
|
btVector3 actualVertVelocity = actualVelocity.dot(_currentUp) * _currentUp;
|
||||||
|
btVector3 actualHorizVelocity = actualVelocity - actualVertVelocity;
|
||||||
|
btVector3 desiredVertVelocity = desiredVelocity.dot(_currentUp) * _currentUp;
|
||||||
|
btVector3 desiredHorizVelocity = desiredVelocity - desiredVertVelocity;
|
||||||
|
|
||||||
|
btVector3 finalVelocity;
|
||||||
|
|
||||||
|
switch (_state) {
|
||||||
|
case State::Ground:
|
||||||
|
case State::Takeoff:
|
||||||
|
{
|
||||||
|
// horizontal ground control
|
||||||
|
const btScalar WALK_ACCELERATION_TIMESCALE = 0.1f;
|
||||||
|
btScalar tau = dt / WALK_ACCELERATION_TIMESCALE;
|
||||||
|
finalVelocity = tau * desiredHorizVelocity + (1.0f - tau) * actualHorizVelocity + actualVertVelocity;
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
if (onGround()) {
|
case State::InAir:
|
||||||
// walking on ground
|
{
|
||||||
if (desiredSpeed < MIN_SPEED) {
|
// horizontal air control
|
||||||
if (actualSpeed < MIN_SPEED) {
|
const btScalar IN_AIR_ACCELERATION_TIMESCALE = 2.0f;
|
||||||
_rigidBody->setLinearVelocity(btVector3(0.0f, 0.0f, 0.0f));
|
btScalar tau = dt / IN_AIR_ACCELERATION_TIMESCALE;
|
||||||
} else {
|
finalVelocity = tau * desiredHorizVelocity + (1.0f - tau) * actualHorizVelocity + actualVertVelocity;
|
||||||
const btScalar HOVER_BRAKING_TIMESCALE = 0.1f;
|
}
|
||||||
btScalar tau = dt / HOVER_BRAKING_TIMESCALE;
|
break;
|
||||||
_rigidBody->setLinearVelocity((1.0f - tau) * actualVelocity);
|
case State::Hover:
|
||||||
}
|
{
|
||||||
} else {
|
// vertical and horizontal air control
|
||||||
// TODO: modify desiredVelocity using floor normal
|
|
||||||
const btScalar WALK_ACCELERATION_TIMESCALE = 0.1f;
|
|
||||||
btScalar tau = dt / WALK_ACCELERATION_TIMESCALE;
|
|
||||||
btVector3 velocityCorrection = tau * (desiredVelocity - actualVelocity);
|
|
||||||
// subtract vertical component
|
|
||||||
velocityCorrection -= velocityCorrection.dot(_currentUp) * _currentUp;
|
|
||||||
_rigidBody->setLinearVelocity(actualVelocity + velocityCorrection);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// transitioning to flying
|
|
||||||
btVector3 velocityCorrection = desiredVelocity - actualVelocity;
|
|
||||||
const btScalar FLY_ACCELERATION_TIMESCALE = 0.2f;
|
const btScalar FLY_ACCELERATION_TIMESCALE = 0.2f;
|
||||||
btScalar tau = dt / FLY_ACCELERATION_TIMESCALE;
|
btScalar tau = dt / FLY_ACCELERATION_TIMESCALE;
|
||||||
if (!_isPushingUp) {
|
finalVelocity = tau * desiredVelocity + (1.0f - tau) * actualVelocity;
|
||||||
// actually falling --> compute a different velocity attenuation factor
|
|
||||||
const btScalar FALL_ACCELERATION_TIMESCALE = 2.0f;
|
|
||||||
tau = dt / FALL_ACCELERATION_TIMESCALE;
|
|
||||||
// zero vertical component
|
|
||||||
velocityCorrection -= velocityCorrection.dot(_currentUp) * _currentUp;
|
|
||||||
}
|
|
||||||
_rigidBody->setLinearVelocity(actualVelocity + tau * velocityCorrection);
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_rigidBody->setLinearVelocity(finalVelocity);
|
||||||
|
|
||||||
// Dynamicaly compute a follow velocity to move this body toward the _followDesiredBodyTransform.
|
// Dynamicaly compute a follow velocity to move this body toward the _followDesiredBodyTransform.
|
||||||
// Rather then add this velocity to velocity the RigidBody, we explicitly teleport the RigidBody towards its goal.
|
// Rather then add this velocity to velocity the RigidBody, we explicitly teleport the RigidBody towards its goal.
|
||||||
// This mirrors the computation done in MyAvatar::FollowHelper::postPhysicsUpdate().
|
// This mirrors the computation done in MyAvatar::FollowHelper::postPhysicsUpdate().
|
||||||
// These two computations must be kept in sync.
|
|
||||||
const float MINIMUM_TIME_REMAINING = 0.005f;
|
const float MINIMUM_TIME_REMAINING = 0.005f;
|
||||||
const float MAX_DISPLACEMENT = 0.5f * _radius;
|
const float MAX_DISPLACEMENT = 0.5f * _radius;
|
||||||
_followTimeRemaining -= dt;
|
_followTimeRemaining -= dt;
|
||||||
|
@ -254,21 +252,7 @@ void CharacterController::playerStep(btCollisionWorld* dynaWorld, btScalar dt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterController::jump() {
|
void CharacterController::jump() {
|
||||||
// check for case where user is holding down "jump" key...
|
_pendingFlags |= PENDING_FLAG_JUMP;
|
||||||
// we'll eventually tansition to "hover"
|
|
||||||
if (!_isJumping) {
|
|
||||||
if (!_isHovering) {
|
|
||||||
_jumpToHoverStart = usecTimestampNow();
|
|
||||||
_pendingFlags |= PENDING_FLAG_JUMP;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
quint64 now = usecTimestampNow();
|
|
||||||
const quint64 JUMP_TO_HOVER_PERIOD = 75 * (USECS_PER_SECOND / 100);
|
|
||||||
if (now - _jumpToHoverStart > JUMP_TO_HOVER_PERIOD) {
|
|
||||||
_isPushingUp = true;
|
|
||||||
setHovering(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CharacterController::onGround() const {
|
bool CharacterController::onGround() const {
|
||||||
|
@ -276,18 +260,44 @@ bool CharacterController::onGround() const {
|
||||||
return _floorDistance < FLOOR_PROXIMITY_THRESHOLD || _hasSupport;
|
return _floorDistance < FLOOR_PROXIMITY_THRESHOLD || _hasSupport;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterController::setHovering(bool hover) {
|
#ifdef DEBUG_STATE_CHANGE
|
||||||
if (hover != _isHovering) {
|
static const char* stateToStr(CharacterController::State state) {
|
||||||
_isHovering = hover;
|
switch (state) {
|
||||||
_isJumping = false;
|
case CharacterController::State::Ground:
|
||||||
|
return "Ground";
|
||||||
|
case CharacterController::State::Takeoff:
|
||||||
|
return "Takeoff";
|
||||||
|
case CharacterController::State::InAir:
|
||||||
|
return "InAir";
|
||||||
|
case CharacterController::State::Hover:
|
||||||
|
return "Hover";
|
||||||
|
default:
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // #ifdef DEBUG_STATE_CHANGE
|
||||||
|
|
||||||
if (_rigidBody) {
|
#ifdef DEBUG_STATE_CHANGE
|
||||||
if (hover) {
|
void CharacterController::setState(State desiredState, const char* reason) {
|
||||||
|
#else
|
||||||
|
void CharacterController::setState(State desiredState) {
|
||||||
|
#endif
|
||||||
|
if (desiredState != _state) {
|
||||||
|
#ifdef DEBUG_STATE_CHANGE
|
||||||
|
qCDebug(physics) << "CharacterController::setState" << stateToStr(desiredState) << "from" << stateToStr(_state) << "," << reason;
|
||||||
|
#endif
|
||||||
|
if (desiredState == State::Hover && _state != State::Hover) {
|
||||||
|
// hover enter
|
||||||
|
if (_rigidBody) {
|
||||||
_rigidBody->setGravity(btVector3(0.0f, 0.0f, 0.0f));
|
_rigidBody->setGravity(btVector3(0.0f, 0.0f, 0.0f));
|
||||||
} else {
|
}
|
||||||
|
} else if (_state == State::Hover && desiredState != State::Hover) {
|
||||||
|
// hover exit
|
||||||
|
if (_rigidBody) {
|
||||||
_rigidBody->setGravity(DEFAULT_CHARACTER_GRAVITY * _currentUp);
|
_rigidBody->setGravity(DEFAULT_CHARACTER_GRAVITY * _currentUp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_state = desiredState;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,9 +345,8 @@ void CharacterController::setEnabled(bool enabled) {
|
||||||
_pendingFlags |= PENDING_FLAG_REMOVE_FROM_SIMULATION;
|
_pendingFlags |= PENDING_FLAG_REMOVE_FROM_SIMULATION;
|
||||||
}
|
}
|
||||||
_pendingFlags &= ~ PENDING_FLAG_ADD_TO_SIMULATION;
|
_pendingFlags &= ~ PENDING_FLAG_ADD_TO_SIMULATION;
|
||||||
_isOnGround = false;
|
|
||||||
}
|
}
|
||||||
setHovering(true);
|
SET_STATE(State::Hover, "setEnabled");
|
||||||
_enabled = enabled;
|
_enabled = enabled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -345,7 +354,7 @@ void CharacterController::setEnabled(bool enabled) {
|
||||||
void CharacterController::updateUpAxis(const glm::quat& rotation) {
|
void CharacterController::updateUpAxis(const glm::quat& rotation) {
|
||||||
btVector3 oldUp = _currentUp;
|
btVector3 oldUp = _currentUp;
|
||||||
_currentUp = quatRotate(glmToBullet(rotation), LOCAL_UP_AXIS);
|
_currentUp = quatRotate(glmToBullet(rotation), LOCAL_UP_AXIS);
|
||||||
if (!_isHovering) {
|
if (_state != State::Hover) {
|
||||||
const btScalar MIN_UP_ERROR = 0.01f;
|
const btScalar MIN_UP_ERROR = 0.01f;
|
||||||
if (oldUp.distance(_currentUp) > MIN_UP_ERROR) {
|
if (oldUp.distance(_currentUp) > MIN_UP_ERROR) {
|
||||||
_rigidBody->setGravity(DEFAULT_CHARACTER_GRAVITY * _currentUp);
|
_rigidBody->setGravity(DEFAULT_CHARACTER_GRAVITY * _currentUp);
|
||||||
|
@ -410,6 +419,10 @@ void CharacterController::preSimulation() {
|
||||||
if (_enabled && _dynamicsWorld) {
|
if (_enabled && _dynamicsWorld) {
|
||||||
// slam body to where it is supposed to be
|
// slam body to where it is supposed to be
|
||||||
_rigidBody->setWorldTransform(_characterBodyTransform);
|
_rigidBody->setWorldTransform(_characterBodyTransform);
|
||||||
|
btVector3 velocity = _rigidBody->getLinearVelocity();
|
||||||
|
|
||||||
|
btVector3 actualVertVelocity = velocity.dot(_currentUp) * _currentUp;
|
||||||
|
btVector3 actualHorizVelocity = velocity - actualVertVelocity;
|
||||||
|
|
||||||
// scan for distant floor
|
// scan for distant floor
|
||||||
// rayStart is at center of bottom sphere
|
// rayStart is at center of bottom sphere
|
||||||
|
@ -424,32 +437,72 @@ void CharacterController::preSimulation() {
|
||||||
_dynamicsWorld->rayTest(rayStart, rayEnd, rayCallback);
|
_dynamicsWorld->rayTest(rayStart, rayEnd, rayCallback);
|
||||||
if (rayCallback.hasHit()) {
|
if (rayCallback.hasHit()) {
|
||||||
_floorDistance = rayLength * rayCallback.m_closestHitFraction - _radius;
|
_floorDistance = rayLength * rayCallback.m_closestHitFraction - _radius;
|
||||||
const btScalar MIN_HOVER_HEIGHT = 3.0f;
|
} else {
|
||||||
if (_isHovering && _floorDistance < MIN_HOVER_HEIGHT && !_isPushingUp) {
|
|
||||||
setHovering(false);
|
|
||||||
}
|
|
||||||
// TODO: use collision events rather than ray-trace test to disable jumping
|
|
||||||
const btScalar JUMP_PROXIMITY_THRESHOLD = 0.1f * _radius;
|
|
||||||
if (_floorDistance < JUMP_PROXIMITY_THRESHOLD) {
|
|
||||||
_isJumping = false;
|
|
||||||
}
|
|
||||||
} else if (!_hasSupport) {
|
|
||||||
_floorDistance = FLT_MAX;
|
_floorDistance = FLT_MAX;
|
||||||
setHovering(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pendingFlags & PENDING_FLAG_JUMP) {
|
const btScalar JUMP_PROXIMITY_THRESHOLD = 0.1f * _radius;
|
||||||
_pendingFlags &= ~ PENDING_FLAG_JUMP;
|
const quint64 TAKE_OFF_TO_IN_AIR_PERIOD = 200 * MSECS_PER_SECOND;
|
||||||
if (onGround()) {
|
const btScalar MIN_HOVER_HEIGHT = 2.5f;
|
||||||
_isJumping = true;
|
const quint64 JUMP_TO_HOVER_PERIOD = 750 * MSECS_PER_SECOND;
|
||||||
btVector3 velocity = _rigidBody->getLinearVelocity();
|
const btScalar MAX_WALKING_SPEED = 2.5f;
|
||||||
|
|
||||||
|
quint64 now = usecTimestampNow();
|
||||||
|
|
||||||
|
// record a time stamp when the jump button was first pressed.
|
||||||
|
if ((_previousFlags & PENDING_FLAG_JUMP) != (_pendingFlags & PENDING_FLAG_JUMP)) {
|
||||||
|
if (_pendingFlags & PENDING_FLAG_JUMP) {
|
||||||
|
_jumpButtonDownStart = now;
|
||||||
|
_jumpButtonDownCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool jumpButtonHeld = _pendingFlags & PENDING_FLAG_JUMP;
|
||||||
|
bool flyingFast = _state == State::Hover && actualHorizVelocity.length() > (MAX_WALKING_SPEED * 0.75f);
|
||||||
|
|
||||||
|
switch (_state) {
|
||||||
|
case State::Ground:
|
||||||
|
if (!rayCallback.hasHit() && !_hasSupport) {
|
||||||
|
SET_STATE(State::Hover, "no ground");
|
||||||
|
} else if (_pendingFlags & PENDING_FLAG_JUMP) {
|
||||||
|
_takeOffJumpButtonID = _jumpButtonDownCount;
|
||||||
|
SET_STATE(State::Takeoff, "jump pressed");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case State::Takeoff:
|
||||||
|
if (!rayCallback.hasHit() && !_hasSupport) {
|
||||||
|
SET_STATE(State::Hover, "no ground");
|
||||||
|
} else if ((now - _takeoffToInAirStart) > TAKE_OFF_TO_IN_AIR_PERIOD) {
|
||||||
|
SET_STATE(State::InAir, "takeoff done");
|
||||||
|
_takeoffToInAirStart = now + USECS_PER_SECOND * 86500.0f;
|
||||||
velocity += _jumpSpeed * _currentUp;
|
velocity += _jumpSpeed * _currentUp;
|
||||||
_rigidBody->setLinearVelocity(velocity);
|
_rigidBody->setLinearVelocity(velocity);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case State::InAir: {
|
||||||
|
if ((velocity.dot(_currentUp) <= (JUMP_SPEED / 2.0f)) && ((_floorDistance < JUMP_PROXIMITY_THRESHOLD) || _hasSupport)) {
|
||||||
|
SET_STATE(State::Ground, "hit ground");
|
||||||
|
} else if (jumpButtonHeld && (_takeOffJumpButtonID != _jumpButtonDownCount)) {
|
||||||
|
SET_STATE(State::Hover, "double jump button");
|
||||||
|
} else if (jumpButtonHeld && (now - _jumpButtonDownStart) > JUMP_TO_HOVER_PERIOD) {
|
||||||
|
SET_STATE(State::Hover, "jump button held");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::Hover:
|
||||||
|
if ((_floorDistance < MIN_HOVER_HEIGHT) && !jumpButtonHeld && !flyingFast) {
|
||||||
|
SET_STATE(State::InAir, "near ground");
|
||||||
|
} else if (((_floorDistance < JUMP_PROXIMITY_THRESHOLD) || _hasSupport) && !flyingFast) {
|
||||||
|
SET_STATE(State::Ground, "touching ground");
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_followTime = 0.0f;
|
|
||||||
|
|
||||||
|
_previousFlags = _pendingFlags;
|
||||||
|
_pendingFlags &= ~PENDING_FLAG_JUMP;
|
||||||
|
|
||||||
|
_followTime = 0.0f;
|
||||||
_followLinearDisplacement = btVector3(0, 0, 0);
|
_followLinearDisplacement = btVector3(0, 0, 0);
|
||||||
_followAngularDisplacement = btQuaternion::getIdentity();
|
_followAngularDisplacement = btQuaternion::getIdentity();
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,8 @@ class btRigidBody;
|
||||||
class btCollisionWorld;
|
class btCollisionWorld;
|
||||||
class btDynamicsWorld;
|
class btDynamicsWorld;
|
||||||
|
|
||||||
|
//#define DEBUG_STATE_CHANGE
|
||||||
|
|
||||||
class CharacterController : public btCharacterControllerInterface {
|
class CharacterController : public btCharacterControllerInterface {
|
||||||
public:
|
public:
|
||||||
CharacterController();
|
CharacterController();
|
||||||
|
@ -75,8 +77,14 @@ public:
|
||||||
|
|
||||||
glm::vec3 getLinearVelocity() const;
|
glm::vec3 getLinearVelocity() const;
|
||||||
|
|
||||||
bool isHovering() const { return _isHovering; }
|
enum class State {
|
||||||
void setHovering(bool enabled);
|
Ground = 0,
|
||||||
|
Takeoff,
|
||||||
|
InAir,
|
||||||
|
Hover
|
||||||
|
};
|
||||||
|
|
||||||
|
State getState() const { return _state; }
|
||||||
|
|
||||||
void setLocalBoundingBox(const glm::vec3& corner, const glm::vec3& scale);
|
void setLocalBoundingBox(const glm::vec3& corner, const glm::vec3& scale);
|
||||||
|
|
||||||
|
@ -86,6 +94,12 @@ public:
|
||||||
bool getRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation);
|
bool getRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
#ifdef DEBUG_STATE_CHANGE
|
||||||
|
void setState(State state, const char* reason);
|
||||||
|
#else
|
||||||
|
void setState(State state);
|
||||||
|
#endif
|
||||||
|
|
||||||
void updateUpAxis(const glm::quat& rotation);
|
void updateUpAxis(const glm::quat& rotation);
|
||||||
bool checkForSupport(btCollisionWorld* collisionWorld) const;
|
bool checkForSupport(btCollisionWorld* collisionWorld) const;
|
||||||
|
|
||||||
|
@ -100,7 +114,10 @@ protected:
|
||||||
|
|
||||||
glm::vec3 _boxScale; // used to compute capsule shape
|
glm::vec3 _boxScale; // used to compute capsule shape
|
||||||
|
|
||||||
quint64 _jumpToHoverStart;
|
quint64 _takeoffToInAirStart;
|
||||||
|
quint64 _jumpButtonDownStart;
|
||||||
|
quint32 _jumpButtonDownCount;
|
||||||
|
quint32 _takeOffJumpButtonID;
|
||||||
|
|
||||||
btScalar _halfHeight;
|
btScalar _halfHeight;
|
||||||
btScalar _radius;
|
btScalar _radius;
|
||||||
|
@ -116,16 +133,13 @@ protected:
|
||||||
btQuaternion _followAngularDisplacement;
|
btQuaternion _followAngularDisplacement;
|
||||||
|
|
||||||
bool _enabled;
|
bool _enabled;
|
||||||
bool _isOnGround;
|
State _state;
|
||||||
bool _isJumping;
|
|
||||||
bool _isFalling;
|
|
||||||
bool _isHovering;
|
|
||||||
bool _isPushingUp;
|
bool _isPushingUp;
|
||||||
|
|
||||||
btDynamicsWorld* _dynamicsWorld { nullptr };
|
btDynamicsWorld* _dynamicsWorld { nullptr };
|
||||||
btRigidBody* _rigidBody { nullptr };
|
btRigidBody* _rigidBody { nullptr };
|
||||||
uint32_t _pendingFlags { 0 };
|
uint32_t _pendingFlags { 0 };
|
||||||
|
uint32_t _previousFlags { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_CharacterControllerInterface_h
|
#endif // hifi_CharacterControllerInterface_h
|
||||||
|
|
|
@ -29,13 +29,13 @@ public:
|
||||||
virtual ~EntityMotionState();
|
virtual ~EntityMotionState();
|
||||||
|
|
||||||
void updateServerPhysicsVariables();
|
void updateServerPhysicsVariables();
|
||||||
virtual bool handleEasyChanges(uint32_t& flags);
|
virtual bool handleEasyChanges(uint32_t& flags) override;
|
||||||
virtual bool handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine);
|
virtual bool handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine) override;
|
||||||
|
|
||||||
/// \return PhysicsMotionType based on params set in EntityItem
|
/// \return PhysicsMotionType based on params set in EntityItem
|
||||||
virtual PhysicsMotionType computePhysicsMotionType() const;
|
virtual PhysicsMotionType computePhysicsMotionType() const override;
|
||||||
|
|
||||||
virtual bool isMoving() const;
|
virtual bool isMoving() const override;
|
||||||
|
|
||||||
// this relays incoming position/rotation to the RigidBody
|
// this relays incoming position/rotation to the RigidBody
|
||||||
virtual void getWorldTransform(btTransform& worldTrans) const override;
|
virtual void getWorldTransform(btTransform& worldTrans) const override;
|
||||||
|
@ -48,8 +48,8 @@ public:
|
||||||
bool shouldSendUpdate(uint32_t simulationStep, const QUuid& sessionID);
|
bool shouldSendUpdate(uint32_t simulationStep, const QUuid& sessionID);
|
||||||
void sendUpdate(OctreeEditPacketSender* packetSender, const QUuid& sessionID, uint32_t step);
|
void sendUpdate(OctreeEditPacketSender* packetSender, const QUuid& sessionID, uint32_t step);
|
||||||
|
|
||||||
virtual uint32_t getIncomingDirtyFlags();
|
virtual uint32_t getIncomingDirtyFlags() override;
|
||||||
virtual void clearIncomingDirtyFlags();
|
virtual void clearIncomingDirtyFlags() override;
|
||||||
|
|
||||||
void incrementAccelerationNearlyGravityCount() { _accelerationNearlyGravityCount++; }
|
void incrementAccelerationNearlyGravityCount() { _accelerationNearlyGravityCount++; }
|
||||||
void resetAccelerationNearlyGravityCount() { _accelerationNearlyGravityCount = 0; }
|
void resetAccelerationNearlyGravityCount() { _accelerationNearlyGravityCount = 0; }
|
||||||
|
@ -80,7 +80,7 @@ public:
|
||||||
|
|
||||||
virtual QString getName() const override;
|
virtual QString getName() const override;
|
||||||
|
|
||||||
virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const;
|
virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const override;
|
||||||
|
|
||||||
// eternal logic can suggest a simuator priority bid for the next outgoing update
|
// eternal logic can suggest a simuator priority bid for the next outgoing update
|
||||||
void setOutgoingPriority(quint8 priority);
|
void setOutgoingPriority(quint8 priority);
|
||||||
|
@ -93,7 +93,7 @@ protected:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
virtual bool isReadyToComputeShape() const override;
|
virtual bool isReadyToComputeShape() const override;
|
||||||
virtual btCollisionShape* computeNewShape();
|
virtual btCollisionShape* computeNewShape() override;
|
||||||
virtual void setMotionType(PhysicsMotionType motionType);
|
virtual void setMotionType(PhysicsMotionType motionType);
|
||||||
|
|
||||||
// In the glorious future (when entities lib depends on physics lib) the EntityMotionState will be
|
// In the glorious future (when entities lib depends on physics lib) the EntityMotionState will be
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// render-utils/src/
|
// render-utils/src/
|
||||||
//
|
//
|
||||||
// Created by Sam Gateau on 5/29/15.
|
// Created by Sam Gateau on 5/29/15.
|
||||||
// Copyright 20154 High Fidelity, Inc.
|
// Copyright 2016 High Fidelity, Inc.
|
||||||
//
|
//
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
@ -15,7 +15,6 @@
|
||||||
#include <RenderArgs.h>
|
#include <RenderArgs.h>
|
||||||
#include <ViewFrustum.h>
|
#include <ViewFrustum.h>
|
||||||
#include <gpu/Context.h>
|
#include <gpu/Context.h>
|
||||||
#include <gpu/StandardShaderLib.h>
|
|
||||||
|
|
||||||
#include "DebugDeferredBuffer.h"
|
#include "DebugDeferredBuffer.h"
|
||||||
#include "DeferredLightingEffect.h"
|
#include "DeferredLightingEffect.h"
|
||||||
|
@ -31,34 +30,11 @@
|
||||||
|
|
||||||
#include "RenderDeferredTask.h"
|
#include "RenderDeferredTask.h"
|
||||||
|
|
||||||
#include "model_vert.h"
|
|
||||||
#include "model_shadow_vert.h"
|
|
||||||
#include "model_normal_map_vert.h"
|
|
||||||
#include "model_lightmap_vert.h"
|
|
||||||
#include "model_lightmap_normal_map_vert.h"
|
|
||||||
#include "skin_model_vert.h"
|
|
||||||
#include "skin_model_shadow_vert.h"
|
|
||||||
#include "skin_model_normal_map_vert.h"
|
|
||||||
|
|
||||||
#include "model_frag.h"
|
|
||||||
#include "model_shadow_frag.h"
|
|
||||||
#include "model_normal_map_frag.h"
|
|
||||||
#include "model_normal_specular_map_frag.h"
|
|
||||||
#include "model_specular_map_frag.h"
|
|
||||||
#include "model_lightmap_frag.h"
|
|
||||||
#include "model_lightmap_normal_map_frag.h"
|
|
||||||
#include "model_lightmap_normal_specular_map_frag.h"
|
|
||||||
#include "model_lightmap_specular_map_frag.h"
|
|
||||||
#include "model_translucent_frag.h"
|
|
||||||
|
|
||||||
#include "overlay3D_vert.h"
|
|
||||||
#include "overlay3D_frag.h"
|
|
||||||
|
|
||||||
#include "drawOpaqueStencil_frag.h"
|
|
||||||
|
|
||||||
using namespace render;
|
using namespace render;
|
||||||
|
|
||||||
void initDeferredPipelines(render::ShapePlumber& plumber);
|
extern void initStencilPipeline(gpu::PipelinePointer& pipeline);
|
||||||
|
extern void initOverlay3DPipelines(render::ShapePlumber& plumber);
|
||||||
|
extern void initDeferredPipelines(render::ShapePlumber& plumber);
|
||||||
|
|
||||||
void PrepareDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
void PrepareDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||||
DependencyManager::get<DeferredLightingEffect>()->prepare(renderContext->args);
|
DependencyManager::get<DeferredLightingEffect>()->prepare(renderContext->args);
|
||||||
|
@ -128,7 +104,7 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) {
|
||||||
addJob<DrawStatus>("DrawStatus", opaques, DrawStatus(statusIconMap));
|
addJob<DrawStatus>("DrawStatus", opaques, DrawStatus(statusIconMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
addJob<DrawOverlay3D>("DrawOverlay3D", shapePlumber);
|
addJob<DrawOverlay3D>("DrawOverlay3D");
|
||||||
|
|
||||||
addJob<HitEffect>("HitEffect");
|
addJob<HitEffect>("HitEffect");
|
||||||
|
|
||||||
|
@ -180,22 +156,8 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Move this to the shapePlumber
|
DrawOverlay3D::DrawOverlay3D() : _shapePlumber{ std::make_shared<ShapePlumber>() } {
|
||||||
gpu::PipelinePointer DrawOverlay3D::_opaquePipeline;
|
initOverlay3DPipelines(*_shapePlumber);
|
||||||
const gpu::PipelinePointer& DrawOverlay3D::getOpaquePipeline() {
|
|
||||||
if (!_opaquePipeline) {
|
|
||||||
auto vs = gpu::Shader::createVertex(std::string(overlay3D_vert));
|
|
||||||
auto ps = gpu::Shader::createPixel(std::string(overlay3D_frag));
|
|
||||||
auto program = gpu::Shader::createProgram(vs, ps);
|
|
||||||
|
|
||||||
auto state = std::make_shared<gpu::State>();
|
|
||||||
state->setDepthTest(false);
|
|
||||||
// additive blending
|
|
||||||
state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
|
||||||
|
|
||||||
_opaquePipeline = gpu::Pipeline::create(program, state);
|
|
||||||
}
|
|
||||||
return _opaquePipeline;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||||
|
@ -246,9 +208,8 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon
|
||||||
batch.setViewTransform(viewMat);
|
batch.setViewTransform(viewMat);
|
||||||
batch.setViewportTransform(args->_viewport);
|
batch.setViewportTransform(args->_viewport);
|
||||||
batch.setStateScissorRect(args->_viewport);
|
batch.setStateScissorRect(args->_viewport);
|
||||||
|
|
||||||
batch.setPipeline(getOpaquePipeline());
|
|
||||||
batch.setResourceTexture(0, args->_whiteTexture);
|
batch.setResourceTexture(0, args->_whiteTexture);
|
||||||
|
|
||||||
renderShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn);
|
renderShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn);
|
||||||
});
|
});
|
||||||
args->_batch = nullptr;
|
args->_batch = nullptr;
|
||||||
|
@ -259,20 +220,7 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon
|
||||||
gpu::PipelinePointer DrawStencilDeferred::_opaquePipeline;
|
gpu::PipelinePointer DrawStencilDeferred::_opaquePipeline;
|
||||||
const gpu::PipelinePointer& DrawStencilDeferred::getOpaquePipeline() {
|
const gpu::PipelinePointer& DrawStencilDeferred::getOpaquePipeline() {
|
||||||
if (!_opaquePipeline) {
|
if (!_opaquePipeline) {
|
||||||
const gpu::int8 STENCIL_OPAQUE = 1;
|
initStencilPipeline(_opaquePipeline);
|
||||||
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
|
|
||||||
auto ps = gpu::Shader::createPixel(std::string(drawOpaqueStencil_frag));
|
|
||||||
auto program = gpu::Shader::createProgram(vs, ps);
|
|
||||||
|
|
||||||
|
|
||||||
gpu::Shader::makeProgram((*program));
|
|
||||||
|
|
||||||
auto state = std::make_shared<gpu::State>();
|
|
||||||
state->setDepthTest(true, false, gpu::LESS_EQUAL);
|
|
||||||
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_OPAQUE, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_REPLACE));
|
|
||||||
state->setColorWriteMask(0);
|
|
||||||
|
|
||||||
_opaquePipeline = gpu::Pipeline::create(program, state);
|
|
||||||
}
|
}
|
||||||
return _opaquePipeline;
|
return _opaquePipeline;
|
||||||
}
|
}
|
||||||
|
@ -413,166 +361,3 @@ void Blit::run(const SceneContextPointer& sceneContext, const RenderContextPoint
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void pipelineBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) {
|
|
||||||
if (pipeline.locations->normalFittingMapUnit > -1) {
|
|
||||||
batch.setResourceTexture(pipeline.locations->normalFittingMapUnit,
|
|
||||||
DependencyManager::get<TextureCache>()->getNormalFittingTexture());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void initDeferredPipelines(render::ShapePlumber& plumber) {
|
|
||||||
using Key = render::ShapeKey;
|
|
||||||
using ShaderPointer = gpu::ShaderPointer;
|
|
||||||
|
|
||||||
auto addPipeline = [&plumber](const Key& key, const ShaderPointer& vertexShader, const ShaderPointer& pixelShader) {
|
|
||||||
auto state = std::make_shared<gpu::State>();
|
|
||||||
|
|
||||||
// Cull backface
|
|
||||||
state->setCullMode(gpu::State::CULL_BACK);
|
|
||||||
|
|
||||||
// Z test depends on transparency
|
|
||||||
state->setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL);
|
|
||||||
|
|
||||||
// Blend if transparent
|
|
||||||
state->setBlendFunction(key.isTranslucent(),
|
|
||||||
// For transparency, keep the highlight intensity
|
|
||||||
gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
|
||||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
|
||||||
|
|
||||||
ShaderPointer program = gpu::Shader::createProgram(vertexShader, pixelShader);
|
|
||||||
plumber.addPipeline(key, program, state, &pipelineBatchSetter);
|
|
||||||
|
|
||||||
// Add a wireframe version
|
|
||||||
if (!key.isWireFrame()) {
|
|
||||||
auto wireFrameKey = Key::Builder(key).withWireframe();
|
|
||||||
auto wireFrameState = std::make_shared<gpu::State>(state->getValues());
|
|
||||||
|
|
||||||
wireFrameState->setFillMode(gpu::State::FILL_LINE);
|
|
||||||
|
|
||||||
plumber.addPipeline(wireFrameKey, program, wireFrameState, &pipelineBatchSetter);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Vertex shaders
|
|
||||||
auto modelVertex = gpu::Shader::createVertex(std::string(model_vert));
|
|
||||||
auto modelNormalMapVertex = gpu::Shader::createVertex(std::string(model_normal_map_vert));
|
|
||||||
auto modelLightmapVertex = gpu::Shader::createVertex(std::string(model_lightmap_vert));
|
|
||||||
auto modelLightmapNormalMapVertex = gpu::Shader::createVertex(std::string(model_lightmap_normal_map_vert));
|
|
||||||
auto modelShadowVertex = gpu::Shader::createVertex(std::string(model_shadow_vert));
|
|
||||||
auto skinModelVertex = gpu::Shader::createVertex(std::string(skin_model_vert));
|
|
||||||
auto skinModelNormalMapVertex = gpu::Shader::createVertex(std::string(skin_model_normal_map_vert));
|
|
||||||
auto skinModelShadowVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert));
|
|
||||||
|
|
||||||
// Pixel shaders
|
|
||||||
auto modelPixel = gpu::Shader::createPixel(std::string(model_frag));
|
|
||||||
auto modelNormalMapPixel = gpu::Shader::createPixel(std::string(model_normal_map_frag));
|
|
||||||
auto modelSpecularMapPixel = gpu::Shader::createPixel(std::string(model_specular_map_frag));
|
|
||||||
auto modelNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_normal_specular_map_frag));
|
|
||||||
auto modelTranslucentPixel = gpu::Shader::createPixel(std::string(model_translucent_frag));
|
|
||||||
auto modelShadowPixel = gpu::Shader::createPixel(std::string(model_shadow_frag));
|
|
||||||
auto modelLightmapPixel = gpu::Shader::createPixel(std::string(model_lightmap_frag));
|
|
||||||
auto modelLightmapNormalMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_map_frag));
|
|
||||||
auto modelLightmapSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_specular_map_frag));
|
|
||||||
auto modelLightmapNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag));
|
|
||||||
|
|
||||||
// Fill the pipelineLib
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder(),
|
|
||||||
modelVertex, modelPixel);
|
|
||||||
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withTangents(),
|
|
||||||
modelNormalMapVertex, modelNormalMapPixel);
|
|
||||||
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withSpecular(),
|
|
||||||
modelVertex, modelSpecularMapPixel);
|
|
||||||
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withTangents().withSpecular(),
|
|
||||||
modelNormalMapVertex, modelNormalSpecularMapPixel);
|
|
||||||
|
|
||||||
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withTranslucent(),
|
|
||||||
modelVertex, modelTranslucentPixel);
|
|
||||||
// FIXME Ignore lightmap for translucents meshpart
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withTranslucent().withLightmap(),
|
|
||||||
modelVertex, modelTranslucentPixel);
|
|
||||||
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withTangents().withTranslucent(),
|
|
||||||
modelNormalMapVertex, modelTranslucentPixel);
|
|
||||||
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withSpecular().withTranslucent(),
|
|
||||||
modelVertex, modelTranslucentPixel);
|
|
||||||
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withTangents().withSpecular().withTranslucent(),
|
|
||||||
modelNormalMapVertex, modelTranslucentPixel);
|
|
||||||
|
|
||||||
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withLightmap(),
|
|
||||||
modelLightmapVertex, modelLightmapPixel);
|
|
||||||
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withLightmap().withTangents(),
|
|
||||||
modelLightmapNormalMapVertex, modelLightmapNormalMapPixel);
|
|
||||||
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withLightmap().withSpecular(),
|
|
||||||
modelLightmapVertex, modelLightmapSpecularMapPixel);
|
|
||||||
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withLightmap().withTangents().withSpecular(),
|
|
||||||
modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel);
|
|
||||||
|
|
||||||
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withSkinned(),
|
|
||||||
skinModelVertex, modelPixel);
|
|
||||||
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withSkinned().withTangents(),
|
|
||||||
skinModelNormalMapVertex, modelNormalMapPixel);
|
|
||||||
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withSkinned().withSpecular(),
|
|
||||||
skinModelVertex, modelSpecularMapPixel);
|
|
||||||
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withSkinned().withTangents().withSpecular(),
|
|
||||||
skinModelNormalMapVertex, modelNormalSpecularMapPixel);
|
|
||||||
|
|
||||||
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withSkinned().withTranslucent(),
|
|
||||||
skinModelVertex, modelTranslucentPixel);
|
|
||||||
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withSkinned().withTangents().withTranslucent(),
|
|
||||||
skinModelNormalMapVertex, modelTranslucentPixel);
|
|
||||||
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withSkinned().withSpecular().withTranslucent(),
|
|
||||||
skinModelVertex, modelTranslucentPixel);
|
|
||||||
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withSkinned().withTangents().withSpecular().withTranslucent(),
|
|
||||||
skinModelNormalMapVertex, modelTranslucentPixel);
|
|
||||||
|
|
||||||
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withDepthOnly(),
|
|
||||||
modelShadowVertex, modelShadowPixel);
|
|
||||||
|
|
||||||
|
|
||||||
addPipeline(
|
|
||||||
Key::Builder().withSkinned().withDepthOnly(),
|
|
||||||
skinModelShadowVertex, modelShadowPixel);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -68,11 +68,10 @@ protected:
|
||||||
|
|
||||||
class DrawStencilDeferred {
|
class DrawStencilDeferred {
|
||||||
public:
|
public:
|
||||||
static const gpu::PipelinePointer& getOpaquePipeline();
|
using JobModel = render::Job::Model<DrawStencilDeferred>;
|
||||||
|
|
||||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||||
|
static const gpu::PipelinePointer& getOpaquePipeline();
|
||||||
using JobModel = render::Job::Model<DrawStencilDeferred>;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable
|
static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable
|
||||||
|
@ -106,15 +105,12 @@ public:
|
||||||
using Config = DrawOverlay3DConfig;
|
using Config = DrawOverlay3DConfig;
|
||||||
using JobModel = render::Job::Model<DrawOverlay3D, Config>;
|
using JobModel = render::Job::Model<DrawOverlay3D, Config>;
|
||||||
|
|
||||||
DrawOverlay3D(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {}
|
DrawOverlay3D();
|
||||||
|
|
||||||
void configure(const Config& config) { _maxDrawn = config.maxDrawn; }
|
void configure(const Config& config) { _maxDrawn = config.maxDrawn; }
|
||||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||||
|
|
||||||
static const gpu::PipelinePointer& getOpaquePipeline();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable
|
|
||||||
render::ShapePlumberPointer _shapePlumber;
|
render::ShapePlumberPointer _shapePlumber;
|
||||||
int _maxDrawn; // initialized by Config
|
int _maxDrawn; // initialized by Config
|
||||||
};
|
};
|
||||||
|
|
234
libraries/render-utils/src/RenderPipelines.cpp
Normal file
234
libraries/render-utils/src/RenderPipelines.cpp
Normal file
|
@ -0,0 +1,234 @@
|
||||||
|
|
||||||
|
//
|
||||||
|
// RenderPipelines.cpp
|
||||||
|
// render-utils/src/
|
||||||
|
//
|
||||||
|
// Created by Zach Pomerantz on 1/28/2016.
|
||||||
|
// Copyright 2016 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <gpu/Context.h>
|
||||||
|
#include <gpu/StandardShaderLib.h>
|
||||||
|
|
||||||
|
#include "TextureCache.h"
|
||||||
|
#include "render/DrawTask.h"
|
||||||
|
|
||||||
|
#include "model_vert.h"
|
||||||
|
#include "model_shadow_vert.h"
|
||||||
|
#include "model_normal_map_vert.h"
|
||||||
|
#include "model_lightmap_vert.h"
|
||||||
|
#include "model_lightmap_normal_map_vert.h"
|
||||||
|
#include "skin_model_vert.h"
|
||||||
|
#include "skin_model_shadow_vert.h"
|
||||||
|
#include "skin_model_normal_map_vert.h"
|
||||||
|
|
||||||
|
#include "model_frag.h"
|
||||||
|
#include "model_shadow_frag.h"
|
||||||
|
#include "model_normal_map_frag.h"
|
||||||
|
#include "model_normal_specular_map_frag.h"
|
||||||
|
#include "model_specular_map_frag.h"
|
||||||
|
#include "model_lightmap_frag.h"
|
||||||
|
#include "model_lightmap_normal_map_frag.h"
|
||||||
|
#include "model_lightmap_normal_specular_map_frag.h"
|
||||||
|
#include "model_lightmap_specular_map_frag.h"
|
||||||
|
#include "model_translucent_frag.h"
|
||||||
|
|
||||||
|
#include "overlay3D_vert.h"
|
||||||
|
#include "overlay3D_frag.h"
|
||||||
|
|
||||||
|
#include "drawOpaqueStencil_frag.h"
|
||||||
|
|
||||||
|
using namespace render;
|
||||||
|
|
||||||
|
void initStencilPipeline(gpu::PipelinePointer& pipeline) {
|
||||||
|
const gpu::int8 STENCIL_OPAQUE = 1;
|
||||||
|
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
|
||||||
|
auto ps = gpu::Shader::createPixel(std::string(drawOpaqueStencil_frag));
|
||||||
|
auto program = gpu::Shader::createProgram(vs, ps);
|
||||||
|
gpu::Shader::makeProgram((*program));
|
||||||
|
|
||||||
|
auto state = std::make_shared<gpu::State>();
|
||||||
|
state->setDepthTest(true, false, gpu::LESS_EQUAL);
|
||||||
|
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_OPAQUE, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_REPLACE));
|
||||||
|
state->setColorWriteMask(0);
|
||||||
|
|
||||||
|
pipeline = gpu::Pipeline::create(program, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initOverlay3DPipelines(ShapePlumber& plumber) {
|
||||||
|
auto vs = gpu::Shader::createVertex(std::string(overlay3D_vert));
|
||||||
|
auto ps = gpu::Shader::createPixel(std::string(overlay3D_frag));
|
||||||
|
auto program = gpu::Shader::createProgram(vs, ps);
|
||||||
|
|
||||||
|
auto opaqueState = std::make_shared<gpu::State>();
|
||||||
|
opaqueState->setDepthTest(false);
|
||||||
|
opaqueState->setBlendFunction(false);
|
||||||
|
|
||||||
|
plumber.addPipeline(ShapeKey::Filter::Builder().withOpaque(), program, opaqueState);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pipelineBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) {
|
||||||
|
if (pipeline.locations->normalFittingMapUnit > -1) {
|
||||||
|
batch.setResourceTexture(pipeline.locations->normalFittingMapUnit,
|
||||||
|
DependencyManager::get<TextureCache>()->getNormalFittingTexture());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void initDeferredPipelines(render::ShapePlumber& plumber) {
|
||||||
|
using Key = render::ShapeKey;
|
||||||
|
using ShaderPointer = gpu::ShaderPointer;
|
||||||
|
|
||||||
|
auto addPipeline = [&plumber](const Key& key, const ShaderPointer& vertexShader, const ShaderPointer& pixelShader) {
|
||||||
|
auto state = std::make_shared<gpu::State>();
|
||||||
|
|
||||||
|
// Cull backface
|
||||||
|
state->setCullMode(gpu::State::CULL_BACK);
|
||||||
|
|
||||||
|
// Z test depends on transparency
|
||||||
|
state->setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL);
|
||||||
|
|
||||||
|
// Blend if transparent
|
||||||
|
state->setBlendFunction(key.isTranslucent(),
|
||||||
|
// For transparency, keep the highlight intensity
|
||||||
|
gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||||
|
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||||
|
|
||||||
|
ShaderPointer program = gpu::Shader::createProgram(vertexShader, pixelShader);
|
||||||
|
plumber.addPipeline(key, program, state, &pipelineBatchSetter);
|
||||||
|
|
||||||
|
// Add a wireframe version
|
||||||
|
if (!key.isWireFrame()) {
|
||||||
|
auto wireFrameKey = Key::Builder(key).withWireframe();
|
||||||
|
auto wireFrameState = std::make_shared<gpu::State>(state->getValues());
|
||||||
|
|
||||||
|
wireFrameState->setFillMode(gpu::State::FILL_LINE);
|
||||||
|
|
||||||
|
plumber.addPipeline(wireFrameKey, program, wireFrameState, &pipelineBatchSetter);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Vertex shaders
|
||||||
|
auto modelVertex = gpu::Shader::createVertex(std::string(model_vert));
|
||||||
|
auto modelNormalMapVertex = gpu::Shader::createVertex(std::string(model_normal_map_vert));
|
||||||
|
auto modelLightmapVertex = gpu::Shader::createVertex(std::string(model_lightmap_vert));
|
||||||
|
auto modelLightmapNormalMapVertex = gpu::Shader::createVertex(std::string(model_lightmap_normal_map_vert));
|
||||||
|
auto modelShadowVertex = gpu::Shader::createVertex(std::string(model_shadow_vert));
|
||||||
|
auto skinModelVertex = gpu::Shader::createVertex(std::string(skin_model_vert));
|
||||||
|
auto skinModelNormalMapVertex = gpu::Shader::createVertex(std::string(skin_model_normal_map_vert));
|
||||||
|
auto skinModelShadowVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert));
|
||||||
|
|
||||||
|
// Pixel shaders
|
||||||
|
auto modelPixel = gpu::Shader::createPixel(std::string(model_frag));
|
||||||
|
auto modelNormalMapPixel = gpu::Shader::createPixel(std::string(model_normal_map_frag));
|
||||||
|
auto modelSpecularMapPixel = gpu::Shader::createPixel(std::string(model_specular_map_frag));
|
||||||
|
auto modelNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_normal_specular_map_frag));
|
||||||
|
auto modelTranslucentPixel = gpu::Shader::createPixel(std::string(model_translucent_frag));
|
||||||
|
auto modelShadowPixel = gpu::Shader::createPixel(std::string(model_shadow_frag));
|
||||||
|
auto modelLightmapPixel = gpu::Shader::createPixel(std::string(model_lightmap_frag));
|
||||||
|
auto modelLightmapNormalMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_map_frag));
|
||||||
|
auto modelLightmapSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_specular_map_frag));
|
||||||
|
auto modelLightmapNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag));
|
||||||
|
|
||||||
|
// Fill the pipelineLib
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder(),
|
||||||
|
modelVertex, modelPixel);
|
||||||
|
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withTangents(),
|
||||||
|
modelNormalMapVertex, modelNormalMapPixel);
|
||||||
|
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withSpecular(),
|
||||||
|
modelVertex, modelSpecularMapPixel);
|
||||||
|
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withTangents().withSpecular(),
|
||||||
|
modelNormalMapVertex, modelNormalSpecularMapPixel);
|
||||||
|
|
||||||
|
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withTranslucent(),
|
||||||
|
modelVertex, modelTranslucentPixel);
|
||||||
|
// FIXME Ignore lightmap for translucents meshpart
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withTranslucent().withLightmap(),
|
||||||
|
modelVertex, modelTranslucentPixel);
|
||||||
|
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withTangents().withTranslucent(),
|
||||||
|
modelNormalMapVertex, modelTranslucentPixel);
|
||||||
|
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withSpecular().withTranslucent(),
|
||||||
|
modelVertex, modelTranslucentPixel);
|
||||||
|
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withTangents().withSpecular().withTranslucent(),
|
||||||
|
modelNormalMapVertex, modelTranslucentPixel);
|
||||||
|
|
||||||
|
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withLightmap(),
|
||||||
|
modelLightmapVertex, modelLightmapPixel);
|
||||||
|
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withLightmap().withTangents(),
|
||||||
|
modelLightmapNormalMapVertex, modelLightmapNormalMapPixel);
|
||||||
|
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withLightmap().withSpecular(),
|
||||||
|
modelLightmapVertex, modelLightmapSpecularMapPixel);
|
||||||
|
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withLightmap().withTangents().withSpecular(),
|
||||||
|
modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel);
|
||||||
|
|
||||||
|
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withSkinned(),
|
||||||
|
skinModelVertex, modelPixel);
|
||||||
|
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withSkinned().withTangents(),
|
||||||
|
skinModelNormalMapVertex, modelNormalMapPixel);
|
||||||
|
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withSkinned().withSpecular(),
|
||||||
|
skinModelVertex, modelSpecularMapPixel);
|
||||||
|
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withSkinned().withTangents().withSpecular(),
|
||||||
|
skinModelNormalMapVertex, modelNormalSpecularMapPixel);
|
||||||
|
|
||||||
|
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withSkinned().withTranslucent(),
|
||||||
|
skinModelVertex, modelTranslucentPixel);
|
||||||
|
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withSkinned().withTangents().withTranslucent(),
|
||||||
|
skinModelNormalMapVertex, modelTranslucentPixel);
|
||||||
|
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withSkinned().withSpecular().withTranslucent(),
|
||||||
|
skinModelVertex, modelTranslucentPixel);
|
||||||
|
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withSkinned().withTangents().withSpecular().withTranslucent(),
|
||||||
|
skinModelNormalMapVertex, modelTranslucentPixel);
|
||||||
|
|
||||||
|
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withDepthOnly(),
|
||||||
|
modelShadowVertex, modelShadowPixel);
|
||||||
|
|
||||||
|
|
||||||
|
addPipeline(
|
||||||
|
Key::Builder().withSkinned().withDepthOnly(),
|
||||||
|
skinModelShadowVertex, modelShadowPixel);
|
||||||
|
}
|
||||||
|
|
|
@ -257,7 +257,13 @@ public:
|
||||||
QConfigPointer config = _jobs.back().getConfiguration();
|
QConfigPointer config = _jobs.back().getConfiguration();
|
||||||
config->setParent(_config.get());
|
config->setParent(_config.get());
|
||||||
config->setObjectName(name.c_str());
|
config->setObjectName(name.c_str());
|
||||||
QObject::connect(config.get(), SIGNAL(dirty()), _config.get(), SLOT(refresh()));
|
|
||||||
|
// Connect dirty->refresh if defined
|
||||||
|
static const char* DIRTY_SIGNAL = "dirty()";
|
||||||
|
if (config->metaObject()->indexOfSignal(DIRTY_SIGNAL) != -1) {
|
||||||
|
QObject::connect(config.get(), SIGNAL(dirty()), _config.get(), SLOT(refresh()));
|
||||||
|
}
|
||||||
|
|
||||||
return _jobs.back().getOutput();
|
return _jobs.back().getOutput();
|
||||||
}
|
}
|
||||||
template <class T, class... A> const Varying addJob(std::string name, A&&... args) {
|
template <class T, class... A> const Varying addJob(std::string name, A&&... args) {
|
||||||
|
|
|
@ -45,6 +45,20 @@ private:
|
||||||
bool _navigationFocused { false };
|
bool _navigationFocused { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QString fixupHifiUrl(const QString& urlString) {
|
||||||
|
static const QString ACCESS_TOKEN_PARAMETER = "access_token";
|
||||||
|
static const QString ALLOWED_HOST = "metaverse.highfidelity.com";
|
||||||
|
QUrl url(urlString);
|
||||||
|
QUrlQuery query(url);
|
||||||
|
if (url.host() == ALLOWED_HOST && query.allQueryItemValues(ACCESS_TOKEN_PARAMETER).empty()) {
|
||||||
|
AccountManager& accountManager = AccountManager::getInstance();
|
||||||
|
query.addQueryItem(ACCESS_TOKEN_PARAMETER, accountManager.getAccountInfo().getAccessToken().token);
|
||||||
|
url.setQuery(query.query());
|
||||||
|
return url.toString();
|
||||||
|
}
|
||||||
|
return urlString;
|
||||||
|
}
|
||||||
|
|
||||||
class UrlHandler : public QObject {
|
class UrlHandler : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
@ -60,20 +74,7 @@ public:
|
||||||
|
|
||||||
// FIXME hack for authentication, remove when we migrate to Qt 5.6
|
// FIXME hack for authentication, remove when we migrate to Qt 5.6
|
||||||
Q_INVOKABLE QString fixupUrl(const QString& originalUrl) {
|
Q_INVOKABLE QString fixupUrl(const QString& originalUrl) {
|
||||||
static const QString ACCESS_TOKEN_PARAMETER = "access_token";
|
return fixupHifiUrl(originalUrl);
|
||||||
static const QString ALLOWED_HOST = "metaverse.highfidelity.com";
|
|
||||||
QString result = originalUrl;
|
|
||||||
QUrl url(originalUrl);
|
|
||||||
QUrlQuery query(url);
|
|
||||||
if (url.host() == ALLOWED_HOST && query.allQueryItemValues(ACCESS_TOKEN_PARAMETER).empty()) {
|
|
||||||
qDebug() << "Updating URL with auth token";
|
|
||||||
AccountManager& accountManager = AccountManager::getInstance();
|
|
||||||
query.addQueryItem(ACCESS_TOKEN_PARAMETER, accountManager.getAccountInfo().getAccessToken().token);
|
|
||||||
url.setQuery(query.query());
|
|
||||||
result = url.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -49,8 +49,11 @@ QString QmlWebWindowClass::getURL() const {
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HACK find a good place to declare and store this
|
||||||
|
extern QString fixupHifiUrl(const QString& urlString);
|
||||||
|
|
||||||
void QmlWebWindowClass::setURL(const QString& urlString) {
|
void QmlWebWindowClass::setURL(const QString& urlString) {
|
||||||
DependencyManager::get<OffscreenUi>()->executeOnUiThread([=] {
|
DependencyManager::get<OffscreenUi>()->executeOnUiThread([=] {
|
||||||
_qmlWindow->setProperty(URL_PROPERTY, urlString);
|
_qmlWindow->setProperty(URL_PROPERTY, fixupHifiUrl(urlString));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -220,18 +220,7 @@ QmlWindowClass::QmlWindowClass(QObject* qmlWindow)
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlWindowClass::~QmlWindowClass() {
|
QmlWindowClass::~QmlWindowClass() {
|
||||||
if (_qmlWindow) {
|
close();
|
||||||
if (_toolWindow) {
|
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
|
||||||
auto toolWindow = offscreenUi->getToolWindow();
|
|
||||||
auto invokeResult = QMetaObject::invokeMethod(toolWindow, "removeTabForUrl", Qt::QueuedConnection,
|
|
||||||
Q_ARG(QVariant, _source));
|
|
||||||
Q_ASSERT(invokeResult);
|
|
||||||
} else {
|
|
||||||
_qmlWindow->deleteLater();
|
|
||||||
}
|
|
||||||
_qmlWindow = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlWindowClass::registerObject(const QString& name, QObject* object) {
|
void QmlWindowClass::registerObject(const QString& name, QObject* object) {
|
||||||
|
@ -331,14 +320,18 @@ void QmlWindowClass::setTitle(const QString& title) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlWindowClass::close() {
|
void QmlWindowClass::close() {
|
||||||
DependencyManager::get<OffscreenUi>()->executeOnUiThread([this] {
|
if (_qmlWindow) {
|
||||||
if (_qmlWindow) {
|
if (_toolWindow) {
|
||||||
_qmlWindow->setProperty("destroyOnInvisible", true);
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
_qmlWindow->setProperty("visible", false);
|
auto toolWindow = offscreenUi->getToolWindow();
|
||||||
|
auto invokeResult = QMetaObject::invokeMethod(toolWindow, "removeTabForUrl", Qt::QueuedConnection,
|
||||||
|
Q_ARG(QVariant, _source));
|
||||||
|
Q_ASSERT(invokeResult);
|
||||||
|
} else {
|
||||||
_qmlWindow->deleteLater();
|
_qmlWindow->deleteLater();
|
||||||
_qmlWindow = nullptr;
|
|
||||||
}
|
}
|
||||||
});
|
_qmlWindow = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlWindowClass::hasClosed() {
|
void QmlWindowClass::hasClosed() {
|
||||||
|
|
|
@ -282,8 +282,8 @@ void SixenseManager::InputDevice::setDebugDrawCalibrated(bool flag) {
|
||||||
|
|
||||||
// the calibration sequence is:
|
// the calibration sequence is:
|
||||||
// (1) reach arm straight out to the sides (xAxis is to the left)
|
// (1) reach arm straight out to the sides (xAxis is to the left)
|
||||||
// (2) press BUTTON_FWD on both hands and hold for one second
|
// (2) press either BUTTON_1 or BUTTON_2 on both hands and hold for one second
|
||||||
// (3) release both BUTTON_FWDs
|
// (3) release both buttons
|
||||||
//
|
//
|
||||||
// The code will:
|
// The code will:
|
||||||
// (4) assume that the orb is on a flat surface (yAxis is UP)
|
// (4) assume that the orb is on a flat surface (yAxis is UP)
|
||||||
|
@ -294,7 +294,8 @@ static const float MAXIMUM_NOISE_LEVEL = 0.05f; // meters
|
||||||
static const quint64 LOCK_DURATION = USECS_PER_SECOND / 4; // time for lock to be acquired
|
static const quint64 LOCK_DURATION = USECS_PER_SECOND / 4; // time for lock to be acquired
|
||||||
|
|
||||||
static bool calibrationRequested(SixenseControllerData* controllers) {
|
static bool calibrationRequested(SixenseControllerData* controllers) {
|
||||||
return (controllers[0].buttons == BUTTON_FWD && controllers[1].buttons == BUTTON_FWD);
|
return (((controllers[0].buttons == BUTTON_1) || (controllers[0].buttons == BUTTON_2)) &&
|
||||||
|
((controllers[1].buttons == BUTTON_1) || (controllers[1].buttons == BUTTON_2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SixenseManager::InputDevice::updateCalibration(SixenseControllerData* controllers) {
|
void SixenseManager::InputDevice::updateCalibration(SixenseControllerData* controllers) {
|
||||||
|
|
Loading…
Reference in a new issue