mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-08-18 11:41:51 +02:00
merge with master
This commit is contained in:
commit
9c1b139d5f
109 changed files with 3056 additions and 1642 deletions
|
@ -31,7 +31,7 @@ If you do not wish to use the Python installation bundled with Visual Studio, yo
|
|||
|
||||
### Step 2. Installing CMake
|
||||
|
||||
Download and install the latest version of CMake 3.9.
|
||||
Download and install the latest version of CMake 3.14.
|
||||
|
||||
Download the file named win64-x64 Installer from the [CMake Website](https://cmake.org/download/). You can access the installer on this [3.14 Version page](https://cmake.org/files/v3.14/). During installation, make sure to check "Add CMake to system PATH for all users" when prompted.
|
||||
|
||||
|
|
|
@ -136,7 +136,8 @@ void DomainGatekeeper::processConnectRequestPacket(QSharedPointer<ReceivedMessag
|
|||
} else {
|
||||
qDebug() << "Refusing connection from node at" << message->getSenderSockAddr()
|
||||
<< "with hardware address" << nodeConnection.hardwareAddress
|
||||
<< "and machine fingerprint" << nodeConnection.machineFingerprint;
|
||||
<< "and machine fingerprint" << nodeConnection.machineFingerprint
|
||||
<< "sysinfo" << nodeConnection.SystemInfo;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,11 @@ NodeConnectionData NodeConnectionData::fromDataStream(QDataStream& dataStream, c
|
|||
dataStream >> newHeader.machineFingerprint;
|
||||
|
||||
// and the operating system type
|
||||
dataStream >> newHeader.SystemInfo;
|
||||
QByteArray compressedSystemInfo;
|
||||
dataStream >> compressedSystemInfo;
|
||||
if (!compressedSystemInfo.isEmpty()) {
|
||||
newHeader.SystemInfo = qUncompress(compressedSystemInfo);
|
||||
}
|
||||
|
||||
dataStream >> newHeader.connectReason;
|
||||
|
||||
|
|
|
@ -340,10 +340,10 @@ Item {
|
|||
text: "GPU: " + root.gpuFrameTime.toFixed(1) + " ms"
|
||||
}
|
||||
StatText {
|
||||
text: "GPU (Per pixel): " + root.gpuFrameTimePerPixel.toFixed(5) + " ns/pp"
|
||||
text: "GPU (Per pixel): " + root.gpuFrameTimePerPixel.toFixed(1) + " ns/pp"
|
||||
}
|
||||
StatText {
|
||||
text: "GPU frame size: " + root.gpuFrameSize.x + " x " + root.gpuFrameSize.y
|
||||
text: "GPU frame size: " + root.gpuFrameSize.x.toFixed(0) + " x " + root.gpuFrameSize.y.toFixed(0)
|
||||
}
|
||||
StatText {
|
||||
text: "LOD Target: " + root.lodTargetFramerate + " Hz Angle: " + root.lodAngle + " deg"
|
||||
|
|
|
@ -91,7 +91,20 @@ Rectangle {
|
|||
Component {
|
||||
id: highlightBar
|
||||
Rectangle {
|
||||
width: tabListView.currentItem.width
|
||||
height: tabListView.currentItem.height
|
||||
color: simplifiedUI.colors.darkBackground
|
||||
x: tabListView.currentItem.x
|
||||
Behavior on x {
|
||||
SmoothedAnimation {
|
||||
duration: 250
|
||||
}
|
||||
}
|
||||
Behavior on width {
|
||||
SmoothedAnimation {
|
||||
duration: 250
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,6 +117,7 @@ Rectangle {
|
|||
orientation: ListView.Horizontal
|
||||
model: tabListModel
|
||||
highlight: highlightBar
|
||||
highlightFollowsCurrentItem: false
|
||||
interactive: contentItem.width > width
|
||||
delegate: Item {
|
||||
visible: model.tabTitle !== "Dev" || (model.tabTitle === "Dev" && root.developerModeEnabled)
|
||||
|
|
|
@ -122,12 +122,22 @@ Flickable {
|
|||
}
|
||||
|
||||
HifiStylesUit.GraphikRegular {
|
||||
text: "<b>CPU:</b> " + PlatformInfo.getCPUBrand()
|
||||
text: "<b>CPU:</b>"
|
||||
Layout.maximumWidth: parent.width
|
||||
height: paintedHeight
|
||||
size: 16
|
||||
color: simplifiedUI.colors.text.white
|
||||
wrapMode: Text.Wrap
|
||||
|
||||
Component.onCompleted: {
|
||||
var cpu = JSON.parse(PlatformInfo.getCPU(0));
|
||||
var cpuModel = cpu.model;
|
||||
if (cpuModel.length === 0) {
|
||||
cpuModel = "Unknown";
|
||||
}
|
||||
|
||||
text = "<b>CPU:</b> " + cpuModel;
|
||||
}
|
||||
}
|
||||
|
||||
HifiStylesUit.GraphikRegular {
|
||||
|
@ -158,12 +168,22 @@ Flickable {
|
|||
}
|
||||
|
||||
HifiStylesUit.GraphikRegular {
|
||||
text: "<b>GPU:</b> " + PlatformInfo.getGraphicsCardType()
|
||||
text: "<b>GPU:</b> "
|
||||
Layout.maximumWidth: parent.width
|
||||
height: paintedHeight
|
||||
size: 16
|
||||
color: simplifiedUI.colors.text.white
|
||||
wrapMode: Text.Wrap
|
||||
|
||||
Component.onCompleted: {
|
||||
var gpu = JSON.parse(PlatformInfo.getGPU(0));
|
||||
var gpuModel = gpu.model;
|
||||
if (gpuModel.length === 0) {
|
||||
gpuModel = "Unknown";
|
||||
}
|
||||
|
||||
text = "<b>GPU:</b> " + gpuModel;
|
||||
}
|
||||
}
|
||||
|
||||
HifiStylesUit.GraphikRegular {
|
||||
|
@ -180,9 +200,11 @@ Flickable {
|
|||
width: 200
|
||||
height: 32
|
||||
text: "Copy to Clipboard"
|
||||
temporaryText: "Copied!"
|
||||
|
||||
onClicked: {
|
||||
Window.copyToClipboard(root.buildPlatformInfoTextToCopy());
|
||||
showTemporaryText();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -206,12 +228,29 @@ Flickable {
|
|||
textToCopy += "Computer Vendor/Model: " + computerVendor + "/" + computerModel + "\n";
|
||||
textToCopy += "Profiled Platform Tier: " + PlatformInfo.getTierProfiled() + "\n";
|
||||
textToCopy += "OS Type: " + PlatformInfo.getOperatingSystemType() + "\n";
|
||||
textToCopy += "CPU: " + PlatformInfo.getCPUBrand() + "\n";
|
||||
|
||||
var cpu = JSON.parse(PlatformInfo.getCPU(0));
|
||||
var cpuModel = cpu.model;
|
||||
if (cpuModel.length === 0) {
|
||||
cpuModel = "Unknown";
|
||||
}
|
||||
|
||||
textToCopy += "CPU: " + cpuModel + "\n";
|
||||
textToCopy += "# CPUs: " + PlatformInfo.getNumCPUs() + "\n";
|
||||
textToCopy += "# CPU Cores: " + PlatformInfo.getNumLogicalCores() + "\n";
|
||||
textToCopy += "RAM: " + PlatformInfo.getTotalSystemMemoryMB() + " MB\n";
|
||||
textToCopy += "GPU: " + PlatformInfo.getGraphicsCardType() + "\n";
|
||||
textToCopy += "VR Hand Controllers: " + (PlatformInfo.hasRiftControllers() ? "Rift" : (PlatformInfo.hasViveControllers() ? "Vive" : "None"));
|
||||
|
||||
var gpu = JSON.parse(PlatformInfo.getGPU(0));
|
||||
var gpuModel = gpu.model;
|
||||
if (gpuModel.length === 0) {
|
||||
gpuModel = "Unknown";
|
||||
}
|
||||
|
||||
textToCopy += "GPU: " + gpuModel + "\n";
|
||||
textToCopy += "VR Hand Controllers: " + (PlatformInfo.hasRiftControllers() ? "Rift" : (PlatformInfo.hasViveControllers() ? "Vive" : "None")) + "\n";
|
||||
|
||||
textToCopy += "\n**All Platform Info**\n";
|
||||
textToCopy += JSON.stringify(JSON.parse(PlatformInfo.getPlatform()), null, 4);
|
||||
|
||||
return textToCopy;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,9 @@ import TabletScriptingInterface 1.0
|
|||
|
||||
Original.Button {
|
||||
id: root
|
||||
// The two properties below are used when calling showTemporaryText()
|
||||
property string originalText: ""
|
||||
property string temporaryText: ""
|
||||
|
||||
SimplifiedConstants.SimplifiedConstants {
|
||||
id: simplifiedUI
|
||||
|
@ -103,4 +106,31 @@ Original.Button {
|
|||
horizontalAlignment: Text.AlignHCenter
|
||||
text: root.text
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: showTemporaryTextTimer
|
||||
interval: 1500
|
||||
repeat: false
|
||||
running: false
|
||||
|
||||
onTriggered: {
|
||||
buttonText.text = root.originalText;
|
||||
root.originalText = "";
|
||||
}
|
||||
}
|
||||
|
||||
function showTemporaryText() {
|
||||
if (root.temporaryText === "") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (showTemporaryTextTimer.running) {
|
||||
showTemporaryTextTimer.restart();
|
||||
return;
|
||||
}
|
||||
|
||||
root.originalText = buttonText.text;
|
||||
buttonText.text = root.temporaryText;
|
||||
showTemporaryTextTimer.start();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3745,18 +3745,6 @@ void Application::resizeGL() {
|
|||
DependencyManager::get<FramebufferCache>()->setFrameBufferSize(fromGlm(renderSize));
|
||||
}
|
||||
|
||||
auto renderResolutionScale = getRenderResolutionScale();
|
||||
if (displayPlugin->getRenderResolutionScale() != renderResolutionScale) {
|
||||
auto renderConfig = _graphicsEngine.getRenderEngine()->getConfiguration();
|
||||
assert(renderConfig);
|
||||
auto mainView = renderConfig->getConfig("RenderMainView.RenderDeferredTask");
|
||||
// mainView can be null if we're rendering in forward mode
|
||||
if (mainView) {
|
||||
mainView->setProperty("resolutionScale", renderResolutionScale);
|
||||
}
|
||||
displayPlugin->setRenderResolutionScale(renderResolutionScale);
|
||||
}
|
||||
|
||||
// FIXME the aspect ratio for stereo displays is incorrect based on this.
|
||||
float aspectRatio = displayPlugin->getRecommendedAspectRatio();
|
||||
_myCamera.setProjection(glm::perspective(glm::radians(_fieldOfView.get()), aspectRatio,
|
||||
|
@ -8546,23 +8534,7 @@ void Application::shareSnapshot(const QString& path, const QUrl& href) {
|
|||
}
|
||||
|
||||
float Application::getRenderResolutionScale() const {
|
||||
auto menu = Menu::getInstance();
|
||||
if (!menu) {
|
||||
return 1.0f;
|
||||
}
|
||||
if (menu->isOptionChecked(MenuOption::RenderResolutionOne)) {
|
||||
return 1.0f;
|
||||
} else if (menu->isOptionChecked(MenuOption::RenderResolutionTwoThird)) {
|
||||
return 0.666f;
|
||||
} else if (menu->isOptionChecked(MenuOption::RenderResolutionHalf)) {
|
||||
return 0.5f;
|
||||
} else if (menu->isOptionChecked(MenuOption::RenderResolutionThird)) {
|
||||
return 0.333f;
|
||||
} else if (menu->isOptionChecked(MenuOption::RenderResolutionQuarter)) {
|
||||
return 0.25f;
|
||||
} else {
|
||||
return 1.0f;
|
||||
}
|
||||
return RenderScriptingInterface::getInstance()->getViewportResolutionScale();
|
||||
}
|
||||
|
||||
void Application::notifyPacketVersionMismatch() {
|
||||
|
|
|
@ -383,28 +383,6 @@ Menu::Menu() {
|
|||
// Developer > Render > OpenVR threaded submit
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::OpenVrThreadedSubmit, 0, true);
|
||||
|
||||
// Developer > Render > Resolution
|
||||
MenuWrapper* resolutionMenu = renderOptionsMenu->addMenu(MenuOption::RenderResolution);
|
||||
QActionGroup* resolutionGroup = new QActionGroup(resolutionMenu);
|
||||
resolutionGroup->setExclusive(true);
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionOne, 0, false));
|
||||
#else
|
||||
resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionOne, 0, true));
|
||||
#endif
|
||||
|
||||
resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionTwoThird, 0, false));
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionHalf, 0, true));
|
||||
#else
|
||||
resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionHalf, 0, false));
|
||||
#endif
|
||||
|
||||
resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionThird, 0, false));
|
||||
resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionQuarter, 0, false));
|
||||
|
||||
//const QString = "Automatic Texture Memory";
|
||||
//const QString = "64 MB";
|
||||
//const QString = "256 MB";
|
||||
|
|
|
@ -168,12 +168,6 @@ namespace MenuOption {
|
|||
const QString RenderMaxTexture4096MB = "4096 MB";
|
||||
const QString RenderMaxTexture6144MB = "6144 MB";
|
||||
const QString RenderMaxTexture8192MB = "8192 MB";
|
||||
const QString RenderResolution = "Scale Resolution";
|
||||
const QString RenderResolutionOne = "1";
|
||||
const QString RenderResolutionTwoThird = "2/3";
|
||||
const QString RenderResolutionHalf = "1/2";
|
||||
const QString RenderResolutionThird = "1/3";
|
||||
const QString RenderResolutionQuarter = "1/4";
|
||||
const QString RenderSensorToWorldMatrix = "Show SensorToWorld Matrix";
|
||||
const QString RenderIKTargets = "Show IK Targets";
|
||||
const QString RenderIKConstraints = "Show IK Constraints";
|
||||
|
|
|
@ -19,13 +19,15 @@
|
|||
* The <code>"far-grab"</code> {@link Entities.ActionType|ActionType} moves and rotates an entity to a target position and
|
||||
* orientation, optionally relative to another entity. Collisions between the entity and the user's avatar are disabled during
|
||||
* the far-grab.
|
||||
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
|
||||
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}:
|
||||
*
|
||||
* @typedef {object} Entities.ActionArguments-FarGrab
|
||||
* @property {Uuid} otherID=null - If an entity ID, the <code>targetPosition</code> and <code>targetRotation</code> are
|
||||
* relative to the entity's position and rotation.
|
||||
* @property {Uuid} otherJointIndex=null - If a joint index in the <code>otherID</code> entity, the <code>targetPosition</code>
|
||||
* and <code>targetRotation</code> are relative to the entity joint's position and rotation.
|
||||
* @property {Vec3} targetPosition=0,0,0 - The target position.
|
||||
* @property {Quat} targetRotation=0,0,0,1 - The target rotation.
|
||||
* @property {Uuid} otherID=null - If an entity ID, the <code>targetPosition</code> and <code>targetRotation</code> are
|
||||
* relative to this entity's position and rotation.
|
||||
* @property {number} linearTimeScale=3.4e+38 - Controls how long it takes for the entity's position to catch up with the
|
||||
* target position. The value is the time for the action to catch up to 1/e = 0.368 of the target value, where the action
|
||||
* is applied using an exponential decay.
|
||||
|
@ -33,6 +35,7 @@
|
|||
* target orientation. The value is the time for the action to catch up to 1/e = 0.368 of the target value, where the
|
||||
* action is applied using an exponential decay.
|
||||
*/
|
||||
// The properties are per ObjectActionTractor.
|
||||
class AvatarActionFarGrab : public ObjectActionTractor {
|
||||
public:
|
||||
AvatarActionFarGrab(const QUuid& id, EntityItemPointer ownerEntity);
|
||||
|
|
|
@ -447,16 +447,16 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) {
|
|||
/**jsdoc
|
||||
* The <code>"hold"</code> {@link Entities.ActionType|ActionType} positions and rotates an entity relative to an avatar's hand.
|
||||
* Collisions between the entity and the user's avatar are disabled during the hold.
|
||||
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
|
||||
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}:
|
||||
*
|
||||
* @typedef {object} Entities.ActionArguments-Hold
|
||||
* @property {Uuid} holderID=MyAvatar.sessionUUID - The ID of the avatar holding the entity.
|
||||
* @property {string} hand=right - The hand holding the entity: <code>"left"</code> or <code>"right"</code>.
|
||||
* @property {Vec3} relativePosition=0,0,0 - The target position relative to the avatar's hand.
|
||||
* @property {Vec3} relativeRotation=0,0,0,1 - The target rotation relative to the avatar's hand.
|
||||
* @property {number} timeScale=3.4e+38 - Controls how long it takes for the entity's position and rotation to catch up with
|
||||
* the target. The value is the time for the action to catch up to 1/e = 0.368 of the target value, where the action is
|
||||
* applied using an exponential decay.
|
||||
* @property {string} hand=right - The hand holding the entity: <code>"left"</code> or <code>"right"</code>.
|
||||
* @property {boolean} kinematic=false - If <code>true</code>, the entity is made kinematic during the action; the entity won't
|
||||
* lag behind the hand but constraint actions such as <code>"hinge"</code> won't act properly.
|
||||
* @property {boolean} kinematicSetVelocity=false - If <code>true</code> and <code>kinematic</code> is <code>true</code>, the
|
||||
|
|
|
@ -30,14 +30,16 @@ void RenderScriptingInterface::loadSettings() {
|
|||
_shadowsEnabled = (_shadowsEnabledSetting.get());
|
||||
_ambientOcclusionEnabled = (_ambientOcclusionEnabledSetting.get());
|
||||
_antialiasingEnabled = (_antialiasingEnabledSetting.get());
|
||||
_viewportResolutionScale = (_viewportResolutionScaleSetting.get());
|
||||
});
|
||||
forceRenderMethod((RenderMethod)_renderMethod);
|
||||
forceShadowsEnabled(_shadowsEnabled);
|
||||
forceAmbientOcclusionEnabled(_ambientOcclusionEnabled);
|
||||
forceAntialiasingEnabled(_antialiasingEnabled);
|
||||
forceViewportResolutionScale(_viewportResolutionScale);
|
||||
}
|
||||
|
||||
RenderScriptingInterface::RenderMethod RenderScriptingInterface::getRenderMethod() {
|
||||
RenderScriptingInterface::RenderMethod RenderScriptingInterface::getRenderMethod() const {
|
||||
return (RenderMethod) _renderMethod;
|
||||
}
|
||||
|
||||
|
@ -64,7 +66,7 @@ QStringList RenderScriptingInterface::getRenderMethodNames() const {
|
|||
return refrenderMethodNames;
|
||||
}
|
||||
|
||||
bool RenderScriptingInterface::getShadowsEnabled() {
|
||||
bool RenderScriptingInterface::getShadowsEnabled() const {
|
||||
return _shadowsEnabled;
|
||||
}
|
||||
|
||||
|
@ -88,7 +90,7 @@ void RenderScriptingInterface::forceShadowsEnabled(bool enabled) {
|
|||
});
|
||||
}
|
||||
|
||||
bool RenderScriptingInterface::getAmbientOcclusionEnabled() {
|
||||
bool RenderScriptingInterface::getAmbientOcclusionEnabled() const {
|
||||
return _ambientOcclusionEnabled;
|
||||
}
|
||||
|
||||
|
@ -112,7 +114,7 @@ void RenderScriptingInterface::forceAmbientOcclusionEnabled(bool enabled) {
|
|||
});
|
||||
}
|
||||
|
||||
bool RenderScriptingInterface::getAntialiasingEnabled() {
|
||||
bool RenderScriptingInterface::getAntialiasingEnabled() const {
|
||||
return _antialiasingEnabled;
|
||||
}
|
||||
|
||||
|
@ -145,3 +147,37 @@ void RenderScriptingInterface::forceAntialiasingEnabled(bool enabled) {
|
|||
}
|
||||
|
||||
|
||||
float RenderScriptingInterface::getViewportResolutionScale() const {
|
||||
return _viewportResolutionScale;
|
||||
}
|
||||
|
||||
void RenderScriptingInterface::setViewportResolutionScale(float scale) {
|
||||
if (_viewportResolutionScale != scale) {
|
||||
forceViewportResolutionScale(scale);
|
||||
emit settingsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderScriptingInterface::forceViewportResolutionScale(float scale) {
|
||||
// just not negative values or zero
|
||||
if (scale <= 0.f) {
|
||||
return;
|
||||
}
|
||||
_renderSettingLock.withWriteLock([&] {
|
||||
_viewportResolutionScale = (scale);
|
||||
_viewportResolutionScaleSetting.set(scale);
|
||||
|
||||
auto renderConfig = qApp->getRenderEngine()->getConfiguration();
|
||||
assert(renderConfig);
|
||||
auto deferredView = renderConfig->getConfig("RenderMainView.RenderDeferredTask");
|
||||
// mainView can be null if we're rendering in forward mode
|
||||
if (deferredView) {
|
||||
deferredView->setProperty("resolutionScale", _viewportResolutionScale);
|
||||
}
|
||||
auto forwardView = renderConfig->getConfig("RenderMainView.RenderForwardTask");
|
||||
// mainView can be null if we're rendering in forward mode
|
||||
if (forwardView) {
|
||||
forwardView->setProperty("resolutionScale", _viewportResolutionScale);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ class RenderScriptingInterface : public QObject {
|
|||
Q_PROPERTY(bool shadowsEnabled READ getShadowsEnabled WRITE setShadowsEnabled NOTIFY settingsChanged)
|
||||
Q_PROPERTY(bool ambientOcclusionEnabled READ getAmbientOcclusionEnabled WRITE setAmbientOcclusionEnabled NOTIFY settingsChanged)
|
||||
Q_PROPERTY(bool antialiasingEnabled READ getAntialiasingEnabled WRITE setAntialiasingEnabled NOTIFY settingsChanged)
|
||||
Q_PROPERTY(float viewportResolutionScale READ getViewportResolutionScale WRITE setViewportResolutionScale NOTIFY settingsChanged)
|
||||
|
||||
public:
|
||||
RenderScriptingInterface();
|
||||
|
@ -66,7 +67,7 @@ public slots:
|
|||
* @function Render.getRenderMethod
|
||||
* @returns {number} <code>"DEFERRED"</code> or <code>"FORWARD"</code>
|
||||
*/
|
||||
RenderMethod getRenderMethod();
|
||||
RenderMethod getRenderMethod() const;
|
||||
|
||||
/**jsdoc
|
||||
* Sets the current render method
|
||||
|
@ -88,7 +89,7 @@ public slots:
|
|||
* @function Render.getShadowsEnabled
|
||||
* @returns {bool} <code>true</code> if shadows are enabled, otherwise <code>false</code>
|
||||
*/
|
||||
bool getShadowsEnabled();
|
||||
bool getShadowsEnabled() const;
|
||||
|
||||
/**jsdoc
|
||||
* Enables or disables shadows
|
||||
|
@ -102,7 +103,7 @@ public slots:
|
|||
* @function Render.getAmbientOcclusionEnabled
|
||||
* @returns {bool} <code>true</code> if ambient occlusion is enabled, otherwise <code>false</code>
|
||||
*/
|
||||
bool getAmbientOcclusionEnabled();
|
||||
bool getAmbientOcclusionEnabled() const;
|
||||
|
||||
/**jsdoc
|
||||
* Enables or disables ambient occlusion
|
||||
|
@ -116,7 +117,7 @@ public slots:
|
|||
* @function Render.getAntialiasingEnabled
|
||||
* @returns {bool} <code>true</code> if anti-aliasing is enabled, otherwise <code>false</code>
|
||||
*/
|
||||
bool getAntialiasingEnabled();
|
||||
bool getAntialiasingEnabled() const;
|
||||
|
||||
/**jsdoc
|
||||
* Enables or disables anti-aliasing
|
||||
|
@ -130,14 +131,14 @@ public slots:
|
|||
* @function Render.getViewportResolutionScale
|
||||
* @returns {number}
|
||||
*/
|
||||
// float getViewportResolutionScale();
|
||||
float getViewportResolutionScale() const;
|
||||
|
||||
/**jsdoc
|
||||
* Sets the current viewport resolution scale
|
||||
* @function Render.setViewportResolutionScale
|
||||
* @param {number} resolutionScale - between epsilon and 1.0
|
||||
*/
|
||||
// void setViewportResolutionScale(float resolutionScale);
|
||||
void setViewportResolutionScale(float resolutionScale);
|
||||
|
||||
signals:
|
||||
void settingsChanged();
|
||||
|
@ -150,19 +151,22 @@ private:
|
|||
int _renderMethod{ RENDER_FORWARD ? render::Args::RenderMethod::FORWARD : render::Args::RenderMethod::DEFERRED };
|
||||
bool _shadowsEnabled{ true };
|
||||
bool _ambientOcclusionEnabled{ false };
|
||||
bool _antialiasingEnabled { true };
|
||||
bool _antialiasingEnabled{ true };
|
||||
float _viewportResolutionScale{ 1.0f };
|
||||
|
||||
// Actual settings saved on disk
|
||||
Setting::Handle<int> _renderMethodSetting { "renderMethod", RENDER_FORWARD ? render::Args::RenderMethod::FORWARD : render::Args::RenderMethod::DEFERRED };
|
||||
Setting::Handle<bool> _shadowsEnabledSetting { "shadowsEnabled", true };
|
||||
Setting::Handle<bool> _ambientOcclusionEnabledSetting { "ambientOcclusionEnabled", false };
|
||||
Setting::Handle<bool> _antialiasingEnabledSetting { "antialiasingEnabled", true };
|
||||
Setting::Handle<float> _viewportResolutionScaleSetting { "viewportResolutionScale", 1.0f };
|
||||
|
||||
// Force assign both setting AND runtime value to the parameter value
|
||||
void forceRenderMethod(RenderMethod renderMethod);
|
||||
void forceShadowsEnabled(bool enabled);
|
||||
void forceAmbientOcclusionEnabled(bool enabled);
|
||||
void forceAntialiasingEnabled(bool enabled);
|
||||
void forceViewportResolutionScale(float scale);
|
||||
|
||||
static std::once_flag registry_flag;
|
||||
};
|
||||
|
|
|
@ -165,14 +165,14 @@ public slots:
|
|||
|
||||
/**jsdoc
|
||||
* Set number of cycles texture size is required to be stable
|
||||
* @function Entities.setMinimumGPUTextureMemStabilityCount
|
||||
* @function Test.setMinimumGPUTextureMemStabilityCount
|
||||
* @param {number} count - Number of cycles to wait
|
||||
*/
|
||||
Q_INVOKABLE void setMinimumGPUTextureMemStabilityCount(int count);
|
||||
|
||||
/**jsdoc
|
||||
* Check whether all textures have been loaded.
|
||||
* @function Entities.isTextureLoadingComplete
|
||||
* @function Test.isTextureLoadingComplete
|
||||
* @returns {boolean} <code>true</code> texture memory usage is not increasing
|
||||
*/
|
||||
Q_INVOKABLE bool isTextureLoadingComplete();
|
||||
|
|
|
@ -14,10 +14,9 @@
|
|||
#include <ScriptEngines.h>
|
||||
#include <OffscreenUi.h>
|
||||
#include <Preferences.h>
|
||||
#include <RenderShadowTask.h>
|
||||
#include <plugins/PluginUtils.h>
|
||||
#include <display-plugins/CompositorHelper.h>
|
||||
|
||||
#include "scripting/RenderScriptingInterface.h"
|
||||
#include "Application.h"
|
||||
#include "DialogsManager.h"
|
||||
#include "LODManager.h"
|
||||
|
@ -113,6 +112,22 @@ void setupPreferences() {
|
|||
};
|
||||
preferences->addPreference(new CheckPreference(GRAPHICS_QUALITY, "Enable Procedural Materials on Meshes", getterMeshShaders, setterMeshShaders));
|
||||
}
|
||||
{
|
||||
// Expose the Viewport Resolution Scale
|
||||
auto getter = []()->float {
|
||||
return RenderScriptingInterface::getInstance()->getViewportResolutionScale();
|
||||
};
|
||||
|
||||
auto setter = [](float value) {
|
||||
RenderScriptingInterface::getInstance()->setViewportResolutionScale(value);
|
||||
};
|
||||
|
||||
auto scaleSlider = new SliderPreference(GRAPHICS_QUALITY, "Resolution Scale", getter, setter);
|
||||
scaleSlider->setMin(0.25f);
|
||||
scaleSlider->setMax(1.0f);
|
||||
scaleSlider->setStep(0.02f);
|
||||
preferences->addPreference(scaleSlider);
|
||||
}
|
||||
|
||||
// UI
|
||||
static const QString UI_CATEGORY { "User Interface" };
|
||||
|
|
|
@ -377,7 +377,7 @@ void Stats::updateStats(bool force) {
|
|||
auto displayPlugin = qApp->getActiveDisplayPlugin();
|
||||
if (displayPlugin) {
|
||||
QVector2D dims(displayPlugin->getRecommendedRenderSize().x, displayPlugin->getRecommendedRenderSize().y);
|
||||
dims *= displayPlugin->getRenderResolutionScale();
|
||||
dims *= qApp->getRenderResolutionScale();
|
||||
STAT_UPDATE(gpuFrameSize, dims);
|
||||
STAT_UPDATE(gpuFrameTimePerPixel, (float)(gpuContext->getFrameTimerGPUAverage()*1000000.0 / double(dims.x()*dims.y())));
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
cmake_minimum_required(VERSION 3.0)
|
||||
set(ENV{MACOSX_DEPLOYMENT_TARGET} 10.9)
|
||||
project(HQLauncher)
|
||||
set (CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/")
|
||||
set(src_files
|
||||
|
@ -26,6 +27,8 @@ set(src_files
|
|||
src/LatestBuildRequest.m
|
||||
src/OrganizationRequest.m
|
||||
src/OrganizationRequest.h
|
||||
src/Interface.h
|
||||
src/Interface.m
|
||||
src/ErrorViewController.h
|
||||
src/ErrorViewController.m
|
||||
src/Settings.h
|
||||
|
@ -67,7 +70,7 @@ add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${src_files})
|
|||
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME ${APP_NAME}
|
||||
MACOSX_BUNDLE_BUNDLE_NAME ${APP_NAME})
|
||||
set_from_env(LAUNCHER_HMAC_SECRET LAUNCHER_HMAC_SECRET "")
|
||||
if (LAUNCHER_HMAC_SECRET STREQUAL "")
|
||||
if ("${LAUNCHER_HMAC_SECRET}" STREQUAL "")
|
||||
message(FATAL_ERROR "LAUNCHER_HMAC_SECRET is not set")
|
||||
endif()
|
||||
|
||||
|
|
|
@ -32,6 +32,6 @@
|
|||
<key>CFBundleName</key>
|
||||
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>CFBundleName</string>
|
||||
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -69,8 +69,17 @@
|
|||
<action selector="hyperLink:" target="YVh-OH-vU8" id="JfS-ot-wAP"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="0CN-kS-xZ5">
|
||||
<rect key="frame" x="66" y="68" width="266" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" alignment="center" title="By signing in, you agree to the High Fidelity" id="zSf-YA-osu">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="xeX-qc-ccB" customClass="HFButton">
|
||||
<rect key="frame" x="205" y="84" width="104" height="42"/>
|
||||
<rect key="frame" x="205" y="111" width="104" height="42"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="square" title="LOG IN" bezelStyle="shadowlessSquare" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="6Ba-S9-5qW">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
|
@ -81,6 +90,18 @@
|
|||
<action selector="login:" target="YVh-OH-vU8" id="uzF-yC-tu1"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="QtF-Xs-rht" customClass="Hyperlink">
|
||||
<rect key="frame" x="336" y="68" width="115" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="Terms of Service" id="O5x-BW-FLk">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="linkColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="linkColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<action selector="termsOfService:" target="YVh-OH-vU8" id="bgc-08-8Lj"/>
|
||||
</connections>
|
||||
</textField>
|
||||
</subviews>
|
||||
<point key="canvasLocation" x="138.5" y="154"/>
|
||||
</customView>
|
||||
|
@ -91,5 +112,14 @@
|
|||
<outlet property="smallLogo" destination="j8K-TD-h7e" id="OVd-p3-nu6"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="wWT-mi-6An">
|
||||
<rect key="frame" x="0.0" y="0.0" width="37" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="Label" id="1Uh-1I-CcU">
|
||||
<font key="font" usesAppearanceFont="YES"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</objects>
|
||||
</document>
|
||||
|
|
|
@ -31,4 +31,9 @@
|
|||
{
|
||||
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://www.highfidelity.com/hq-support"]];
|
||||
}
|
||||
|
||||
- (IBAction)termsOfService:(id)sender
|
||||
{
|
||||
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://www.highfidelity.com/termsofservice"]];
|
||||
}
|
||||
@end
|
||||
|
|
8
launchers/darwin/src/Interface.h
Normal file
8
launchers/darwin/src/Interface.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface Interface : NSObject
|
||||
|
||||
-(id _Nonnull) initWith:(NSString * _Nonnull) aPathToInterface;
|
||||
-(NSInteger) getVersion:(out NSError * _Nullable * _Nonnull) anError;
|
||||
|
||||
@end
|
90
launchers/darwin/src/Interface.m
Normal file
90
launchers/darwin/src/Interface.m
Normal file
|
@ -0,0 +1,90 @@
|
|||
#import "Interface.h"
|
||||
|
||||
@implementation Interface
|
||||
{
|
||||
NSString *pathTo;
|
||||
}
|
||||
|
||||
-(id) initWith:(NSString*)aPathToInterface
|
||||
{
|
||||
[self init];
|
||||
self->pathTo = [NSString stringWithFormat:@"%@/Contents/MacOS/interface", aPathToInterface];
|
||||
return self;
|
||||
}
|
||||
|
||||
-(NSInteger) getVersion:(out NSError * _Nullable *) outError
|
||||
{
|
||||
NSTask * interface = [[NSTask alloc] init];
|
||||
NSPipe * standardOut = [NSPipe pipe];
|
||||
|
||||
interface.launchPath = self->pathTo;
|
||||
interface.arguments = @[ @"--version" ];
|
||||
interface.standardOutput = standardOut;
|
||||
|
||||
NSLog(@"calling interface at %@", self->pathTo);
|
||||
|
||||
NSError *error = nil;
|
||||
[interface launch];
|
||||
[interface waitUntilExit];
|
||||
if (0 != [interface terminationStatus]) {
|
||||
*outError = [NSError errorWithDomain:@"interface"
|
||||
code:-1
|
||||
userInfo:@{NSUnderlyingErrorKey: error}];
|
||||
return 0;
|
||||
}
|
||||
|
||||
NSFileHandle * fh = [standardOut fileHandleForReading];
|
||||
NSData * data = [fh readDataToEndOfFile];
|
||||
NSString * output = [NSString stringWithUTF8String:[data bytes]];
|
||||
if (output == nil) {
|
||||
NSDictionary * userInfo = @{
|
||||
NSLocalizedDescriptionKey: NSLocalizedString(@"Couldn't start interface", nil)
|
||||
};
|
||||
*outError = [NSError errorWithDomain:@"interface"
|
||||
code:-1
|
||||
userInfo:userInfo];
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Interface returns the build version as a string like this:
|
||||
// "Interface 33333-DEADBEEF". This code grabs the substring
|
||||
// between "Interface " and the hyphon ("-")
|
||||
NSRange start = [output rangeOfString:@"Interface "];
|
||||
if (start.length == 0) {
|
||||
NSDictionary * userInfo = @{
|
||||
NSLocalizedDescriptionKey: NSLocalizedString(@"Couldn't read interface's version", nil)
|
||||
};
|
||||
*outError = [NSError errorWithDomain:@"interface"
|
||||
code:-2
|
||||
userInfo:userInfo];
|
||||
return 0;
|
||||
}
|
||||
NSRange end = [output rangeOfString:@"-"];
|
||||
if (end.length == 0) {
|
||||
NSDictionary * userInfo = @{
|
||||
NSLocalizedDescriptionKey: NSLocalizedString(@"Couldn't read interface's version", nil)
|
||||
};
|
||||
*outError = [NSError errorWithDomain:@"interface"
|
||||
code:-2
|
||||
userInfo:userInfo];
|
||||
return 0;
|
||||
}
|
||||
NSRange subRange = {start.length, end.location - start.length};
|
||||
NSString * versionStr;
|
||||
@try {
|
||||
versionStr = [output substringWithRange:subRange];
|
||||
}
|
||||
@catch (NSException *) {
|
||||
NSDictionary * userInfo = @{
|
||||
NSLocalizedDescriptionKey: NSLocalizedString(@"Couldn't read interface's version", nil)
|
||||
};
|
||||
*outError = [NSError errorWithDomain:@"interface"
|
||||
code:-2
|
||||
userInfo:userInfo];
|
||||
return 0;
|
||||
}
|
||||
|
||||
return versionStr.integerValue;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,17 +1,36 @@
|
|||
#import "LatestBuildRequest.h"
|
||||
#import "Launcher.h"
|
||||
#import "Settings.h"
|
||||
#import "Interface.h"
|
||||
|
||||
@implementation LatestBuildRequest
|
||||
|
||||
- (NSInteger) getCurrentVersion {
|
||||
NSInteger currentVersion;
|
||||
@try {
|
||||
NSString* interfaceAppPath = [[Launcher.sharedLauncher getAppPath] stringByAppendingString:@"interface.app"];
|
||||
NSError * error = nil;
|
||||
Interface * interface = [[Interface alloc] initWith:interfaceAppPath];
|
||||
currentVersion = [interface getVersion:&error];
|
||||
if (currentVersion == 0 && error != nil) {
|
||||
NSLog(@"can't get version from interface, falling back to settings: %@", error);
|
||||
currentVersion = [Settings.sharedSettings latestBuildVersion];
|
||||
}
|
||||
} @catch (NSException *exception) {
|
||||
NSLog(@"an exception was thrown: %@", exception);
|
||||
currentVersion = [Settings.sharedSettings latestBuildVersion];
|
||||
}
|
||||
return currentVersion;
|
||||
}
|
||||
|
||||
- (void) requestLatestBuildInfo {
|
||||
NSMutableURLRequest *request = [NSMutableURLRequest new];
|
||||
[request setURL:[NSURL URLWithString:@"https://thunder.highfidelity.com/builds/api/tags/latest?format=json"]];
|
||||
[request setHTTPMethod:@"GET"];
|
||||
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
|
||||
|
||||
|
||||
NSURLSession* session = [NSURLSession sharedSession];
|
||||
// We're using an ephermeral session here to ensure the tags api response is never cached.
|
||||
NSURLSession * session = [NSURLSession sessionWithConfiguration:NSURLSessionConfiguration.ephemeralSessionConfiguration];
|
||||
NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
|
||||
|
||||
|
||||
|
@ -45,8 +64,8 @@
|
|||
BOOL appDirectoryExist = [fileManager fileExistsAtPath:[[sharedLauncher getAppPath] stringByAppendingString:@"interface.app"]];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
Settings* settings = [Settings sharedSettings];
|
||||
NSInteger currentVersion = [settings latestBuildVersion];
|
||||
|
||||
NSInteger currentVersion = [self getCurrentVersion];
|
||||
NSLog(@"Latest Build Request -> does build directory exist: %@", appDirectoryExist ? @"TRUE" : @"FALSE");
|
||||
NSLog(@"Latest Build Request -> current version: %ld", currentVersion);
|
||||
NSLog(@"Latest Build Request -> latest version: %ld", buildNumber.integerValue);
|
||||
|
@ -105,11 +124,10 @@
|
|||
NSDictionary* macInstallerObject = [installers objectForKey:@"mac"];
|
||||
NSString* macInstallerUrl = [macInstallerObject valueForKey:@"zip_url"];
|
||||
|
||||
BOOL appDirectoryExist = [fileManager fileExistsAtPath:[[sharedLauncher getAppPath] stringByAppendingString:@"interface.app"]];
|
||||
|
||||
Settings* settings = [Settings sharedSettings];
|
||||
NSInteger currentVersion = [settings latestBuildVersion];
|
||||
BOOL latestVersionAvailable = (currentVersion != buildNumber.integerValue);
|
||||
NSString* interfaceAppPath = [[sharedLauncher getAppPath] stringByAppendingString:@"interface.app"];
|
||||
BOOL appDirectoryExist = [fileManager fileExistsAtPath:interfaceAppPath];
|
||||
|
||||
BOOL latestVersionAvailable = ([self getCurrentVersion] != buildNumber.integerValue);
|
||||
[[Settings sharedSettings] buildVersion:buildNumber.integerValue];
|
||||
|
||||
BOOL shouldDownloadInterface = (latestVersionAvailable || !appDirectoryExist);
|
||||
|
|
|
@ -5,13 +5,13 @@ void redirectLogToDocuments()
|
|||
{
|
||||
NSString* filePath = [[NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES) objectAtIndex:0]
|
||||
stringByAppendingString:@"/Launcher/"];
|
||||
|
||||
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
|
||||
NSError * error = nil;
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:filePath withIntermediateDirectories:TRUE attributes:nil error:&error];
|
||||
}
|
||||
NSString *pathForLog = [filePath stringByAppendingPathComponent:@"log.txt"];
|
||||
|
||||
|
||||
freopen([pathForLog cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);
|
||||
}
|
||||
|
||||
|
@ -23,12 +23,12 @@ int main(int argc, const char* argv[]) {
|
|||
NSLog(@"launcher is already running");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
[NSApplication sharedApplication];
|
||||
Launcher* sharedLauncher = [Launcher sharedLauncher];
|
||||
[Settings sharedSettings];
|
||||
[NSApp setDelegate: sharedLauncher];
|
||||
|
||||
|
||||
// Referenced from https://stackoverflow.com/questions/9155015/handle-cmd-q-in-cocoa-application-and-menu-item-quit-application-programmatic
|
||||
id menubar = [[NSMenu new] autorelease];
|
||||
id appMenuItem = [[NSMenuItem new] autorelease];
|
||||
|
@ -40,7 +40,7 @@ int main(int argc, const char* argv[]) {
|
|||
id quitMenuItem = [[[NSMenuItem alloc] initWithTitle:quitTitle action:@selector(terminate:) keyEquivalent:@"q"] autorelease];
|
||||
[appMenu addItem:quitMenuItem];
|
||||
[appMenuItem setSubmenu:appMenu];
|
||||
|
||||
|
||||
[[NSApplication sharedApplication] activateIgnoringOtherApps:TRUE];
|
||||
return NSApplicationMain(argc, argv);
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ BEGIN
|
|||
CTEXT "",IDC_MESSAGE2_LABEL,35,172,239,15,NOT WS_VISIBLE
|
||||
CTEXT "",IDC_ACTION2_LABEL,15,147,278,25,NOT WS_VISIBLE
|
||||
RTEXT "",IDC_TERMS,15,172,180,15,NOT WS_VISIBLE
|
||||
LTEXT "",IDC_TERMS2,197,172,80,15,NOT WS_VISIBLE
|
||||
CONTROL "",IDC_TERMS_LINK,"Button", BS_OWNERDRAW | BS_FLAT | NOT WS_VISIBLE | WS_TABSTOP,197,172,80,15
|
||||
CTEXT "",IDC_TROUBLE,65,203,174,15,NOT WS_VISIBLE
|
||||
CONTROL "NEXT",IDC_BUTTON_NEXT,"Button",BS_OWNERDRAW | BS_FLAT | NOT WS_VISIBLE | WS_TABSTOP,107,158,94,16
|
||||
CONTROL "Having Trouble?",IDC_TROUBLE_LINK,"Button",BS_OWNERDRAW | BS_FLAT | NOT WS_VISIBLE | WS_TABSTOP,126,203,56,11
|
||||
|
|
|
@ -37,6 +37,7 @@ static CString GRAPHIK_REGULAR = _T("Graphik-Regular");
|
|||
static CString GRAPHIK_SEMIBOLD = _T("Graphik-Semibold");
|
||||
|
||||
static CString TROUBLE_URL = _T("https://www.highfidelity.com/hq-support");
|
||||
static CString TERMS_URL = _T("https://www.highfidelity.com/termsofservice");
|
||||
|
||||
|
||||
CLauncherDlg::CLauncherDlg(CWnd* pParent)
|
||||
|
@ -54,6 +55,7 @@ void CLauncherDlg::DoDataExchange(CDataExchange* pDX)
|
|||
{
|
||||
DDX_Control(pDX, IDC_BUTTON_NEXT, m_btnNext);
|
||||
DDX_Control(pDX, IDC_TROUBLE_LINK, m_trouble_link);
|
||||
DDX_Control(pDX, IDC_TERMS_LINK, m_terms_link);
|
||||
DDX_Control(pDX, IDC_ORGNAME, m_orgname);
|
||||
DDX_Control(pDX, IDC_USERNAME, m_username);
|
||||
DDX_Control(pDX, IDC_PASSWORD, m_password);
|
||||
|
@ -69,6 +71,7 @@ BEGIN_MESSAGE_MAP(CLauncherDlg, CDialog)
|
|||
ON_EN_SETFOCUS(IDC_PASSWORD, &CLauncherDlg::OnPassEditChangeFocus)
|
||||
ON_BN_CLICKED(IDC_BUTTON_NEXT, &CLauncherDlg::OnNextClicked)
|
||||
ON_BN_CLICKED(IDC_TROUBLE_LINK, &CLauncherDlg::OnTroubleClicked)
|
||||
ON_BN_CLICKED(IDC_TERMS_LINK, &CLauncherDlg::OnTermsClicked)
|
||||
ON_WM_CTLCOLOR()
|
||||
ON_WM_DRAWITEM()
|
||||
ON_WM_SETCURSOR()
|
||||
|
@ -103,7 +106,6 @@ BOOL CLauncherDlg::OnInitDialog() {
|
|||
m_password_banner = (CStatic *)GetDlgItem(IDC_PASSWORD_BANNER);
|
||||
|
||||
m_terms = (CStatic *)GetDlgItem(IDC_TERMS);
|
||||
m_terms2 = (CStatic *)GetDlgItem(IDC_TERMS2);
|
||||
m_trouble = (CStatic *)GetDlgItem(IDC_TROUBLE);
|
||||
|
||||
m_voxel = (CStatic *)GetDlgItem(IDC_VOXEL);
|
||||
|
@ -223,6 +225,10 @@ afx_msg void CLauncherDlg::OnTroubleClicked() {
|
|||
LauncherUtils::executeOnForeground(TROUBLE_URL, _T(""));
|
||||
}
|
||||
|
||||
afx_msg void CLauncherDlg::OnTermsClicked() {
|
||||
LauncherUtils::executeOnForeground(TERMS_URL, _T(""));
|
||||
}
|
||||
|
||||
afx_msg void CLauncherDlg::OnNextClicked() {
|
||||
if (_drawStep != DrawStep::DrawChoose) {
|
||||
CString token;
|
||||
|
@ -275,7 +281,7 @@ void CLauncherDlg::drawLogo(CHwndRenderTarget* pRenderTarget) {
|
|||
CD2DBitmap m_pBitmamLogo(pRenderTarget, IDB_PNG2, _T("PNG"));
|
||||
auto size = pRenderTarget->GetSize();
|
||||
int logoWidth = 231;
|
||||
int logoHeight = 181;
|
||||
int logoHeight = 173;
|
||||
float logoPosX = 0.5f * (size.width - logoWidth);
|
||||
float logoPosY = 0.95f * (size.height - logoHeight);
|
||||
CD2DRectF logoRec(logoPosX, logoPosY, logoPosX + logoWidth, logoPosY + logoHeight);
|
||||
|
@ -362,9 +368,9 @@ void CLauncherDlg::prepareChoose() {
|
|||
m_action_label->SetWindowTextW(_T("Choose a display name"));
|
||||
m_message_label->SetWindowTextW(_T("This is the name that your teammates will see."));
|
||||
m_terms->ShowWindow(SW_SHOW);
|
||||
m_terms2->ShowWindow(SW_SHOW);
|
||||
m_terms_link.ShowWindow(SW_SHOW);
|
||||
m_terms->SetWindowTextW(_T("By signing in, you agree to the High Fidelity"));
|
||||
m_terms2->SetWindowTextW(_T("Terms of Service"));
|
||||
m_terms_link.SetWindowTextW(_T("Terms of Service"));
|
||||
CRect rec;
|
||||
m_btnNext.GetWindowRect(&rec);
|
||||
ScreenToClient(&rec);
|
||||
|
@ -380,7 +386,7 @@ void CLauncherDlg::prepareProcess(DrawStep step) {
|
|||
m_trouble->ShowWindow(SW_HIDE);
|
||||
m_trouble_link.ShowWindow(SW_HIDE);
|
||||
m_terms->ShowWindow(SW_HIDE);
|
||||
m_terms2->ShowWindow(SW_HIDE);
|
||||
m_terms_link.ShowWindow(SW_HIDE);
|
||||
m_orgname_banner->ShowWindow(SW_HIDE);
|
||||
m_username_banner->ShowWindow(SW_HIDE);
|
||||
m_password_banner->ShowWindow(SW_HIDE);
|
||||
|
@ -465,7 +471,7 @@ BOOL CLauncherDlg::getTextFormat(int resID, TextFormat& formatOut) {
|
|||
case IDC_TERMS:
|
||||
formatOut.size = TERMS_FONT_SIZE;
|
||||
break;
|
||||
case IDC_TERMS2:
|
||||
case IDC_TERMS_LINK:
|
||||
formatOut.size = TERMS_FONT_SIZE;
|
||||
formatOut.isBold = true;
|
||||
break;
|
||||
|
@ -542,6 +548,14 @@ void CLauncherDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
|
|||
dc.SelectObject(buttonFont);
|
||||
}
|
||||
dc.DrawText(_T("Having Trouble"), CRect(rect.left, rect.top, rect.right, rect.bottom), DT_CENTER | DT_VCENTER | DT_SINGLELINE);
|
||||
} else if (nIDCtl == IDC_TERMS_LINK) {
|
||||
dc.FillSolidRect(rect, COLOR_BLACK);
|
||||
dc.SetTextColor(COLOR_LIGHT_GREY);
|
||||
CFont buttonFont;
|
||||
if (LauncherUtils::getFont(GRAPHIK_SEMIBOLD, TERMS_FONT_SIZE, true, buttonFont)) {
|
||||
dc.SelectObject(buttonFont);
|
||||
}
|
||||
dc.DrawText(_T("Terms of Service"), CRect(rect.left, rect.top, rect.right, rect.bottom), DT_LEFT | DT_TOP | DT_SINGLELINE);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -72,13 +72,13 @@ protected:
|
|||
HICON m_hIcon;
|
||||
CButton m_btnNext;
|
||||
CButton m_trouble_link;
|
||||
CButton m_terms_link;
|
||||
|
||||
CStatic* m_message_label;
|
||||
CStatic* m_action_label;
|
||||
CStatic* m_message2_label;
|
||||
CStatic* m_action2_label;
|
||||
CStatic* m_terms;
|
||||
CStatic* m_terms2;
|
||||
CStatic* m_trouble;
|
||||
CStatic* m_voxel;
|
||||
|
||||
|
@ -111,6 +111,7 @@ protected:
|
|||
afx_msg HCURSOR OnQueryDragIcon();
|
||||
afx_msg void OnNextClicked();
|
||||
afx_msg void OnTroubleClicked();
|
||||
afx_msg void OnTermsClicked();
|
||||
afx_msg void OnOrgEditChangeFocus();
|
||||
afx_msg void OnUserEditChangeFocus();
|
||||
afx_msg void OnPassEditChangeFocus();
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#define IDC_USERNAME_BANNER 1019
|
||||
#define IDC_PASSWORD_BANNER 1020
|
||||
#define IDC_TERMS 1021
|
||||
#define IDC_TERMS2 1022
|
||||
#define IDC_TERMS_LINK 1022
|
||||
#define IDC_TROUBLE 1023
|
||||
#define IDC_VOXEL 1024
|
||||
#define IDC_TROUBLE_LINK 1027
|
||||
|
|
|
@ -109,23 +109,20 @@ bool Basic2DWindowOpenGLDisplayPlugin::internalActivate() {
|
|||
return Parent::internalActivate();
|
||||
}
|
||||
|
||||
gpu::PipelinePointer Basic2DWindowOpenGLDisplayPlugin::getCompositeScenePipeline() {
|
||||
gpu::PipelinePointer Basic2DWindowOpenGLDisplayPlugin::getRenderTexturePipeline() {
|
||||
#if defined(Q_OS_ANDROID)
|
||||
return _linearToSRGBPipeline;
|
||||
return _linearToSRGBPipeline;
|
||||
#else
|
||||
return _SRGBToLinearPipeline;
|
||||
|
||||
#ifndef USE_GLES
|
||||
return _SRGBToLinearPipeline;
|
||||
#else
|
||||
return _drawTexturePipeline;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
gpu::Element Basic2DWindowOpenGLDisplayPlugin::getCompositeFBColorSpace() {
|
||||
#if defined(Q_OS_ANDROID)
|
||||
return gpu::Element::COLOR_SRGBA_32;
|
||||
#else
|
||||
return gpu::Element::COLOR_RGBA_32;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void Basic2DWindowOpenGLDisplayPlugin::compositeExtra() {
|
||||
#if defined(Q_OS_ANDROID)
|
||||
auto& virtualPadManager = VirtualPad::Manager::instance();
|
||||
|
|
|
@ -37,8 +37,7 @@ public:
|
|||
|
||||
virtual void pluginUpdate() override {};
|
||||
|
||||
virtual gpu::PipelinePointer getCompositeScenePipeline() override;
|
||||
virtual gpu::Element getCompositeFBColorSpace() override;
|
||||
virtual gpu::PipelinePointer getRenderTexturePipeline() override;
|
||||
|
||||
protected:
|
||||
mutable bool _isThrottled = false;
|
||||
|
|
|
@ -62,7 +62,7 @@ public:
|
|||
|
||||
PresentThread() {
|
||||
connect(qApp, &QCoreApplication::aboutToQuit, [this] {
|
||||
shutdown();
|
||||
shutdown();
|
||||
});
|
||||
setObjectName("Present");
|
||||
|
||||
|
@ -82,12 +82,11 @@ public:
|
|||
|
||||
Lock lock(_mutex);
|
||||
_shutdown = true;
|
||||
_condition.wait(lock, [&] { return !_shutdown; });
|
||||
_condition.wait(lock, [&] { return !_shutdown; });
|
||||
qCDebug(displayPlugins) << "Present thread shutdown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setNewDisplayPlugin(OpenGLDisplayPlugin* plugin) {
|
||||
Lock lock(_mutex);
|
||||
if (isRunning()) {
|
||||
|
@ -104,7 +103,6 @@ public:
|
|||
_context->moveToThread(this);
|
||||
}
|
||||
|
||||
|
||||
virtual void run() override {
|
||||
PROFILE_SET_THREAD_NAME("Present Thread");
|
||||
|
||||
|
@ -131,7 +129,6 @@ public:
|
|||
_condition.notify_one();
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
// Main thread does it's thing while we wait on the lock to release
|
||||
Lock lock(_mutex);
|
||||
|
@ -201,7 +198,7 @@ public:
|
|||
#if defined(Q_OS_MAC)
|
||||
_context->doneCurrent();
|
||||
#endif
|
||||
|
||||
|
||||
_refreshRateController->sleepThreadIfNeeded(this, currentPlugin->isHmd());
|
||||
}
|
||||
|
||||
|
@ -235,7 +232,6 @@ public:
|
|||
_condition.notify_one();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
void makeCurrent();
|
||||
void doneCurrent();
|
||||
|
@ -245,7 +241,6 @@ private:
|
|||
// Used to allow the main thread to perform context operations
|
||||
Condition _condition;
|
||||
|
||||
|
||||
QThread* _targetOperationThread { nullptr };
|
||||
bool _pendingOtherThreadOperation { false };
|
||||
bool _finishedOtherThreadOperation { false };
|
||||
|
@ -302,7 +297,6 @@ bool OpenGLDisplayPlugin::activate() {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
// This should not return until the new context has been customized
|
||||
// and the old context (if any) has been uncustomized
|
||||
presentThread->setNewDisplayPlugin(this);
|
||||
|
@ -334,7 +328,7 @@ void OpenGLDisplayPlugin::deactivate() {
|
|||
|
||||
_container->showDisplayPluginsTools(false);
|
||||
if (!_container->currentDisplayActions().isEmpty()) {
|
||||
foreach(auto itemInfo, _container->currentDisplayActions()) {
|
||||
foreach (auto itemInfo, _container->currentDisplayActions()) {
|
||||
_container->removeMenuItem(itemInfo.first, itemInfo.second);
|
||||
}
|
||||
_container->currentDisplayActions().clear();
|
||||
|
@ -368,7 +362,6 @@ void OpenGLDisplayPlugin::customizeContext() {
|
|||
image = image.convertToFormat(QImage::Format_ARGB32);
|
||||
}
|
||||
if ((image.width() > 0) && (image.height() > 0)) {
|
||||
|
||||
cursorData.texture = gpu::Texture::createStrict(
|
||||
gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA),
|
||||
image.width(), image.height(),
|
||||
|
@ -384,7 +377,7 @@ void OpenGLDisplayPlugin::customizeContext() {
|
|||
}
|
||||
}
|
||||
|
||||
if (!_drawTexturePipeline) {
|
||||
if (!_linearToSRGBPipeline) {
|
||||
gpu::StatePointer blendState = gpu::StatePointer(new gpu::State());
|
||||
blendState->setDepthTest(gpu::State::DepthTest(false));
|
||||
blendState->setBlendFunction(true,
|
||||
|
@ -397,17 +390,17 @@ void OpenGLDisplayPlugin::customizeContext() {
|
|||
scissorState->setDepthTest(gpu::State::DepthTest(false));
|
||||
scissorState->setScissorEnable(true);
|
||||
|
||||
_drawTexturePipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTexture), scissorState);
|
||||
_drawTexturePipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTexture), scissorState);
|
||||
|
||||
_linearToSRGBPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureGammaLinearToSRGB), scissorState);
|
||||
_linearToSRGBPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureGammaLinearToSRGB), scissorState);
|
||||
|
||||
_SRGBToLinearPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureGammaSRGBToLinear), scissorState);
|
||||
_SRGBToLinearPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureGammaSRGBToLinear), scissorState);
|
||||
|
||||
_hudPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTexture), blendState);
|
||||
_hudPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTexture), blendState);
|
||||
|
||||
_mirrorHUDPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureMirroredX), blendState);
|
||||
_mirrorHUDPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureMirroredX), blendState);
|
||||
|
||||
_cursorPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTransformedTexture), blendState);
|
||||
_cursorPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTransformedTexture), blendState);
|
||||
}
|
||||
|
||||
updateCompositeFramebuffer();
|
||||
|
@ -418,9 +411,9 @@ void OpenGLDisplayPlugin::uncustomizeContext() {
|
|||
_drawTexturePipeline.reset();
|
||||
_linearToSRGBPipeline.reset();
|
||||
_SRGBToLinearPipeline.reset();
|
||||
_cursorPipeline.reset();
|
||||
_hudPipeline.reset();
|
||||
_mirrorHUDPipeline.reset();
|
||||
_cursorPipeline.reset();
|
||||
_compositeFramebuffer.reset();
|
||||
|
||||
withPresentThreadLock([&] {
|
||||
|
@ -433,7 +426,6 @@ void OpenGLDisplayPlugin::uncustomizeContext() {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
// Pressing Alt (and Meta) key alone activates the menubar because its style inherits the
|
||||
// SHMenuBarAltKeyNavigation from QWindowsStyle. This makes it impossible for a scripts to
|
||||
// receive keyPress events for the Alt (and Meta) key in a reliable manner.
|
||||
|
@ -514,11 +506,18 @@ void OpenGLDisplayPlugin::captureFrame(const std::string& filename) const {
|
|||
});
|
||||
}
|
||||
|
||||
void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer& texture, const glm::ivec4& viewport, const glm::ivec4& scissor) {
|
||||
void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch,
|
||||
const gpu::TexturePointer& texture,
|
||||
const glm::ivec4& viewport,
|
||||
const glm::ivec4& scissor) {
|
||||
renderFromTexture(batch, texture, viewport, scissor, nullptr);
|
||||
}
|
||||
|
||||
void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer& texture, const glm::ivec4& viewport, const glm::ivec4& scissor, const gpu::FramebufferPointer& copyFbo /*=gpu::FramebufferPointer()*/) {
|
||||
void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch,
|
||||
const gpu::TexturePointer& texture,
|
||||
const glm::ivec4& viewport,
|
||||
const glm::ivec4& scissor,
|
||||
const gpu::FramebufferPointer& copyFbo /*=gpu::FramebufferPointer()*/) {
|
||||
auto fbo = gpu::FramebufferPointer();
|
||||
batch.enableStereo(false);
|
||||
batch.resetViewTransform();
|
||||
|
@ -528,13 +527,13 @@ void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::Textur
|
|||
batch.setViewportTransform(viewport);
|
||||
batch.setResourceTexture(0, texture);
|
||||
|
||||
batch.setPipeline(_drawTexturePipeline);
|
||||
|
||||
batch.setPipeline(getRenderTexturePipeline());
|
||||
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
if (copyFbo) {
|
||||
gpu::Vec4i copyFboRect(0, 0, copyFbo->getWidth(), copyFbo->getHeight());
|
||||
gpu::Vec4i sourceRect(scissor.x, scissor.y, scissor.x + scissor.z, scissor.y + scissor.w);
|
||||
float aspectRatio = (float)scissor.w / (float) scissor.z; // height/width
|
||||
float aspectRatio = (float)scissor.w / (float)scissor.z; // height/width
|
||||
// scale width first
|
||||
int xOffset = 0;
|
||||
int yOffset = 0;
|
||||
|
@ -635,11 +634,6 @@ void OpenGLDisplayPlugin::compositePointer() {
|
|||
});
|
||||
}
|
||||
|
||||
// Overridden by Basic2DWindowDisplayPlugin and OculusDisplayPlugin
|
||||
gpu::PipelinePointer OpenGLDisplayPlugin::getCompositeScenePipeline() {
|
||||
return _drawTexturePipeline;
|
||||
}
|
||||
|
||||
void OpenGLDisplayPlugin::compositeScene() {
|
||||
render([&](gpu::Batch& batch) {
|
||||
batch.enableStereo(false);
|
||||
|
@ -682,7 +676,7 @@ void OpenGLDisplayPlugin::internalPresent() {
|
|||
render([&](gpu::Batch& batch) {
|
||||
// Note: _displayTexture must currently be the same size as the display.
|
||||
uvec2 dims = _displayTexture ? uvec2(_displayTexture->getDimensions()) : getSurfacePixels();
|
||||
auto viewport = ivec4(uvec2(0), dims);
|
||||
auto viewport = ivec4(uvec2(0), dims);
|
||||
renderFromTexture(batch, _displayTexture ? _displayTexture : _compositeFramebuffer->getRenderBuffer(0), viewport, viewport);
|
||||
});
|
||||
swapBuffers();
|
||||
|
@ -765,7 +759,7 @@ float OpenGLDisplayPlugin::presentRate() const {
|
|||
return _presentRate.rate();
|
||||
}
|
||||
|
||||
std::function<void(int)> OpenGLDisplayPlugin::getRefreshRateOperator() {
|
||||
std::function<void(int)> OpenGLDisplayPlugin::getRefreshRateOperator() {
|
||||
return [](int targetRefreshRate) {
|
||||
auto refreshRateController = DependencyManager::get<PresentThread>()->getRefreshRateController();
|
||||
refreshRateController->setRefreshRateLimitPeriod(targetRefreshRate);
|
||||
|
@ -781,7 +775,6 @@ float OpenGLDisplayPlugin::renderRate() const {
|
|||
return _renderRate.rate();
|
||||
}
|
||||
|
||||
|
||||
void OpenGLDisplayPlugin::swapBuffers() {
|
||||
static auto context = _container->getPrimaryWidget()->context();
|
||||
context->swapBuffers();
|
||||
|
@ -909,17 +902,10 @@ void OpenGLDisplayPlugin::render(std::function<void(gpu::Batch& batch)> f) {
|
|||
OpenGLDisplayPlugin::~OpenGLDisplayPlugin() {
|
||||
}
|
||||
|
||||
// Added this to allow desktop composite framebuffer to be RGBA while mobile is SRGBA
|
||||
// Overridden by Basic2DWindowDisplayPlugin
|
||||
// FIXME: Eventually it would be ideal to have both framebuffers be of the same type
|
||||
gpu::Element OpenGLDisplayPlugin::getCompositeFBColorSpace() {
|
||||
return gpu::Element::COLOR_RGBA_32;
|
||||
}
|
||||
|
||||
void OpenGLDisplayPlugin::updateCompositeFramebuffer() {
|
||||
auto renderSize = glm::uvec2(getRecommendedRenderSize());
|
||||
if (!_compositeFramebuffer || _compositeFramebuffer->getSize() != renderSize) {
|
||||
_compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", getCompositeFBColorSpace(), renderSize.x, renderSize.y));
|
||||
_compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_RGBA_32, renderSize.x, renderSize.y));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -950,14 +936,13 @@ void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer ne
|
|||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
|
||||
// maintain aspect ratio, filling the width first if possible. If that makes the height too
|
||||
// much, fill height instead. TODO: only do this when texture changes
|
||||
GLint newX = 0;
|
||||
GLint newY = 0;
|
||||
float aspectRatio = (float)texHeight / (float)texWidth;
|
||||
GLint newWidth = target->width();
|
||||
GLint newHeight = std::round(aspectRatio * (float) target->width());
|
||||
GLint newHeight = std::round(aspectRatio * (float)target->width());
|
||||
if (newHeight > target->height()) {
|
||||
newHeight = target->height();
|
||||
newWidth = std::round((float)target->height() / aspectRatio);
|
||||
|
@ -966,7 +951,7 @@ void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer ne
|
|||
newY = (target->height() - newHeight) / 2;
|
||||
}
|
||||
|
||||
glBlitNamedFramebuffer(fbo[0], fbo[1], 0, 0, texWidth, texHeight, newX, newY, newX + newWidth, newY + newHeight, GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
glBlitNamedFramebuffer(fbo[0], fbo[1], 0, 0, texWidth, texHeight, newX, newY, newX + newWidth, newY + newHeight, GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
|
||||
// don't delete the textures!
|
||||
glDeleteFramebuffers(2, fbo);
|
||||
|
@ -975,3 +960,11 @@ void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer ne
|
|||
#endif
|
||||
}
|
||||
|
||||
gpu::PipelinePointer OpenGLDisplayPlugin::getRenderTexturePipeline() {
|
||||
return _drawTexturePipeline;
|
||||
}
|
||||
|
||||
gpu::PipelinePointer OpenGLDisplayPlugin::getCompositeScenePipeline() {
|
||||
return _drawTexturePipeline;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,11 +23,9 @@
|
|||
|
||||
#include <gpu/Batch.h>
|
||||
|
||||
namespace gpu {
|
||||
namespace gl {
|
||||
class GLBackend;
|
||||
}
|
||||
}
|
||||
namespace gpu { namespace gl {
|
||||
class GLBackend;
|
||||
}} // namespace gpu::gl
|
||||
|
||||
class RefreshRateController;
|
||||
|
||||
|
@ -35,10 +33,12 @@ class OpenGLDisplayPlugin : public DisplayPlugin {
|
|||
Q_OBJECT
|
||||
Q_PROPERTY(float hudAlpha MEMBER _hudAlpha)
|
||||
using Parent = DisplayPlugin;
|
||||
|
||||
protected:
|
||||
using Mutex = std::mutex;
|
||||
using Lock = std::unique_lock<Mutex>;
|
||||
using Condition = std::condition_variable;
|
||||
|
||||
public:
|
||||
~OpenGLDisplayPlugin();
|
||||
// These must be final to ensure proper ordering of operations
|
||||
|
@ -55,13 +55,9 @@ public:
|
|||
void captureFrame(const std::string& outputName) const override;
|
||||
void submitFrame(const gpu::FramePointer& newFrame) override;
|
||||
|
||||
glm::uvec2 getRecommendedRenderSize() const override {
|
||||
return getSurfacePixels();
|
||||
}
|
||||
glm::uvec2 getRecommendedRenderSize() const override { return getSurfacePixels(); }
|
||||
|
||||
glm::uvec2 getRecommendedUiSize() const override {
|
||||
return getSurfaceSize();
|
||||
}
|
||||
glm::uvec2 getRecommendedUiSize() const override { return getSurfaceSize(); }
|
||||
|
||||
virtual bool setDisplayTexture(const QString& name) override;
|
||||
virtual bool onDisplayTextureReset() { return false; };
|
||||
|
@ -84,9 +80,10 @@ public:
|
|||
// Three threads, one for rendering, one for texture transfers, one reserved for the GL driver
|
||||
int getRequiredThreadCount() const override { return 3; }
|
||||
|
||||
void copyTextureToQuickFramebuffer(NetworkTexturePointer source, QOpenGLFramebufferObject* target, GLsync* fenceSync) override;
|
||||
|
||||
virtual std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> getHUDOperator() override;
|
||||
void copyTextureToQuickFramebuffer(NetworkTexturePointer source,
|
||||
QOpenGLFramebufferObject* target,
|
||||
GLsync* fenceSync) override;
|
||||
|
||||
protected:
|
||||
friend class PresentThread;
|
||||
|
@ -105,10 +102,7 @@ protected:
|
|||
virtual void compositeLayers();
|
||||
virtual void compositeScene();
|
||||
virtual void compositePointer();
|
||||
virtual void compositeExtra() {};
|
||||
|
||||
virtual gpu::PipelinePointer getCompositeScenePipeline();
|
||||
virtual gpu::Element getCompositeFBColorSpace();
|
||||
virtual void compositeExtra(){};
|
||||
|
||||
// These functions must only be called on the presentation thread
|
||||
virtual void customizeContext();
|
||||
|
@ -125,8 +119,15 @@ protected:
|
|||
// Plugin specific functionality to send the composed scene to the output window or device
|
||||
virtual void internalPresent();
|
||||
|
||||
void renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer& texture, const glm::ivec4& viewport, const glm::ivec4& scissor, const gpu::FramebufferPointer& fbo);
|
||||
void renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer& texture, const glm::ivec4& viewport, const glm::ivec4& scissor);
|
||||
void renderFromTexture(gpu::Batch& batch,
|
||||
const gpu::TexturePointer& texture,
|
||||
const glm::ivec4& viewport,
|
||||
const glm::ivec4& scissor,
|
||||
const gpu::FramebufferPointer& fbo);
|
||||
void renderFromTexture(gpu::Batch& batch,
|
||||
const gpu::TexturePointer& texture,
|
||||
const glm::ivec4& viewport,
|
||||
const glm::ivec4& scissor);
|
||||
virtual void updateFrameData();
|
||||
virtual glm::mat4 getViewCorrection() { return glm::mat4(); }
|
||||
|
||||
|
@ -138,7 +139,7 @@ protected:
|
|||
|
||||
void render(std::function<void(gpu::Batch& batch)> f);
|
||||
|
||||
bool _vsyncEnabled { true };
|
||||
bool _vsyncEnabled{ true };
|
||||
QThread* _presentThread{ nullptr };
|
||||
std::queue<gpu::FramePointer> _newFrameQueue;
|
||||
RateCounter<200> _droppedFrameRate;
|
||||
|
@ -147,7 +148,7 @@ protected:
|
|||
RateCounter<200> _renderRate;
|
||||
|
||||
gpu::FramePointer _currentFrame;
|
||||
gpu::Frame* _lastFrame { nullptr };
|
||||
gpu::Frame* _lastFrame{ nullptr };
|
||||
mat4 _prevRenderView;
|
||||
gpu::FramebufferPointer _compositeFramebuffer;
|
||||
gpu::PipelinePointer _hudPipeline;
|
||||
|
@ -157,9 +158,11 @@ protected:
|
|||
gpu::PipelinePointer _linearToSRGBPipeline;
|
||||
gpu::PipelinePointer _SRGBToLinearPipeline;
|
||||
gpu::PipelinePointer _cursorPipeline;
|
||||
|
||||
gpu::TexturePointer _displayTexture{};
|
||||
float _compositeHUDAlpha { 1.0f };
|
||||
float _compositeHUDAlpha{ 1.0f };
|
||||
|
||||
virtual gpu::PipelinePointer getRenderTexturePipeline();
|
||||
virtual gpu::PipelinePointer getCompositeScenePipeline();
|
||||
|
||||
struct CursorData {
|
||||
QImage image;
|
||||
|
@ -169,19 +172,19 @@ protected:
|
|||
};
|
||||
|
||||
std::map<uint16_t, CursorData> _cursorsData;
|
||||
bool _lockCurrentTexture { false };
|
||||
bool _lockCurrentTexture{ false };
|
||||
|
||||
void assertNotPresentThread() const;
|
||||
void assertIsPresentThread() const;
|
||||
|
||||
template<typename F>
|
||||
template <typename F>
|
||||
void withPresentThreadLock(F f) const {
|
||||
assertIsPresentThread();
|
||||
Lock lock(_presentMutex);
|
||||
f();
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
template <typename F>
|
||||
void withNonPresentThreadLock(F f) const {
|
||||
assertNotPresentThread();
|
||||
Lock lock(_presentMutex);
|
||||
|
@ -198,4 +201,3 @@ protected:
|
|||
QImage getScreenshot(float aspectRatio);
|
||||
QImage getSecondaryCameraScreenshot();
|
||||
};
|
||||
|
||||
|
|
|
@ -207,7 +207,7 @@ void EntityTreeRenderer::stopDomainAndNonOwnedEntities() {
|
|||
|
||||
if (entityItem && !entityItem->getScript().isEmpty()) {
|
||||
if (!(entityItem->isLocalEntity() || (entityItem->isAvatarEntity() && entityItem->getOwningAvatarID() == getTree()->getMyAvatarSessionUUID()))) {
|
||||
if (entityItem->contains(_avatarPosition)) {
|
||||
if (_currentEntitiesInside.contains(entityID)) {
|
||||
_entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity");
|
||||
}
|
||||
_entitiesScriptEngine->unloadEntityScript(entityID, true);
|
||||
|
@ -222,6 +222,7 @@ void EntityTreeRenderer::clearDomainAndNonOwnedEntities() {
|
|||
|
||||
auto sessionUUID = getTree()->getMyAvatarSessionUUID();
|
||||
std::unordered_map<EntityItemID, EntityRendererPointer> savedEntities;
|
||||
std::unordered_set<EntityRendererPointer> savedRenderables;
|
||||
// remove all entities from the scene
|
||||
auto scene = _viewState->getMain3DScene();
|
||||
if (scene) {
|
||||
|
@ -232,11 +233,12 @@ void EntityTreeRenderer::clearDomainAndNonOwnedEntities() {
|
|||
fadeOutRenderable(renderer);
|
||||
} else {
|
||||
savedEntities[entry.first] = entry.second;
|
||||
savedRenderables.insert(entry.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_renderablesToUpdate = savedEntities;
|
||||
_renderablesToUpdate = savedRenderables;
|
||||
_entitiesInScene = savedEntities;
|
||||
|
||||
if (_layeredZones.clearDomainAndNonOwnedZones(sessionUUID)) {
|
||||
|
@ -389,13 +391,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
|
|||
PerformanceTimer pt("change");
|
||||
std::unordered_set<EntityItemID> changedEntities;
|
||||
_changedEntitiesGuard.withWriteLock([&] {
|
||||
#if 0
|
||||
// FIXME Weird build failure in latest VC update that fails to compile when using std::swap
|
||||
changedEntities.swap(_changedEntities);
|
||||
#else
|
||||
changedEntities.insert(_changedEntities.begin(), _changedEntities.end());
|
||||
_changedEntities.clear();
|
||||
#endif
|
||||
});
|
||||
|
||||
{
|
||||
|
@ -404,7 +400,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
|
|||
auto renderable = renderableForEntityId(entityId);
|
||||
if (renderable) {
|
||||
// only add valid renderables _renderablesToUpdate
|
||||
_renderablesToUpdate.insert({ entityId, renderable });
|
||||
_renderablesToUpdate.insert(renderable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -414,8 +410,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
|
|||
// we expect to update all renderables within available time budget
|
||||
PROFILE_RANGE_EX(simulation_physics, "UpdateRenderables", 0xffff00ff, (uint64_t)_renderablesToUpdate.size());
|
||||
uint64_t updateStart = usecTimestampNow();
|
||||
for (const auto& entry : _renderablesToUpdate) {
|
||||
const auto& renderable = entry.second;
|
||||
for (const auto& renderable : _renderablesToUpdate) {
|
||||
assert(renderable); // only valid renderables are added to _renderablesToUpdate
|
||||
renderable->updateInScene(scene, transaction);
|
||||
}
|
||||
|
@ -424,8 +419,8 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
|
|||
|
||||
// compute average per-renderable update cost
|
||||
float cost = (float)(usecTimestampNow() - updateStart) / (float)(numRenderables);
|
||||
const float blend = 0.1f;
|
||||
_avgRenderableUpdateCost = (1.0f - blend) * _avgRenderableUpdateCost + blend * cost;
|
||||
const float BLEND = 0.1f;
|
||||
_avgRenderableUpdateCost = (1.0f - BLEND) * _avgRenderableUpdateCost + BLEND * cost;
|
||||
} else {
|
||||
// we expect the cost to updating all renderables to exceed available time budget
|
||||
// so we first sort by priority and update in order until out of time
|
||||
|
@ -450,43 +445,40 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
|
|||
PrioritySortUtil::PriorityQueue<SortableRenderer> sortedRenderables(views);
|
||||
sortedRenderables.reserve(_renderablesToUpdate.size());
|
||||
{
|
||||
PROFILE_RANGE_EX(simulation_physics, "SortRenderables", 0xffff00ff, (uint64_t)_renderablesToUpdate.size());
|
||||
std::unordered_map<EntityItemID, EntityRendererPointer>::iterator itr = _renderablesToUpdate.begin();
|
||||
while (itr != _renderablesToUpdate.end()) {
|
||||
assert(itr->second); // only valid renderables are added to _renderablesToUpdate
|
||||
sortedRenderables.push(SortableRenderer(itr->second));
|
||||
++itr;
|
||||
PROFILE_RANGE_EX(simulation_physics, "BuildSortedRenderables", 0xffff00ff, (uint64_t)_renderablesToUpdate.size());
|
||||
for (const auto& renderable : _renderablesToUpdate) {
|
||||
assert(renderable); // only valid renderables are added to _renderablesToUpdate
|
||||
sortedRenderables.push(SortableRenderer(renderable));
|
||||
}
|
||||
}
|
||||
{
|
||||
PROFILE_RANGE_EX(simulation_physics, "UpdateRenderables", 0xffff00ff, sortedRenderables.size());
|
||||
PROFILE_RANGE_EX(simulation_physics, "SortAndUpdateRenderables", 0xffff00ff, sortedRenderables.size());
|
||||
|
||||
// compute remaining time budget
|
||||
const auto& sortedRenderablesVector = sortedRenderables.getSortedVector();
|
||||
uint64_t updateStart = usecTimestampNow();
|
||||
uint64_t timeBudget = MIN_SORTED_UPDATE_RENDERABLES_TIME_BUDGET;
|
||||
uint64_t sortCost = updateStart - sortStart;
|
||||
uint64_t timeBudget = MIN_SORTED_UPDATE_RENDERABLES_TIME_BUDGET;
|
||||
if (sortCost < MAX_UPDATE_RENDERABLES_TIME_BUDGET - MIN_SORTED_UPDATE_RENDERABLES_TIME_BUDGET) {
|
||||
timeBudget = MAX_UPDATE_RENDERABLES_TIME_BUDGET - sortCost;
|
||||
}
|
||||
uint64_t expiry = updateStart + timeBudget;
|
||||
|
||||
// process the sorted renderables
|
||||
size_t numSorted = sortedRenderables.size();
|
||||
const auto& sortedRenderablesVector = sortedRenderables.getSortedVector();
|
||||
for (const auto& sortedRenderable : sortedRenderablesVector) {
|
||||
if (usecTimestampNow() > expiry) {
|
||||
break;
|
||||
}
|
||||
const auto& renderable = sortedRenderable.getRenderer();
|
||||
renderable->updateInScene(scene, transaction);
|
||||
_renderablesToUpdate.erase(renderable->getEntity()->getID());
|
||||
_renderablesToUpdate.erase(renderable);
|
||||
}
|
||||
|
||||
// compute average per-renderable update cost
|
||||
size_t numUpdated = numSorted - sortedRenderables.size() + 1; // add one to avoid divide by zero
|
||||
size_t numUpdated = sortedRenderables.size() - _renderablesToUpdate.size() + 1; // add one to avoid divide by zero
|
||||
float cost = (float)(usecTimestampNow() - updateStart) / (float)(numUpdated);
|
||||
const float blend = 0.1f;
|
||||
_avgRenderableUpdateCost = (1.0f - blend) * _avgRenderableUpdateCost + blend * cost;
|
||||
const float BLEND = 0.1f;
|
||||
_avgRenderableUpdateCost = (1.0f - BLEND) * _avgRenderableUpdateCost + BLEND * cost;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -990,7 +982,6 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) {
|
|||
|
||||
void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) {
|
||||
// If it's in a pending queue, remove it
|
||||
_renderablesToUpdate.erase(entityID);
|
||||
_entitiesToAdd.erase(entityID);
|
||||
|
||||
auto itr = _entitiesInScene.find(entityID);
|
||||
|
@ -1000,7 +991,7 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) {
|
|||
}
|
||||
|
||||
if (_tree && !_shuttingDown && _entitiesScriptEngine && !itr->second->getEntity()->getScript().isEmpty()) {
|
||||
if (itr->second->getEntity()->contains(_avatarPosition)) {
|
||||
if (_currentEntitiesInside.contains(entityID)) {
|
||||
_entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity");
|
||||
}
|
||||
_entitiesScriptEngine->unloadEntityScript(entityID, true);
|
||||
|
@ -1013,6 +1004,7 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) {
|
|||
}
|
||||
|
||||
auto renderable = itr->second;
|
||||
_renderablesToUpdate.erase(renderable);
|
||||
_entitiesInScene.erase(itr);
|
||||
|
||||
if (!renderable) {
|
||||
|
@ -1047,7 +1039,7 @@ void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID, bool
|
|||
QString scriptUrl = entity->getScript();
|
||||
if ((shouldLoad && unloadFirst) || scriptUrl.isEmpty()) {
|
||||
if (_entitiesScriptEngine) {
|
||||
if (entity->contains(_avatarPosition)) {
|
||||
if (_currentEntitiesInside.contains(entityID)) {
|
||||
_entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity");
|
||||
}
|
||||
_entitiesScriptEngine->unloadEntityScript(entityID);
|
||||
|
|
|
@ -246,7 +246,7 @@ private:
|
|||
ReadWriteLockable _changedEntitiesGuard;
|
||||
std::unordered_set<EntityItemID> _changedEntities;
|
||||
|
||||
std::unordered_map<EntityItemID, EntityRendererPointer> _renderablesToUpdate;
|
||||
std::unordered_set<EntityRendererPointer> _renderablesToUpdate;
|
||||
std::unordered_map<EntityItemID, EntityRendererPointer> _entitiesInScene;
|
||||
std::unordered_map<EntityItemID, EntityItemWeakPointer> _entitiesToAdd;
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ class EntityTreeElementExtraEncodeData;
|
|||
class ReadBitstreamToTreeParams;
|
||||
|
||||
/**jsdoc
|
||||
* Ambient light is defined by the following properties.
|
||||
* Ambient light is defined by the following properties:
|
||||
* @typedef {object} Entities.AmbientLight
|
||||
* @property {number} ambientIntensity=0.5 - The intensity of the light.
|
||||
* @property {string} ambientURL="" - A cube map image that defines the color of the light coming from each direction. If
|
||||
|
|
|
@ -48,16 +48,18 @@ bool operator!=(const AnimationPropertyGroup& a, const AnimationPropertyGroup& b
|
|||
|
||||
|
||||
/**jsdoc
|
||||
* The AnimationProperties are used to configure an animation.
|
||||
* An animation is configured by the following properties:
|
||||
* @typedef {object} Entities.AnimationProperties
|
||||
* @property {string} url="" - The URL of the FBX file that has the animation.
|
||||
* @property {boolean} allowTranslation=true - <code>true</code> to enable translations contained in the animation to be
|
||||
* played, <code>false</code> to disable translations.
|
||||
* @property {number} fps=30 - The speed in frames/s that the animation is played at.
|
||||
* @property {number} firstFrame=0 - The first frame to play in the animation.
|
||||
* @property {number} lastFrame=100000 - The last frame to play in the animation.
|
||||
* @property {number} currentFrame=0 - The current frame being played in the animation.
|
||||
* @property {boolean} running=false - If <code>true</code> then the animation should play.
|
||||
* @property {boolean} loop=true - If <code>true</code> then the animation should be continuously repeated in a loop.
|
||||
* @property {boolean} hold=false - If <code>true</code> then the rotations and translations of the last frame played should be
|
||||
* @property {boolean} loop=true - If <code>true</code> then the animation is continuously repeated in a loop.
|
||||
* @property {boolean} hold=false - If <code>true</code> then the rotations and translations of the last frame played are
|
||||
* maintained when the animation stops playing.
|
||||
*/
|
||||
void AnimationPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const {
|
||||
|
|
|
@ -31,9 +31,8 @@ static const float INITIAL_BLOOM_THRESHOLD { 0.7f };
|
|||
static const float INITIAL_BLOOM_SIZE { 0.9f };
|
||||
|
||||
/**jsdoc
|
||||
* Bloom is defined by the following properties.
|
||||
* Bloom is defined by the following properties:
|
||||
* @typedef {object} Entities.Bloom
|
||||
*
|
||||
* @property {number} bloomIntensity=0.25 - The intensity of the bloom effect.
|
||||
* @property {number} bloomThreshold=0.7 - The threshold for the bloom effect.
|
||||
* @property {number} bloomSize=0.9 - The size of the bloom effect.
|
||||
|
|
|
@ -94,47 +94,48 @@ variables. These argument variables are used by the code which is run when bull
|
|||
#include "EntityItem.h"
|
||||
|
||||
/**jsdoc
|
||||
* <p>An entity action may be one of the following types:</p>
|
||||
* <table>
|
||||
* <thead>
|
||||
* <tr><th>Value</th><th>Type</th><th>Description</th><th>Arguments</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td><code>"far-grab"</code></td><td>Avatar action</td>
|
||||
* <td>Moves and rotates an entity to a target position and orientation, optionally relative to another entity. Collisions
|
||||
* between the entity and the user's avatar are disabled during the far-grab.</td>
|
||||
* <td>{@link Entities.ActionArguments-FarGrab}</td></tr>
|
||||
* <tr><td><code>"hold"</code></td><td>Avatar action</td>
|
||||
* <td>Positions and rotates an entity relative to an avatar's hand. Collisions between the entity and the user's avatar
|
||||
* are disabled during the hold.</td>
|
||||
* <td>{@link Entities.ActionArguments-Hold}</td></tr>
|
||||
* <tr><td><code>"offset"</code></td><td>Object action</td>
|
||||
* <td>Moves an entity so that it is a set distance away from a target point.</td>
|
||||
* <td>{@link Entities.ActionArguments-Offset}</td></tr>
|
||||
* <tr><td><code>"tractor"</code></td><td>Object action</td>
|
||||
* <td>Moves and rotates an entity to a target position and orientation, optionally relative to another entity.</td>
|
||||
* <td>{@link Entities.ActionArguments-Tractor}</td></tr>
|
||||
* <tr><td><code>"travel-oriented"</code></td><td>Object action</td>
|
||||
* <td>Orients an entity to align with its direction of travel.</td>
|
||||
* <td>{@link Entities.ActionArguments-TravelOriented}</td></tr>
|
||||
* <tr><td><code>"hinge"</code></td><td>Object constraint</td>
|
||||
* <td>Lets an entity pivot about an axis or connects two entities with a hinge joint.</td>
|
||||
* <td>{@link Entities.ActionArguments-Hinge}</td></tr>
|
||||
* <tr><td><code>"slider"</code></td><td>Object constraint</td>
|
||||
* <td>Lets an entity slide and rotate along an axis, or connects two entities that slide and rotate along a shared
|
||||
* axis.</td>
|
||||
* <td>{@link Entities.ActionArguments-Slider|ActionArguments-Slider}</td></tr>
|
||||
* <tr><td><code>"cone-twist"</code></td><td>Object constraint</td>
|
||||
* <td>Connects two entities with a joint that can move through a cone and can twist.</td>
|
||||
* <td>{@link Entities.ActionArguments-ConeTwist}</td></tr>
|
||||
* <tr><td><code>"ball-socket"</code></td><td>Object constraint</td>
|
||||
* <td>Connects two entities with a ball and socket joint.</td>
|
||||
* <td>{@link Entities.ActionArguments-BallSocket}</td></tr>
|
||||
* <tr><td><code>"spring"</code></td><td colspan="3">Synonym for <code>"tractor"</code>. <em>Legacy value.</em></td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* @typedef {string} Entities.ActionType
|
||||
*/
|
||||
* <p>An entity action may be one of the following types:</p>
|
||||
* <table>
|
||||
* <thead>
|
||||
* <tr><th>Value</th><th>Type</th><th>Description</th><th>Arguments</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td><code>"far-grab"</code></td><td>Avatar action</td>
|
||||
* <td>Moves and rotates an entity to a target position and orientation, optionally relative to another entity. Collisions
|
||||
* between the entity and the user's avatar are disabled during the far-grab.</td>
|
||||
* <td>{@link Entities.ActionArguments-FarGrab}</td></tr>
|
||||
* <tr><td><code>"hold"</code></td><td>Avatar action</td>
|
||||
* <td>Positions and rotates an entity relative to an avatar's hand. Collisions between the entity and the user's avatar
|
||||
* are disabled during the hold.</td>
|
||||
* <td>{@link Entities.ActionArguments-Hold}</td></tr>
|
||||
* <tr><td><code>"offset"</code></td><td>Object action</td>
|
||||
* <td>Moves an entity so that it is a set distance away from a target point.</td>
|
||||
* <td>{@link Entities.ActionArguments-Offset}</td></tr>
|
||||
* <tr><td><code>"tractor"</code></td><td>Object action</td>
|
||||
* <td>Moves and rotates an entity to a target position and orientation, optionally relative to another entity.</td>
|
||||
* <td>{@link Entities.ActionArguments-Tractor}</td></tr>
|
||||
* <tr><td><code>"travel-oriented"</code></td><td>Object action</td>
|
||||
* <td>Orients an entity to align with its direction of travel.</td>
|
||||
* <td>{@link Entities.ActionArguments-TravelOriented}</td></tr>
|
||||
* <tr><td><code>"hinge"</code></td><td>Object constraint</td>
|
||||
* <td>Lets an entity pivot about an axis or connects two entities with a hinge joint.</td>
|
||||
* <td>{@link Entities.ActionArguments-Hinge}</td></tr>
|
||||
* <tr><td><code>"slider"</code></td><td>Object constraint</td>
|
||||
* <td>Lets an entity slide and rotate along an axis, or connects two entities that slide and rotate along a shared
|
||||
* axis.</td>
|
||||
* <td>{@link Entities.ActionArguments-Slider|ActionArguments-Slider}</td></tr>
|
||||
* <tr><td><code>"cone-twist"</code></td><td>Object constraint</td>
|
||||
* <td>Connects two entities with a joint that can move through a cone and can twist.</td>
|
||||
* <td>{@link Entities.ActionArguments-ConeTwist}</td></tr>
|
||||
* <tr><td><code>"ball-socket"</code></td><td>Object constraint</td>
|
||||
* <td>Connects two entities with a ball and socket joint.</td>
|
||||
* <td>{@link Entities.ActionArguments-BallSocket}</td></tr>
|
||||
* <tr><td><code>"spring"</code></td><td colspan="3">Synonym for <code>"tractor"</code>.
|
||||
* <span class="important">Deprecated.</span></td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* @typedef {string} Entities.ActionType
|
||||
*/
|
||||
// Note: The "none" action type is not listed because it's an internal "uninitialized" value and not useful for scripts.
|
||||
EntityDynamicType EntityDynamicInterface::dynamicTypeFromString(QString dynamicTypeString) {
|
||||
QString normalizedDynamicTypeString = dynamicTypeString.toLower().remove('-').remove('_');
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -2121,9 +2121,10 @@ void EntityTree::fixupNeedsParentFixups() {
|
|||
_needsParentFixup.clear();
|
||||
}
|
||||
|
||||
std::unordered_set<QUuid> seenEntityIds;
|
||||
QMutableVectorIterator<EntityItemWeakPointer> iter(entitiesToFixup);
|
||||
while (iter.hasNext()) {
|
||||
EntityItemWeakPointer entityWP = iter.next();
|
||||
const auto& entityWP = iter.next();
|
||||
EntityItemPointer entity = entityWP.lock();
|
||||
if (!entity) {
|
||||
// entity was deleted before we found its parent
|
||||
|
@ -2131,6 +2132,17 @@ void EntityTree::fixupNeedsParentFixups() {
|
|||
continue;
|
||||
}
|
||||
|
||||
const auto id = entity->getID();
|
||||
// BUGZ-771 some entities seem to never be removed by the below logic and further seem to accumulate dupes within the _needsParentFixup list
|
||||
// This block ensures that duplicates are removed from entitiesToFixup before it's re-appended to _needsParentFixup
|
||||
if (0 != seenEntityIds.count(id)) {
|
||||
// Entity was duplicated inside entitiesToFixup
|
||||
iter.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
seenEntityIds.insert(id);
|
||||
|
||||
entity->requiresRecalcBoxes();
|
||||
bool queryAACubeSuccess { false };
|
||||
bool maxAACubeSuccess { false };
|
||||
|
|
|
@ -42,7 +42,10 @@ public:
|
|||
* <tr><th>Value</th><th>Description</th><th>Properties</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td><code>"Box"</code></td><td>A rectangular prism. This is a synonym of <code>"Shape"</code> for the case
|
||||
* <tr><td><code>"Shape"</code></td><td>A basic entity such as a cube.
|
||||
* See also, the <code>"Box"</code> and <code>"Sphere"</code> entity types.</td>
|
||||
* <td>{@link Entities.EntityProperties-Shape|EntityProperties-Shape}</td></tr>
|
||||
* <tr><td><code>"Box"</code></td><td>A rectangular prism. This is a synonym of <code>"Shape"</code> for the case
|
||||
* where the entity's <code>shape</code> property value is <code>"Cube"</code>.<br />
|
||||
* If an entity is created with its <code>type</code>
|
||||
* set to <code>"Box"</code> it will always be created with a <code>shape</code> property value of
|
||||
|
@ -56,16 +59,13 @@ public:
|
|||
* <code>"Sphere"</code>. If an entity of type <code>Box</code> or <code>Shape</code> has its <code>shape</code> set
|
||||
* to <code>"Sphere"</code> then its <code>type</code> will be reported as <code>"Sphere"</code>.
|
||||
* <td>{@link Entities.EntityProperties-Sphere|EntityProperties-Sphere}</td></tr>
|
||||
* <tr><td><code>"Shape"</code></td><td>A basic entity such as a cube.
|
||||
* See also, the <code>"Box"</code> and <code>"Sphere"</code> entity types.</td>
|
||||
* <td>{@link Entities.EntityProperties-Shape|EntityProperties-Shape}</td></tr>
|
||||
* <tr><td><code>"Model"</code></td><td>A mesh model from an FBX or OBJ file.</td>
|
||||
* <tr><td><code>"Model"</code></td><td>A mesh model from a glTf, FBX, or OBJ file.</td>
|
||||
* <td>{@link Entities.EntityProperties-Model|EntityProperties-Model}</td></tr>
|
||||
* <tr><td><code>"Text"</code></td><td>A pane of text oriented in space.</td>
|
||||
* <td>{@link Entities.EntityProperties-Text|EntityProperties-Text}</td></tr>
|
||||
* <tr><td><code>"Image"</code></td><td>An image oriented in space.</td>
|
||||
* <td>{@link Entities.EntityProperties-Image|EntityProperties-Image}</td></tr>
|
||||
* <tr><td><code>"Web"</code></td><td>A browsable Web page.</td>
|
||||
* <tr><td><code>"Web"</code></td><td>A browsable web page.</td>
|
||||
* <td>{@link Entities.EntityProperties-Web|EntityProperties-Web}</td></tr>
|
||||
* <tr><td><code>"ParticleEffect"</code></td><td>A particle system that can be used to simulate things such as fire,
|
||||
* smoke, snow, magic spells, etc.</td>
|
||||
|
@ -78,7 +78,7 @@ public:
|
|||
* <td>{@link Entities.EntityProperties-PolyVox|EntityProperties-PolyVox}</td></tr>
|
||||
* <tr><td><code>"Grid"</code></td><td>A grid of lines in a plane.</td>
|
||||
* <td>{@link Entities.EntityProperties-Grid|EntityProperties-Grid}</td></tr>
|
||||
* <tr><td><code>"Gizmo"</code></td><td>An entity with various UI-related properties.</td>
|
||||
* <tr><td><code>"Gizmo"</code></td><td>A gizmo intended for UI.</td>
|
||||
* <td>{@link Entities.EntityProperties-Gizmo|EntityProperties-Gizmo}</td></tr>
|
||||
* <tr><td><code>"Light"</code></td><td>A local lighting effect.</td>
|
||||
* <td>{@link Entities.EntityProperties-Light|EntityProperties-Light}</td></tr>
|
||||
|
|
|
@ -41,35 +41,33 @@ static const glm::vec3 INITIAL_EQUIPPABLE_INDICATOR_OFFSET { glm::vec3(0.0f) };
|
|||
|
||||
|
||||
/**jsdoc
|
||||
* Grab is defined by the following properties.
|
||||
* Grabbing behavior is defined by the following properties:
|
||||
*
|
||||
* @typedef {object} Entities.Grab
|
||||
*
|
||||
* @property {boolean} grabbable=true - If <code>true</code> the entity can be grabbed.
|
||||
* @property {boolean} grabKinematic=true - If <code>true</code> the entity is updated in a kinematic manner.
|
||||
* If <code>false</code> it will be grabbed using a tractor action. A kinematic grab will make the item appear more
|
||||
* tightly held, but will cause it to behave poorly when interacting with dynamic entities.
|
||||
* @property {boolean} grabFollowsController=true - If <code>true</code> the entity will follow the motions of the
|
||||
* hand-controller even if the avatar's hand can't get to the implied position. This should be <code>true</code>
|
||||
* for tools, pens, etc and false for things meant to decorate the hand.
|
||||
*
|
||||
* @property {boolean} triggerable=false - If <code>true</code> the entity will receive calls to trigger
|
||||
* @property {boolean} grabbable=true - If <code>true</code> then the entity can be grabbed.
|
||||
* @property {boolean} grabKinematic=true - If <code>true</code> then the entity will be updated in a kinematic manner when
|
||||
* grabbed; if <code>false</code> it will be grabbed using a tractor action. A kinematic grab will make the item appear
|
||||
* more tightly held but will cause it to behave poorly when interacting with dynamic entities.
|
||||
* @property {boolean} grabFollowsController=true - If <code>true</code> then the entity will follow the motions of the hand
|
||||
* controller even if the avatar's hand can't get to the implied position. This should be set <code>true</code> for tools,
|
||||
* pens, etc. and <code>false</code> for things meant to decorate the hand.
|
||||
* @property {boolean} triggerable=false - If <code>true</code> then the entity will receive calls to trigger
|
||||
* {@link Controller|Controller entity methods}.
|
||||
*
|
||||
* @property {boolean} equippable=true - If <code>true</code> the entity can be equipped.
|
||||
* @property {boolean} grabDelegateToParent=true - If <code>true</code> and the entity is grabbed, the grab will be transferred
|
||||
* to its parent entity if there is one; if <code>false</code>, a child entity can be grabbed and moved relative to its
|
||||
* parent.
|
||||
* @property {boolean} equippable=true - If <code>true</code> then the entity can be equipped.
|
||||
* @property {Vec3} equippableLeftPosition=0,0,0 - Positional offset from the left hand, when equipped.
|
||||
* @property {Quat} equippableLeftRotation=0,0,0,1 - Rotational offset from the left hand, when equipped.
|
||||
* @property {Vec3} equippableRightPosition=0,0,0 - Positional offset from the right hand, when equipped.
|
||||
* @property {Quat} equippableRightRotation=0,0,0,1 - Rotational offset from the right hand, when equipped.
|
||||
*
|
||||
* @property {string} equippableIndicatorURL="" - If non-empty, this model will be used to indicate that an
|
||||
* entity is equippable, rather than the default.
|
||||
* @property {Vec3} equippableIndicatorScale=1,1,1 - If equippableIndicatorURL is non-empty, this controls the
|
||||
* @property {Vec3} equippableIndicatorScale=1,1,1 - If <code>equippableIndicatorURL</code> is non-empty, this controls the
|
||||
scale of the displayed indicator.
|
||||
* @property {Vec3} equippableIndicatorOffset=0,0,0 - If equippableIndicatorURL is non-empty, this controls the
|
||||
* @property {Vec3} equippableIndicatorOffset=0,0,0 - If <code>equippableIndicatorURL</code> is non-empty, this controls the
|
||||
relative offset of the displayed object from the equippable entity.
|
||||
*/
|
||||
|
||||
|
||||
class GrabPropertyGroup : public PropertyGroup {
|
||||
public:
|
||||
// EntityItemProperty related helpers
|
||||
|
|
|
@ -43,7 +43,7 @@ static const float INITIAL_KEY_LIGHT_ALTITUDE{ 200.0f };
|
|||
// FIXME: Document hazeAttenuationKeyLight, hazeKeyLightRange, and hazeKeyLightAltitude once they're working and are provided
|
||||
// in the Create app's UI.
|
||||
/**jsdoc
|
||||
* Haze is defined by the following properties.
|
||||
* Haze is defined by the following properties:
|
||||
* @typedef {object} Entities.Haze
|
||||
*
|
||||
* @property {number} hazeRange=1000 - The horizontal distance at which visibility is reduced to 95%; i.e., 95% of each pixel's
|
||||
|
@ -56,7 +56,7 @@ static const float INITIAL_KEY_LIGHT_ALTITUDE{ 200.0f };
|
|||
* haze color are blended 50/50.
|
||||
*
|
||||
* @property {boolean} hazeAltitudeEffect=false - If <code>true</code> then haze decreases with altitude as defined by the
|
||||
* entity's local coordinate system; <code>hazeBaseRef</code> and </code>hazeCeiling</code> are used.
|
||||
* entity's local coordinate system; <code>hazeBaseRef</code> and <code>hazeCeiling</code> are used.
|
||||
* @property {number} hazeBaseRef=0 - The y-axis value in the entity's local coordinate system at which the haze density starts
|
||||
* reducing with altitude.
|
||||
* @property {number} hazeCeiling=200 - The y-axis value in the entity's local coordinate system at which the haze density has
|
||||
|
@ -65,9 +65,11 @@ static const float INITIAL_KEY_LIGHT_ALTITUDE{ 200.0f };
|
|||
* @property {number} hazeBackgroundBlend=0 - The proportion of the skybox image to show through the haze: <code>0.0</code>
|
||||
* displays no skybox image; <code>1.0</code> displays no haze.
|
||||
*
|
||||
* @property {boolean} hazeAttenuateKeyLight=false - <em>Currently not supported.</em>
|
||||
* @property {number} hazeKeyLightRange=1000 - <em>Currently not supported.</em>
|
||||
* @property {number} hazeKeyLightAltitude=200 - <em>Currently not supported.</em>
|
||||
* @property {boolean} hazeAttenuateKeyLight=false - If <code>true</code> then the haze attenuates the key light;
|
||||
* <code>hazeKeyLightRange</code> and <code>hazeKeyLightAltitude</code> are used.
|
||||
* @property {number} hazeKeyLightRange=1000 - The distance at which the haze attenuates the key light by 95%.
|
||||
* @property {number} hazeKeyLightAltitude=200 - The altitude at which the haze starts attenuating the key light (i.e., the
|
||||
* altitude at which the distance starts being calculated).
|
||||
*/
|
||||
class HazePropertyGroup : public PropertyGroup {
|
||||
public:
|
||||
|
|
|
@ -28,13 +28,13 @@ class EntityTreeElementExtraEncodeData;
|
|||
class ReadBitstreamToTreeParams;
|
||||
|
||||
/**jsdoc
|
||||
* A key light is defined by the following properties.
|
||||
* A key light is defined by the following properties:
|
||||
* @typedef {object} Entities.KeyLight
|
||||
* @property {Color} color=255,255,255 - The color of the light.
|
||||
* @property {number} intensity=1 - The intensity of the light.
|
||||
* @property {Vec3} direction=0,-1,0 - The direction the light is shining.
|
||||
* @property {boolean} castShadows=false - If <code>true</code> then shadows are cast. Shadows are cast by avatars, plus
|
||||
* {@link Entities.EntityType|Model} and {@link Entities.EntityType|Shape} entities that have their
|
||||
* {@link Entities.EntityProperties-Model|Model} and {@link Entities.EntityProperties-Shape|Shape} entities that have their
|
||||
* <code>{@link Entities.EntityProperties|canCastShadow}</code> property set to <code>true</code>.
|
||||
*/
|
||||
class KeyLightPropertyGroup : public PropertyGroup {
|
||||
|
|
|
@ -63,7 +63,7 @@ class PolyVoxEntityItem : public EntityItem {
|
|||
virtual int getOnCount() const { return 0; }
|
||||
|
||||
/**jsdoc
|
||||
* <p>A <code>PolyVoxSurfaceStyle</code> may be one of the following:</p>
|
||||
* <p>The surface of a {@link Entities.EntityProperties-PolyVox|PolyVox} entity may be one of the following styles:</p>
|
||||
* <table>
|
||||
* <thead>
|
||||
* <tr><th>Value</th><th>Type</th><th>Description</th></tr>
|
||||
|
|
|
@ -26,19 +26,17 @@ class OctreePacketData;
|
|||
class ReadBitstreamToTreeParams;
|
||||
|
||||
/**jsdoc
|
||||
* Pulse is defined by the following properties.
|
||||
* A color and alpha pulse that an entity may have.
|
||||
* @typedef {object} Entities.Pulse
|
||||
*
|
||||
* @property {number} min=0 - The minimum value of the pulse multiplier.
|
||||
* @property {number} max=1 - The maximum value of the pulse multiplier.
|
||||
* @property {number} period=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from
|
||||
* <code>min</code> to <code>max</code>, then <code>max</code> to <code>min</code> in one period.
|
||||
* @property {PulseMode} colorMode="none" - If "in", the color is pulsed in phase with the pulse period; if "out"
|
||||
* @property {Entities.PulseMode} colorMode="none" - If "in", the color is pulsed in phase with the pulse period; if "out"
|
||||
* the color is pulsed out of phase with the pulse period.
|
||||
* @property {PulseMode} alphaMode="none" - If "in", the alpha is pulsed in phase with the pulse period; if "out"
|
||||
* @property {Entities.PulseMode} alphaMode="none" - If "in", the alpha is pulsed in phase with the pulse period; if "out"
|
||||
* the alpha is pulsed out of phase with the pulse period.
|
||||
*/
|
||||
|
||||
class PulsePropertyGroup : public PropertyGroup {
|
||||
public:
|
||||
// EntityItemProperty related helpers
|
||||
|
|
|
@ -25,31 +25,32 @@ class ReadBitstreamToTreeParams;
|
|||
using u8vec3Color = glm::u8vec3;
|
||||
|
||||
/**jsdoc
|
||||
* A RingGizmo is defined by the following properties.
|
||||
* A {@link Entities.EntityProperties-Gizmo|ring Gizmo} entity is defined by the following properties:
|
||||
* @typedef {object} Entities.RingGizmo
|
||||
*
|
||||
* @property {number} startAngle=0 - The angle at which the ring will start, in degrees.
|
||||
* @property {number} endAngle=360 - The angle at which the ring will end, in degrees.
|
||||
* @property {number} innerRadius=0 - The inner radius of the ring as a fraction of the total radius. 0-1.
|
||||
* @property {number} startAngle=0 - The angle at which the ring starts, in degrees.
|
||||
* @property {number} endAngle=360 - The angle at which the ring ends, in degrees.
|
||||
* @property {number} innerRadius=0 - The inner radius of the ring as a fraction of the total radius, range <code>0.0</code>
|
||||
* — <code>1.0</code>.
|
||||
|
||||
* @property {Color} innerStartColor - The color at the inner start point of the ring.
|
||||
* @property {Color} innerEndColor - The color at the inner end point of the ring.
|
||||
* @property {Color} outerStartColor - The color at the outer start point of the ring.
|
||||
* @property {Color} outerEndColor - The color at the outer end point of the ring.
|
||||
* @property {number} innerStartAlpha=1 - The alpha at the inner start point of the ring.
|
||||
* @property {number} innerEndAlpha=1 - The alpha at the inner end point of the ring.
|
||||
* @property {number} outerStartAlpha=1 - The alpha at the outer start point of the ring.
|
||||
* @property {number} outerEndAlpha=1 - The alpha at the outer end point of the ring.
|
||||
* @property {Color} innerStartColor=255,255,255 - The color at the inner start point of the ring.
|
||||
* @property {Color} innerEndColor=255,255,255 - The color at the inner end point of the ring.
|
||||
* @property {Color} outerStartColor=255,255,255 - The color at the outer start point of the ring.
|
||||
* @property {Color} outerEndColor=255,255,255 - The color at the outer end point of the ring.
|
||||
* @property {number} innerStartAlpha=1 - The opacity at the inner start point of the ring.
|
||||
* @property {number} innerEndAlpha=1 - The opacity at the inner end point of the ring.
|
||||
* @property {number} outerStartAlpha=1 - The opacity at the outer start point of the ring.
|
||||
* @property {number} outerEndAlpha=1 - The opacity at the outer end point of the ring.
|
||||
|
||||
* @property {boolean} hasTickMarks=false - Whether or not to render tick marks.
|
||||
* @property {number} majorTickMarksAngle - The angle between major tick marks, in degrees.
|
||||
* @property {number} minorTickMarksAngle - The angle between minor tick marks, in degrees.
|
||||
* @property {number} majorTickMarksLength - The length of the major tick marks, as a fraction of the radius. A positive value draws tick marks
|
||||
* outwards from the inner radius; a negative value draws tick marks inwards from the outer radius.
|
||||
* @property {number} minorTickMarksLength - The length of the minor tick marks, as a fraction of the radius. A positive value draws tick marks
|
||||
* outwards from the inner radius; a negative value draws tick marks inwards from the outer radius.
|
||||
* @property {Color} majorTickMarksColor - The color of the major tick marks.
|
||||
* @property {Color} minorTickMarksColor - The color of the minor tick marks.
|
||||
* @property {boolean} hasTickMarks=false - <code>true</code> to render tick marks, otherwise <code>false</code>.
|
||||
* @property {number} majorTickMarksAngle=0 - The angle between major tick marks, in degrees.
|
||||
* @property {number} minorTickMarksAngle=0 - The angle between minor tick marks, in degrees.
|
||||
* @property {number} majorTickMarksLength=0 - The length of the major tick marks as a fraction of the radius. A positive value
|
||||
* draws tick marks outwards from the inner radius; a negative value draws tick marks inwards from the outer radius.
|
||||
* @property {number} minorTickMarksLength=0 - The length of the minor tick marks, as a fraction of the radius. A positive
|
||||
* value draws tick marks outwards from the inner radius; a negative value draws tick marks inwards from the outer radius.
|
||||
* @property {Color} majorTickMarksColor=255,255,255 - The color of the major tick marks.
|
||||
* @property {Color} minorTickMarksColor=255,255,255 - The color of the minor tick marks.
|
||||
*/
|
||||
|
||||
class RingGizmoPropertyGroup : public PropertyGroup {
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
namespace entity {
|
||||
|
||||
/**jsdoc
|
||||
* <p>A <code>Shape</code>, <code>Box</code>, or <code>Sphere</code> {@link Entities.EntityType|EntityType} may display as
|
||||
* one of the following geometrical shapes:</p>
|
||||
* <p>A <code>"Shape"</code>, <code>"Box"</code>, or <code>"Sphere"</code> {@link Entities.EntityType|EntityType} may
|
||||
* display as one of the following geometrical shapes:</p>
|
||||
* <table>
|
||||
* <thead>
|
||||
* <tr><th>Value</th><th>Dimensions</th><th>Notes</th></tr>
|
||||
|
|
|
@ -30,7 +30,7 @@ class EntityTreeElementExtraEncodeData;
|
|||
class ReadBitstreamToTreeParams;
|
||||
|
||||
/**jsdoc
|
||||
* A skybox is defined by the following properties.
|
||||
* A skybox is defined by the following properties:
|
||||
* @typedef {object} Entities.Skybox
|
||||
* @property {Color} color=0,0,0 - Sets the color of the sky if <code>url</code> is <code>""</code>, otherwise modifies the
|
||||
* color of the cube map image.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
set(TARGET_NAME networking)
|
||||
setup_hifi_library(Network)
|
||||
link_hifi_libraries(shared)
|
||||
link_hifi_libraries(shared platform)
|
||||
|
||||
target_openssl()
|
||||
target_tbb()
|
||||
|
|
|
@ -956,7 +956,7 @@ void AccountManager::saveLoginStatus(bool isLoggedIn) {
|
|||
QProcess launcher;
|
||||
launcher.setProgram(launcherPath);
|
||||
launcher.startDetached();
|
||||
qApp->quit();
|
||||
QMetaObject::invokeMethod(qApp, "quit", Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,6 +26,8 @@
|
|||
#include <ThreadHelpers.h>
|
||||
#include <LogHandler.h>
|
||||
#include <UUID.h>
|
||||
#include <platform/Platform.h>
|
||||
#include <platform/PlatformKeys.h>
|
||||
|
||||
#include "AccountManager.h"
|
||||
#include "AddressManager.h"
|
||||
|
@ -42,6 +44,7 @@
|
|||
using namespace std::chrono;
|
||||
|
||||
const int KEEPALIVE_PING_INTERVAL_MS = 1000;
|
||||
const int MAX_SYSTEM_INFO_SIZE = 1000;
|
||||
|
||||
NodeList::NodeList(char newOwnerType, int socketListenPort, int dtlsListenPort) :
|
||||
LimitedNodeList(socketListenPort, dtlsListenPort),
|
||||
|
@ -418,19 +421,20 @@ void NodeList::sendDomainServerCheckIn() {
|
|||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
packetStream << FingerprintUtils::getMachineFingerprint();
|
||||
|
||||
QString systemInfo;
|
||||
#if defined Q_OS_WIN
|
||||
systemInfo = "OS:Windows";
|
||||
#elif defined Q_OS_OSX
|
||||
systemInfo = "OS:OSX";
|
||||
#elif defined Q_OS_LINUX
|
||||
systemInfo = "OS:Linux";
|
||||
#elif defined Q_OS_ANDROID
|
||||
systemInfo = "OS:Android";
|
||||
#else
|
||||
systemInfo = "OS:Unknown";
|
||||
#endif
|
||||
packetStream << systemInfo;
|
||||
auto desc = platform::getAll();
|
||||
|
||||
QByteArray systemInfo(desc.dump().c_str());
|
||||
QByteArray compressedSystemInfo = qCompress(systemInfo);
|
||||
|
||||
if (compressedSystemInfo.size() > MAX_SYSTEM_INFO_SIZE) {
|
||||
// Highly unlikely, as not even unreasonable machines will
|
||||
// overflow the max size, but prevent MTU overflow anyway.
|
||||
// We could do something sophisticated like clearing specific
|
||||
// values if they're too big, but we'll save that for later.
|
||||
compressedSystemInfo.clear();
|
||||
}
|
||||
|
||||
packetStream << compressedSystemInfo;
|
||||
|
||||
packetStream << _connectReason;
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <LogHandler.h>
|
||||
#include <shared/QtHelpers.h>
|
||||
|
||||
#include <platform/Platform.h>
|
||||
#include "NetworkLogging.h"
|
||||
|
||||
ThreadedAssignment::ThreadedAssignment(ReceivedMessage& message) :
|
||||
|
@ -38,6 +39,16 @@ ThreadedAssignment::ThreadedAssignment(ReceivedMessage& message) :
|
|||
// if the NL tells us we got a DS response, clear our member variable of queued check-ins
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
connect(nodeList.data(), &NodeList::receivedDomainServerList, this, &ThreadedAssignment::clearQueuedCheckIns);
|
||||
|
||||
platform::create();
|
||||
if (!platform::enumeratePlatform()) {
|
||||
qCDebug(networking) << "Failed to enumerate platform.";
|
||||
}
|
||||
}
|
||||
|
||||
ThreadedAssignment::~ThreadedAssignment() {
|
||||
stop();
|
||||
platform::destroy();
|
||||
}
|
||||
|
||||
void ThreadedAssignment::setFinished(bool isFinished) {
|
||||
|
|
|
@ -22,7 +22,7 @@ class ThreadedAssignment : public Assignment {
|
|||
Q_OBJECT
|
||||
public:
|
||||
ThreadedAssignment(ReceivedMessage& message);
|
||||
~ThreadedAssignment() { stop(); }
|
||||
~ThreadedAssignment();
|
||||
|
||||
virtual void aboutToFinish() { };
|
||||
void addPacketStatsAndSendStatsPacket(QJsonObject statsObject);
|
||||
|
|
|
@ -72,7 +72,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
return static_cast<PacketVersion>(DomainConnectionDeniedVersion::IncludesExtraInfo);
|
||||
|
||||
case PacketType::DomainConnectRequest:
|
||||
return static_cast<PacketVersion>(DomainConnectRequestVersion::HasSystemInfo);
|
||||
return static_cast<PacketVersion>(DomainConnectRequestVersion::HasCompressedSystemInfo);
|
||||
|
||||
case PacketType::DomainServerAddedNode:
|
||||
return static_cast<PacketVersion>(DomainServerAddedNodeVersion::PermissionsGrid);
|
||||
|
|
|
@ -347,7 +347,8 @@ enum class DomainConnectRequestVersion : PacketVersion {
|
|||
AlwaysHasMachineFingerprint,
|
||||
HasTimestamp,
|
||||
HasReason,
|
||||
HasSystemInfo
|
||||
HasSystemInfo,
|
||||
HasCompressedSystemInfo
|
||||
};
|
||||
|
||||
enum class DomainConnectionDeniedVersion : PacketVersion {
|
||||
|
|
|
@ -37,7 +37,7 @@ private slots:
|
|||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
* Set the maximum number of entity packets that the client can send per second.
|
||||
* Sets the maximum number of entity packets that the client can send per second.
|
||||
* @function Entities.setPacketsPerSecond
|
||||
* @param {number} packetsPerSecond - Integer maximum number of entity packets that the client can send per second.
|
||||
*/
|
||||
|
@ -45,7 +45,7 @@ public slots:
|
|||
void setPacketsPerSecond(int packetsPerSecond) { return _packetSender->setPacketsPerSecond(packetsPerSecond); }
|
||||
|
||||
/**jsdoc
|
||||
* Get the maximum number of entity packets that the client can send per second.
|
||||
* Gets the maximum number of entity packets that the client can send per second.
|
||||
* @function Entities.getPacketsPerSecond
|
||||
* @returns {number} Integer maximum number of entity packets that the client can send per second.
|
||||
*/
|
||||
|
@ -53,7 +53,7 @@ public slots:
|
|||
int getPacketsPerSecond() const { return _packetSender->getPacketsPerSecond(); }
|
||||
|
||||
/**jsdoc
|
||||
* Check whether servers exist for the client to send entity packets to, i.e., whether you are connected to a domain and
|
||||
* Checks whether servers exist for the client to send entity packets to, i.e., whether you are connected to a domain and
|
||||
* its entity server is working.
|
||||
* @function Entities.serversExist
|
||||
* @returns {boolean} <code>true</code> if servers exist for the client to send entity packets to, otherwise
|
||||
|
@ -63,7 +63,7 @@ public slots:
|
|||
bool serversExist() const { return _packetSender->serversExist(); }
|
||||
|
||||
/**jsdoc
|
||||
* Check whether the client has entity packets waiting to be sent.
|
||||
* Checks whether the client has entity packets waiting to be sent.
|
||||
* @function Entities.hasPacketsToSend
|
||||
* @returns {boolean} <code>true</code> if the client has entity packets waiting to be sent, otherwise <code>false</code>.
|
||||
*/
|
||||
|
@ -71,7 +71,7 @@ public slots:
|
|||
bool hasPacketsToSend() const { return _packetSender->hasPacketsToSend(); }
|
||||
|
||||
/**jsdoc
|
||||
* Get the number of entity packets the client has waiting to be sent.
|
||||
* Gets the number of entity packets the client has waiting to be sent.
|
||||
* @function Entities.packetsToSendCount
|
||||
* @returns {number} Integer number of entity packets the client has waiting to be sent.
|
||||
*/
|
||||
|
@ -79,7 +79,7 @@ public slots:
|
|||
int packetsToSendCount() const { return (int)_packetSender->packetsToSendCount(); }
|
||||
|
||||
/**jsdoc
|
||||
* Get the entity packets per second send rate of the client over its lifetime.
|
||||
* Gets the entity packets per second send rate of the client over its lifetime.
|
||||
* @function Entities.getLifetimePPS
|
||||
* @returns {number} Entity packets per second send rate of the client over its lifetime.
|
||||
*/
|
||||
|
@ -87,7 +87,7 @@ public slots:
|
|||
float getLifetimePPS() const { return _packetSender->getLifetimePPS(); }
|
||||
|
||||
/**jsdoc
|
||||
* Get the entity bytes per second send rate of the client over its lifetime.
|
||||
* Gets the entity bytes per second send rate of the client over its lifetime.
|
||||
* @function Entities.getLifetimeBPS
|
||||
* @returns {number} Entity bytes per second send rate of the client over its lifetime.
|
||||
*/
|
||||
|
@ -95,7 +95,7 @@ public slots:
|
|||
float getLifetimeBPS() const { return _packetSender->getLifetimeBPS(); }
|
||||
|
||||
/**jsdoc
|
||||
* Get the entity packets per second queued rate of the client over its lifetime.
|
||||
* Gets the entity packets per second queued rate of the client over its lifetime.
|
||||
* @function Entities.getLifetimePPSQueued
|
||||
* @returns {number} Entity packets per second queued rate of the client over its lifetime.
|
||||
*/
|
||||
|
@ -103,7 +103,7 @@ public slots:
|
|||
float getLifetimePPSQueued() const { return _packetSender->getLifetimePPSQueued(); }
|
||||
|
||||
/**jsdoc
|
||||
* Get the entity bytes per second queued rate of the client over its lifetime.
|
||||
* Gets the entity bytes per second queued rate of the client over its lifetime.
|
||||
* @function Entities.getLifetimeBPSQueued
|
||||
* @returns {number} Entity bytes per second queued rate of the client over its lifetime.
|
||||
*/
|
||||
|
@ -111,7 +111,7 @@ public slots:
|
|||
float getLifetimeBPSQueued() const { return _packetSender->getLifetimeBPSQueued(); }
|
||||
|
||||
/**jsdoc
|
||||
* Get the lifetime of the client from the first entity packet sent until now, in microseconds.
|
||||
* Gets the lifetime of the client from the first entity packet sent until now, in microseconds.
|
||||
* @function Entities.getLifetimeInUsecs
|
||||
* @returns {number} Lifetime of the client from the first entity packet sent until now, in microseconds.
|
||||
*/
|
||||
|
@ -119,7 +119,7 @@ public slots:
|
|||
long long unsigned int getLifetimeInUsecs() const { return _packetSender->getLifetimeInUsecs(); }
|
||||
|
||||
/**jsdoc
|
||||
* Get the lifetime of the client from the first entity packet sent until now, in seconds.
|
||||
* Gets the lifetime of the client from the first entity packet sent until now, in seconds.
|
||||
* @function Entities.getLifetimeInSeconds
|
||||
* @returns {number} Lifetime of the client from the first entity packet sent until now, in seconds.
|
||||
*/
|
||||
|
@ -127,7 +127,7 @@ public slots:
|
|||
float getLifetimeInSeconds() const { return _packetSender->getLifetimeInSeconds(); }
|
||||
|
||||
/**jsdoc
|
||||
* Get the total number of entity packets sent by the client over its lifetime.
|
||||
* Gets the total number of entity packets sent by the client over its lifetime.
|
||||
* @function Entities.getLifetimePacketsSent
|
||||
* @returns {number} The total number of entity packets sent by the client over its lifetime.
|
||||
*/
|
||||
|
@ -135,7 +135,7 @@ public slots:
|
|||
long long unsigned int getLifetimePacketsSent() const { return _packetSender->getLifetimePacketsSent(); }
|
||||
|
||||
/**jsdoc
|
||||
* Get the total bytes of entity packets sent by the client over its lifetime.
|
||||
* Gets the total bytes of entity packets sent by the client over its lifetime.
|
||||
* @function Entities.getLifetimeBytesSent
|
||||
* @returns {number} The total bytes of entity packets sent by the client over its lifetime.
|
||||
*/
|
||||
|
@ -143,7 +143,7 @@ public slots:
|
|||
long long unsigned int getLifetimeBytesSent() const { return _packetSender->getLifetimeBytesSent(); }
|
||||
|
||||
/**jsdoc
|
||||
* Get the total number of entity packets queued by the client over its lifetime.
|
||||
* Gets the total number of entity packets queued by the client over its lifetime.
|
||||
* @function Entities.getLifetimePacketsQueued
|
||||
* @returns {number} The total number of entity packets queued by the client over its lifetime.
|
||||
*/
|
||||
|
@ -151,7 +151,7 @@ public slots:
|
|||
long long unsigned int getLifetimePacketsQueued() const { return _packetSender->getLifetimePacketsQueued(); }
|
||||
|
||||
/**jsdoc
|
||||
* Get the total bytes of entity packets queued by the client over its lifetime.
|
||||
* Gets the total bytes of entity packets queued by the client over its lifetime.
|
||||
* @function Entities.getLifetimeBytesQueued
|
||||
* @returns {number} The total bytes of entity packets queued by the client over its lifetime.
|
||||
*/
|
||||
|
|
|
@ -145,7 +145,7 @@ bool ObjectActionOffset::updateArguments(QVariantMap arguments) {
|
|||
/**jsdoc
|
||||
* The <code>"offset"</code> {@link Entities.ActionType|ActionType} moves an entity so that it is a set distance away from a
|
||||
* target point.
|
||||
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
|
||||
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}:
|
||||
*
|
||||
* @typedef {object} Entities.ActionArguments-Offset
|
||||
* @property {Vec3} pointToOffsetFrom=0,0,0 - The target point to offset the entity from.
|
||||
|
|
|
@ -341,15 +341,15 @@ bool ObjectActionTractor::updateArguments(QVariantMap arguments) {
|
|||
/**jsdoc
|
||||
* The <code>"tractor"</code> {@link Entities.ActionType|ActionType} moves and rotates an entity to a target position and
|
||||
* orientation, optionally relative to another entity.
|
||||
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
|
||||
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}:
|
||||
*
|
||||
* @typedef {object} Entities.ActionArguments-Tractor
|
||||
* @property {Uuid} otherID=null - If an entity ID, the <code>targetPosition</code> and <code>targetRotation</code> are
|
||||
* relative to the entity's position and rotation.
|
||||
* @property {Uuid} otherJointIndex=null - If a joint index in the <code>otherID</code> entity, the <code>targetPosition</code>
|
||||
* and <code>targetRotation</code> are relative to the entity joint's position and rotation.
|
||||
* @property {Vec3} targetPosition=0,0,0 - The target position.
|
||||
* @property {Quat} targetRotation=0,0,0,1 - The target rotation.
|
||||
* @property {Uuid} otherID=null - If an entity ID, the <code>targetPosition</code> and <code>targetRotation</code> are
|
||||
* relative to this entity's position and rotation.
|
||||
* @property {Uuid} otherJointIndex=null - If an entity JointIndex, the <code>targetPosition</code> and
|
||||
* <code>targetRotation</code> are relative to this entity's joint's position and rotation.
|
||||
* @property {number} linearTimeScale=3.4e+38 - Controls how long it takes for the entity's position to catch up with the
|
||||
* target position. The value is the time for the action to catch up to 1/e = 0.368 of the target value, where the action
|
||||
* is applied using an exponential decay.
|
||||
|
|
|
@ -152,7 +152,7 @@ bool ObjectActionTravelOriented::updateArguments(QVariantMap arguments) {
|
|||
/**jsdoc
|
||||
* The <code>"travel-oriented"</code> {@link Entities.ActionType|ActionType} orients an entity to align with its direction of
|
||||
* travel.
|
||||
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
|
||||
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}:
|
||||
*
|
||||
* @typedef {object} Entities.ActionArguments-TravelOriented
|
||||
* @property {Vec3} forward=0,0,0 - The axis of the entity to align with the entity's direction of travel.
|
||||
|
|
|
@ -183,11 +183,11 @@ bool ObjectConstraintBallSocket::updateArguments(QVariantMap arguments) {
|
|||
|
||||
/**jsdoc
|
||||
* The <code>"ball-socket"</code> {@link Entities.ActionType|ActionType} connects two entities with a ball and socket joint.
|
||||
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
|
||||
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}:
|
||||
*
|
||||
* @typedef {object} Entities.ActionArguments-BallSocket
|
||||
* @property {Vec3} pivot=0,0,0 - The local offset of the joint relative to the entity's position.
|
||||
* @property {Uuid} otherEntityID=null - The ID of the other entity that is connected to the joint.
|
||||
* @property {Vec3} pivot=0,0,0 - The local offset of the joint relative to the entity's position.
|
||||
* @property {Vec3} otherPivot=0,0,0 - The local offset of the joint relative to the other entity's position.
|
||||
*/
|
||||
QVariantMap ObjectConstraintBallSocket::getArguments() {
|
||||
|
|
|
@ -264,17 +264,18 @@ bool ObjectConstraintConeTwist::updateArguments(QVariantMap arguments) {
|
|||
/**jsdoc
|
||||
* The <code>"cone-twist"</code> {@link Entities.ActionType|ActionType} connects two entities with a joint that can move
|
||||
* through a cone and can twist.
|
||||
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
|
||||
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}:
|
||||
*
|
||||
* @typedef {object} Entities.ActionArguments-ConeTwist
|
||||
* @property {Uuid} otherEntityID=null - The ID of the other entity that is connected to the joint.
|
||||
* @property {Vec3} pivot=0,0,0 - The local offset of the joint relative to the entity's position.
|
||||
* @property {Vec3} axis=1,0,0 - The axis of the entity that moves through the cone. Must be a non-zero vector.
|
||||
* @property {Uuid} otherEntityID=null - The ID of the other entity that is connected to the joint.
|
||||
* @property {Vec3} otherPivot=0,0,0 - The local offset of the joint relative to the other entity's position.
|
||||
* @property {Vec3} otherAxis=1,0,0 - The axis of the other entity that moves through the cone. Must be a non-zero vector.
|
||||
* @property {number} swingSpan1=6.238 - The angle through which the joint can move in one axis of the cone, in radians.
|
||||
* @property {number} swingSpan2=6.238 - The angle through which the joint can move in the other axis of the cone, in radians.
|
||||
* @property {number} twistSpan=6.238 - The angle through with the joint can twist, in radians.
|
||||
* @property {number} swingSpan1=2*Math.PI - The angle through which the joint can move in one axis of the cone, in radians.
|
||||
* @property {number} swingSpan2=2*Math.PI - The angle through which the joint can move in the other axis of the cone, in
|
||||
* radians.
|
||||
* @property {number} twistSpan=2*Math.PI - The angle through with the joint can twist, in radians.
|
||||
*/
|
||||
QVariantMap ObjectConstraintConeTwist::getArguments() {
|
||||
QVariantMap arguments = ObjectDynamic::getArguments();
|
||||
|
|
|
@ -248,18 +248,19 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) {
|
|||
/**jsdoc
|
||||
* The <code>"hinge"</code> {@link Entities.ActionType|ActionType} lets an entity pivot about an axis or connects two entities
|
||||
* with a hinge joint.
|
||||
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
|
||||
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}:
|
||||
*
|
||||
* @typedef {object} Entities.ActionArguments-Hinge
|
||||
* @property {Uuid} otherEntityID=null - The ID of the other entity that is connected to the joint, if any. If none is
|
||||
* specified then the first entity simply pivots about its specified <code>axis</code>.
|
||||
* @property {Vec3} pivot=0,0,0 - The local offset of the joint relative to the entity's position.
|
||||
* @property {Vec3} axis=1,0,0 - The axis of the entity that it pivots about. Must be a non-zero vector.
|
||||
* @property {Uuid} otherEntityID=null - The ID of the other entity that is connected to the joint, if any. If none is
|
||||
* specified then the first entity simply pivots about its specified <code>axis</code>.
|
||||
* @property {Vec3} otherPivot=0,0,0 - The local offset of the joint relative to the other entity's position.
|
||||
* @property {Vec3} otherAxis=1,0,0 - The axis of the other entity that it pivots about. Must be a non-zero vector.
|
||||
* @property {number} low=-6.283 - The most negative angle that the hinge can take, in radians.
|
||||
* @property {number} high=6.283 - The most positive angle that the hinge can take, in radians.
|
||||
* @property {number} angle=0 - The current angle of the hinge. <em>Read-only.</em>
|
||||
* @property {number} low=-2*Math.PI - The most negative angle that the hinge can take, in radians.
|
||||
* @property {number} high=2*Math.PI - The most positive angle that the hinge can take, in radians.
|
||||
* @property {number} angle=0 - The current angle of the hinge, in radians, range <code>-Math.PI</code> –
|
||||
* <code>Math.PI</code>. <em>Read-only.</em>
|
||||
*/
|
||||
QVariantMap ObjectConstraintHinge::getArguments() {
|
||||
QVariantMap arguments = ObjectDynamic::getArguments();
|
||||
|
|
|
@ -264,27 +264,27 @@ bool ObjectConstraintSlider::updateArguments(QVariantMap arguments) {
|
|||
/**jsdoc
|
||||
* The <code>"slider"</code> {@link Entities.ActionType|ActionType} lets an entity slide and rotate along an axis, or connects
|
||||
* two entities that slide and rotate along a shared axis.
|
||||
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
|
||||
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}:
|
||||
*
|
||||
* @typedef {object} Entities.ActionArguments-Slider
|
||||
* @property {Uuid} otherEntityID=null - The ID of the other entity that is connected to the joint, if any. If none is
|
||||
* specified then the first entity simply slides and rotates about its specified <code>axis</code>.
|
||||
* @property {Vec3} point=0,0,0 - The local position of a point in the entity that slides along the axis.
|
||||
* @property {Vec3} axis=1,0,0 - The axis of the entity that slides along the joint. Must be a non-zero vector.
|
||||
* @property {Uuid} otherEntityID=null - The ID of the other entity that is connected to the joint, if any. If non is
|
||||
* specified then the first entity simply slides and rotates about its specified <code>axis</code>.
|
||||
* @property {Vec3} otherPoint=0,0,0 - The local position of a point in the other entity that slides along the axis.
|
||||
* @property {Vec3} axis=1,0,0 - The axis of the other entity that slides along the joint. Must be a non-zero vector.
|
||||
* @property {Vec3} otherAxis=1,0,0 - The axis of the other entity that slides along the joint. Must be a non-zero vector.
|
||||
* @property {number} linearLow=1.17e-38 - The most negative linear offset from the entity's initial point that the entity can
|
||||
* have along the slider.
|
||||
* @property {number} linearHigh=3.40e+38 - The most positive linear offset from the entity's initial point that the entity can
|
||||
* have along the slider.
|
||||
* @property {number} angularLow=-6.283 - The most negative angle that the entity can rotate about the axis if the action
|
||||
* @property {number} angularLow=-2*Math.PI - The most negative angle that the entity can rotate about the axis if the action
|
||||
* involves only one entity, otherwise the most negative angle the rotation can be between the two entities. In radians.
|
||||
* @property {number} angularHigh=6.283 - The most positive angle that the entity can rotate about the axis if the action
|
||||
* @property {number} angularHigh=Math.PI - The most positive angle that the entity can rotate about the axis if the action
|
||||
* involves only one entity, otherwise the most positive angle the rotation can be between the two entities. In radians.
|
||||
* @property {number} linearPosition=0 - The current linear offset the entity is from its initial point if the action involves
|
||||
* only one entity, otherwise the linear offset between the two entities' action points. <em>Read-only.</em>
|
||||
* @property {number} angularPosition=0 - The current angular offset of the entity from its initial rotation if the action
|
||||
* involves only one entity, otherwise the angular offset between the two entities. <em>Read-only.</em>
|
||||
* involves only one entity, otherwise the angular offset between the two entities. In radians. <em>Read-only.</em>
|
||||
*/
|
||||
QVariantMap ObjectConstraintSlider::getArguments() {
|
||||
QVariantMap arguments = ObjectDynamic::getArguments();
|
||||
|
|
|
@ -94,36 +94,36 @@ bool ObjectDynamic::updateArguments(QVariantMap arguments) {
|
|||
}
|
||||
|
||||
/**jsdoc
|
||||
* Different entity action types have different arguments: some common to all actions (listed below) and some specific to each
|
||||
* {@link Entities.ActionType|ActionType} (linked to below). The arguments are accessed as an object of property names and
|
||||
* values.
|
||||
*
|
||||
* @typedef {object} Entities.ActionArguments
|
||||
* @property {Entities.ActionType} type - The type of action.
|
||||
* @property {string} tag="" - A string that a script can use for its own purposes.
|
||||
* @property {number} ttl=0 - How long the action should exist, in seconds, before it is automatically deleted. A value of
|
||||
* <code>0</code> means that the action should not be deleted.
|
||||
* @property {boolean} isMine=true - Is <code>true</code> if you created the action during your current Interface session,
|
||||
* <code>false</code> otherwise. <em>Read-only.</em>
|
||||
* @property {boolean} ::no-motion-state - Is present when the entity hasn't been registered with the physics engine yet (e.g.,
|
||||
* if the action hasn't been properly configured), otherwise <code>undefined</code>. <em>Read-only.</em>
|
||||
* @property {boolean} ::active - Is <code>true</code> when the action is modifying the entity's motion, <code>false</code>
|
||||
* otherwise. Is present once the entity has been registered with the physics engine, otherwise <code>undefined</code>.
|
||||
* <em>Read-only.</em>
|
||||
* @property {Entities.PhysicsMotionType} ::motion-type - How the entity moves with the action. Is present once the entity has
|
||||
* been registered with the physics engine, otherwise <code>undefined</code>. <em>Read-only.</em>
|
||||
*
|
||||
* @see The different action types have additional arguments as follows:
|
||||
* @see {@link Entities.ActionArguments-FarGrab|ActionArguments-FarGrab}
|
||||
* @see {@link Entities.ActionArguments-Hold|ActionArguments-Hold}
|
||||
* @see {@link Entities.ActionArguments-Offset|ActionArguments-Offset}
|
||||
* @see {@link Entities.ActionArguments-Tractor|ActionArguments-Tractor}
|
||||
* @see {@link Entities.ActionArguments-TravelOriented|ActionArguments-TravelOriented}
|
||||
* @see {@link Entities.ActionArguments-Hinge|ActionArguments-Hinge}
|
||||
* @see {@link Entities.ActionArguments-Slider|ActionArguments-Slider}
|
||||
* @see {@link Entities.ActionArguments-ConeTwist|ActionArguments-ConeTwist}
|
||||
* @see {@link Entities.ActionArguments-BallSocket|ActionArguments-BallSocket}
|
||||
*/
|
||||
* Different entity action types have different arguments: some common to all actions (listed in the table) and some specific
|
||||
* to each {@link Entities.ActionType|ActionType} (linked to below). The arguments are accessed as an object of property names
|
||||
* and values.
|
||||
*
|
||||
* @typedef {object} Entities.ActionArguments
|
||||
* @property {Entities.ActionType} type - The type of action.
|
||||
* @property {string} tag="" - A string that a script can use for its own purposes.
|
||||
* @property {number} ttl=0 - How long the action should exist, in seconds, before it is automatically deleted. A value of
|
||||
* <code>0</code> means that the action should not be deleted.
|
||||
* @property {boolean} isMine=true - Is <code>true</code> if the action was created during the current client session,
|
||||
* <code>false</code> otherwise. <em>Read-only.</em>
|
||||
* @property {boolean} ::no-motion-state - Is present when the entity hasn't been registered with the physics engine yet (e.g.,
|
||||
* if the action hasn't been properly configured), otherwise <code>undefined</code>. <em>Read-only.</em>
|
||||
* @property {boolean} ::active - Is <code>true</code> when the action is modifying the entity's motion, <code>false</code>
|
||||
* otherwise. Is present once the entity has been registered with the physics engine, otherwise <code>undefined</code>.
|
||||
* <em>Read-only.</em>
|
||||
* @property {Entities.PhysicsMotionType} ::motion-type - How the entity moves with the action. Is present once the entity has
|
||||
* been registered with the physics engine, otherwise <code>undefined</code>. <em>Read-only.</em>
|
||||
*
|
||||
* @comment The different action types have additional arguments as follows:
|
||||
* @see {@link Entities.ActionArguments-FarGrab|ActionArguments-FarGrab}
|
||||
* @see {@link Entities.ActionArguments-Hold|ActionArguments-Hold}
|
||||
* @see {@link Entities.ActionArguments-Offset|ActionArguments-Offset}
|
||||
* @see {@link Entities.ActionArguments-Tractor|ActionArguments-Tractor}
|
||||
* @see {@link Entities.ActionArguments-TravelOriented|ActionArguments-TravelOriented}
|
||||
* @see {@link Entities.ActionArguments-Hinge|ActionArguments-Hinge}
|
||||
* @see {@link Entities.ActionArguments-Slider|ActionArguments-Slider}
|
||||
* @see {@link Entities.ActionArguments-ConeTwist|ActionArguments-ConeTwist}
|
||||
* @see {@link Entities.ActionArguments-BallSocket|ActionArguments-BallSocket}
|
||||
*/
|
||||
// Note: The "type" property is set in EntityItem::getActionArguments().
|
||||
QVariantMap ObjectDynamic::getArguments() {
|
||||
QVariantMap arguments;
|
||||
|
|
|
@ -5,3 +5,11 @@ link_hifi_libraries(shared)
|
|||
|
||||
GroupSources("src")
|
||||
target_json()
|
||||
|
||||
if (APPLE)
|
||||
# link in required OS X frameworks and include the right GL headers
|
||||
find_library(OpenGL OpenGL)
|
||||
find_library(AppKit AppKit)
|
||||
|
||||
target_link_libraries(${TARGET_NAME} ${OpenGL} ${AppKit})
|
||||
endif ()
|
||||
|
|
|
@ -147,14 +147,6 @@ public:
|
|||
virtual void submitFrame(const gpu::FramePointer& newFrame) = 0;
|
||||
virtual void captureFrame(const std::string& outputName) const { }
|
||||
|
||||
virtual float getRenderResolutionScale() const {
|
||||
return _renderResolutionScale;
|
||||
}
|
||||
|
||||
void setRenderResolutionScale(float renderResolutionScale) {
|
||||
_renderResolutionScale = renderResolutionScale;
|
||||
}
|
||||
|
||||
// The size of the rendering target (may be larger than the device size due to distortion)
|
||||
virtual glm::uvec2 getRecommendedRenderSize() const = 0;
|
||||
|
||||
|
@ -235,8 +227,6 @@ protected:
|
|||
|
||||
MovingAverage<float, 10> _movingAveragePresent;
|
||||
|
||||
float _renderResolutionScale { 1.0f };
|
||||
|
||||
private:
|
||||
QMutex _presentMutex;
|
||||
QWaitCondition _presentCondition;
|
||||
|
|
|
@ -72,10 +72,10 @@ bool NetworkMaterialResource::parseJSONColor(const QJsonValue& array, glm::vec3&
|
|||
}
|
||||
|
||||
/**jsdoc
|
||||
* A material or set of materials such as may be used by a {@link Entities.EntityType|Material} entity.
|
||||
* @typedef {object} MaterialResource
|
||||
* A material or set of materials used by a {@link Entities.EntityType|Material entity}.
|
||||
* @typedef {object} Entities.MaterialResource
|
||||
* @property {number} materialVersion=1 - The version of the material. <em>Currently not used.</em>
|
||||
* @property {Material|Material[]} materials - The details of the material or materials.
|
||||
* @property {Entities.Material|Entities.Material[]} materials - The details of the material or materials.
|
||||
*/
|
||||
NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMaterials(const QJsonDocument& materialJSON, const QUrl& baseUrl) {
|
||||
ParsedMaterials toReturn;
|
||||
|
@ -111,61 +111,73 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater
|
|||
}
|
||||
|
||||
/**jsdoc
|
||||
* A material such as may be used by a {@link Entities.EntityType|Material} entity.
|
||||
* @typedef {object} Material
|
||||
* A material used in a {@link Entities.MaterialResource|MaterialResource}.
|
||||
* @typedef {object} Entities.Material
|
||||
* @property {string} model="hifi_pbr" - Different material models support different properties and rendering modes.
|
||||
* Supported models are: "hifi_pbr", "hifi_shader_simple"
|
||||
* Supported models are: <code>"hifi_pbr"</code>, <code>"hifi_shader_simple"</code>.
|
||||
* @property {string} name="" - A name for the material. Supported by all material models.
|
||||
* @property {Color|RGBS|string} emissive - The emissive color, i.e., the color that the material emits. A {@link Color} value
|
||||
* is treated as sRGB. A {@link RGBS} value can be either RGB or sRGB. Set to <code>"fallthrough"</code> to fallthrough to
|
||||
* the material below. "hifi_pbr" model only.
|
||||
* @property {number|string} opacity=1.0 - The opacity, <code>0.0</code> – <code>1.0</code>. Set to <code>"fallthrough"</code> to fallthrough to
|
||||
* the material below. Supported by all material models.
|
||||
* @property {boolean|string} unlit=false - If <code>true</code>, the material is not lit. Set to <code>"fallthrough"</code> to fallthrough to
|
||||
* the material below. "hifi_pbr" model only.
|
||||
* @property {Color|RGBS|string} albedo - The albedo color. A {@link Color} value is treated as sRGB. A {@link RGBS} value can
|
||||
* be either RGB or sRGB. Set to <code>"fallthrough"</code> to fallthrough to the material below. Set to <code>"fallthrough"</code> to fallthrough to
|
||||
* the material below. Supported by all material models.
|
||||
* @property {number|string} roughness - The roughness, <code>0.0</code> – <code>1.0</code>. Set to <code>"fallthrough"</code> to fallthrough to
|
||||
* the material below. "hifi_pbr" model only.
|
||||
* @property {number|string} metallic - The metallicness, <code>0.0</code> – <code>1.0</code>. Set to <code>"fallthrough"</code> to fallthrough to
|
||||
* the material below. "hifi_pbr" model only.
|
||||
* @property {number|string} scattering - The scattering, <code>0.0</code> – <code>1.0</code>. Set to <code>"fallthrough"</code> to fallthrough to
|
||||
* the material below. "hifi_pbr" model only.
|
||||
* @property {string} emissiveMap - URL of emissive texture image. Set to <code>"fallthrough"</code> to fallthrough to
|
||||
* the material below. "hifi_pbr" model only.
|
||||
* @property {string} albedoMap - URL of albedo texture image. Set to <code>"fallthrough"</code> to fallthrough to
|
||||
* the material below. "hifi_pbr" model only.
|
||||
* @property {string} opacityMap - URL of opacity texture image. Set value the same as the <code>albedoMap</code> value for
|
||||
* transparency. "hifi_pbr" model only.
|
||||
* @property {string} roughnessMap - URL of roughness texture image. Can use this or <code>glossMap</code>, but not both. Set to <code>"fallthrough"</code>
|
||||
* to fallthrough to the material below. "hifi_pbr" model only.
|
||||
* @property {string} glossMap - URL of gloss texture image. Can use this or <code>roughnessMap</code>, but not both. Set to <code>"fallthrough"</code>
|
||||
* to fallthrough to the material below. "hifi_pbr" model only.
|
||||
* @property {string} metallicMap - URL of metallic texture image. Can use this or <code>specularMap</code>, but not both. Set to <code>"fallthrough"</code>
|
||||
* to fallthrough to the material below. "hifi_pbr" model only.
|
||||
* @property {string} specularMap - URL of specular texture image. Can use this or <code>metallicMap</code>, but not both. Set to <code>"fallthrough"</code>
|
||||
* to fallthrough to the material below. "hifi_pbr" model only.
|
||||
* @property {string} normalMap - URL of normal texture image. Can use this or <code>bumpMap</code>, but not both. Set to <code>"fallthrough"</code>
|
||||
* to fallthrough to the material below. "hifi_pbr" model only.
|
||||
* @property {string} bumpMap - URL of bump texture image. Can use this or <code>normalMap</code>, but not both. Set to <code>"fallthrough"</code>
|
||||
* to fallthrough to the material below. "hifi_pbr" model only.
|
||||
* @property {string} occlusionMap - URL of occlusion texture image. Set to <code>"fallthrough"</code> to fallthrough to the material below. "hifi_pbr" model only.
|
||||
* @property {string} scatteringMap - URL of scattering texture image. Only used if <code>normalMap</code> or
|
||||
* <code>bumpMap</code> is specified. Set to <code>"fallthrough"</code> to fallthrough to the material below. "hifi_pbr" model only.
|
||||
* @property {string} lightMap - URL of light map texture image. <em>Currently not used.</em>. Set to <code>"fallthrough"</code>
|
||||
* to fallthrough to the material below. "hifi_pbr" model only.
|
||||
* @property {string} texCoordTransform0 - The transform to use for all of the maps besides occlusionMap and lightMap. Currently unused. Set to
|
||||
* <code>"fallthrough"</code> to fallthrough to the material below. "hifi_pbr" model only.
|
||||
* @property {string} texCoordTransform1 - The transform to use for occlusionMap and lightMap. Currently unused. Set to <code>"fallthrough"</code>
|
||||
* to fallthrough to the material below. "hifi_pbr" model only.
|
||||
* @property {string} lightmapParams - Parameters for controlling how lightMap is used. Currently unused. Set to <code>"fallthrough"</code>
|
||||
* to fallthrough to the material below. "hifi_pbr" model only.
|
||||
* @property {string} materialParams - Parameters for controlling the material projection and repition. Currently unused. Set to <code>"fallthrough"</code>
|
||||
* to fallthrough to the material below. "hifi_pbr" model only.
|
||||
* @property {bool} defaultFallthrough=false - If <code>true</code>, all properties will fallthrough to the material below unless they are set. If
|
||||
* <code>false</code>, they will respect the individual properties' fallthrough state. "hifi_pbr" model only.
|
||||
* @property {ProceduralData} procedural - The definition of a procedural shader material. "hifi_shader_simple" model only.
|
||||
* @property {ColorFloat|RGBS|string} emissive - The emissive color, i.e., the color that the material emits. A
|
||||
* {@link ColorFloat} value is treated as sRGB and must have component values in the range <code>0.0</code> —
|
||||
* <code>1.0</code>. A {@link RGBS} value can be either RGB or sRGB.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {number|string} opacity=1.0 - The opacity, range <code>0.0</code> – <code>1.0</code>.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {boolean|string} unlit=false - If <code>true</code>, the material is not lit, otherwise it is.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. Supported by all material models.
|
||||
* @property {ColorFloat|RGBS|string} albedo - The albedo color. A {@link ColorFloat} value is treated as sRGB and must have
|
||||
* component values in the range <code>0.0</code> — <code>1.0</code>. A {@link RGBS} value can be either RGB or sRGB.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. Supported by all material models.
|
||||
* @property {number|string} roughness - The roughness, range <code>0.0</code> – <code>1.0</code>.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {number|string} metallic - The metallicness, range <code>0.0</code> – <code>1.0</code>.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {number|string} scattering - The scattering, range <code>0.0</code> – <code>1.0</code>.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} emissiveMap - The URL of the emissive texture image.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} albedoMap - The URL of the albedo texture image.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} opacityMap - The URL of the opacity texture image. Set the value the same as the <code>albedoMap</code>
|
||||
* value for transparency.
|
||||
* <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} roughnessMap - The URL of the roughness texture image. You can use this or <code>glossMap</code>, but not
|
||||
* both.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} glossMap - The URL of the gloss texture image. You can use this or <code>roughnessMap</code>, but not
|
||||
* both.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} metallicMap - The URL of the metallic texture image. You can use this or <code>specularMap</code>, but
|
||||
* not both.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} specularMap - The URL of the specular texture image. You can use this or <code>metallicMap</code>, but
|
||||
* not both.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} normalMap - The URL of the normal texture image. You can use this or <code>bumpMap</code>, but not both.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} bumpMap - The URL of the bump texture image. You can use this or <code>normalMap</code>, but not both.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} occlusionMap - The URL of the occlusion texture image.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} scatteringMap - The URL of the scattering texture image. Only used if <code>normalMap</code> or
|
||||
* <code>bumpMap</code> is specified.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} lightMap - The URL of the light map texture image.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {Mat4|string} texCoordTransform0 - The transform to use for all of the maps apart from <code>occlusionMap</code>
|
||||
* and <code>lightMap</code>.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {Mat4|string} texCoordTransform1 - The transform to use for <code>occlusionMap</code> and <code>lightMap</code>.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} lightmapParams - Parameters for controlling how lightMap is used.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* <p><em>Currently not used.</em></p>
|
||||
* @property {string} materialParams - Parameters for controlling the material projection and repetition.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* <p><em>Currently not used.</em></p>
|
||||
* @property {boolean} defaultFallthrough=false - If <code>true</code>, all properties fall through to the material below
|
||||
* unless they are set. If <code>false</code>, they respect their individual fall-through setting. <code>"hifi_pbr"</code>
|
||||
* model only.
|
||||
* @property {ProceduralData} procedural - The definition of a procedural shader material. <code>"hifi_shader_simple"</code> model only.
|
||||
*/
|
||||
// Note: See MaterialEntityItem.h for default values used in practice.
|
||||
std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource::parseJSONMaterial(const QJsonObject& materialJSON, const QUrl& baseUrl) {
|
||||
|
@ -396,7 +408,7 @@ std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource
|
|||
material->setPropertyDoesFallthrough(graphics::Material::ExtraFlagBit::LIGHTMAP_PARAMS);
|
||||
}
|
||||
}
|
||||
// TODO: implement lightmapParams
|
||||
// TODO: implement lightmapParams and update JSDoc
|
||||
} else if (key == "materialParams") {
|
||||
auto value = materialJSON.value(key);
|
||||
if (value.isString()) {
|
||||
|
@ -405,7 +417,7 @@ std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource
|
|||
material->setPropertyDoesFallthrough(graphics::Material::ExtraFlagBit::MATERIAL_PARAMS);
|
||||
}
|
||||
}
|
||||
// TODO: implement materialParams
|
||||
// TODO: implement materialParams and update JSDoc
|
||||
} else if (key == "defaultFallthrough") {
|
||||
auto value = materialJSON.value(key);
|
||||
if (value.isBool()) {
|
||||
|
|
|
@ -273,44 +273,6 @@ graphics::MeshPointer DeferredLightingEffect::getSpotLightMesh() {
|
|||
return _spotLightMesh;
|
||||
}
|
||||
|
||||
gpu::FramebufferPointer PreparePrimaryFramebuffer::createFramebuffer(const char* name, const glm::uvec2& frameSize) {
|
||||
gpu::FramebufferPointer framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(name));
|
||||
auto colorFormat = gpu::Element::COLOR_SRGBA_32;
|
||||
|
||||
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR);
|
||||
auto primaryColorTexture = gpu::Texture::createRenderBuffer(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler);
|
||||
|
||||
framebuffer->setRenderBuffer(0, primaryColorTexture);
|
||||
|
||||
auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format
|
||||
auto primaryDepthTexture = gpu::Texture::createRenderBuffer(depthFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler);
|
||||
|
||||
framebuffer->setDepthStencilBuffer(primaryDepthTexture, depthFormat);
|
||||
|
||||
return framebuffer;
|
||||
}
|
||||
|
||||
void PreparePrimaryFramebuffer::configure(const Config& config) {
|
||||
_resolutionScale = config.resolutionScale;
|
||||
}
|
||||
|
||||
void PreparePrimaryFramebuffer::run(const RenderContextPointer& renderContext, Output& primaryFramebuffer) {
|
||||
glm::uvec2 frameSize(renderContext->args->_viewport.z, renderContext->args->_viewport.w);
|
||||
glm::uvec2 scaledFrameSize(glm::vec2(frameSize) * _resolutionScale);
|
||||
|
||||
// Resizing framebuffers instead of re-building them seems to cause issues with threaded
|
||||
// rendering
|
||||
if (!_primaryFramebuffer || _primaryFramebuffer->getSize() != scaledFrameSize) {
|
||||
_primaryFramebuffer = createFramebuffer("deferredPrimary", scaledFrameSize);
|
||||
}
|
||||
|
||||
primaryFramebuffer = _primaryFramebuffer;
|
||||
|
||||
// Set viewport for the rest of the scaled passes
|
||||
renderContext->args->_viewport.z = scaledFrameSize.x;
|
||||
renderContext->args->_viewport.w = scaledFrameSize.y;
|
||||
}
|
||||
|
||||
void PrepareDeferred::run(const RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) {
|
||||
auto args = renderContext->args;
|
||||
|
||||
|
|
|
@ -74,36 +74,6 @@ private:
|
|||
friend class RenderDeferredCleanup;
|
||||
};
|
||||
|
||||
class PreparePrimaryFramebufferConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(float resolutionScale MEMBER resolutionScale NOTIFY dirty)
|
||||
public:
|
||||
|
||||
float resolutionScale{ 1.0f };
|
||||
|
||||
signals:
|
||||
void dirty();
|
||||
};
|
||||
|
||||
class PreparePrimaryFramebuffer {
|
||||
public:
|
||||
|
||||
using Output = gpu::FramebufferPointer;
|
||||
using Config = PreparePrimaryFramebufferConfig;
|
||||
using JobModel = render::Job::ModelO<PreparePrimaryFramebuffer, Output, Config>;
|
||||
|
||||
PreparePrimaryFramebuffer(float resolutionScale = 1.0f) : _resolutionScale{resolutionScale} {}
|
||||
void configure(const Config& config);
|
||||
void run(const render::RenderContextPointer& renderContext, Output& primaryFramebuffer);
|
||||
|
||||
gpu::FramebufferPointer _primaryFramebuffer;
|
||||
float _resolutionScale{ 1.0f };
|
||||
|
||||
private:
|
||||
|
||||
static gpu::FramebufferPointer createFramebuffer(const char* name, const glm::uvec2& size);
|
||||
};
|
||||
|
||||
class PrepareDeferred {
|
||||
public:
|
||||
// Inputs: primaryFramebuffer and lightingModel
|
||||
|
|
|
@ -1692,10 +1692,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
using packBlendshapeOffsetTo = void(glm::uvec4& packed, const BlendshapeOffsetUnpacked& unpacked);
|
||||
|
||||
void packBlendshapeOffsetTo_Pos_F32_3xSN10_Nor_3xSN10_Tan_3xSN10(glm::uvec4& packed, const BlendshapeOffsetUnpacked& unpacked) {
|
||||
static void packBlendshapeOffsetTo_Pos_F32_3xSN10_Nor_3xSN10_Tan_3xSN10(glm::uvec4& packed, const BlendshapeOffsetUnpacked& unpacked) {
|
||||
float len = glm::compMax(glm::abs(unpacked.positionOffset));
|
||||
glm::vec3 normalizedPos(unpacked.positionOffset);
|
||||
if (len > 0.0f) {
|
||||
|
@ -1712,6 +1709,37 @@ void packBlendshapeOffsetTo_Pos_F32_3xSN10_Nor_3xSN10_Tan_3xSN10(glm::uvec4& pac
|
|||
);
|
||||
}
|
||||
|
||||
static void packBlendshapeOffsets_ref(BlendshapeOffsetUnpacked* unpacked, BlendshapeOffsetPacked* packed, int size) {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
packBlendshapeOffsetTo_Pos_F32_3xSN10_Nor_3xSN10_Tan_3xSN10((*packed).packedPosNorTan, (*unpacked));
|
||||
++unpacked;
|
||||
++packed;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__x86_64__)
|
||||
//
|
||||
// Runtime CPU dispatch
|
||||
//
|
||||
#include <CPUDetect.h>
|
||||
|
||||
void packBlendshapeOffsets_AVX2(float (*unpacked)[9], uint32_t (*packed)[4], int size);
|
||||
|
||||
static void packBlendshapeOffsets(BlendshapeOffsetUnpacked* unpacked, BlendshapeOffsetPacked* packed, int size) {
|
||||
static bool _cpuSupportsAVX2 = cpuSupportsAVX2();
|
||||
if (_cpuSupportsAVX2) {
|
||||
static_assert(sizeof(BlendshapeOffsetUnpacked) == 9 * sizeof(float), "struct BlendshapeOffsetUnpacked size doesn't match.");
|
||||
static_assert(sizeof(BlendshapeOffsetPacked) == 4 * sizeof(uint32_t), "struct BlendshapeOffsetPacked size doesn't match.");
|
||||
packBlendshapeOffsets_AVX2((float(*)[9])unpacked, (uint32_t(*)[4])packed, size);
|
||||
} else {
|
||||
packBlendshapeOffsets_ref(unpacked, packed, size);
|
||||
}
|
||||
}
|
||||
|
||||
#else // portable reference code
|
||||
static auto& packBlendshapeOffsets = packBlendshapeOffsets_ref;
|
||||
#endif
|
||||
|
||||
class Blender : public QRunnable {
|
||||
public:
|
||||
|
||||
|
@ -1736,21 +1764,28 @@ Blender::Blender(ModelPointer model, HFMModel::ConstPointer hfmModel, int blendN
|
|||
void Blender::run() {
|
||||
DETAILED_PROFILE_RANGE_EX(simulation_animation, __FUNCTION__, 0xFFFF0000, 0, { { "url", _model->getURL().toString() } });
|
||||
int numBlendshapeOffsets = 0; // number of offsets required for all meshes.
|
||||
int maxBlendshapeOffsets = 0; // number of offsets in the largest mesh.
|
||||
int numMeshes = 0; // number of meshes in this model.
|
||||
for (auto meshIter = _hfmModel->meshes.cbegin(); meshIter != _hfmModel->meshes.cend(); ++meshIter) {
|
||||
numMeshes++;
|
||||
if (meshIter->blendshapes.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
int numVertsInMesh = meshIter->vertices.size();
|
||||
numBlendshapeOffsets += numVertsInMesh;
|
||||
maxBlendshapeOffsets = std::max(maxBlendshapeOffsets, numVertsInMesh);
|
||||
}
|
||||
|
||||
// all elements are default constructed to zero offsets.
|
||||
QVector<BlendshapeOffset> packedBlendshapeOffsets(numBlendshapeOffsets);
|
||||
QVector<BlendshapeOffsetUnpacked> unpackedBlendshapeOffsets(numBlendshapeOffsets);
|
||||
|
||||
// allocate the required size
|
||||
// allocate the required sizes
|
||||
QVector<int> blendedMeshSizes;
|
||||
blendedMeshSizes.reserve(numMeshes);
|
||||
|
||||
QVector<BlendshapeOffset> packedBlendshapeOffsets;
|
||||
packedBlendshapeOffsets.resize(numBlendshapeOffsets);
|
||||
|
||||
QVector<BlendshapeOffsetUnpacked> unpackedBlendshapeOffsets;
|
||||
unpackedBlendshapeOffsets.resize(maxBlendshapeOffsets); // reuse for all meshes
|
||||
|
||||
int offset = 0;
|
||||
for (auto meshIter = _hfmModel->meshes.cbegin(); meshIter != _hfmModel->meshes.cend(); ++meshIter) {
|
||||
if (meshIter->blendshapes.isEmpty()) {
|
||||
|
@ -1760,6 +1795,9 @@ void Blender::run() {
|
|||
int numVertsInMesh = meshIter->vertices.size();
|
||||
blendedMeshSizes.push_back(numVertsInMesh);
|
||||
|
||||
// initialize offsets to zero
|
||||
memset(unpackedBlendshapeOffsets.data(), 0, numVertsInMesh * sizeof(BlendshapeOffsetUnpacked));
|
||||
|
||||
// for each blendshape in this mesh, accumulate the offsets into unpackedBlendshapeOffsets.
|
||||
const float NORMAL_COEFFICIENT_SCALE = 0.01f;
|
||||
for (int i = 0, n = qMin(_blendshapeCoefficients.size(), meshIter->blendshapes.size()); i < n; i++) {
|
||||
|
@ -1774,7 +1812,7 @@ void Blender::run() {
|
|||
for (int j = 0; j < blendshape.indices.size(); ++j) {
|
||||
int index = blendshape.indices.at(j);
|
||||
|
||||
auto& currentBlendshapeOffset = unpackedBlendshapeOffsets[offset + index];
|
||||
auto& currentBlendshapeOffset = unpackedBlendshapeOffsets[index];
|
||||
currentBlendshapeOffset.positionOffset += blendshape.vertices.at(j) * vertexCoefficient;
|
||||
currentBlendshapeOffset.normalOffset += blendshape.normals.at(j) * normalCoefficient;
|
||||
if (j < blendshape.tangents.size()) {
|
||||
|
@ -1782,20 +1820,15 @@ void Blender::run() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// convert unpackedBlendshapeOffsets into packedBlendshapeOffsets for the gpu.
|
||||
auto unpacked = unpackedBlendshapeOffsets.data();
|
||||
auto packed = packedBlendshapeOffsets.data() + offset;
|
||||
packBlendshapeOffsets(unpacked, packed, numVertsInMesh);
|
||||
|
||||
offset += numVertsInMesh;
|
||||
}
|
||||
|
||||
// convert unpackedBlendshapeOffsets into packedBlendshapeOffsets for the gpu.
|
||||
// FIXME it feels like we could be more effectively using SIMD here
|
||||
{
|
||||
auto unpacked = unpackedBlendshapeOffsets.data();
|
||||
auto packed = packedBlendshapeOffsets.data();
|
||||
for (int i = 0; i < unpackedBlendshapeOffsets.size(); ++i) {
|
||||
packBlendshapeOffsetTo_Pos_F32_3xSN10_Nor_3xSN10_Tan_3xSN10((*packed).packedPosNorTan, (*unpacked));
|
||||
++unpacked;
|
||||
++packed;
|
||||
}
|
||||
}
|
||||
Q_ASSERT(offset == numBlendshapeOffsets);
|
||||
|
||||
// post the result to the ModelBlender, which will dispatch to the model if still alive
|
||||
QMetaObject::invokeMethod(DependencyManager::get<ModelBlender>().data(), "setBlendedVertices",
|
||||
|
|
|
@ -106,34 +106,6 @@ void DrawLayered3D::run(const RenderContextPointer& renderContext, const Inputs&
|
|||
}
|
||||
}
|
||||
|
||||
void CompositeHUD::run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& inputs) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_context);
|
||||
|
||||
// We do not want to render HUD elements in secondary camera
|
||||
if (nsightActive() || renderContext->args->_renderMode == RenderArgs::RenderMode::SECONDARY_CAMERA_RENDER_MODE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Grab the HUD texture
|
||||
#if !defined(DISABLE_QML)
|
||||
gpu::doInBatch("CompositeHUD", renderContext->args->_context, [&](gpu::Batch& batch) {
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
renderContext->args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
renderContext->args->getViewFrustum().evalViewTransform(viewMat);
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat, true);
|
||||
if (inputs) {
|
||||
batch.setFramebuffer(inputs);
|
||||
}
|
||||
if (renderContext->args->_hudOperator) {
|
||||
renderContext->args->_hudOperator(batch, renderContext->args->_hudTexture, renderContext->args->_renderMode == RenderArgs::RenderMode::MIRROR_RENDER_MODE);
|
||||
}
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void Blit::run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& srcFramebuffer) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_context);
|
||||
|
@ -205,6 +177,34 @@ void Blit::run(const RenderContextPointer& renderContext, const gpu::Framebuffer
|
|||
});
|
||||
}
|
||||
|
||||
void NewOrDefaultFramebuffer::run(const render::RenderContextPointer& renderContext, const Input& input, Output& output) {
|
||||
RenderArgs* args = renderContext->args;
|
||||
// auto frameSize = input;
|
||||
glm::uvec2 frameSize(args->_viewport.z, args->_viewport.w);
|
||||
output.reset();
|
||||
|
||||
// First if the default Framebuffer is the correct size then use it
|
||||
auto destBlitFbo = args->_blitFramebuffer;
|
||||
if (destBlitFbo && destBlitFbo->getSize() == frameSize) {
|
||||
output = destBlitFbo;
|
||||
return;
|
||||
}
|
||||
|
||||
// Else use the lodal Framebuffer
|
||||
if (_outputFramebuffer && _outputFramebuffer->getSize() != frameSize) {
|
||||
_outputFramebuffer.reset();
|
||||
}
|
||||
|
||||
if (!_outputFramebuffer) {
|
||||
_outputFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("newFramebuffer.out"));
|
||||
auto colorFormat = gpu::Element::COLOR_SRGBA_32;
|
||||
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR);
|
||||
auto colorTexture = gpu::Texture::createRenderBuffer(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler);
|
||||
_outputFramebuffer->setRenderBuffer(0, colorTexture);
|
||||
}
|
||||
|
||||
output = _outputFramebuffer;
|
||||
}
|
||||
|
||||
void ResolveFramebuffer::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) {
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
@ -235,42 +235,6 @@ void ResolveFramebuffer::run(const render::RenderContextPointer& renderContext,
|
|||
});
|
||||
}
|
||||
|
||||
void ResolveNewFramebuffer::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) {
|
||||
RenderArgs* args = renderContext->args;
|
||||
auto srcFbo = inputs;
|
||||
outputs.reset();
|
||||
|
||||
// Check valid src
|
||||
if (!srcFbo) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check valid size for sr and dest
|
||||
auto frameSize(srcFbo->getSize());
|
||||
|
||||
// Resizing framebuffers instead of re-building them seems to cause issues with threaded rendering
|
||||
if (_outputFramebuffer && _outputFramebuffer->getSize() != frameSize) {
|
||||
_outputFramebuffer.reset();
|
||||
}
|
||||
|
||||
if (!_outputFramebuffer) {
|
||||
_outputFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("resolvedNew.out"));
|
||||
auto colorFormat = gpu::Element::COLOR_SRGBA_32;
|
||||
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR);
|
||||
auto colorTexture = gpu::Texture::createRenderBuffer(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler);
|
||||
_outputFramebuffer->setRenderBuffer(0, colorTexture);
|
||||
}
|
||||
|
||||
gpu::Vec4i rectSrc;
|
||||
rectSrc.z = frameSize.x;
|
||||
rectSrc.w = frameSize.y;
|
||||
gpu::doInBatch("ResolveNew", args->_context, [&](gpu::Batch& batch) { batch.blit(srcFbo, rectSrc, _outputFramebuffer, rectSrc); });
|
||||
|
||||
outputs = _outputFramebuffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ExtractFrustums::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_context);
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#include "LightStage.h"
|
||||
#include "LightingModel.h"
|
||||
|
||||
|
||||
|
||||
class BeginGPURangeTimer {
|
||||
public:
|
||||
using JobModel = render::Job::ModelO<BeginGPURangeTimer, gpu::RangeTimerPointer>;
|
||||
|
@ -75,16 +77,6 @@ protected:
|
|||
bool _opaquePass { true };
|
||||
};
|
||||
|
||||
class CompositeHUD {
|
||||
public:
|
||||
// IF specified the input Framebuffer is actively set by the batch of this job before calling the HUDOperator.
|
||||
// If not, the current Framebuffer is left unchanged.
|
||||
//using Inputs = gpu::FramebufferPointer;
|
||||
using JobModel = render::Job::ModelI<CompositeHUD, gpu::FramebufferPointer>;
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext, const gpu::FramebufferPointer& inputs);
|
||||
};
|
||||
|
||||
class Blit {
|
||||
public:
|
||||
using JobModel = render::Job::ModelI<Blit, gpu::FramebufferPointer>;
|
||||
|
@ -92,6 +84,16 @@ public:
|
|||
void run(const render::RenderContextPointer& renderContext, const gpu::FramebufferPointer& srcFramebuffer);
|
||||
};
|
||||
|
||||
class NewOrDefaultFramebuffer {
|
||||
public:
|
||||
using Input = glm::uvec2;
|
||||
using Output = gpu::FramebufferPointer;
|
||||
using JobModel = render::Job::ModelIO<NewOrDefaultFramebuffer, Input, Output>;
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext, const Input& input, Output& output);
|
||||
private:
|
||||
gpu::FramebufferPointer _outputFramebuffer;
|
||||
};
|
||||
|
||||
class ResolveFramebuffer {
|
||||
public:
|
||||
|
@ -102,18 +104,6 @@ public:
|
|||
void run(const render::RenderContextPointer& renderContext, const Inputs& source, Outputs& dest);
|
||||
};
|
||||
|
||||
class ResolveNewFramebuffer {
|
||||
public:
|
||||
using Inputs = gpu::FramebufferPointer;
|
||||
using Outputs = gpu::FramebufferPointer;
|
||||
using JobModel = render::Job::ModelIO<ResolveNewFramebuffer, Inputs, Outputs>;
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext, const Inputs& source, Outputs& dest);
|
||||
private:
|
||||
gpu::FramebufferPointer _outputFramebuffer;
|
||||
};
|
||||
|
||||
|
||||
class ExtractFrustums {
|
||||
public:
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "FadeEffect.h"
|
||||
#include "BloomStage.h"
|
||||
#include "RenderUtilsLogging.h"
|
||||
#include "RenderHUDLayerTask.h"
|
||||
|
||||
#include "AmbientOcclusionEffect.h"
|
||||
#include "AntialiasingEffect.h"
|
||||
|
@ -96,11 +97,8 @@ RenderDeferredTask::RenderDeferredTask()
|
|||
void RenderDeferredTask::configure(const Config& config) {
|
||||
// Propagate resolution scale to sub jobs who need it
|
||||
auto preparePrimaryBufferConfig = config.getConfig<PreparePrimaryFramebuffer>("PreparePrimaryBuffer");
|
||||
auto upsamplePrimaryBufferConfig = config.getConfig<Upsample>("PrimaryBufferUpscale");
|
||||
assert(preparePrimaryBufferConfig);
|
||||
assert(upsamplePrimaryBufferConfig);
|
||||
preparePrimaryBufferConfig->setProperty("resolutionScale", config.resolutionScale);
|
||||
upsamplePrimaryBufferConfig->setProperty("factor", 1.0f / config.resolutionScale);
|
||||
preparePrimaryBufferConfig->setResolutionScale(config.resolutionScale);
|
||||
}
|
||||
|
||||
void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) {
|
||||
|
@ -232,8 +230,6 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
task.addJob<DrawLayered3D>("DrawInFrontOpaque", inFrontOpaquesInputs, true);
|
||||
task.addJob<DrawLayered3D>("DrawInFrontTransparent", inFrontTransparentsInputs, false);
|
||||
|
||||
const auto toneAndPostRangeTimer = task.addJob<BeginGPURangeTimer>("BeginToneAndPostRangeTimer", "PostToneLayeredAntialiasing");
|
||||
|
||||
// AA job before bloom to limit flickering
|
||||
const auto antialiasingInputs = Antialiasing::Inputs(deferredFrameTransform, lightingFramebuffer, linearDepthTarget, velocityBuffer).asVarying();
|
||||
task.addJob<Antialiasing>("Antialiasing", antialiasingInputs);
|
||||
|
@ -243,8 +239,8 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
task.addJob<BloomEffect>("Bloom", bloomInputs);
|
||||
|
||||
// Lighting Buffer ready for tone mapping
|
||||
const auto toneMappingInputs = ToneMappingDeferred::Inputs(lightingFramebuffer, scaledPrimaryFramebuffer).asVarying();
|
||||
task.addJob<ToneMappingDeferred>("ToneMapping", toneMappingInputs);
|
||||
const auto toneMappingInputs = ToneMappingDeferred::Input(lightingFramebuffer, scaledPrimaryFramebuffer).asVarying();
|
||||
const auto toneMappedBuffer = task.addJob<ToneMappingDeferred>("ToneMapping", toneMappingInputs);
|
||||
|
||||
// Debugging task is happening in the "over" layer after tone mapping and just before HUD
|
||||
{ // Debug the bounds of the rendered items, still look at the zbuffer
|
||||
|
@ -255,21 +251,11 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
}
|
||||
|
||||
// Upscale to finale resolution
|
||||
const auto primaryFramebuffer = task.addJob<render::Upsample>("PrimaryBufferUpscale", scaledPrimaryFramebuffer);
|
||||
const auto primaryFramebuffer = task.addJob<render::UpsampleToBlitFramebuffer>("PrimaryBufferUpscale", toneMappedBuffer);
|
||||
|
||||
// Composite the HUD and HUD overlays
|
||||
task.addJob<CompositeHUD>("HUD", primaryFramebuffer);
|
||||
|
||||
const auto nullJitter = Varying(glm::vec2(0.0f, 0.0f));
|
||||
const auto hudOpaquesInputs = DrawLayered3D::Inputs(hudOpaque, lightingModel, nullJitter).asVarying();
|
||||
const auto hudTransparentsInputs = DrawLayered3D::Inputs(hudTransparent, lightingModel, nullJitter).asVarying();
|
||||
task.addJob<DrawLayered3D>("DrawHUDOpaque", hudOpaquesInputs, true);
|
||||
task.addJob<DrawLayered3D>("DrawHUDTransparent", hudTransparentsInputs, false);
|
||||
|
||||
task.addJob<EndGPURangeTimer>("ToneAndPostRangeTimer", toneAndPostRangeTimer);
|
||||
|
||||
// Blit!
|
||||
task.addJob<Blit>("Blit", primaryFramebuffer);
|
||||
// HUD Layer
|
||||
const auto renderHUDLayerInputs = RenderHUDLayerTask::Input(primaryFramebuffer, lightingModel, hudOpaque, hudTransparent).asVarying();
|
||||
task.addJob<RenderHUDLayerTask>("RenderHUDLayer", renderHUDLayerInputs);
|
||||
}
|
||||
|
||||
RenderDeferredTaskDebug::RenderDeferredTaskDebug() {
|
||||
|
@ -435,6 +421,44 @@ void RenderDeferredTaskDebug::build(JobModel& task, const render::Varying& input
|
|||
|
||||
}
|
||||
|
||||
gpu::FramebufferPointer PreparePrimaryFramebuffer::createFramebuffer(const char* name, const glm::uvec2& frameSize) {
|
||||
gpu::FramebufferPointer framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(name));
|
||||
auto colorFormat = gpu::Element::COLOR_SRGBA_32;
|
||||
|
||||
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR);
|
||||
auto primaryColorTexture = gpu::Texture::createRenderBuffer(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler);
|
||||
|
||||
framebuffer->setRenderBuffer(0, primaryColorTexture);
|
||||
|
||||
auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format
|
||||
auto primaryDepthTexture = gpu::Texture::createRenderBuffer(depthFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler);
|
||||
|
||||
framebuffer->setDepthStencilBuffer(primaryDepthTexture, depthFormat);
|
||||
|
||||
return framebuffer;
|
||||
}
|
||||
|
||||
void PreparePrimaryFramebuffer::configure(const Config& config) {
|
||||
_resolutionScale = config.getResolutionScale();
|
||||
}
|
||||
|
||||
void PreparePrimaryFramebuffer::run(const RenderContextPointer& renderContext, Output& primaryFramebuffer) {
|
||||
glm::uvec2 frameSize(renderContext->args->_viewport.z, renderContext->args->_viewport.w);
|
||||
glm::uvec2 scaledFrameSize(glm::vec2(frameSize) * _resolutionScale);
|
||||
|
||||
// Resizing framebuffers instead of re-building them seems to cause issues with threaded
|
||||
// rendering
|
||||
if (!_primaryFramebuffer || _primaryFramebuffer->getSize() != scaledFrameSize) {
|
||||
_primaryFramebuffer = createFramebuffer("deferredPrimary", scaledFrameSize);
|
||||
}
|
||||
|
||||
primaryFramebuffer = _primaryFramebuffer;
|
||||
|
||||
// Set viewport for the rest of the scaled passes
|
||||
renderContext->args->_viewport.z = scaledFrameSize.x;
|
||||
renderContext->args->_viewport.w = scaledFrameSize.y;
|
||||
}
|
||||
|
||||
|
||||
void RenderTransparentDeferred::run(const RenderContextPointer& renderContext, const Inputs& inputs) {
|
||||
assert(renderContext->args);
|
||||
|
|
|
@ -149,4 +149,42 @@ public:
|
|||
private:
|
||||
};
|
||||
|
||||
|
||||
class PreparePrimaryFramebufferConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(float resolutionScale WRITE setResolutionScale READ getResolutionScale)
|
||||
public:
|
||||
float getResolutionScale() const { return resolutionScale; }
|
||||
void setResolutionScale(float scale) {
|
||||
const float SCALE_RANGE_MIN = 0.1f;
|
||||
const float SCALE_RANGE_MAX = 2.0f;
|
||||
resolutionScale = std::max(SCALE_RANGE_MIN, std::min(SCALE_RANGE_MAX, scale));
|
||||
}
|
||||
|
||||
signals:
|
||||
void dirty();
|
||||
|
||||
protected:
|
||||
float resolutionScale{ 1.0f };
|
||||
};
|
||||
|
||||
class PreparePrimaryFramebuffer {
|
||||
public:
|
||||
|
||||
using Output = gpu::FramebufferPointer;
|
||||
using Config = PreparePrimaryFramebufferConfig;
|
||||
using JobModel = render::Job::ModelO<PreparePrimaryFramebuffer, Output, Config>;
|
||||
|
||||
PreparePrimaryFramebuffer(float resolutionScale = 1.0f) : _resolutionScale{ resolutionScale } {}
|
||||
void configure(const Config& config);
|
||||
void run(const render::RenderContextPointer& renderContext, Output& primaryFramebuffer);
|
||||
|
||||
gpu::FramebufferPointer _primaryFramebuffer;
|
||||
float _resolutionScale{ 1.0f };
|
||||
|
||||
private:
|
||||
|
||||
static gpu::FramebufferPointer createFramebuffer(const char* name, const glm::uvec2& size);
|
||||
};
|
||||
|
||||
#endif // hifi_RenderDeferredTask_h
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <gpu/Texture.h>
|
||||
#include <graphics/ShaderConstants.h>
|
||||
#include <render/ShapePipeline.h>
|
||||
#include <render/ResampleTask.h>
|
||||
|
||||
#include <render/FilterTask.h>
|
||||
|
||||
|
@ -32,6 +33,7 @@
|
|||
#include "FramebufferCache.h"
|
||||
#include "TextureCache.h"
|
||||
#include "RenderCommonTask.h"
|
||||
#include "RenderHUDLayerTask.h"
|
||||
|
||||
namespace ru {
|
||||
using render_utils::slot::texture::Texture;
|
||||
|
@ -47,6 +49,13 @@ using namespace render;
|
|||
|
||||
extern void initForwardPipelines(ShapePlumber& plumber);
|
||||
|
||||
void RenderForwardTask::configure(const Config& config) {
|
||||
// Propagate resolution scale to sub jobs who need it
|
||||
auto preparePrimaryBufferConfig = config.getConfig<PreparePrimaryFramebufferMSAA>("PreparePrimaryBuffer");
|
||||
assert(preparePrimaryBufferConfig);
|
||||
preparePrimaryBufferConfig->setResolutionScale(config.resolutionScale);
|
||||
}
|
||||
|
||||
void RenderForwardTask::build(JobModel& task, const render::Varying& input, render::Varying& output) {
|
||||
task.addJob<SetRenderMethod>("SetRenderMethodTask", render::Args::FORWARD);
|
||||
|
||||
|
@ -87,16 +96,19 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend
|
|||
// First job, alter faded
|
||||
fadeEffect->build(task, opaques);
|
||||
|
||||
// Prepare objects shared by several jobs
|
||||
const auto deferredFrameTransform = task.addJob<GenerateDeferredFrameTransform>("DeferredFrameTransform");
|
||||
|
||||
// GPU jobs: Start preparing the main framebuffer
|
||||
const auto framebuffer = task.addJob<PrepareFramebuffer>("PrepareFramebuffer");
|
||||
const auto scaledPrimaryFramebuffer = task.addJob<PreparePrimaryFramebufferMSAA>("PreparePrimaryBuffer");
|
||||
|
||||
task.addJob<PrepareForward>("PrepareForward", lightFrame);
|
||||
// Prepare deferred, generate the shared Deferred Frame Transform. Only valid with the scaled frame buffer
|
||||
const auto deferredFrameTransform = task.addJob<GenerateDeferredFrameTransform>("DeferredFrameTransform");
|
||||
|
||||
// Prepare Forward Framebuffer pass
|
||||
const auto prepareForwardInputs = PrepareForward::Inputs(scaledPrimaryFramebuffer, lightFrame).asVarying();
|
||||
task.addJob<PrepareForward>("PrepareForward", prepareForwardInputs);
|
||||
|
||||
// draw a stencil mask in hidden regions of the framebuffer.
|
||||
task.addJob<PrepareStencil>("PrepareStencil", framebuffer);
|
||||
task.addJob<PrepareStencil>("PrepareStencil", scaledPrimaryFramebuffer);
|
||||
|
||||
// Draw opaques forward
|
||||
const auto opaqueInputs = DrawForward::Inputs(opaques, lightingModel).asVarying();
|
||||
|
@ -128,94 +140,103 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend
|
|||
task.addJob<DebugZoneLighting>("DrawZoneStack", debugZoneInputs);
|
||||
}
|
||||
|
||||
// Just resolve the msaa
|
||||
const auto resolveInputs =
|
||||
ResolveFramebuffer::Inputs(framebuffer, static_cast<gpu::FramebufferPointer>(nullptr)).asVarying();
|
||||
const auto resolvedFramebuffer = task.addJob<ResolveFramebuffer>("Resolve", resolveInputs);
|
||||
//auto resolvedFramebuffer = task.addJob<ResolveNewFramebuffer>("Resolve", framebuffer);
|
||||
|
||||
#if defined(Q_OS_ANDROID)
|
||||
|
||||
// Just resolve the msaa
|
||||
const auto resolveInputs = ResolveFramebuffer::Inputs(scaledPrimaryFramebuffer, static_cast<gpu::FramebufferPointer>(nullptr)).asVarying();
|
||||
const auto resolvedFramebuffer = task.addJob<ResolveFramebuffer>("Resolve", resolveInputs);
|
||||
|
||||
const auto toneMappedBuffer = resolvedFramebuffer;
|
||||
#else
|
||||
const auto newResolvedFramebuffer = task.addJob<NewOrDefaultFramebuffer>("MakeResolvingFramebuffer");
|
||||
|
||||
|
||||
// Just resolve the msaa
|
||||
const auto resolveInputs = ResolveFramebuffer::Inputs(scaledPrimaryFramebuffer, newResolvedFramebuffer).asVarying();
|
||||
const auto resolvedFramebuffer = task.addJob<ResolveFramebuffer>("Resolve", resolveInputs);
|
||||
|
||||
// Lighting Buffer ready for tone mapping
|
||||
// Forward rendering on GLES doesn't support tonemapping to and from the same FBO, so we specify
|
||||
// the output FBO as null, which causes the tonemapping to target the blit framebuffer
|
||||
const auto toneMappingInputs = ToneMappingDeferred::Inputs(resolvedFramebuffer, static_cast<gpu::FramebufferPointer>(nullptr)).asVarying();
|
||||
task.addJob<ToneMappingDeferred>("ToneMapping", toneMappingInputs);
|
||||
const auto toneMappingInputs = ToneMappingDeferred::Input(resolvedFramebuffer, resolvedFramebuffer).asVarying();
|
||||
const auto toneMappedBuffer = task.addJob<ToneMappingDeferred>("ToneMapping", toneMappingInputs);
|
||||
|
||||
#endif
|
||||
|
||||
// Layered Overlays
|
||||
// Composite the HUD and HUD overlays
|
||||
task.addJob<CompositeHUD>("HUD", resolvedFramebuffer);
|
||||
// Upscale to finale resolution
|
||||
const auto primaryFramebuffer = task.addJob<render::UpsampleToBlitFramebuffer>("PrimaryBufferUpscale", toneMappedBuffer);
|
||||
|
||||
const auto hudOpaquesInputs = DrawLayered3D::Inputs(hudOpaque, lightingModel, nullJitter).asVarying();
|
||||
const auto hudTransparentsInputs = DrawLayered3D::Inputs(hudTransparent, lightingModel, nullJitter).asVarying();
|
||||
task.addJob<DrawLayered3D>("DrawHUDOpaque", hudOpaquesInputs, true);
|
||||
task.addJob<DrawLayered3D>("DrawHUDTransparent", hudTransparentsInputs, false);
|
||||
|
||||
// Disable blit because we do tonemapping and compositing directly to the blit FBO
|
||||
// Blit!
|
||||
// task.addJob<Blit>("Blit", framebuffer);
|
||||
// HUD Layer
|
||||
const auto renderHUDLayerInputs = RenderHUDLayerTask::Input(primaryFramebuffer, lightingModel, hudOpaque, hudTransparent).asVarying();
|
||||
task.addJob<RenderHUDLayerTask>("RenderHUDLayer", renderHUDLayerInputs);
|
||||
}
|
||||
|
||||
void PrepareFramebuffer::configure(const Config& config) {
|
||||
gpu::FramebufferPointer PreparePrimaryFramebufferMSAA::createFramebuffer(const char* name, const glm::uvec2& frameSize, int numSamples) {
|
||||
gpu::FramebufferPointer framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(name));
|
||||
|
||||
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR);
|
||||
|
||||
auto colorFormat = gpu::Element::COLOR_SRGBA_32;
|
||||
auto colorTexture =
|
||||
gpu::Texture::createRenderBufferMultisample(colorFormat, frameSize.x, frameSize.y, numSamples, defaultSampler);
|
||||
framebuffer->setRenderBuffer(0, colorTexture);
|
||||
|
||||
auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format
|
||||
auto depthTexture =
|
||||
gpu::Texture::createRenderBufferMultisample(depthFormat, frameSize.x, frameSize.y, numSamples, defaultSampler);
|
||||
framebuffer->setDepthStencilBuffer(depthTexture, depthFormat);
|
||||
|
||||
return framebuffer;
|
||||
}
|
||||
|
||||
void PreparePrimaryFramebufferMSAA::configure(const Config& config) {
|
||||
_resolutionScale = config.getResolutionScale();
|
||||
_numSamples = config.getNumSamples();
|
||||
}
|
||||
|
||||
void PrepareFramebuffer::run(const RenderContextPointer& renderContext, gpu::FramebufferPointer& framebuffer) {
|
||||
void PreparePrimaryFramebufferMSAA::run(const RenderContextPointer& renderContext, gpu::FramebufferPointer& framebuffer) {
|
||||
glm::uvec2 frameSize(renderContext->args->_viewport.z, renderContext->args->_viewport.w);
|
||||
glm::uvec2 scaledFrameSize(glm::vec2(frameSize) * _resolutionScale);
|
||||
|
||||
// Resizing framebuffers instead of re-building them seems to cause issues with threaded rendering
|
||||
if (_framebuffer && (_framebuffer->getSize() != frameSize || _framebuffer->getNumSamples() != _numSamples)) {
|
||||
_framebuffer.reset();
|
||||
if (!_framebuffer || (_framebuffer->getSize() != scaledFrameSize) || (_framebuffer->getNumSamples() != _numSamples)) {
|
||||
_framebuffer = createFramebuffer("forward", scaledFrameSize, _numSamples);
|
||||
}
|
||||
|
||||
if (!_framebuffer) {
|
||||
_framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("forward"));
|
||||
|
||||
int numSamples = _numSamples;
|
||||
|
||||
auto colorFormat = gpu::Element::COLOR_SRGBA_32;
|
||||
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR);
|
||||
auto colorTexture =
|
||||
gpu::Texture::createRenderBufferMultisample(colorFormat, frameSize.x, frameSize.y, numSamples, defaultSampler);
|
||||
_framebuffer->setRenderBuffer(0, colorTexture);
|
||||
|
||||
auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format
|
||||
auto depthTexture =
|
||||
gpu::Texture::createRenderBufferMultisample(depthFormat, frameSize.x, frameSize.y, numSamples, defaultSampler);
|
||||
_framebuffer->setDepthStencilBuffer(depthTexture, depthFormat);
|
||||
}
|
||||
|
||||
auto args = renderContext->args;
|
||||
gpu::doInBatch("PrepareFramebuffer::run", args->_context, [&](gpu::Batch& batch) {
|
||||
batch.enableStereo(false);
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setStateScissorRect(args->_viewport);
|
||||
|
||||
batch.setFramebuffer(_framebuffer);
|
||||
batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH |
|
||||
gpu::Framebuffer::BUFFER_STENCIL,
|
||||
vec4(vec3(0), 0), 1.0, 0, true);
|
||||
});
|
||||
|
||||
framebuffer = _framebuffer;
|
||||
|
||||
// Set viewport for the rest of the scaled passes
|
||||
renderContext->args->_viewport.z = scaledFrameSize.x;
|
||||
renderContext->args->_viewport.w = scaledFrameSize.y;
|
||||
}
|
||||
|
||||
void PrepareForward::run(const RenderContextPointer& renderContext, const Inputs& inputs) {
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
auto primaryFramebuffer = inputs.get0();
|
||||
auto lightStageFrame = inputs.get1();
|
||||
|
||||
gpu::doInBatch("RenderForward::Draw::run", args->_context, [&](gpu::Batch& batch) {
|
||||
args->_batch = &batch;
|
||||
|
||||
batch.enableStereo(false);
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setStateScissorRect(args->_viewport);
|
||||
|
||||
batch.setFramebuffer(primaryFramebuffer);
|
||||
batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH |
|
||||
gpu::Framebuffer::BUFFER_STENCIL,
|
||||
vec4(vec3(0), 0), 1.0, 0, true);
|
||||
|
||||
graphics::LightPointer keySunLight;
|
||||
auto lightStage = args->_scene->getStage<LightStage>();
|
||||
if (lightStage) {
|
||||
keySunLight = lightStage->getCurrentKeyLight(*inputs);
|
||||
keySunLight = lightStage->getCurrentKeyLight(*lightStageFrame);
|
||||
}
|
||||
|
||||
graphics::LightPointer keyAmbiLight;
|
||||
if (lightStage) {
|
||||
keyAmbiLight = lightStage->getCurrentAmbientLight(*inputs);
|
||||
keyAmbiLight = lightStage->getCurrentAmbientLight(*lightStageFrame);
|
||||
}
|
||||
|
||||
if (keySunLight) {
|
||||
|
|
|
@ -17,39 +17,59 @@
|
|||
#include "AssembleLightingStageTask.h"
|
||||
#include "LightingModel.h"
|
||||
|
||||
class RenderForwardTaskConfig : public render::Task::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(float resolutionScale MEMBER resolutionScale NOTIFY dirty)
|
||||
public:
|
||||
float resolutionScale{ 1.f };
|
||||
|
||||
signals:
|
||||
void dirty();
|
||||
};
|
||||
|
||||
class RenderForwardTask {
|
||||
public:
|
||||
using Input = render::VaryingSet3<RenderFetchCullSortTask::Output, LightingModelPointer, AssembleLightingStageTask::Output>;
|
||||
using JobModel = render::Task::ModelI<RenderForwardTask, Input>;
|
||||
using Config = RenderForwardTaskConfig;
|
||||
using JobModel = render::Task::ModelI<RenderForwardTask, Input, Config>;
|
||||
|
||||
RenderForwardTask() {}
|
||||
|
||||
void configure(const Config& config);
|
||||
void build(JobModel& task, const render::Varying& input, render::Varying& output);
|
||||
};
|
||||
|
||||
|
||||
class PrepareFramebufferConfig : public render::Job::Config {
|
||||
class PreparePrimaryFramebufferMSAAConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int numSamples WRITE setNumSamples READ getNumSamples NOTIFY dirty)
|
||||
Q_PROPERTY(float resolutionScale WRITE setResolutionScale READ getResolutionScale)
|
||||
Q_PROPERTY(int numSamples WRITE setNumSamples READ getNumSamples)
|
||||
public:
|
||||
float getResolutionScale() const { return resolutionScale; }
|
||||
void setResolutionScale(float scale) {
|
||||
const float SCALE_RANGE_MIN = 0.1f;
|
||||
const float SCALE_RANGE_MAX = 2.0f;
|
||||
resolutionScale = std::max(SCALE_RANGE_MIN, std::min(SCALE_RANGE_MAX, scale));
|
||||
}
|
||||
|
||||
int getNumSamples() const { return numSamples; }
|
||||
void setNumSamples(int num) {
|
||||
numSamples = std::max(1, std::min(32, num));
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
signals:
|
||||
void dirty();
|
||||
|
||||
protected:
|
||||
float resolutionScale{ 1.0f };
|
||||
int numSamples{ 4 };
|
||||
};
|
||||
|
||||
class PrepareFramebuffer {
|
||||
class PreparePrimaryFramebufferMSAA {
|
||||
public:
|
||||
using Inputs = gpu::FramebufferPointer;
|
||||
using Config = PrepareFramebufferConfig;
|
||||
using JobModel = render::Job::ModelO<PrepareFramebuffer, Inputs, Config>;
|
||||
using Output = gpu::FramebufferPointer;
|
||||
using Config = PreparePrimaryFramebufferMSAAConfig;
|
||||
using JobModel = render::Job::ModelO<PreparePrimaryFramebufferMSAA, Output, Config>;
|
||||
|
||||
void configure(const Config& config);
|
||||
void run(const render::RenderContextPointer& renderContext,
|
||||
|
@ -57,12 +77,15 @@ public:
|
|||
|
||||
private:
|
||||
gpu::FramebufferPointer _framebuffer;
|
||||
float _resolutionScale{ 1.0f };
|
||||
int _numSamples;
|
||||
|
||||
static gpu::FramebufferPointer createFramebuffer(const char* name, const glm::uvec2& frameSize, int numSamples);
|
||||
};
|
||||
|
||||
class PrepareForward {
|
||||
public:
|
||||
using Inputs = LightStage::FramePointer;
|
||||
using Inputs = render::VaryingSet2 <gpu::FramebufferPointer, LightStage::FramePointer>;
|
||||
using JobModel = render::Job::ModelI<PrepareForward, Inputs>;
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext,
|
||||
|
|
60
libraries/render-utils/src/RenderHUDLayerTask.cpp
Normal file
60
libraries/render-utils/src/RenderHUDLayerTask.cpp
Normal file
|
@ -0,0 +1,60 @@
|
|||
//
|
||||
// Created by Sam Gateau on 2019/06/14
|
||||
// Copyright 2013-2019 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 "RenderHUDLayerTask.h"
|
||||
|
||||
#include <gpu/Context.h>
|
||||
#include "RenderCommonTask.h"
|
||||
|
||||
using namespace render;
|
||||
|
||||
void CompositeHUD::run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& inputs) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_context);
|
||||
|
||||
// We do not want to render HUD elements in secondary camera
|
||||
if (nsightActive() || renderContext->args->_renderMode == RenderArgs::RenderMode::SECONDARY_CAMERA_RENDER_MODE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Grab the HUD texture
|
||||
#if !defined(DISABLE_QML)
|
||||
gpu::doInBatch("CompositeHUD", renderContext->args->_context, [&](gpu::Batch& batch) {
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
renderContext->args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
renderContext->args->getViewFrustum().evalViewTransform(viewMat);
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat, true);
|
||||
if (inputs) {
|
||||
batch.setFramebuffer(inputs);
|
||||
}
|
||||
if (renderContext->args->_hudOperator) {
|
||||
renderContext->args->_hudOperator(batch, renderContext->args->_hudTexture, renderContext->args->_renderMode == RenderArgs::RenderMode::MIRROR_RENDER_MODE);
|
||||
}
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void RenderHUDLayerTask::build(JobModel& task, const render::Varying& input, render::Varying& output) {
|
||||
const auto& inputs = input.get<Input>();
|
||||
|
||||
const auto& primaryFramebuffer = inputs[0];
|
||||
const auto& lightingModel = inputs[1];
|
||||
const auto& hudOpaque = inputs[2];
|
||||
const auto& hudTransparent = inputs[3];
|
||||
|
||||
// Composite the HUD and HUD overlays
|
||||
task.addJob<CompositeHUD>("HUD", primaryFramebuffer);
|
||||
|
||||
// And HUD Layer objects
|
||||
const auto nullJitter = Varying(glm::vec2(0.0f, 0.0f));
|
||||
const auto hudOpaquesInputs = DrawLayered3D::Inputs(hudOpaque, lightingModel, nullJitter).asVarying();
|
||||
const auto hudTransparentsInputs = DrawLayered3D::Inputs(hudTransparent, lightingModel, nullJitter).asVarying();
|
||||
task.addJob<DrawLayered3D>("DrawHUDOpaque", hudOpaquesInputs, true);
|
||||
task.addJob<DrawLayered3D>("DrawHUDTransparent", hudTransparentsInputs, false);
|
||||
}
|
34
libraries/render-utils/src/RenderHUDLayerTask.h
Normal file
34
libraries/render-utils/src/RenderHUDLayerTask.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
//
|
||||
// Created by Sam Gateau on 2019/06/14
|
||||
// Copyright 2013-2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_RenderHUDLayerTask_h
|
||||
#define hifi_RenderHUDLayerTask_h
|
||||
|
||||
#include "LightingModel.h"
|
||||
|
||||
|
||||
class CompositeHUD {
|
||||
public:
|
||||
// IF specified the input Framebuffer is actively set by the batch of this job before calling the HUDOperator.
|
||||
// If not, the current Framebuffer is left unchanged.
|
||||
//using Inputs = gpu::FramebufferPointer;
|
||||
using JobModel = render::Job::ModelI<CompositeHUD, gpu::FramebufferPointer>;
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext, const gpu::FramebufferPointer& inputs);
|
||||
};
|
||||
|
||||
class RenderHUDLayerTask {
|
||||
public:
|
||||
// Framebuffer where to draw, lighting model, opaque items, transparent items
|
||||
using Input = render::VaryingSet4<gpu::FramebufferPointer, LightingModelPointer, render::ItemBounds, render::ItemBounds>;
|
||||
using JobModel = render::Task::ModelI<RenderHUDLayerTask, Input>;
|
||||
|
||||
void build(JobModel& task, const render::Varying& input, render::Varying& output);
|
||||
};
|
||||
|
||||
#endif // hifi_RenderHUDLayerTask_h
|
|
@ -47,14 +47,13 @@ void ToneMappingEffect::setToneCurve(ToneCurve curve) {
|
|||
}
|
||||
}
|
||||
|
||||
void ToneMappingEffect::render(RenderArgs* args, const gpu::TexturePointer& lightingBuffer, const gpu::FramebufferPointer& requestedDestinationFramebuffer) {
|
||||
void ToneMappingEffect::render(RenderArgs* args, const gpu::TexturePointer& lightingBuffer, const gpu::FramebufferPointer& destinationFramebuffer) {
|
||||
if (!_blitLightBuffer) {
|
||||
init(args);
|
||||
}
|
||||
|
||||
auto destinationFramebuffer = requestedDestinationFramebuffer;
|
||||
if (!destinationFramebuffer) {
|
||||
destinationFramebuffer = args->_blitFramebuffer;
|
||||
|
||||
if (!lightingBuffer || !destinationFramebuffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto framebufferSize = glm::ivec2(lightingBuffer->getDimensions());
|
||||
|
@ -83,9 +82,15 @@ void ToneMappingDeferred::configure(const Config& config) {
|
|||
_toneMappingEffect.setToneCurve((ToneMappingEffect::ToneCurve)config.curve);
|
||||
}
|
||||
|
||||
void ToneMappingDeferred::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) {
|
||||
void ToneMappingDeferred::run(const render::RenderContextPointer& renderContext, const Input& input, Output& output) {
|
||||
|
||||
auto lightingBuffer = input.get0()->getRenderBuffer(0);
|
||||
auto destFbo = input.get1();
|
||||
|
||||
if (!destFbo) {
|
||||
destFbo = renderContext->args->_blitFramebuffer;
|
||||
}
|
||||
|
||||
auto lightingBuffer = inputs.get0()->getRenderBuffer(0);
|
||||
auto destFbo = inputs.get1();
|
||||
_toneMappingEffect.render(renderContext->args, lightingBuffer, destFbo);
|
||||
output = destFbo;
|
||||
}
|
||||
|
|
|
@ -82,12 +82,13 @@ signals:
|
|||
class ToneMappingDeferred {
|
||||
public:
|
||||
// Inputs: lightingFramebuffer, destinationFramebuffer
|
||||
using Inputs = render::VaryingSet2<gpu::FramebufferPointer, gpu::FramebufferPointer>;
|
||||
using Input = render::VaryingSet2<gpu::FramebufferPointer, gpu::FramebufferPointer>;
|
||||
using Output = gpu::FramebufferPointer;
|
||||
using Config = ToneMappingConfig;
|
||||
using JobModel = render::Job::ModelI<ToneMappingDeferred, Inputs, Config>;
|
||||
using JobModel = render::Job::ModelIO<ToneMappingDeferred, Input, Output, Config>;
|
||||
|
||||
void configure(const Config& config);
|
||||
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs);
|
||||
void run(const render::RenderContextPointer& renderContext, const Input& input, Output& output);
|
||||
|
||||
ToneMappingEffect _toneMappingEffect;
|
||||
};
|
||||
|
|
|
@ -135,3 +135,43 @@ void Upsample::run(const RenderContextPointer& renderContext, const gpu::Framebu
|
|||
args->_viewport = viewport;
|
||||
}
|
||||
}
|
||||
|
||||
gpu::PipelinePointer UpsampleToBlitFramebuffer::_pipeline;
|
||||
|
||||
void UpsampleToBlitFramebuffer::run(const RenderContextPointer& renderContext, const Input& input, gpu::FramebufferPointer& resampledFrameBuffer) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
RenderArgs* args = renderContext->args;
|
||||
auto sourceFramebuffer = input;
|
||||
|
||||
resampledFrameBuffer = args->_blitFramebuffer;
|
||||
|
||||
if (resampledFrameBuffer != sourceFramebuffer) {
|
||||
if (!_pipeline) {
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::gpu::program::drawTransformUnitQuadTextureOpaque);
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(gpu::State::DepthTest(false, false));
|
||||
_pipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
const auto bufferSize = resampledFrameBuffer->getSize();
|
||||
glm::ivec4 viewport{ 0, 0, bufferSize.x, bufferSize.y };
|
||||
|
||||
gpu::doInBatch("Upsample::run", args->_context, [&](gpu::Batch& batch) {
|
||||
batch.enableStereo(false);
|
||||
|
||||
batch.setFramebuffer(resampledFrameBuffer);
|
||||
|
||||
batch.setViewportTransform(viewport);
|
||||
batch.setProjectionTransform(glm::mat4());
|
||||
batch.resetViewTransform();
|
||||
batch.setPipeline(_pipeline);
|
||||
|
||||
batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(bufferSize, viewport));
|
||||
batch.setResourceTexture(0, sourceFramebuffer->getRenderBuffer(0));
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
});
|
||||
|
||||
// Set full final viewport
|
||||
args->_viewport = viewport;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,6 +67,20 @@ namespace render {
|
|||
|
||||
gpu::FramebufferPointer getResampledFrameBuffer(const gpu::FramebufferPointer& sourceFramebuffer);
|
||||
};
|
||||
|
||||
class UpsampleToBlitFramebuffer {
|
||||
public:
|
||||
using Input = gpu::FramebufferPointer;
|
||||
using JobModel = Job::ModelIO<UpsampleToBlitFramebuffer, Input, gpu::FramebufferPointer>;
|
||||
|
||||
UpsampleToBlitFramebuffer() {}
|
||||
|
||||
void run(const RenderContextPointer& renderContext, const Input& input, gpu::FramebufferPointer& resampledFrameBuffer);
|
||||
|
||||
protected:
|
||||
|
||||
static gpu::PipelinePointer _pipeline;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // hifi_render_ResampleTask_h
|
||||
|
|
|
@ -2205,6 +2205,7 @@ void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString&
|
|||
* lifetime: 300 // Delete after 5 minutes.
|
||||
* });
|
||||
*/
|
||||
// The JSDoc is for the callEntityScriptMethod() call in this method.
|
||||
// since all of these operations can be asynch we will always do the actual work in the response handler
|
||||
// for the download
|
||||
void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, const QString& scriptOrURL, const QString& contents, bool isURL, bool success , const QString& status) {
|
||||
|
@ -2389,8 +2390,10 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co
|
|||
* <p>Note: Can only be connected to via <code>this.unoad = function () { ... }</code> in the entity script.</p>
|
||||
* <table><tr><th>Available in:</th><td>Client Entity Scripts</td><td>Server Entity Scripts</td></tr></table>
|
||||
* @function Entities.unload
|
||||
* @param {Uuid} entityID - The ID of the entity that the script is running in.
|
||||
* @returns {Signal}
|
||||
*/
|
||||
// The JSDoc is for the callEntityScriptMethod() call in this method.
|
||||
void ScriptEngine::unloadEntityScript(const EntityItemID& entityID, bool shouldRemoveFromMap) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
#ifdef THREAD_DEBUGGING
|
||||
|
|
|
@ -318,6 +318,7 @@ public:
|
|||
|
||||
/**jsdoc
|
||||
* Adds a function to the list of functions called when an entity event occurs on a particular entity.
|
||||
* <p>See also, the {@link Entities} API.</p>
|
||||
* @function Script.addEventHandler
|
||||
* @param {Uuid} entityID - The ID of the entity.
|
||||
* @param {Script.EntityEvent} eventName - The name of the entity event.
|
||||
|
@ -341,6 +342,7 @@ public:
|
|||
|
||||
/**jsdoc
|
||||
* Removes a function from the list of functions called when an entity event occurs on a particular entity.
|
||||
* <p>See also, the {@link Entities} API.</p>
|
||||
* @function Script.removeEventHandler
|
||||
* @param {Uuid} entityID - The ID of the entity.
|
||||
* @param {Script.EntityEvent} eventName - The name of the entity event.
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
* <tr><td><code>"none"</code></td><td>The entity will not be billboarded.</td></tr>
|
||||
* <tr><td><code>"yaw"</code></td><td>The entity will yaw, but not pitch, to face the camera. Its actual rotation will be
|
||||
* ignored.</td></tr>
|
||||
* <tr><td><code>"full"</code></td><td>The entity will be billboarded to face the camera. Its actual rotation will be
|
||||
* <tr><td><code>"full"</code></td><td>The entity will yaw and pitch to face the camera. Its actual rotation will be
|
||||
* ignored.</td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
|
|
|
@ -8,6 +8,22 @@
|
|||
|
||||
#include "ComponentMode.h"
|
||||
|
||||
/**jsdoc
|
||||
* <p>How an effect is applied in a {@link Entities.EntityProperties-Zone|Zone} entity.</p>
|
||||
* <table>
|
||||
* <thead>
|
||||
* <tr><th>Value</th><th>Description</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td><code>"inherit"</code></td><td>The effect from any enclosing zone continues into this zone.</td></tr>
|
||||
* <tr><td><code>"disabled"</code></td><td>The effect — from any enclosing zone and this zone — is disabled in
|
||||
* this zone.</td></tr>
|
||||
* <tr><td><code>"enabled"</code></td><td>The effect from this zone is enabled, overriding the effect from any enclosing
|
||||
* zone.</td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* @typedef {string} Entities.ComponentMode
|
||||
*/
|
||||
const char* componentModeNames[] = {
|
||||
"inherit",
|
||||
"disabled",
|
||||
|
@ -22,6 +38,20 @@ QString ComponentModeHelpers::getNameForComponentMode(ComponentMode mode) {
|
|||
return componentModeNames[(int)mode];
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
* <p>The priority of updates from avatars in a zone to other clients.</p>
|
||||
* <table>
|
||||
* <thead>
|
||||
* <tr><th>Value</th><th>Description</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td><code>"inherit"</code></td><td>The update priority from any enclosing zone continues into this zone.</td></tr>
|
||||
* <tr><td><code>"crowd"</code></td><td>The update priority in this zone is the normal priority.</td></tr>
|
||||
* <tr><td><code>"hero"</code></td><td>Avatars in this zone have an increased update priority.</td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* @typedef {string} Entities.AvatarPriorityMode
|
||||
*/
|
||||
const char* avatarPriorityModeNames[] = {
|
||||
"inherit",
|
||||
"crowd",
|
||||
|
|
|
@ -12,16 +12,16 @@
|
|||
#include "QString"
|
||||
|
||||
/**jsdoc
|
||||
* <p>Controls how the Gizmo behaves and renders</p>
|
||||
* <p>A {@link Entities.EntityProperties-Gizmo|Gizmo} entity may be one of the following types:</p>
|
||||
* <table>
|
||||
* <thead>
|
||||
* <tr><th>Value</th><th>Description</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td><code>ring</code></td><td>A ring gizmo.</td></tr>
|
||||
* <tr><td><code>"ring"</code></td><td>A ring gizmo.</td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* @typedef {string} GizmoType
|
||||
* @typedef {string} Entities.GizmoType
|
||||
*/
|
||||
|
||||
enum GizmoType {
|
||||
|
|
|
@ -66,7 +66,7 @@ void PointerEvent::setButton(Button button) {
|
|||
}
|
||||
|
||||
/**jsdoc
|
||||
* A PointerEvent defines a 2D or 3D mouse or similar pointer event.
|
||||
* A 2D or 3D mouse or similar pointer event.
|
||||
* @typedef {object} PointerEvent
|
||||
* @property {string} type - The type of event: <code>"Press"</code>, <code>"DoublePress"</code>, <code>"Release"</code>, or
|
||||
* <code>"Move"</code>.
|
||||
|
|
|
@ -12,17 +12,17 @@
|
|||
#include "QString"
|
||||
|
||||
/**jsdoc
|
||||
* <p>How the geometry of the entity is rendered.</p>
|
||||
* <p>How the geometry of an entity is rendered.</p>
|
||||
* <table>
|
||||
* <thead>
|
||||
* <tr><th>Value</th><th>Description</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td><code>solid</code></td><td>The entity will be drawn as a solid shape.</td></tr>
|
||||
* <tr><td><code>lines</code></td><td>The entity will be drawn as wireframe.</td></tr>
|
||||
* <tr><td><code>"solid"</code></td><td>The entity is drawn as a solid shape.</td></tr>
|
||||
* <tr><td><code>"lines"</code></td><td>The entity is drawn as wireframe.</td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* @typedef {string} PrimitiveMode
|
||||
* @typedef {string} Entities.PrimitiveMode
|
||||
*/
|
||||
|
||||
enum class PrimitiveMode {
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace PrioritySortUtil {
|
|||
class PriorityQueue {
|
||||
public:
|
||||
PriorityQueue() = delete;
|
||||
PriorityQueue(const ConicalViewFrustums& views) : _views(views) { }
|
||||
PriorityQueue(const ConicalViewFrustums& views) : _views(views), _usecCurrentTime(usecTimestampNow()) { }
|
||||
PriorityQueue(const ConicalViewFrustums& views, float angularWeight, float centerWeight, float ageWeight)
|
||||
: _views(views), _angularWeight(angularWeight), _centerWeight(centerWeight), _ageWeight(ageWeight)
|
||||
, _usecCurrentTime(usecTimestampNow()) {
|
||||
|
|
|
@ -18,12 +18,12 @@
|
|||
* <tr><th>Value</th><th>Description</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td><code>none</code></td><td>No pulsing.</td></tr>
|
||||
* <tr><td><code>in</code></td><td>Pulse in phase with the pulse period.</td></tr>
|
||||
* <tr><td><code>out</code></td><td>Pulse out of phase with the pulse period.</td></tr>
|
||||
* <tr><td><code>"none"</code></td><td>No pulsing.</td></tr>
|
||||
* <tr><td><code>"in"</code></td><td>Pulse in phase with the pulse period.</td></tr>
|
||||
* <tr><td><code>"out"</code></td><td>Pulse out of phase with the pulse period.</td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* @typedef {string} PulseMode
|
||||
* @typedef {string} Entities.PulseMode
|
||||
*/
|
||||
|
||||
enum class PulseMode {
|
||||
|
|
|
@ -122,43 +122,43 @@ glm::vec3 vec3FromVariant(const QVariant &object, bool& valid);
|
|||
glm::vec3 vec3FromVariant(const QVariant &object);
|
||||
|
||||
/**jsdoc
|
||||
* A color vector. See also the {@link Vec3(0)|Vec3} object.
|
||||
*
|
||||
* @typedef {object} Color
|
||||
* @property {number} red - Red component value. Integer in the range <code>0</code> - <code>255</code>. Synonyms: <code>r</code>, <code>x</code>.
|
||||
* @property {number} green - Green component value. Integer in the range <code>0</code> - <code>255</code>. Synonyms: <code>g</code>, <code>y</code>.
|
||||
* @property {number} blue - Blue component value. Integer in the range <code>0</code> - <code>255</code>. Synonyms: <code>b</code>, <code>z</code>.
|
||||
* @example <caption>Colors can be set in multiple ways and modified with their aliases, but still stringify in the same way</caption>
|
||||
* Entities.editEntity(<id>, { color: { x: 1, y: 2, z: 3 }}); // { red: 1, green: 2, blue: 3 }
|
||||
* Entities.editEntity(<id>, { color: { r: 4, g: 5, b: 6 }}); // { red: 4, green: 5, blue: 6 }
|
||||
* Entities.editEntity(<id>, { color: { red: 7, green: 8, blue: 9 }}); // { red: 7, green: 8, blue: 9 }
|
||||
* Entities.editEntity(<id>, { color: [10, 11, 12] }); // { red: 10, green: 11, blue: 12 }
|
||||
* Entities.editEntity(<id>, { color: 13 }); // { red: 13, green: 13, blue: 13 }
|
||||
* var color = Entities.getEntityProperties(<id>).color; // { red: 13, green: 13, blue: 13 }
|
||||
* color.g = 14; // { red: 13, green: 14, blue: 13 }
|
||||
* color.blue = 15; // { red: 13, green: 14, blue: 15 }
|
||||
* Entities.editEntity(<id>, { color: "red"}); // { red: 255, green: 0, blue: 0 }
|
||||
* Entities.editEntity(<id>, { color: "#00FF00"}); // { red: 0, green: 255, blue: 0 }
|
||||
*/
|
||||
* A color vector. See also the {@link Vec3(0)|Vec3} object.
|
||||
*
|
||||
* @typedef {object} Color
|
||||
* @property {number} red - Red component value. Integer in the range <code>0</code> - <code>255</code>. Synonyms: <code>r</code>, <code>x</code>.
|
||||
* @property {number} green - Green component value. Integer in the range <code>0</code> - <code>255</code>. Synonyms: <code>g</code>, <code>y</code>.
|
||||
* @property {number} blue - Blue component value. Integer in the range <code>0</code> - <code>255</code>. Synonyms: <code>b</code>, <code>z</code>.
|
||||
* @example <caption>Colors can be set in multiple ways and modified with their aliases, but still stringify in the same way</caption>
|
||||
* Entities.editEntity(<id>, { color: { x: 1, y: 2, z: 3 }}); // { red: 1, green: 2, blue: 3 }
|
||||
* Entities.editEntity(<id>, { color: { r: 4, g: 5, b: 6 }}); // { red: 4, green: 5, blue: 6 }
|
||||
* Entities.editEntity(<id>, { color: { red: 7, green: 8, blue: 9 }}); // { red: 7, green: 8, blue: 9 }
|
||||
* Entities.editEntity(<id>, { color: [10, 11, 12] }); // { red: 10, green: 11, blue: 12 }
|
||||
* Entities.editEntity(<id>, { color: 13 }); // { red: 13, green: 13, blue: 13 }
|
||||
* var color = Entities.getEntityProperties(<id>).color; // { red: 13, green: 13, blue: 13 }
|
||||
* color.g = 14; // { red: 13, green: 14, blue: 13 }
|
||||
* color.blue = 15; // { red: 13, green: 14, blue: 15 }
|
||||
* Entities.editEntity(<id>, { color: "red"}); // { red: 255, green: 0, blue: 0 }
|
||||
* Entities.editEntity(<id>, { color: "#00FF00"}); // { red: 0, green: 255, blue: 0 }
|
||||
*/
|
||||
/**jsdoc
|
||||
* A color vector. See also the {@link Vec3(0)|Vec3} object.
|
||||
*
|
||||
* @typedef {object} ColorFloat
|
||||
* @property {number} red - Red component value. Real in the range <code>0</code> - <code>255</code>. Synonyms: <code>r</code>, <code>x</code>.
|
||||
* @property {number} green - Green component value. Real in the range <code>0</code> - <code>255</code>. Synonyms: <code>g</code>, <code>y</code>.
|
||||
* @property {number} blue - Blue component value. Real in the range <code>0</code> - <code>255</code>. Synonyms: <code>b</code>, <code>z</code>.
|
||||
* @example <caption>ColorFloats can be set in multiple ways and modified with their aliases, but still stringify in the same way</caption>
|
||||
* Entities.editEntity(<id>, { color: { x: 1, y: 2, z: 3 }}); // { red: 1, green: 2, blue: 3 }
|
||||
* Entities.editEntity(<id>, { color: { r: 4, g: 5, b: 6 }}); // { red: 4, green: 5, blue: 6 }
|
||||
* Entities.editEntity(<id>, { color: { red: 7, green: 8, blue: 9 }}); // { red: 7, green: 8, blue: 9 }
|
||||
* Entities.editEntity(<id>, { color: [10, 11, 12] }); // { red: 10, green: 11, blue: 12 }
|
||||
* Entities.editEntity(<id>, { color: 13 }); // { red: 13, green: 13, blue: 13 }
|
||||
* var color = Entities.getEntityProperties(<id>).color; // { red: 13, green: 13, blue: 13 }
|
||||
* color.g = 14; // { red: 13, green: 14, blue: 13 }
|
||||
* color.blue = 15; // { red: 13, green: 14, blue: 15 }
|
||||
* Entities.editEntity(<id>, { color: "red"}); // { red: 255, green: 0, blue: 0 }
|
||||
* Entities.editEntity(<id>, { color: "#00FF00"}); // { red: 0, green: 255, blue: 0 }
|
||||
*/
|
||||
* A color vector with real values. Values may also be <code>null</code>. See also the {@link Vec3(0)|Vec3} object.
|
||||
*
|
||||
* @typedef {object} ColorFloat
|
||||
* @property {number} red - Red component value. Real in the range <code>0</code> - <code>255</code>. Synonyms: <code>r</code>, <code>x</code>.
|
||||
* @property {number} green - Green component value. Real in the range <code>0</code> - <code>255</code>. Synonyms: <code>g</code>, <code>y</code>.
|
||||
* @property {number} blue - Blue component value. Real in the range <code>0</code> - <code>255</code>. Synonyms: <code>b</code>, <code>z</code>.
|
||||
* @example <caption>ColorFloats can be set in multiple ways and modified with their aliases, but still stringify in the same way</caption>
|
||||
* Entities.editEntity(<id>, { color: { x: 1, y: 2, z: 3 }}); // { red: 1, green: 2, blue: 3 }
|
||||
* Entities.editEntity(<id>, { color: { r: 4, g: 5, b: 6 }}); // { red: 4, green: 5, blue: 6 }
|
||||
* Entities.editEntity(<id>, { color: { red: 7, green: 8, blue: 9 }}); // { red: 7, green: 8, blue: 9 }
|
||||
* Entities.editEntity(<id>, { color: [10, 11, 12] }); // { red: 10, green: 11, blue: 12 }
|
||||
* Entities.editEntity(<id>, { color: 13 }); // { red: 13, green: 13, blue: 13 }
|
||||
* var color = Entities.getEntityProperties(<id>).color; // { red: 13, green: 13, blue: 13 }
|
||||
* color.g = 14; // { red: 13, green: 14, blue: 13 }
|
||||
* color.blue = 15; // { red: 13, green: 14, blue: 15 }
|
||||
* Entities.editEntity(<id>, { color: "red"}); // { red: 255, green: 0, blue: 0 }
|
||||
* Entities.editEntity(<id>, { color: "#00FF00"}); // { red: 0, green: 255, blue: 0 }
|
||||
*/
|
||||
QScriptValue u8vec3ToScriptValue(QScriptEngine* engine, const glm::u8vec3& vec3);
|
||||
QScriptValue u8vec3ColorToScriptValue(QScriptEngine* engine, const glm::u8vec3& vec3);
|
||||
void u8vec3FromScriptValue(const QScriptValue& object, glm::u8vec3& vec3);
|
||||
|
|
|
@ -12,18 +12,18 @@
|
|||
#include "QString"
|
||||
|
||||
/**jsdoc
|
||||
* <p>In which layer an entity is rendered.</p>
|
||||
* <p>A layer in which an entity may be rendered.</p>
|
||||
* <table>
|
||||
* <thead>
|
||||
* <tr><th>Value</th><th>Description</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td><code>world</code></td><td>The entity will be drawn in the world with everything else.</td></tr>
|
||||
* <tr><td><code>front</code></td><td>The entity will be drawn on top of the world layer, but behind the HUD sphere.</td></tr>
|
||||
* <tr><td><code>hud</code></td><td>The entity will be drawn on top of other layers and the HUD sphere.</td></tr>
|
||||
* <tr><td><code>"world"</code></td><td>The entity is drawn in the world with everything else.</td></tr>
|
||||
* <tr><td><code>"front"</code></td><td>The entity is drawn on top of the world layer but behind the HUD sphere.</td></tr>
|
||||
* <tr><td><code>"hud"</code></td><td>The entity is drawn on top of other layers and the HUD sphere.</td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* @typedef {string} RenderLayer
|
||||
* @typedef {string} Entities.RenderLayer
|
||||
*/
|
||||
|
||||
enum class RenderLayer {
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "NumericalConstants.h" // for MILLIMETERS_PER_METER
|
||||
|
||||
/**jsdoc
|
||||
* <p>A ShapeType defines the shape used for collisions or zones.</p>
|
||||
* <p>Defines the shape used for collisions or zones.</p>
|
||||
* <table>
|
||||
* <thead>
|
||||
* <tr><th>Value</th><th>Description</th></tr>
|
||||
|
|
|
@ -1348,7 +1348,20 @@ SpatiallyNestablePointer SpatiallyNestable::findByID(QUuid id, bool& success) {
|
|||
return parentWP.lock();
|
||||
}
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* <p>An in-world item may be one of the following types:</p>
|
||||
* <table>
|
||||
* <thead>
|
||||
* <tr><th>Value</th><th>Description</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td><code>"entity"</code></td><td>The item is an entity.</td></tr>
|
||||
* <tr><td><code>"avatar"</code></td><td>The item is an avatar.</td></tr>
|
||||
* <tr><td><code>"unknown"</code></td><td>The item cannot be found.</td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* @typedef {string} Entities.NestableType
|
||||
*/
|
||||
QString SpatiallyNestable::nestableTypeToString(NestableType nestableType) {
|
||||
switch(nestableType) {
|
||||
case NestableType::Entity:
|
||||
|
|
|
@ -12,14 +12,14 @@
|
|||
#include "QString"
|
||||
|
||||
/**jsdoc
|
||||
* <p>Controls how the web surface processed PointerEvents</p>
|
||||
* <p>Specifies how a web surface processes events.</p>
|
||||
* <table>
|
||||
* <thead>
|
||||
* <tr><th>Value</th><th>Description</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td><code>touch</code></td><td>Events are processed as touch events.</td></tr>
|
||||
* <tr><td><code>mouse</code></td><td>Events are processed as mouse events.</td></tr>
|
||||
* <tr><td><code>"touch"</code></td><td>Events are processed as touch events.</td></tr>
|
||||
* <tr><td><code>"mouse"</code></td><td>Events are processed as mouse events.</td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* @typedef {string} WebInputMode
|
||||
|
|
285
libraries/shared/src/avx2/BlendshapePacking_avx2.cpp
Normal file
285
libraries/shared/src/avx2/BlendshapePacking_avx2.cpp
Normal file
|
@ -0,0 +1,285 @@
|
|||
//
|
||||
// BlendshapePacking_avx2.cpp
|
||||
//
|
||||
// Created by Ken Cooke on 6/22/19.
|
||||
// Copyright 2019 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
|
||||
//
|
||||
|
||||
#ifdef __AVX2__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <immintrin.h>
|
||||
|
||||
void packBlendshapeOffsets_AVX2(float (*unpacked)[9], uint32_t (*packed)[4], int size) {
|
||||
|
||||
int i = 0;
|
||||
for (; i < size - 7; i += 8) { // blocks of 8
|
||||
|
||||
//
|
||||
// deinterleave (8x9 to 9x8 matrix transpose)
|
||||
//
|
||||
__m256 s0 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_loadu_ps(&unpacked[i+0][0])), _mm_loadu_ps(&unpacked[i+4][0]), 1);
|
||||
__m256 s1 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_loadu_ps(&unpacked[i+1][0])), _mm_loadu_ps(&unpacked[i+5][0]), 1);
|
||||
__m256 s2 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_loadu_ps(&unpacked[i+2][0])), _mm_loadu_ps(&unpacked[i+6][0]), 1);
|
||||
__m256 s3 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_loadu_ps(&unpacked[i+3][0])), _mm_loadu_ps(&unpacked[i+7][0]), 1);
|
||||
__m256 s4 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_loadu_ps(&unpacked[i+0][4])), _mm_loadu_ps(&unpacked[i+4][4]), 1);
|
||||
__m256 s5 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_loadu_ps(&unpacked[i+1][4])), _mm_loadu_ps(&unpacked[i+5][4]), 1);
|
||||
__m256 s6 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_loadu_ps(&unpacked[i+2][4])), _mm_loadu_ps(&unpacked[i+6][4]), 1);
|
||||
__m256 s7 = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_loadu_ps(&unpacked[i+3][4])), _mm_loadu_ps(&unpacked[i+7][4]), 1);
|
||||
|
||||
__m256 t0 = _mm256_unpacklo_ps(s0, s1);
|
||||
__m256 t1 = _mm256_unpackhi_ps(s0, s1);
|
||||
__m256 t2 = _mm256_unpacklo_ps(s2, s3);
|
||||
__m256 t3 = _mm256_unpackhi_ps(s2, s3);
|
||||
__m256 t4 = _mm256_unpacklo_ps(s4, s5);
|
||||
__m256 t5 = _mm256_unpackhi_ps(s4, s5);
|
||||
__m256 t6 = _mm256_unpacklo_ps(s6, s7);
|
||||
__m256 t7 = _mm256_unpackhi_ps(s6, s7);
|
||||
|
||||
__m256 px = _mm256_shuffle_ps(t0, t2, _MM_SHUFFLE(1,0,1,0));
|
||||
__m256 py = _mm256_shuffle_ps(t0, t2, _MM_SHUFFLE(3,2,3,2));
|
||||
__m256 pz = _mm256_shuffle_ps(t1, t3, _MM_SHUFFLE(1,0,1,0));
|
||||
__m256 nx = _mm256_shuffle_ps(t1, t3, _MM_SHUFFLE(3,2,3,2));
|
||||
__m256 ny = _mm256_shuffle_ps(t4, t6, _MM_SHUFFLE(1,0,1,0));
|
||||
__m256 nz = _mm256_shuffle_ps(t4, t6, _MM_SHUFFLE(3,2,3,2));
|
||||
__m256 tx = _mm256_shuffle_ps(t5, t7, _MM_SHUFFLE(1,0,1,0));
|
||||
__m256 ty = _mm256_shuffle_ps(t5, t7, _MM_SHUFFLE(3,2,3,2));
|
||||
|
||||
__m256 tz = _mm256_i32gather_ps(unpacked[i+0], _mm256_setr_epi32(8,17,26,35,44,53,62,71), sizeof(float));
|
||||
|
||||
// abs(pos)
|
||||
__m256 apx = _mm256_andnot_ps(_mm256_set1_ps(-0.0f), px);
|
||||
__m256 apy = _mm256_andnot_ps(_mm256_set1_ps(-0.0f), py);
|
||||
__m256 apz = _mm256_andnot_ps(_mm256_set1_ps(-0.0f), pz);
|
||||
|
||||
// len = compMax(abs(pos))
|
||||
__m256 len = _mm256_max_ps(_mm256_max_ps(apx, apy), apz);
|
||||
|
||||
// detect zeros
|
||||
__m256 mask = _mm256_cmp_ps(len, _mm256_setzero_ps(), _CMP_EQ_OQ);
|
||||
|
||||
// rcp = 1.0f / len
|
||||
__m256 rcp = _mm256_div_ps(_mm256_set1_ps(1.0f), len);
|
||||
|
||||
// replace +inf with 1.0f
|
||||
rcp = _mm256_blendv_ps(rcp, _mm256_set1_ps(1.0f), mask);
|
||||
len = _mm256_blendv_ps(len, _mm256_set1_ps(1.0f), mask);
|
||||
|
||||
// pos *= 1.0f / len
|
||||
px = _mm256_mul_ps(px, rcp);
|
||||
py = _mm256_mul_ps(py, rcp);
|
||||
pz = _mm256_mul_ps(pz, rcp);
|
||||
|
||||
// clamp(vec, -1.0f, 1.0f)
|
||||
px = _mm256_min_ps(_mm256_max_ps(px, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f));
|
||||
py = _mm256_min_ps(_mm256_max_ps(py, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f));
|
||||
pz = _mm256_min_ps(_mm256_max_ps(pz, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f));
|
||||
nx = _mm256_min_ps(_mm256_max_ps(nx, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f));
|
||||
ny = _mm256_min_ps(_mm256_max_ps(ny, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f));
|
||||
nz = _mm256_min_ps(_mm256_max_ps(nz, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f));
|
||||
tx = _mm256_min_ps(_mm256_max_ps(tx, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f));
|
||||
ty = _mm256_min_ps(_mm256_max_ps(ty, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f));
|
||||
tz = _mm256_min_ps(_mm256_max_ps(tz, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f));
|
||||
|
||||
// vec *= 511.0f
|
||||
px = _mm256_mul_ps(px, _mm256_set1_ps(511.0f));
|
||||
py = _mm256_mul_ps(py, _mm256_set1_ps(511.0f));
|
||||
pz = _mm256_mul_ps(pz, _mm256_set1_ps(511.0f));
|
||||
nx = _mm256_mul_ps(nx, _mm256_set1_ps(511.0f));
|
||||
ny = _mm256_mul_ps(ny, _mm256_set1_ps(511.0f));
|
||||
nz = _mm256_mul_ps(nz, _mm256_set1_ps(511.0f));
|
||||
tx = _mm256_mul_ps(tx, _mm256_set1_ps(511.0f));
|
||||
ty = _mm256_mul_ps(ty, _mm256_set1_ps(511.0f));
|
||||
tz = _mm256_mul_ps(tz, _mm256_set1_ps(511.0f));
|
||||
|
||||
// veci = lrint(vec) & 03ff
|
||||
__m256i pxi = _mm256_and_si256(_mm256_cvtps_epi32(px), _mm256_set1_epi32(0x3ff));
|
||||
__m256i pyi = _mm256_and_si256(_mm256_cvtps_epi32(py), _mm256_set1_epi32(0x3ff));
|
||||
__m256i pzi = _mm256_and_si256(_mm256_cvtps_epi32(pz), _mm256_set1_epi32(0x3ff));
|
||||
__m256i nxi = _mm256_and_si256(_mm256_cvtps_epi32(nx), _mm256_set1_epi32(0x3ff));
|
||||
__m256i nyi = _mm256_and_si256(_mm256_cvtps_epi32(ny), _mm256_set1_epi32(0x3ff));
|
||||
__m256i nzi = _mm256_and_si256(_mm256_cvtps_epi32(nz), _mm256_set1_epi32(0x3ff));
|
||||
__m256i txi = _mm256_and_si256(_mm256_cvtps_epi32(tx), _mm256_set1_epi32(0x3ff));
|
||||
__m256i tyi = _mm256_and_si256(_mm256_cvtps_epi32(ty), _mm256_set1_epi32(0x3ff));
|
||||
__m256i tzi = _mm256_and_si256(_mm256_cvtps_epi32(tz), _mm256_set1_epi32(0x3ff));
|
||||
|
||||
// pack = (xi << 0) | (yi << 10) | (zi << 20);
|
||||
__m256i li = _mm256_castps_si256(len); // length
|
||||
__m256i pi = _mm256_or_si256(_mm256_or_si256(pxi, _mm256_slli_epi32(pyi, 10)), _mm256_slli_epi32(pzi, 20)); // position
|
||||
__m256i ni = _mm256_or_si256(_mm256_or_si256(nxi, _mm256_slli_epi32(nyi, 10)), _mm256_slli_epi32(nzi, 20)); // normal
|
||||
__m256i ti = _mm256_or_si256(_mm256_or_si256(txi, _mm256_slli_epi32(tyi, 10)), _mm256_slli_epi32(tzi, 20)); // tangent
|
||||
|
||||
//
|
||||
// interleave (4x4 matrix transpose)
|
||||
//
|
||||
__m256i u0 = _mm256_unpacklo_epi32(li, pi);
|
||||
__m256i u1 = _mm256_unpackhi_epi32(li, pi);
|
||||
__m256i u2 = _mm256_unpacklo_epi32(ni, ti);
|
||||
__m256i u3 = _mm256_unpackhi_epi32(ni, ti);
|
||||
|
||||
__m256i v0 = _mm256_unpacklo_epi64(u0, u2);
|
||||
__m256i v1 = _mm256_unpackhi_epi64(u0, u2);
|
||||
__m256i v2 = _mm256_unpacklo_epi64(u1, u3);
|
||||
__m256i v3 = _mm256_unpackhi_epi64(u1, u3);
|
||||
|
||||
__m256i w0 = _mm256_permute2f128_si256(v0, v1, 0x20);
|
||||
__m256i w1 = _mm256_permute2f128_si256(v2, v3, 0x20);
|
||||
__m256i w2 = _mm256_permute2f128_si256(v0, v1, 0x31);
|
||||
__m256i w3 = _mm256_permute2f128_si256(v2, v3, 0x31);
|
||||
|
||||
// store pack x 8
|
||||
_mm256_storeu_si256((__m256i*)packed[i+0], w0);
|
||||
_mm256_storeu_si256((__m256i*)packed[i+2], w1);
|
||||
_mm256_storeu_si256((__m256i*)packed[i+4], w2);
|
||||
_mm256_storeu_si256((__m256i*)packed[i+6], w3);
|
||||
}
|
||||
|
||||
if (i < size) { // remainder
|
||||
int rem = size - i;
|
||||
|
||||
//
|
||||
// deinterleave (8x9 to 9x8 matrix transpose)
|
||||
//
|
||||
__m256 s0 = _mm256_setzero_ps();
|
||||
__m256 s1 = _mm256_setzero_ps();
|
||||
__m256 s2 = _mm256_setzero_ps();
|
||||
__m256 s3 = _mm256_setzero_ps();
|
||||
__m256 s4 = _mm256_setzero_ps();
|
||||
__m256 s5 = _mm256_setzero_ps();
|
||||
__m256 s6 = _mm256_setzero_ps();
|
||||
__m256 s7 = _mm256_setzero_ps();
|
||||
|
||||
switch (rem) {
|
||||
case 7: s6 = _mm256_loadu_ps(unpacked[i+6]);
|
||||
case 6: s5 = _mm256_loadu_ps(unpacked[i+5]);
|
||||
case 5: s4 = _mm256_loadu_ps(unpacked[i+4]);
|
||||
case 4: s3 = _mm256_loadu_ps(unpacked[i+3]);
|
||||
case 3: s2 = _mm256_loadu_ps(unpacked[i+2]);
|
||||
case 2: s1 = _mm256_loadu_ps(unpacked[i+1]);
|
||||
case 1: s0 = _mm256_loadu_ps(unpacked[i+0]);
|
||||
}
|
||||
|
||||
__m256 t0 = _mm256_unpacklo_ps(s0, s1);
|
||||
__m256 t1 = _mm256_unpackhi_ps(s0, s1);
|
||||
__m256 t2 = _mm256_unpacklo_ps(s2, s3);
|
||||
__m256 t3 = _mm256_unpackhi_ps(s2, s3);
|
||||
__m256 t4 = _mm256_unpacklo_ps(s4, s5);
|
||||
__m256 t5 = _mm256_unpackhi_ps(s4, s5);
|
||||
__m256 t6 = _mm256_unpacklo_ps(s6, s7);
|
||||
__m256 t7 = _mm256_unpackhi_ps(s6, s7);
|
||||
|
||||
s0 = _mm256_shuffle_ps(t0, t2, _MM_SHUFFLE(1,0,1,0));
|
||||
s1 = _mm256_shuffle_ps(t0, t2, _MM_SHUFFLE(3,2,3,2));
|
||||
s2 = _mm256_shuffle_ps(t1, t3, _MM_SHUFFLE(1,0,1,0));
|
||||
s3 = _mm256_shuffle_ps(t1, t3, _MM_SHUFFLE(3,2,3,2));
|
||||
s4 = _mm256_shuffle_ps(t4, t6, _MM_SHUFFLE(1,0,1,0));
|
||||
s5 = _mm256_shuffle_ps(t4, t6, _MM_SHUFFLE(3,2,3,2));
|
||||
s6 = _mm256_shuffle_ps(t5, t7, _MM_SHUFFLE(1,0,1,0));
|
||||
s7 = _mm256_shuffle_ps(t5, t7, _MM_SHUFFLE(3,2,3,2));
|
||||
|
||||
__m256 px = _mm256_permute2f128_ps(s0, s4, 0x20);
|
||||
__m256 py = _mm256_permute2f128_ps(s1, s5, 0x20);
|
||||
__m256 pz = _mm256_permute2f128_ps(s2, s6, 0x20);
|
||||
__m256 nx = _mm256_permute2f128_ps(s3, s7, 0x20);
|
||||
__m256 ny = _mm256_permute2f128_ps(s0, s4, 0x31);
|
||||
__m256 nz = _mm256_permute2f128_ps(s1, s5, 0x31);
|
||||
__m256 tx = _mm256_permute2f128_ps(s2, s6, 0x31);
|
||||
__m256 ty = _mm256_permute2f128_ps(s3, s7, 0x31);
|
||||
|
||||
__m256i loadmask = _mm256_cvtepi8_epi32(_mm_cvtsi64_si128(0xffffffffffffffffULL >> (64 - 8 * rem)));
|
||||
__m256 tz = _mm256_mask_i32gather_ps(_mm256_setzero_ps(), unpacked[i+0], _mm256_setr_epi32(8,17,26,35,44,53,62,71),
|
||||
_mm256_castsi256_ps(loadmask), sizeof(float));
|
||||
// abs(pos)
|
||||
__m256 apx = _mm256_andnot_ps(_mm256_set1_ps(-0.0f), px);
|
||||
__m256 apy = _mm256_andnot_ps(_mm256_set1_ps(-0.0f), py);
|
||||
__m256 apz = _mm256_andnot_ps(_mm256_set1_ps(-0.0f), pz);
|
||||
|
||||
// len = compMax(abs(pos))
|
||||
__m256 len = _mm256_max_ps(_mm256_max_ps(apx, apy), apz);
|
||||
|
||||
// detect zeros
|
||||
__m256 mask = _mm256_cmp_ps(len, _mm256_setzero_ps(), _CMP_EQ_OQ);
|
||||
|
||||
// rcp = 1.0f / len
|
||||
__m256 rcp = _mm256_div_ps(_mm256_set1_ps(1.0f), len);
|
||||
|
||||
// replace +inf with 1.0f
|
||||
rcp = _mm256_blendv_ps(rcp, _mm256_set1_ps(1.0f), mask);
|
||||
len = _mm256_blendv_ps(len, _mm256_set1_ps(1.0f), mask);
|
||||
|
||||
// pos *= 1.0f / len
|
||||
px = _mm256_mul_ps(px, rcp);
|
||||
py = _mm256_mul_ps(py, rcp);
|
||||
pz = _mm256_mul_ps(pz, rcp);
|
||||
|
||||
// clamp(vec, -1.0f, 1.0f)
|
||||
px = _mm256_min_ps(_mm256_max_ps(px, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f));
|
||||
py = _mm256_min_ps(_mm256_max_ps(py, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f));
|
||||
pz = _mm256_min_ps(_mm256_max_ps(pz, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f));
|
||||
nx = _mm256_min_ps(_mm256_max_ps(nx, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f));
|
||||
ny = _mm256_min_ps(_mm256_max_ps(ny, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f));
|
||||
nz = _mm256_min_ps(_mm256_max_ps(nz, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f));
|
||||
tx = _mm256_min_ps(_mm256_max_ps(tx, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f));
|
||||
ty = _mm256_min_ps(_mm256_max_ps(ty, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f));
|
||||
tz = _mm256_min_ps(_mm256_max_ps(tz, _mm256_set1_ps(-1.0f)), _mm256_set1_ps(1.0f));
|
||||
|
||||
// vec *= 511.0f
|
||||
px = _mm256_mul_ps(px, _mm256_set1_ps(511.0f));
|
||||
py = _mm256_mul_ps(py, _mm256_set1_ps(511.0f));
|
||||
pz = _mm256_mul_ps(pz, _mm256_set1_ps(511.0f));
|
||||
nx = _mm256_mul_ps(nx, _mm256_set1_ps(511.0f));
|
||||
ny = _mm256_mul_ps(ny, _mm256_set1_ps(511.0f));
|
||||
nz = _mm256_mul_ps(nz, _mm256_set1_ps(511.0f));
|
||||
tx = _mm256_mul_ps(tx, _mm256_set1_ps(511.0f));
|
||||
ty = _mm256_mul_ps(ty, _mm256_set1_ps(511.0f));
|
||||
tz = _mm256_mul_ps(tz, _mm256_set1_ps(511.0f));
|
||||
|
||||
// veci = lrint(vec) & 03ff
|
||||
__m256i pxi = _mm256_and_si256(_mm256_cvtps_epi32(px), _mm256_set1_epi32(0x3ff));
|
||||
__m256i pyi = _mm256_and_si256(_mm256_cvtps_epi32(py), _mm256_set1_epi32(0x3ff));
|
||||
__m256i pzi = _mm256_and_si256(_mm256_cvtps_epi32(pz), _mm256_set1_epi32(0x3ff));
|
||||
__m256i nxi = _mm256_and_si256(_mm256_cvtps_epi32(nx), _mm256_set1_epi32(0x3ff));
|
||||
__m256i nyi = _mm256_and_si256(_mm256_cvtps_epi32(ny), _mm256_set1_epi32(0x3ff));
|
||||
__m256i nzi = _mm256_and_si256(_mm256_cvtps_epi32(nz), _mm256_set1_epi32(0x3ff));
|
||||
__m256i txi = _mm256_and_si256(_mm256_cvtps_epi32(tx), _mm256_set1_epi32(0x3ff));
|
||||
__m256i tyi = _mm256_and_si256(_mm256_cvtps_epi32(ty), _mm256_set1_epi32(0x3ff));
|
||||
__m256i tzi = _mm256_and_si256(_mm256_cvtps_epi32(tz), _mm256_set1_epi32(0x3ff));
|
||||
|
||||
// pack = (xi << 0) | (yi << 10) | (zi << 20);
|
||||
__m256i li = _mm256_castps_si256(len); // length
|
||||
__m256i pi = _mm256_or_si256(_mm256_or_si256(pxi, _mm256_slli_epi32(pyi, 10)), _mm256_slli_epi32(pzi, 20)); // position
|
||||
__m256i ni = _mm256_or_si256(_mm256_or_si256(nxi, _mm256_slli_epi32(nyi, 10)), _mm256_slli_epi32(nzi, 20)); // normal
|
||||
__m256i ti = _mm256_or_si256(_mm256_or_si256(txi, _mm256_slli_epi32(tyi, 10)), _mm256_slli_epi32(tzi, 20)); // tangent
|
||||
|
||||
//
|
||||
// interleave (4x4 matrix transpose)
|
||||
//
|
||||
__m256i u0 = _mm256_unpacklo_epi32(li, pi);
|
||||
__m256i u1 = _mm256_unpackhi_epi32(li, pi);
|
||||
__m256i u2 = _mm256_unpacklo_epi32(ni, ti);
|
||||
__m256i u3 = _mm256_unpackhi_epi32(ni, ti);
|
||||
|
||||
__m256i v0 = _mm256_unpacklo_epi64(u0, u2);
|
||||
__m256i v1 = _mm256_unpackhi_epi64(u0, u2);
|
||||
__m256i v2 = _mm256_unpacklo_epi64(u1, u3);
|
||||
__m256i v3 = _mm256_unpackhi_epi64(u1, u3);
|
||||
|
||||
// store pack x 8
|
||||
switch (rem) {
|
||||
case 7: _mm_storeu_si128((__m128i*)packed[i+6], _mm256_extractf128_si256(v2, 1));
|
||||
case 6: _mm_storeu_si128((__m128i*)packed[i+5], _mm256_extractf128_si256(v1, 1));
|
||||
case 5: _mm_storeu_si128((__m128i*)packed[i+4], _mm256_extractf128_si256(v0, 1));
|
||||
case 4: _mm_storeu_si128((__m128i*)packed[i+3], _mm256_castsi256_si128(v3));
|
||||
case 3: _mm_storeu_si128((__m128i*)packed[i+2], _mm256_castsi256_si128(v2));
|
||||
case 2: _mm_storeu_si128((__m128i*)packed[i+1], _mm256_castsi256_si128(v1));
|
||||
case 1: _mm_storeu_si128((__m128i*)packed[i+0], _mm256_castsi256_si128(v0));
|
||||
}
|
||||
}
|
||||
|
||||
_mm256_zeroupper();
|
||||
}
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue