Merge branch 'master' of https://github.com/highfidelity/hifi into loginInitiative2

This commit is contained in:
Wayne Chen 2018-11-05 09:13:25 -08:00
commit 2dd20de1bd
109 changed files with 1252 additions and 1302 deletions

View file

@ -69,10 +69,10 @@ void ScriptableAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
AvatarData::setSkeletonModelURL(skeletonModelURL);
}
static AnimPose composeAnimPose(const FBXJoint& fbxJoint, const glm::quat rotation, const glm::vec3 translation) {
static AnimPose composeAnimPose(const HFMJoint& joint, const glm::quat rotation, const glm::vec3 translation) {
glm::mat4 translationMat = glm::translate(translation);
glm::mat4 rotationMat = glm::mat4_cast(fbxJoint.preRotation * rotation * fbxJoint.postRotation);
glm::mat4 finalMat = translationMat * fbxJoint.preTransform * rotationMat * fbxJoint.postTransform;
glm::mat4 rotationMat = glm::mat4_cast(joint.preRotation * rotation * joint.postRotation);
glm::mat4 finalMat = translationMat * joint.preTransform * rotationMat * joint.postTransform;
return AnimPose(finalMat);
}
@ -93,7 +93,7 @@ void ScriptableAvatar::update(float deltatime) {
}
_animationDetails.currentFrame = currentFrame;
const QVector<FBXJoint>& modelJoints = _bind->getGeometry().joints;
const QVector<HFMJoint>& modelJoints = _bind->getGeometry().joints;
QStringList animationJointNames = _animation->getJointNames();
const int nJoints = modelJoints.size();
@ -102,8 +102,8 @@ void ScriptableAvatar::update(float deltatime) {
}
const int frameCount = _animation->getFrames().size();
const FBXAnimationFrame& floorFrame = _animation->getFrames().at((int)glm::floor(currentFrame) % frameCount);
const FBXAnimationFrame& ceilFrame = _animation->getFrames().at((int)glm::ceil(currentFrame) % frameCount);
const HFMAnimationFrame& floorFrame = _animation->getFrames().at((int)glm::floor(currentFrame) % frameCount);
const HFMAnimationFrame& ceilFrame = _animation->getFrames().at((int)glm::ceil(currentFrame) % frameCount);
const float frameFraction = glm::fract(currentFrame);
std::vector<AnimPose> poses = _animSkeleton->getRelativeDefaultPoses();

View file

@ -157,6 +157,11 @@ Item {
}
}
}
Keys.onReturnPressed: {
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
linkAccountBody.login();
}
}
Item {
id: bottomContainer

View file

@ -86,7 +86,7 @@ Item {
loginButtonAtSignIn.text = "Log In";
loginButtonAtSignIn.color = hifi.buttons.black;
emailField.placeholderText = "Username or Email";
var savedUsername = Settings.getValue("wallet/savedUsername", "");
var savedUsername = Settings.getValue("keepMeLoggedIn/savedUsername", "");
emailField.text = savedUsername === "Unknown user" ? "" : savedUsername;
emailField.anchors.top = loginContainer.top;
emailField.anchors.topMargin = !root.isTablet ? 0.2 * root.height : 0.24 * root.height;
@ -209,7 +209,6 @@ Item {
width: banner.width
height: signInBody.textFieldHeight
font.family: signInBody.fontFamily
text: Settings.getValue("wallet/savedUsername", "");
anchors {
top: parent.top
left: parent.left
@ -311,8 +310,8 @@ Item {
}
HifiControlsUit.CheckBox {
id: autoLogoutCheckbox
checked: !Settings.getValue("wallet/autoLogout", false);
text: qsTr("Keep Me Logged In")
checked: Settings.getValue("keepMeLoggedIn", false);
text: qsTr("Keep Me Logged In");
boxSize: 18;
labelFontFamily: signInBody.fontFamily
labelFontSize: 18;
@ -323,15 +322,17 @@ Item {
right: passwordField.right;
}
onCheckedChanged: {
Settings.setValue("wallet/autoLogout", !checked);
Settings.setValue("keepMeLoggedIn", checked);
if (checked) {
Settings.setValue("wallet/savedUsername", Account.username);
Settings.setValue("keepMeLoggedIn/savedUsername", Account.username);
var savedUsername = Settings.getValue("keepMeLoggedIn/savedUsername", "");
usernameField.text = savedUsername === "Unknown user" ? "" : savedUsername;
} else {
Settings.setValue("wallet/savedUsername", "");
Settings.setValue("keepMeLoggedIn/savedUsername", "");
}
}
Component.onDestruction: {
Settings.setValue("wallet/autoLogout", !checked);
Settings.setValue("keepMeLoggedIn", checked);
}
}
Item {
@ -431,6 +432,11 @@ Item {
case Qt.Key_Enter:
case Qt.Key_Return:
event.accepted = true;
if (loginDialog.isLogIn) {
Settings.setValue("keepMeLoggedIn/savedUsername", emailField.text);
} else {
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
}
signInBody.login();
break;
}

View file

@ -14,9 +14,9 @@
import Hifi 1.0 as Hifi
import QtQuick 2.5
import QtGraphicalEffects 1.0
import "../../../styles-uit"
import "../../../controls-uit" as HifiControlsUit
import "../../../controls" as HifiControls
import "qrc:////qml//styles-uit"
import "qrc:////qml//controls-uit" as HifiControlsUit
import "qrc:////qml//controls" as HifiControls
// references XXX from root context
@ -33,13 +33,15 @@ Rectangle {
property string buttonLayout: "leftright";
readonly property string securityPicBodyText: "When you see your Security Pic, your actions and data are securely making use of your " +
"Wallet's private keys.<br><br>You can change your Security Pic in your Wallet.";
"private keys.<br><br>You can change your Security Pic via Settings > Security...";
id: root;
visible: false;
anchors.fill: parent;
color: Qt.rgba(0, 0, 0, 0.5);
z: 999;
HifiConstants { id: hifi; }
onVisibleChanged: {
if (!visible) {

View file

@ -74,8 +74,7 @@ In your Wallet's Send Money tab, choose from your list of connections, or choose
isExpanded: false;
question: "What is a Security Pic?"
answer: "Your Security Pic acts as an extra layer of Wallet security. \
When you see your Security Pic, you know that your actions and data are securely making use of your account. \
<br><br><b><font color='#0093C5'><a href='#securitypic'>Tap here to change your Security Pic.</a></font></b>";
When you see your Security Pic, you know that your actions and data are securely making use of your account.";
}
ListElement {
isExpanded: false;
@ -137,7 +136,7 @@ At the moment, there is currently no way to convert HFC to other currencies. Sta
anchors.left: parent.left;
width: parent.width;
height: questionText.paintedHeight + 50;
RalewaySemiBold {
id: plusMinusButton;
text: model.isExpanded ? "-" : "+";
@ -217,8 +216,6 @@ At the moment, there is currently no way to convert HFC to other currencies. Sta
}
} else if (link === "#support") {
Qt.openUrlExternally("mailto:support@highfidelity.com");
} else if (link === "#securitypic") {
sendSignalToWallet({method: 'walletSecurity_changeSecurityImage'});
}
}
}

View file

@ -1,246 +0,0 @@
//
// Security.qml
// qml/hifi/commerce/wallet
//
// Security
//
// Created by Zach Fox on 2017-08-18
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import Hifi 1.0 as Hifi
import QtQuick 2.5
import QtGraphicalEffects 1.0
import "../../../styles-uit"
import "../../../controls-uit" as HifiControlsUit
import "../../../controls" as HifiControls
// references XXX from root context
Item {
HifiConstants { id: hifi; }
id: root;
property string keyFilePath;
Connections {
target: Commerce;
onKeyFilePathIfExistsResult: {
root.keyFilePath = path;
}
}
// Username Text
RalewayRegular {
id: usernameText;
text: Account.username;
// Text size
size: 24;
// Style
color: hifi.colors.white;
elide: Text.ElideRight;
// Anchors
anchors.top: parent.top;
anchors.left: parent.left;
anchors.leftMargin: 20;
width: parent.width/2;
height: 80;
}
Item {
id: securityContainer;
anchors.top: usernameText.bottom;
anchors.topMargin: 20;
anchors.left: parent.left;
anchors.right: parent.right;
anchors.bottom: parent.bottom;
RalewaySemiBold {
id: securityText;
text: "Security";
// Anchors
anchors.top: parent.top;
anchors.left: parent.left;
anchors.leftMargin: 20;
anchors.right: parent.right;
height: 30;
// Text size
size: 18;
// Style
color: hifi.colors.blueHighlight;
}
Rectangle {
id: securityTextSeparator;
// Size
width: parent.width;
height: 1;
// Anchors
anchors.left: parent.left;
anchors.right: parent.right;
anchors.top: securityText.bottom;
anchors.topMargin: 8;
// Style
color: hifi.colors.faintGray;
}
Item {
id: changeSecurityImageContainer;
anchors.top: securityTextSeparator.bottom;
anchors.topMargin: 8;
anchors.left: parent.left;
anchors.leftMargin: 40;
anchors.right: parent.right;
anchors.rightMargin: 55;
height: 75;
HiFiGlyphs {
id: changeSecurityImageImage;
text: hifi.glyphs.securityImage;
// Size
size: 80;
// Anchors
anchors.top: parent.top;
anchors.bottom: parent.bottom;
anchors.left: parent.left;
// Style
color: hifi.colors.white;
}
RalewaySemiBold {
text: "Security Pic";
// Anchors
anchors.top: parent.top;
anchors.bottom: parent.bottom;
anchors.left: changeSecurityImageImage.right;
anchors.leftMargin: 30;
width: 50;
// Text size
size: 18;
// Style
color: hifi.colors.white;
}
// "Change Security Pic" button
HifiControlsUit.Button {
id: changeSecurityImageButton;
color: hifi.buttons.blue;
colorScheme: hifi.colorSchemes.dark;
anchors.right: parent.right;
anchors.verticalCenter: parent.verticalCenter;
width: 140;
height: 40;
text: "Change";
onClicked: {
sendSignalToWallet({method: 'walletSecurity_changeSecurityImage'});
}
}
}
Item {
id: autoLogoutContainer;
anchors.top: changeSecurityImageContainer.bottom;
anchors.topMargin: 8;
anchors.left: parent.left;
anchors.leftMargin: 40;
anchors.right: parent.right;
anchors.rightMargin: 55;
height: 75;
HiFiGlyphs {
id: autoLogoutImage;
text: hifi.glyphs.walletKey;
// Size
size: 80;
// Anchors
anchors.top: parent.top;
anchors.topMargin: 20;
anchors.left: parent.left;
// Style
color: hifi.colors.white;
}
HifiControlsUit.CheckBox {
id: autoLogoutCheckbox;
checked: Settings.getValue("wallet/autoLogout", false);
text: "Automatically Log Out when Exiting Interface"
// Anchors
anchors.verticalCenter: autoLogoutImage.verticalCenter;
anchors.left: autoLogoutImage.right;
anchors.leftMargin: 20;
anchors.right: autoLogoutHelp.left;
anchors.rightMargin: 12;
boxSize: 28;
labelFontSize: 18;
color: hifi.colors.white;
onCheckedChanged: {
Settings.setValue("wallet/autoLogout", checked);
if (checked) {
Settings.setValue("wallet/savedUsername", Account.username);
} else {
Settings.setValue("wallet/savedUsername", "");
}
}
}
RalewaySemiBold {
id: autoLogoutHelp;
text: '[?]';
// Anchors
anchors.verticalCenter: autoLogoutImage.verticalCenter;
anchors.right: parent.right;
width: 30;
height: 30;
// Text size
size: 18;
// Style
color: hifi.colors.blueHighlight;
MouseArea {
anchors.fill: parent;
hoverEnabled: true;
onEntered: {
parent.color = hifi.colors.blueAccent;
}
onExited: {
parent.color = hifi.colors.blueHighlight;
}
onClicked: {
sendSignalToWallet({method: 'walletSecurity_autoLogoutHelp'});
}
}
}
}
}
//
// FUNCTION DEFINITIONS START
//
//
// Function Name: fromScript()
//
// Relevant Variables:
// None
//
// Arguments:
// message: The message sent from the JavaScript.
// Messages are in format "{method, params}", like json-rpc.
//
// Description:
// Called when a message is received from a script.
//
function fromScript(message) {
switch (message.method) {
default:
console.log('Unrecognized message from wallet.js:', JSON.stringify(message));
}
}
signal sendSignalToWallet(var msg);
//
// FUNCTION DEFINITIONS END
//
}

View file

@ -142,7 +142,7 @@ Rectangle {
Image {
id: titleBarSecurityImage;
source: "";
visible: titleBarSecurityImage.source !== "" && !securityImageChange.visible;
visible: titleBarSecurityImage.source !== "";
anchors.right: parent.right;
anchors.rightMargin: 6;
anchors.top: parent.top;
@ -232,10 +232,6 @@ Rectangle {
root.isPassword = msg.isPasswordField;
} else if (msg.method === 'walletSetup_lowerKeyboard') {
root.keyboardRaised = false;
} else if (msg.method === 'walletSecurity_changePassphraseCancelled') {
root.activeView = "security";
} else if (msg.method === 'walletSecurity_changePassphraseSuccess') {
root.activeView = "security";
} else {
sendToScript(msg);
}
@ -245,27 +241,6 @@ Rectangle {
}
}
}
SecurityImageChange {
id: securityImageChange;
visible: root.activeView === "securityImageChange";
z: 997;
anchors.top: titleBarContainer.bottom;
anchors.left: parent.left;
anchors.right: parent.right;
anchors.bottom: parent.bottom;
Connections {
onSendSignalToWallet: {
if (msg.method === 'walletSecurity_changeSecurityImageCancelled') {
root.activeView = "security";
} else if (msg.method === 'walletSecurity_changeSecurityImageSuccess') {
root.activeView = "security";
} else {
sendToScript(msg);
}
}
}
}
//
// TAB CONTENTS START
@ -366,39 +341,6 @@ Rectangle {
}
}
Security {
id: security;
visible: root.activeView === "security";
anchors.top: titleBarContainer.bottom;
anchors.bottom: tabButtonsContainer.top;
anchors.left: parent.left;
anchors.right: parent.right;
Connections {
onSendSignalToWallet: {
if (msg.method === 'walletSecurity_changePassphrase') {
root.activeView = "passphraseChange";
passphraseChange.clearPassphraseFields();
passphraseChange.resetSubmitButton();
} else if (msg.method === 'walletSecurity_changeSecurityImage') {
securityImageChange.initModel();
root.activeView = "securityImageChange";
} else if (msg.method === 'walletSecurity_autoLogoutHelp') {
lightboxPopup.titleText = "Automatically Log Out";
lightboxPopup.bodyText = "By default, after you log in to High Fidelity, you will stay logged in to your High Fidelity " +
"account even after you close and re-open Interface. This means anyone who opens Interface on your computer " +
"could make purchases with your Wallet.\n\n" +
"If you do not want to stay logged in across Interface sessions, check this box.";
lightboxPopup.button1text = "CLOSE";
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.visible = true;
}
}
}
}
Help {
id: help;
visible: root.activeView === "help";
@ -407,14 +349,6 @@ Rectangle {
anchors.left: parent.left;
anchors.right: parent.right;
Connections {
onSendSignalToWallet: {
if (msg.method === 'walletSecurity_changeSecurityImage') {
securityImageChange.initModel();
root.activeView = "securityImageChange";
}
}
}
}
@ -427,8 +361,8 @@ Rectangle {
//
Item {
id: tabButtonsContainer;
visible: !needsLogIn.visible && root.activeView !== "passphraseChange" && root.activeView !== "securityImageChange" && sendMoney.currentActiveView !== "sendAssetStep";
property int numTabs: 5;
visible: !needsLogIn.visible && root.activeView !== "passphraseChange" && sendMoney.currentActiveView !== "sendAssetStep";
property int numTabs: 4;
// Size
width: root.width;
height: 90;
@ -452,7 +386,7 @@ Rectangle {
anchors.left: parent.left;
anchors.bottom: parent.bottom;
width: parent.width / tabButtonsContainer.numTabs;
HiFiGlyphs {
id: homeTabIcon;
text: hifi.glyphs.home2;
@ -506,7 +440,7 @@ Rectangle {
anchors.left: walletHomeButtonContainer.right;
anchors.bottom: parent.bottom;
width: parent.width / tabButtonsContainer.numTabs;
HiFiGlyphs {
id: exchangeMoneyTabIcon;
text: hifi.glyphs.leftRightArrows;
@ -550,7 +484,7 @@ Rectangle {
anchors.left: exchangeMoneyButtonContainer.right;
anchors.bottom: parent.bottom;
width: parent.width / tabButtonsContainer.numTabs;
HiFiGlyphs {
id: sendMoneyTabIcon;
text: hifi.glyphs.paperPlane;
@ -596,70 +530,16 @@ Rectangle {
}
}
// "SECURITY" tab button
Rectangle {
id: securityButtonContainer;
visible: !walletSetup.visible;
color: root.activeView === "security" ? hifi.colors.blueAccent : hifi.colors.black;
anchors.top: parent.top;
anchors.left: sendMoneyButtonContainer.right;
anchors.bottom: parent.bottom;
width: parent.width / tabButtonsContainer.numTabs;
HiFiGlyphs {
id: securityTabIcon;
text: hifi.glyphs.lock;
// Size
size: 38;
// Anchors
anchors.horizontalCenter: parent.horizontalCenter;
anchors.top: parent.top;
anchors.topMargin: 2;
// Style
color: root.activeView === "security" || securityTabMouseArea.containsMouse ? hifi.colors.white : hifi.colors.blueHighlight;
}
RalewaySemiBold {
text: "SECURITY";
// Text size
size: 16;
// Anchors
anchors.bottom: parent.bottom;
height: parent.height/2;
anchors.left: parent.left;
anchors.leftMargin: 4;
anchors.right: parent.right;
anchors.rightMargin: 4;
// Style
color: root.activeView === "security" || securityTabMouseArea.containsMouse ? hifi.colors.white : hifi.colors.blueHighlight;
wrapMode: Text.WordWrap;
// Alignment
horizontalAlignment: Text.AlignHCenter;
verticalAlignment: Text.AlignTop;
}
MouseArea {
id: securityTabMouseArea;
anchors.fill: parent;
hoverEnabled: enabled;
onClicked: {
root.activeView = "security";
tabButtonsContainer.resetTabButtonColors();
}
onEntered: parent.color = hifi.colors.blueHighlight;
onExited: parent.color = root.activeView === "security" ? hifi.colors.blueAccent : hifi.colors.black;
}
}
// "HELP" tab button
Rectangle {
id: helpButtonContainer;
visible: !walletSetup.visible;
color: root.activeView === "help" ? hifi.colors.blueAccent : hifi.colors.black;
anchors.top: parent.top;
anchors.left: securityButtonContainer.right;
anchors.left: sendMoneyButtonContainer.right;
anchors.bottom: parent.bottom;
width: parent.width / tabButtonsContainer.numTabs;
HiFiGlyphs {
id: helpTabIcon;
text: hifi.glyphs.question;

View file

@ -243,7 +243,6 @@ Item {
height: 50;
text: "Set Up Wallet";
onClicked: {
securityImageSelection.initModel();
root.activeView = "step_2";
}
}
@ -267,124 +266,6 @@ Item {
// FIRST PAGE END
//
//
// SECURITY IMAGE SELECTION START
//
Item {
id: securityImageContainer;
visible: root.activeView === "step_2";
// Anchors
anchors.top: titleBarContainer.bottom;
anchors.topMargin: 30;
anchors.bottom: parent.bottom;
anchors.left: parent.left;
anchors.leftMargin: 16;
anchors.right: parent.right;
anchors.rightMargin: 16;
// Text below title bar
RalewayRegular {
id: securityImageTitleHelper;
text: "Choose a Security Pic:";
// Text size
size: 24;
// Anchors
anchors.top: parent.top;
anchors.left: parent.left;
height: 50;
width: paintedWidth;
// Style
color: hifi.colors.white;
// Alignment
horizontalAlignment: Text.AlignHLeft;
verticalAlignment: Text.AlignVCenter;
}
SecurityImageSelection {
id: securityImageSelection;
// Anchors
anchors.top: securityImageTitleHelper.bottom;
anchors.left: parent.left;
anchors.right: parent.right;
height: 300;
Connections {
onSendSignalToWallet: {
sendSignalToWallet(msg);
}
}
}
// Text below security images
RalewayRegular {
text: "<b>Your security picture shows you that the service asking for your passphrase is authorized.</b> You can change your secure picture at any time.";
// Text size
size: 18;
// Anchors
anchors.top: securityImageSelection.bottom;
anchors.topMargin: 40;
anchors.left: parent.left;
anchors.right: parent.right;
height: paintedHeight;
// Style
color: hifi.colors.white;
wrapMode: Text.WordWrap;
// Alignment
horizontalAlignment: Text.AlignHLeft;
verticalAlignment: Text.AlignVCenter;
}
// Navigation Bar
Item {
// Size
width: parent.width;
height: 50;
// Anchors:
anchors.left: parent.left;
anchors.bottom: parent.bottom;
anchors.bottomMargin: 50;
// "Back" button
HifiControlsUit.Button {
color: hifi.buttons.noneBorderlessWhite;
colorScheme: hifi.colorSchemes.dark;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
anchors.left: parent.left;
anchors.leftMargin: 20;
width: 200;
text: "Back"
onClicked: {
securityImageSelection.resetSelection();
root.activeView = "step_1";
}
}
// "Next" button
HifiControlsUit.Button {
enabled: securityImageSelection.currentIndex !== -1;
color: hifi.buttons.blue;
colorScheme: hifi.colorSchemes.dark;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
anchors.right: parent.right;
anchors.rightMargin: 20;
width: 200;
text: "Next";
onClicked: {
root.lastPage = "step_2";
var securityImagePath = securityImageSelection.getImagePathFromImageID(securityImageSelection.getSelectedImageIndex())
Commerce.chooseSecurityImage(securityImagePath);
root.activeView = "step_3";
passphraseSelection.clearPassphraseFields();
}
}
}
}
//
// SECURITY IMAGE SELECTION END
//
//
// SECURE PASSPHRASE SELECTION START
//
@ -525,7 +406,6 @@ Item {
width: 200;
text: "Back"
onClicked: {
securityImageSelection.resetSelection();
root.lastPage = "step_3";
root.activeView = "step_2";
}

View file

@ -0,0 +1,344 @@
//
// Security.qml
// qml\hifi\dialogs\security
//
// Security
//
// Created by Zach Fox on 2018-10-31
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import Hifi 1.0 as Hifi
import QtQuick 2.5
import QtGraphicalEffects 1.0
import "qrc:////qml//styles-uit" as HifiStylesUit
import "qrc:////qml//controls-uit" as HifiControlsUit
import "qrc:////qml//controls" as HifiControls
import "qrc:////qml//hifi//commerce//common" as HifiCommerceCommon
Rectangle {
HifiStylesUit.HifiConstants { id: hifi; }
id: root;
color: hifi.colors.baseGray;
property string title: "Security Settings";
property bool walletSetUp;
QtObject {
id: margins
property real paddings: root.width / 20.25
property real sizeCheckBox: root.width / 13.5
property real sizeText: root.width / 2.5
property real sizeLevel: root.width / 5.8
property real sizeDesktop: root.width / 5.8
property real sizeVR: root.width / 13.5
}
Connections {
target: Commerce;
onWalletStatusResult: {
if (walletStatus === 5) {
Commerce.getSecurityImage();
root.walletSetUp = true;
} else {
root.walletSetUp = false;
}
}
onSecurityImageResult: {
if (exists) {
currentSecurityPicture.source = "";
currentSecurityPicture.source = "image://security/securityImage";
}
}
}
Component.onCompleted: {
Commerce.getWalletStatus();
}
HifiCommerceCommon.CommerceLightbox {
z: 996;
id: lightboxPopup;
visible: false;
anchors.fill: parent;
}
SecurityImageChange {
id: securityImageChange;
visible: false;
z: 997;
anchors.top: usernameText.bottom;
anchors.left: parent.left;
anchors.right: parent.right;
anchors.bottom: parent.bottom;
Connections {
onSendSignalToParent: {
securityImageChange.visible = false;
}
}
}
// Username Text
HifiStylesUit.RalewayRegular {
id: usernameText;
text: Account.username === "Unknown user" ? "Please Log In" : Account.username;
// Text size
size: 24;
// Style
color: hifi.colors.white;
elide: Text.ElideRight;
// Anchors
anchors.top: parent.top;
anchors.left: parent.left;
anchors.leftMargin: 20;
anchors.right: parent.right;
anchors.rightMargin: 20;
height: 60;
}
Item {
id: pleaseLogInContainer;
visible: Account.username === "Unknown user";
anchors.top: usernameText.bottom;
anchors.left: parent.left;
anchors.right: parent.right;
anchors.bottom: parent.bottom;
HifiStylesUit.RalewayRegular {
text: "Please log in for security settings."
// Text size
size: 24;
// Style
color: hifi.colors.white;
// Anchors
anchors.bottom: openLoginButton.top;
anchors.left: parent.left;
anchors.right: parent.right;
horizontalAlignment: Text.AlignHCenter;
verticalAlignment: Text.AlignVCenter;
height: 60;
}
HifiControlsUit.Button {
id: openLoginButton;
color: hifi.buttons.white;
colorScheme: hifi.colorSchemes.dark;
anchors.centerIn: parent;
width: 140;
height: 40;
text: "Log In";
onClicked: {
DialogsManager.showLoginDialog();
}
}
}
Item {
id: securitySettingsContainer;
visible: !pleaseLogInContainer.visible;
anchors.top: usernameText.bottom;
anchors.left: parent.left;
anchors.right: parent.right;
anchors.bottom: parent.bottom;
Item {
id: accountContainer;
anchors.top: securitySettingsContainer.top;
anchors.left: parent.left;
anchors.right: parent.right;
height: childrenRect.height;
Rectangle {
id: accountHeaderContainer;
anchors.top: parent.top;
anchors.left: parent.left;
anchors.right: parent.right;
height: 55;
color: hifi.colors.baseGrayHighlight;
HifiStylesUit.RalewaySemiBold {
text: "Account";
anchors.fill: parent;
anchors.leftMargin: 20;
color: hifi.colors.white;
size: 18;
}
}
Item {
id: keepMeLoggedInContainer;
anchors.top: accountHeaderContainer.bottom;
anchors.left: parent.left;
anchors.right: parent.right;
height: 80;
HifiControlsUit.CheckBox {
id: autoLogoutCheckbox;
checked: Settings.getValue("keepMeLoggedIn", false);
text: "Keep Me Logged In"
// Anchors
anchors.verticalCenter: parent.verticalCenter;
anchors.left: parent.left;
anchors.leftMargin: 20;
boxSize: 24;
labelFontSize: 18;
colorScheme: hifi.colorSchemes.dark
color: hifi.colors.white;
width: 240;
onCheckedChanged: {
Settings.setValue("keepMeLoggedIn", checked);
if (checked) {
Settings.setValue("keepMeLoggedIn/savedUsername", Account.username);
} else {
Settings.setValue("keepMeLoggedIn/savedUsername", "");
}
}
}
HifiStylesUit.RalewaySemiBold {
id: autoLogoutHelp;
text: '[?]';
// Anchors
anchors.verticalCenter: parent.verticalCenter;
anchors.right: autoLogoutCheckbox.right;
width: 30;
height: 30;
// Text size
size: 18;
// Style
color: hifi.colors.blueHighlight;
MouseArea {
anchors.fill: parent;
hoverEnabled: true;
onEntered: {
parent.color = hifi.colors.blueAccent;
}
onExited: {
parent.color = hifi.colors.blueHighlight;
}
onClicked: {
lightboxPopup.titleText = "Keep Me Logged In";
lightboxPopup.bodyText = "If you choose to stay logged in, ensure that this is a trusted device.\n\n" +
"Also, remember that logging out may not disconnect you from a domain.";
lightboxPopup.button1text = "OK";
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.visible = true;
}
}
}
}
}
Item {
id: walletContainer;
anchors.top: accountContainer.bottom;
anchors.left: parent.left;
anchors.right: parent.right;
height: childrenRect.height;
Rectangle {
id: walletHeaderContainer;
anchors.top: parent.top;
anchors.left: parent.left;
anchors.right: parent.right;
height: 55;
color: hifi.colors.baseGrayHighlight;
HifiStylesUit.RalewaySemiBold {
text: "Wallet";
anchors.fill: parent;
anchors.leftMargin: 20;
color: hifi.colors.white;
size: 18;
}
}
Item {
id: walletSecurityPictureContainer;
visible: root.walletSetUp;
anchors.top: walletHeaderContainer.bottom;
anchors.left: parent.left;
anchors.right: parent.right;
height: 80;
Image {
id: currentSecurityPicture;
source: "";
visible: true;
anchors.left: parent.left;
anchors.leftMargin: 20;
anchors.verticalCenter: parent.verticalCenter;
height: 40;
width: height;
mipmap: true;
cache: false;
}
HifiStylesUit.RalewaySemiBold {
id: securityPictureText;
text: "Wallet Security Picture";
// Anchors
anchors.top: parent.top;
anchors.bottom: parent.bottom;
anchors.left: currentSecurityPicture.right;
anchors.leftMargin: 12;
width: paintedWidth;
// Text size
size: 18;
// Style
color: hifi.colors.white;
}
// "Change Security Pic" button
HifiControlsUit.Button {
id: changeSecurityImageButton;
color: hifi.buttons.white;
colorScheme: hifi.colorSchemes.dark;
anchors.left: securityPictureText.right;
anchors.leftMargin: 12;
anchors.verticalCenter: parent.verticalCenter;
width: 140;
height: 40;
text: "Change";
onClicked: {
securityImageChange.visible = true;
securityImageChange.initModel();
}
}
}
Item {
id: walletNotSetUpContainer;
visible: !root.walletSetUp;
anchors.top: walletHeaderContainer.bottom;
anchors.left: parent.left;
anchors.right: parent.right;
height: 60;
HifiStylesUit.RalewayRegular {
text: "Your wallet is not set up.\n" +
"Open the WALLET app to get started.";
// Anchors
anchors.fill: parent;
// Text size
size: 18;
// Style
color: hifi.colors.white;
horizontalAlignment: Text.AlignHCenter;
verticalAlignment: Text.AlignVCenter;
}
}
}
}
}

View file

@ -1,11 +1,11 @@
//
// SecurityImageChange.qml
// qml/hifi/commerce/wallet
// qml\hifi\dialogs\security
//
// SecurityImageChange
// Security
//
// Created by Zach Fox on 2017-08-18
// Copyright 2017 High Fidelity, Inc.
// Created by Zach Fox on 2018-10-31
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@ -13,16 +13,17 @@
import Hifi 1.0 as Hifi
import QtQuick 2.5
import "../../../styles-uit"
import "../../../controls-uit" as HifiControlsUit
import "../../../controls" as HifiControls
import "qrc:////qml//styles-uit" as HifiStylesUit
import "qrc:////qml//controls-uit" as HifiControlsUit
import "qrc:////qml//controls" as HifiControls
// references XXX from root context
Item {
HifiConstants { id: hifi; }
Rectangle {
HifiStylesUit.HifiConstants { id: hifi; }
id: root;
color: hifi.colors.baseGray;
property bool justSubmitted: false;
Connections {
@ -33,7 +34,7 @@ Item {
securityImageChangePageSecurityImage.source = "image://security/securityImage";
if (exists) { // Success submitting new security image
if (root.justSubmitted) {
sendSignalToWallet({method: "walletSecurity_changeSecurityImageSuccess"});
sendSignalToParent({method: "walletSecurity_changeSecurityImageSuccess"});
root.justSubmitted = false;
}
} else if (root.justSubmitted) {
@ -72,7 +73,7 @@ Item {
anchors.bottom: parent.bottom;
height: 22;
// Lock icon
HiFiGlyphs {
HifiStylesUit.HiFiGlyphs {
id: lockIcon;
text: hifi.glyphs.lock;
anchors.bottom: parent.bottom;
@ -83,8 +84,8 @@ Item {
verticalAlignment: Text.AlignBottom;
color: hifi.colors.white;
}
// "Security image" text below pic
RalewayRegular {
// "Security image" text below image
HifiStylesUit.RalewayRegular {
id: securityImageText;
text: "SECURITY PIC";
// Text size
@ -116,9 +117,9 @@ Item {
anchors.bottom: parent.bottom;
// "Change Security Image" text
RalewaySemiBold {
HifiStylesUit.RalewaySemiBold {
id: securityImageTitle;
text: "Change Security Pic:";
text: "Change Security Image:";
// Text size
size: 18;
anchors.top: parent.top;
@ -139,12 +140,6 @@ Item {
anchors.right: parent.right;
anchors.rightMargin: 16;
height: 300;
Connections {
onSendSignalToWallet: {
sendSignalToWallet(msg);
}
}
}
// Navigation Bar
@ -169,7 +164,7 @@ Item {
width: 150;
text: "Cancel"
onClicked: {
sendSignalToWallet({method: "walletSecurity_changeSecurityImageCancelled"});
sendSignalToParent({method: "walletSecurity_changeSecurityImageCancelled"});
}
}
@ -197,7 +192,7 @@ Item {
// SECURITY IMAGE SELECTION END
//
signal sendSignalToWallet(var msg);
signal sendSignalToParent(var msg);
function initModel() {
securityImageSelection.initModel();

View file

@ -1,11 +1,11 @@
//
// SecurityImageModel.qml
// qml/hifi/commerce
// qml\hifi\dialogs\security
//
// SecurityImageModel
// Security
//
// Created by Zach Fox on 2017-08-17
// Copyright 2017 High Fidelity, Inc.
// Created by Zach Fox on 2018-10-31
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html

View file

@ -1,11 +1,11 @@
//
// SecurityImageSelection.qml
// qml/hifi/commerce/wallet
// qml\hifi\dialogs\security
//
// SecurityImageSelection
// Security
//
// Created by Zach Fox on 2017-08-17
// Copyright 2017 High Fidelity, Inc.
// Created by Zach Fox on 2018-10-31
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@ -13,14 +13,14 @@
import Hifi 1.0 as Hifi
import QtQuick 2.5
import "../../../styles-uit"
import "../../../controls-uit" as HifiControlsUit
import "../../../controls" as HifiControls
import "qrc:////qml//styles-uit" as HifiStylesUit
import "qrc:////qml//controls-uit" as HifiControlsUit
import "qrc:////qml//controls" as HifiControls
// references XXX from root context
Item {
HifiConstants { id: hifi; }
HifiStylesUit.HifiConstants { id: hifi; }
id: root;
property alias currentIndex: securityImageGrid.currentIndex;
@ -64,17 +64,15 @@ Item {
}
}
highlight: Rectangle {
width: securityImageGrid.cellWidth;
height: securityImageGrid.cellHeight;
color: hifi.colors.blueHighlight;
}
width: securityImageGrid.cellWidth;
height: securityImageGrid.cellHeight;
color: hifi.colors.blueHighlight;
}
}
//
// FUNCTION DEFINITIONS START
//
signal sendSignalToWallet(var msg);
function getImagePathFromImageID(imageID) {
return (imageID ? gridModel.getImagePathFromImageID(imageID) : "");
}

View file

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View file

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View file

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

View file

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View file

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

View file

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View file

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View file

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View file

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

View file

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View file

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View file

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View file

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View file

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

View file

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

View file

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View file

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View file

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View file

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View file

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 79 KiB

View file

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View file

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View file

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

View file

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

View file

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View file

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View file

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View file

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

View file

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View file

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

View file

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View file

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

View file

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

View file

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View file

@ -385,7 +385,7 @@ static const int INTERVAL_TO_CHECK_HMD_WORN_STATUS = 500; // milliseconds
static const QString DESKTOP_DISPLAY_PLUGIN_NAME = "Desktop";
static const QString ACTIVE_DISPLAY_PLUGIN_SETTING_NAME = "activeDisplayPlugin";
static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system";
static const QString AUTO_LOGOUT_SETTING_NAME = "wallet/autoLogout";
static const QString KEEP_ME_LOGGED_IN_SETTING_NAME = "keepMeLoggedIn";
const std::vector<std::pair<QString, Application::AcceptURLMethod>> Application::_acceptedExtensions {
{ SVO_EXTENSION, &Application::importSVOFromURL },
@ -2563,8 +2563,8 @@ void Application::cleanupBeforeQuit() {
}
DependencyManager::destroy<ScriptEngines>();
bool autoLogout = Setting::Handle<bool>(AUTO_LOGOUT_SETTING_NAME, false).get();
if (autoLogout) {
bool keepMeLoggedIn = Setting::Handle<bool>(KEEP_ME_LOGGED_IN_SETTING_NAME, false).get();
if (!keepMeLoggedIn) {
DependencyManager::get<AccountManager>()->removeAccountFromFile();
}
@ -2969,13 +2969,13 @@ void Application::initializeUi() {
QUrl{ "hifi/commerce/wallet/PassphraseChange.qml" },
QUrl{ "hifi/commerce/wallet/PassphraseModal.qml" },
QUrl{ "hifi/commerce/wallet/PassphraseSelection.qml" },
QUrl{ "hifi/commerce/wallet/Security.qml" },
QUrl{ "hifi/commerce/wallet/SecurityImageChange.qml" },
QUrl{ "hifi/commerce/wallet/SecurityImageModel.qml" },
QUrl{ "hifi/commerce/wallet/SecurityImageSelection.qml" },
QUrl{ "hifi/commerce/wallet/Wallet.qml" },
QUrl{ "hifi/commerce/wallet/WalletHome.qml" },
QUrl{ "hifi/commerce/wallet/WalletSetup.qml" },
QUrl{ "hifi/dialogs/security/Security.qml" },
QUrl{ "hifi/dialogs/security/SecurityImageChange.qml" },
QUrl{ "hifi/dialogs/security/SecurityImageModel.qml" },
QUrl{ "hifi/dialogs/security/SecurityImageSelection.qml" },
}, callback);
qmlRegisterType<ResourceImageItem>("Hifi", 1, 0, "ResourceImageItem");
qmlRegisterType<Preference>("Hifi", 1, 0, "Preference");

View file

@ -265,6 +265,18 @@ Menu::Menu() {
QString("hifi/tablet/TabletGraphicsPreferences.qml"), "GraphicsPreferencesDialog");
});
// Settings > Security...
action = addActionToQMenuAndActionHash(settingsMenu, "Security...");
connect(action, &QAction::triggered, [] {
auto tablet = DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system");
auto hmd = DependencyManager::get<HMDScriptingInterface>();
tablet->pushOntoStack("hifi/dialogs/security/Security.qml");
if (!hmd->getShouldShowTablet()) {
hmd->toggleShouldShowTablet();
}
});
// Settings > Developer Menu
addCheckableActionToQMenuAndActionHash(settingsMenu, "Developer Menu", 0, false, this, SLOT(toggleDeveloperMenus()));

View file

@ -235,7 +235,7 @@ bool ModelPackager::zipModel() {
return true;
}
void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename, const FBXGeometry& geometry) {
void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename, const HFMGeometry& geometry) {
bool isBodyType = _modelType == FSTReader::BODY_ONLY_MODEL || _modelType == FSTReader::HEAD_AND_BODY_MODEL;
@ -370,7 +370,7 @@ void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename
void ModelPackager::listTextures() {
_textures.clear();
foreach (const FBXMaterial mat, _geometry->materials) {
foreach (const HFMMaterial mat, _geometry->materials) {
if (!mat.albedoTexture.filename.isEmpty() && mat.albedoTexture.content.isEmpty() &&
!_textures.contains(mat.albedoTexture.filename)) {
_textures << mat.albedoTexture.filename;

View file

@ -19,7 +19,7 @@
#include "ui/ModelsBrowser.h"
class FBXGeometry;
class HFMGeometry;
class ModelPackager : public QObject {
public:
@ -32,7 +32,7 @@ private:
bool editProperties();
bool zipModel();
void populateBasicMapping(QVariantHash& mapping, QString filename, const FBXGeometry& geometry);
void populateBasicMapping(QVariantHash& mapping, QString filename, const HFMGeometry& geometry);
void listTextures();
bool copyTextures(const QString& oldDir, const QDir& newDir);
@ -44,7 +44,7 @@ private:
QString _scriptDir;
QVariantHash _mapping;
std::unique_ptr<FBXGeometry> _geometry;
std::unique_ptr<HFMGeometry> _geometry;
QStringList _textures;
QStringList _scripts;
};

View file

@ -27,7 +27,7 @@
ModelPropertiesDialog::ModelPropertiesDialog(FSTReader::ModelType modelType, const QVariantHash& originalMapping,
const QString& basePath, const FBXGeometry& geometry) :
const QString& basePath, const HFMGeometry& geometry) :
_modelType(modelType),
_originalMapping(originalMapping),
_basePath(basePath),
@ -249,7 +249,7 @@ QComboBox* ModelPropertiesDialog::createJointBox(bool withNone) const {
if (withNone) {
box->addItem("(none)");
}
foreach (const FBXJoint& joint, _geometry.joints) {
foreach (const HFMJoint& joint, _geometry.joints) {
if (joint.isSkeletonJoint || !_geometry.hasSkeletonJoints) {
box->addItem(joint.name);
}

View file

@ -30,7 +30,7 @@ class ModelPropertiesDialog : public QDialog {
public:
ModelPropertiesDialog(FSTReader::ModelType modelType, const QVariantHash& originalMapping,
const QString& basePath, const FBXGeometry& geometry);
const QString& basePath, const HFMGeometry& geometry);
QVariantHash getMapping() const;
@ -50,7 +50,7 @@ private:
FSTReader::ModelType _modelType;
QVariantHash _originalMapping;
QString _basePath;
FBXGeometry _geometry;
HFMGeometry _geometry;
QLineEdit* _name = nullptr;
QPushButton* _textureDirectory = nullptr;
QPushButton* _scriptDirectory = nullptr;

View file

@ -155,7 +155,7 @@ MyAvatar::MyAvatar(QThread* thread) :
});
connect(_skeletonModel.get(), &Model::rigReady, this, [this]() {
if (_shouldLoadScripts) {
auto geometry = getSkeletonModel()->getFBXGeometry();
auto geometry = getSkeletonModel()->getHFMGeometry();
qApp->loadAvatarScripts(geometry.scripts);
_shouldLoadScripts = false;
}
@ -2429,10 +2429,10 @@ void MyAvatar::attachmentDataToEntityProperties(const AttachmentData& data, Enti
void MyAvatar::initHeadBones() {
int neckJointIndex = -1;
if (_skeletonModel->isLoaded()) {
neckJointIndex = _skeletonModel->getFBXGeometry().neckJointIndex;
neckJointIndex = _skeletonModel->getHFMGeometry().neckJointIndex;
}
if (neckJointIndex == -1) {
neckJointIndex = (_skeletonModel->getFBXGeometry().headJointIndex - 1);
neckJointIndex = (_skeletonModel->getHFMGeometry().headJointIndex - 1);
if (neckJointIndex < 0) {
// return if the head is not even there. can't cauterize!!
return;
@ -2443,7 +2443,7 @@ void MyAvatar::initHeadBones() {
q.push(neckJointIndex);
_headBoneSet.insert(neckJointIndex);
// fbxJoints only hold links to parents not children, so we have to do a bit of extra work here.
// hfmJoints only hold links to parents not children, so we have to do a bit of extra work here.
while (q.size() > 0) {
int jointIndex = q.front();
for (int i = 0; i < _skeletonModel->getJointStateCount(); i++) {
@ -2592,11 +2592,11 @@ void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) {
if (_skeletonModel && _skeletonModel->isLoaded()) {
const Rig& rig = _skeletonModel->getRig();
const FBXGeometry& geometry = _skeletonModel->getFBXGeometry();
const HFMGeometry& geometry = _skeletonModel->getHFMGeometry();
for (int i = 0; i < rig.getJointStateCount(); i++) {
AnimPose jointPose;
rig.getAbsoluteJointPoseInRigFrame(i, jointPose);
const FBXJointShapeInfo& shapeInfo = geometry.joints[i].shapeInfo;
const HFMJointShapeInfo& shapeInfo = geometry.joints[i].shapeInfo;
const AnimPose pose = rigToWorldPose * jointPose;
for (size_t j = 0; j < shapeInfo.debugLines.size() / 2; j++) {
glm::vec3 pointA = pose.xformPoint(shapeInfo.debugLines[2 * j]);
@ -4012,7 +4012,7 @@ float MyAvatar::getSitStandStateChange() const {
}
QVector<QString> MyAvatar::getScriptUrls() {
QVector<QString> scripts = _skeletonModel->isLoaded() ? _skeletonModel->getFBXGeometry().scripts : QVector<QString>();
QVector<QString> scripts = _skeletonModel->isLoaded() ? _skeletonModel->getHFMGeometry().scripts : QVector<QString>();
return scripts;
}

View file

@ -90,7 +90,7 @@ static AnimPose computeHipsInSensorFrame(MyAvatar* myAvatar, bool isFlying) {
// Called within Model::simulate call, below.
void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
const FBXGeometry& geometry = getFBXGeometry();
const HFMGeometry& geometry = getHFMGeometry();
Head* head = _owningAvatar->getHead();

View file

@ -219,7 +219,11 @@ QString transactionString(const QJsonObject& valueObject) {
if (!message.isEmpty()) {
result += QString("<br>with memo: <i>\"%1\"</i>").arg(message);
}
} else if (sentMoney <= 0 && receivedMoney <= 0 && (sentCerts > 0 || receivedCerts > 0) && !KNOWN_USERS.contains(valueObject["sender_name"].toString())) {
} else if (sentMoney <= 0 && receivedMoney <= 0 &&
(sentCerts > 0 || receivedCerts > 0) &&
!KNOWN_USERS.contains(valueObject["sender_name"].toString()) &&
!KNOWN_USERS.contains(valueObject["recipient_name"].toString())
) {
// this is a non-HFC asset transfer.
if (sentCerts > 0) {
QString recipient = userLink(valueObject["recipient_name"].toString(), valueObject["place_name"].toString());

View file

@ -687,7 +687,7 @@ void Wallet::chooseSecurityImage(const QString& filename) {
delete _securityImage;
}
QString path = PathUtils::resourcesPath();
path.append("/qml/hifi/commerce/wallet/");
path.append("/qml/hifi/dialogs/security/");
path.append(filename);
// now create a new security image pixmap

View file

@ -131,7 +131,7 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha
// should never fall in here when collision model not fully loaded
// TODO: assert that all geometries exist and are loaded
//assert(_model && _model->isLoaded() && _compoundShapeResource && _compoundShapeResource->isLoaded());
const FBXGeometry& collisionGeometry = resource->getFBXGeometry();
const HFMGeometry& collisionGeometry = resource->getHFMGeometry();
ShapeInfo::PointCollection& pointCollection = shapeInfo.getPointCollection();
pointCollection.clear();
@ -139,15 +139,15 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha
// the way OBJ files get read, each section under a "g" line is its own meshPart. We only expect
// to find one actual "mesh" (with one or more meshParts in it), but we loop over the meshes, just in case.
foreach (const FBXMesh& mesh, collisionGeometry.meshes) {
foreach (const HFMMesh& mesh, collisionGeometry.meshes) {
// each meshPart is a convex hull
foreach (const FBXMeshPart &meshPart, mesh.parts) {
foreach (const HFMMeshPart &meshPart, mesh.parts) {
pointCollection.push_back(QVector<glm::vec3>());
ShapeInfo::PointList& pointsInPart = pointCollection[i];
// run through all the triangles and (uniquely) add each point to the hull
uint32_t numIndices = (uint32_t)meshPart.triangleIndices.size();
// TODO: assert rather than workaround after we start sanitizing FBXMesh higher up
// TODO: assert rather than workaround after we start sanitizing HFMMesh higher up
//assert(numIndices % TRIANGLE_STRIDE == 0);
numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXReader
@ -168,7 +168,7 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha
// run through all the quads and (uniquely) add each point to the hull
numIndices = (uint32_t)meshPart.quadIndices.size();
// TODO: assert rather than workaround after we start sanitizing FBXMesh higher up
// TODO: assert rather than workaround after we start sanitizing HFMMesh higher up
//assert(numIndices % QUAD_STRIDE == 0);
numIndices -= numIndices % QUAD_STRIDE; // WORKAROUND lack of sanity checking in FBXReader
@ -206,7 +206,7 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha
// to the visual model and apply them to the collision model (without regard for the
// collision model's extents).
glm::vec3 scaleToFit = dimensions / resource->getFBXGeometry().getUnscaledMeshExtents().size();
glm::vec3 scaleToFit = dimensions / resource->getHFMGeometry().getUnscaledMeshExtents().size();
// multiply each point by scale
for (int32_t i = 0; i < pointCollection.size(); i++) {
for (int32_t j = 0; j < pointCollection[i].size(); j++) {
@ -216,11 +216,11 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha
}
shapeInfo.setParams(type, dimensions, resource->getURL().toString());
} else if (type >= SHAPE_TYPE_SIMPLE_HULL && type <= SHAPE_TYPE_STATIC_MESH) {
const FBXGeometry& fbxGeometry = resource->getFBXGeometry();
int numFbxMeshes = fbxGeometry.meshes.size();
const HFMGeometry& hfmGeometry = resource->getHFMGeometry();
int numHFMMeshes = hfmGeometry.meshes.size();
int totalNumVertices = 0;
for (int i = 0; i < numFbxMeshes; i++) {
const FBXMesh& mesh = fbxGeometry.meshes.at(i);
for (int i = 0; i < numHFMMeshes; i++) {
const HFMMesh& mesh = hfmGeometry.meshes.at(i);
totalNumVertices += mesh.vertices.size();
}
const int32_t MAX_VERTICES_PER_STATIC_MESH = 1e6;
@ -230,7 +230,7 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha
return;
}
auto& meshes = resource->getFBXGeometry().meshes;
auto& meshes = resource->getHFMGeometry().meshes;
int32_t numMeshes = (int32_t)(meshes.size());
const int MAX_ALLOWED_MESH_COUNT = 1000;
@ -285,12 +285,12 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha
if (type == SHAPE_TYPE_STATIC_MESH) {
// copy into triangleIndices
size_t triangleIndicesCount = 0;
for (const FBXMeshPart& meshPart : mesh.parts) {
for (const HFMMeshPart& meshPart : mesh.parts) {
triangleIndicesCount += meshPart.triangleIndices.count();
}
triangleIndices.reserve((int)triangleIndicesCount);
for (const FBXMeshPart& meshPart : mesh.parts) {
for (const HFMMeshPart& meshPart : mesh.parts) {
const int* indexItr = meshPart.triangleIndices.cbegin();
while (indexItr != meshPart.triangleIndices.cend()) {
triangleIndices.push_back(*indexItr);
@ -299,11 +299,11 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha
}
} else if (type == SHAPE_TYPE_SIMPLE_COMPOUND) {
// for each mesh copy unique part indices, separated by special bogus (flag) index values
for (const FBXMeshPart& meshPart : mesh.parts) {
for (const HFMMeshPart& meshPart : mesh.parts) {
// collect unique list of indices for this part
std::set<int32_t> uniqueIndices;
auto numIndices = meshPart.triangleIndices.count();
// TODO: assert rather than workaround after we start sanitizing FBXMesh higher up
// TODO: assert rather than workaround after we start sanitizing HFMMesh higher up
//assert(numIndices% TRIANGLE_STRIDE == 0);
numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXReader

View file

@ -446,7 +446,7 @@ QVariant ModelOverlay::getProperty(const QString& property) {
if (property == "jointNames") {
if (_model && _model->isActive()) {
// note: going through Rig because Model::getJointNames() (which proxies to FBXGeometry) was always empty
// note: going through Rig because Model::getJointNames() (which proxies to HFMGeometry) was always empty
const Rig* rig = &(_model->getRig());
return mapJoints<QStringList, QString>([rig](int jointIndex) -> QString {
return rig->nameOfJoint(jointIndex);
@ -574,7 +574,7 @@ void ModelOverlay::animate() {
QVector<JointData> jointsData;
const QVector<FBXAnimationFrame>& frames = _animation->getFramesReference(); // NOTE: getFrames() is too heavy
const QVector<HFMAnimationFrame>& frames = _animation->getFramesReference(); // NOTE: getFrames() is too heavy
int frameCount = frames.size();
if (frameCount <= 0) {
return;
@ -606,10 +606,10 @@ void ModelOverlay::animate() {
}
QStringList animationJointNames = _animation->getGeometry().getJointNames();
auto& fbxJoints = _animation->getGeometry().joints;
auto& hfmJoints = _animation->getGeometry().joints;
auto& originalFbxJoints = _model->getFBXGeometry().joints;
auto& originalFbxIndices = _model->getFBXGeometry().jointIndices;
auto& originalHFMJoints = _model->getHFMGeometry().joints;
auto& originalFbxIndices = _model->getHFMGeometry().jointIndices;
const QVector<glm::quat>& rotations = frames[_lastKnownCurrentFrame].rotations;
const QVector<glm::vec3>& translations = frames[_lastKnownCurrentFrame].translations;
@ -626,23 +626,23 @@ void ModelOverlay::animate() {
translationMat = glm::translate(translations[index]);
}
} else if (index < animationJointNames.size()) {
QString jointName = fbxJoints[index].name;
QString jointName = hfmJoints[index].name;
if (originalFbxIndices.contains(jointName)) {
// Making sure the joint names exist in the original model the animation is trying to apply onto. If they do, then remap and get its translation.
int remappedIndex = originalFbxIndices[jointName] - 1; // JointIndeces seem to always start from 1 and the found index is always 1 higher than actual.
translationMat = glm::translate(originalFbxJoints[remappedIndex].translation);
translationMat = glm::translate(originalHFMJoints[remappedIndex].translation);
}
}
glm::mat4 rotationMat;
if (index < rotations.size()) {
rotationMat = glm::mat4_cast(fbxJoints[index].preRotation * rotations[index] * fbxJoints[index].postRotation);
rotationMat = glm::mat4_cast(hfmJoints[index].preRotation * rotations[index] * hfmJoints[index].postRotation);
} else {
rotationMat = glm::mat4_cast(fbxJoints[index].preRotation * fbxJoints[index].postRotation);
rotationMat = glm::mat4_cast(hfmJoints[index].preRotation * hfmJoints[index].postRotation);
}
glm::mat4 finalMat = (translationMat * fbxJoints[index].preTransform *
rotationMat * fbxJoints[index].postTransform);
glm::mat4 finalMat = (translationMat * hfmJoints[index].preTransform *
rotationMat * hfmJoints[index].postTransform);
auto& jointData = jointsData[j];
jointData.translation = extractTranslation(finalMat);
jointData.translationIsDefaultPose = false;

View file

@ -101,7 +101,7 @@ void AnimClip::copyFromNetworkAnim() {
// build a mapping from animation joint indices to skeleton joint indices.
// by matching joints with the same name.
const FBXGeometry& geom = _networkAnim->getGeometry();
const HFMGeometry& geom = _networkAnim->getGeometry();
AnimSkeleton animSkeleton(geom);
const auto animJointCount = animSkeleton.getNumJoints();
const auto skeletonJointCount = _skeleton->getNumJoints();
@ -120,7 +120,7 @@ void AnimClip::copyFromNetworkAnim() {
for (int frame = 0; frame < frameCount; frame++) {
const FBXAnimationFrame& fbxAnimFrame = geom.animationFrames[frame];
const HFMAnimationFrame& hfmAnimFrame = geom.animationFrames[frame];
// init all joints in animation to default pose
// this will give us a resonable result for bones in the model skeleton but not in the animation.
@ -132,8 +132,8 @@ void AnimClip::copyFromNetworkAnim() {
for (int animJoint = 0; animJoint < animJointCount; animJoint++) {
int skeletonJoint = jointMap[animJoint];
const glm::vec3& fbxAnimTrans = fbxAnimFrame.translations[animJoint];
const glm::quat& fbxAnimRot = fbxAnimFrame.rotations[animJoint];
const glm::vec3& hfmAnimTrans = hfmAnimFrame.translations[animJoint];
const glm::quat& hfmAnimRot = hfmAnimFrame.rotations[animJoint];
// skip joints that are in the animation but not in the skeleton.
if (skeletonJoint >= 0 && skeletonJoint < skeletonJointCount) {
@ -146,19 +146,19 @@ void AnimClip::copyFromNetworkAnim() {
preRot.scale() = glm::vec3(1.0f);
postRot.scale() = glm::vec3(1.0f);
AnimPose rot(glm::vec3(1.0f), fbxAnimRot, glm::vec3());
AnimPose rot(glm::vec3(1.0f), hfmAnimRot, glm::vec3());
// adjust translation offsets, so large translation animatons on the reference skeleton
// will be adjusted when played on a skeleton with short limbs.
const glm::vec3& fbxZeroTrans = geom.animationFrames[0].translations[animJoint];
const glm::vec3& hfmZeroTrans = geom.animationFrames[0].translations[animJoint];
const AnimPose& relDefaultPose = _skeleton->getRelativeDefaultPose(skeletonJoint);
float boneLengthScale = 1.0f;
const float EPSILON = 0.0001f;
if (fabsf(glm::length(fbxZeroTrans)) > EPSILON) {
boneLengthScale = glm::length(relDefaultPose.trans()) / glm::length(fbxZeroTrans);
if (fabsf(glm::length(hfmZeroTrans)) > EPSILON) {
boneLengthScale = glm::length(relDefaultPose.trans()) / glm::length(hfmZeroTrans);
}
AnimPose trans = AnimPose(glm::vec3(1.0f), glm::quat(), relDefaultPose.trans() + boneLengthScale * (fbxAnimTrans - fbxZeroTrans));
AnimPose trans = AnimPose(glm::vec3(1.0f), glm::quat(), relDefaultPose.trans() + boneLengthScale * (hfmAnimTrans - hfmZeroTrans));
_anim[frame][skeletonJoint] = trans * preRot * rot * postRot;
}

View file

@ -16,17 +16,17 @@
#include "AnimationLogging.h"
AnimSkeleton::AnimSkeleton(const FBXGeometry& fbxGeometry) {
AnimSkeleton::AnimSkeleton(const HFMGeometry& geometry) {
// convert to std::vector of joints
std::vector<FBXJoint> joints;
joints.reserve(fbxGeometry.joints.size());
for (auto& joint : fbxGeometry.joints) {
std::vector<HFMJoint> joints;
joints.reserve(geometry.joints.size());
for (auto& joint : geometry.joints) {
joints.push_back(joint);
}
buildSkeletonFromJoints(joints);
}
AnimSkeleton::AnimSkeleton(const std::vector<FBXJoint>& joints) {
AnimSkeleton::AnimSkeleton(const std::vector<HFMJoint>& joints) {
buildSkeletonFromJoints(joints);
}
@ -166,7 +166,7 @@ void AnimSkeleton::mirrorAbsolutePoses(AnimPoseVec& poses) const {
}
}
void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints) {
void AnimSkeleton::buildSkeletonFromJoints(const std::vector<HFMJoint>& joints) {
_joints = joints;
_jointsSize = (int)joints.size();
// build a cache of bind poses
@ -177,7 +177,7 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints)
_relativePreRotationPoses.reserve(_jointsSize);
_relativePostRotationPoses.reserve(_jointsSize);
// iterate over FBXJoints and extract the bind pose information.
// iterate over HFMJoints and extract the bind pose information.
for (int i = 0; i < _jointsSize; i++) {
// build pre and post transforms
@ -240,7 +240,7 @@ void AnimSkeleton::dump(bool verbose) const {
qCDebug(animation) << " absDefaultPose =" << getAbsoluteDefaultPose(i);
qCDebug(animation) << " relDefaultPose =" << getRelativeDefaultPose(i);
if (verbose) {
qCDebug(animation) << " fbxJoint =";
qCDebug(animation) << " hfmJoint =";
qCDebug(animation) << " isFree =" << _joints[i].isFree;
qCDebug(animation) << " freeLineage =" << _joints[i].freeLineage;
qCDebug(animation) << " parentIndex =" << _joints[i].parentIndex;

View file

@ -23,8 +23,8 @@ public:
using Pointer = std::shared_ptr<AnimSkeleton>;
using ConstPointer = std::shared_ptr<const AnimSkeleton>;
explicit AnimSkeleton(const FBXGeometry& fbxGeometry);
explicit AnimSkeleton(const std::vector<FBXJoint>& joints);
explicit AnimSkeleton(const HFMGeometry& geometry);
explicit AnimSkeleton(const std::vector<HFMJoint>& joints);
int nameToJointIndex(const QString& jointName) const;
const QString& getJointName(int jointIndex) const;
int getNumJoints() const;
@ -64,9 +64,9 @@ public:
std::vector<int> lookUpJointIndices(const std::vector<QString>& jointNames) const;
protected:
void buildSkeletonFromJoints(const std::vector<FBXJoint>& joints);
void buildSkeletonFromJoints(const std::vector<HFMJoint>& joints);
std::vector<FBXJoint> _joints;
std::vector<HFMJoint> _joints;
int _jointsSize { 0 };
AnimPoseVec _relativeDefaultPoses;
AnimPoseVec _absoluteDefaultPoses;

View file

@ -69,7 +69,7 @@ void AnimationReader::run() {
if (urlValid) {
// Parse the FBX directly from the QNetworkReply
FBXGeometry::Pointer fbxgeo;
HFMGeometry::Pointer fbxgeo;
if (_url.path().toLower().endsWith(".fbx")) {
fbxgeo.reset(readFBX(_data, QVariantHash(), _url.path()));
} else {
@ -100,40 +100,40 @@ QStringList Animation::getJointNames() const {
}
QStringList names;
if (_geometry) {
foreach (const FBXJoint& joint, _geometry->joints) {
foreach (const HFMJoint& joint, _geometry->joints) {
names.append(joint.name);
}
}
return names;
}
QVector<FBXAnimationFrame> Animation::getFrames() const {
QVector<HFMAnimationFrame> Animation::getFrames() const {
if (QThread::currentThread() != thread()) {
QVector<FBXAnimationFrame> result;
QVector<HFMAnimationFrame> result;
BLOCKING_INVOKE_METHOD(const_cast<Animation*>(this), "getFrames",
Q_RETURN_ARG(QVector<FBXAnimationFrame>, result));
Q_RETURN_ARG(QVector<HFMAnimationFrame>, result));
return result;
}
if (_geometry) {
return _geometry->animationFrames;
} else {
return QVector<FBXAnimationFrame>();
return QVector<HFMAnimationFrame>();
}
}
const QVector<FBXAnimationFrame>& Animation::getFramesReference() const {
const QVector<HFMAnimationFrame>& Animation::getFramesReference() const {
return _geometry->animationFrames;
}
void Animation::downloadFinished(const QByteArray& data) {
// parse the animation/fbx file on a background thread.
AnimationReader* animationReader = new AnimationReader(_url, data);
connect(animationReader, SIGNAL(onSuccess(FBXGeometry::Pointer)), SLOT(animationParseSuccess(FBXGeometry::Pointer)));
connect(animationReader, SIGNAL(onSuccess(HFMGeometry::Pointer)), SLOT(animationParseSuccess(HFMGeometry::Pointer)));
connect(animationReader, SIGNAL(onError(int, QString)), SLOT(animationParseError(int, QString)));
QThreadPool::globalInstance()->start(animationReader);
}
void Animation::animationParseSuccess(FBXGeometry::Pointer geometry) {
void Animation::animationParseSuccess(HFMGeometry::Pointer geometry) {
qCDebug(animation) << "Animation parse success" << _url.toDisplayString();

View file

@ -66,7 +66,7 @@ public:
QString getType() const override { return "Animation"; }
const FBXGeometry& getGeometry() const { return *_geometry; }
const HFMGeometry& getGeometry() const { return *_geometry; }
virtual bool isLoaded() const override;
@ -80,20 +80,20 @@ public:
* @function AnimationObject.getFrames
* @returns {FBXAnimationFrame[]}
*/
Q_INVOKABLE QVector<FBXAnimationFrame> getFrames() const;
Q_INVOKABLE QVector<HFMAnimationFrame> getFrames() const;
const QVector<FBXAnimationFrame>& getFramesReference() const;
const QVector<HFMAnimationFrame>& getFramesReference() const;
protected:
virtual void downloadFinished(const QByteArray& data) override;
protected slots:
void animationParseSuccess(FBXGeometry::Pointer geometry);
void animationParseSuccess(HFMGeometry::Pointer geometry);
void animationParseError(int error, QString str);
private:
FBXGeometry::Pointer _geometry;
HFMGeometry::Pointer _geometry;
};
/// Reads geometry in a worker thread.
@ -105,7 +105,7 @@ public:
virtual void run() override;
signals:
void onSuccess(FBXGeometry::Pointer geometry);
void onSuccess(HFMGeometry::Pointer geometry);
void onError(int error, QString str);
private:

View file

@ -19,17 +19,17 @@ QStringList AnimationObject::getJointNames() const {
return qscriptvalue_cast<AnimationPointer>(thisObject())->getJointNames();
}
QVector<FBXAnimationFrame> AnimationObject::getFrames() const {
QVector<HFMAnimationFrame> AnimationObject::getFrames() const {
return qscriptvalue_cast<AnimationPointer>(thisObject())->getFrames();
}
QVector<glm::quat> AnimationFrameObject::getRotations() const {
return qscriptvalue_cast<FBXAnimationFrame>(thisObject()).rotations;
return qscriptvalue_cast<HFMAnimationFrame>(thisObject()).rotations;
}
void registerAnimationTypes(QScriptEngine* engine) {
qScriptRegisterSequenceMetaType<QVector<FBXAnimationFrame> >(engine);
engine->setDefaultPrototype(qMetaTypeId<FBXAnimationFrame>(), engine->newQObject(
qScriptRegisterSequenceMetaType<QVector<HFMAnimationFrame> >(engine);
engine->setDefaultPrototype(qMetaTypeId<HFMAnimationFrame>(), engine->newQObject(
new AnimationFrameObject(), QScriptEngine::ScriptOwnership));
engine->setDefaultPrototype(qMetaTypeId<AnimationPointer>(), engine->newQObject(
new AnimationObject(), QScriptEngine::ScriptOwnership));

View file

@ -23,13 +23,13 @@ class QScriptEngine;
class AnimationObject : public QObject, protected QScriptable {
Q_OBJECT
Q_PROPERTY(QStringList jointNames READ getJointNames)
Q_PROPERTY(QVector<FBXAnimationFrame> frames READ getFrames)
Q_PROPERTY(QVector<HFMAnimationFrame> frames READ getFrames)
public:
Q_INVOKABLE QStringList getJointNames() const;
Q_INVOKABLE QVector<FBXAnimationFrame> getFrames() const;
Q_INVOKABLE QVector<HFMAnimationFrame> getFrames() const;
};
/// Scriptable wrapper for animation frames.

View file

@ -260,7 +260,7 @@ void Rig::destroyAnimGraph() {
_rightEyeJointChildren.clear();
}
void Rig::initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOffset) {
void Rig::initJointStates(const HFMGeometry& geometry, const glm::mat4& modelOffset) {
_geometryOffset = AnimPose(geometry.offset);
_invGeometryOffset = _geometryOffset.inverse();
_geometryToRigTransform = modelOffset * geometry.offset;
@ -307,7 +307,7 @@ void Rig::initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOff
_rightEyeJointChildren = _animSkeleton->getChildrenOfJoint(geometry.rightEyeJointIndex);
}
void Rig::reset(const FBXGeometry& geometry) {
void Rig::reset(const HFMGeometry& geometry) {
_geometryOffset = AnimPose(geometry.offset);
_invGeometryOffset = _geometryOffset.inverse();
_animSkeleton = std::make_shared<AnimSkeleton>(geometry);
@ -1253,7 +1253,7 @@ const glm::vec3 DOP14_NORMALS[DOP14_COUNT] = {
// returns true if the given point lies inside of the k-dop, specified by shapeInfo & shapePose.
// if the given point does lie within the k-dop, it also returns the amount of displacement necessary to push that point outward
// such that it lies on the surface of the kdop.
static bool findPointKDopDisplacement(const glm::vec3& point, const AnimPose& shapePose, const FBXJointShapeInfo& shapeInfo, glm::vec3& displacementOut) {
static bool findPointKDopDisplacement(const glm::vec3& point, const AnimPose& shapePose, const HFMJointShapeInfo& shapeInfo, glm::vec3& displacementOut) {
// transform point into local space of jointShape.
glm::vec3 localPoint = shapePose.inverse().xformPoint(point);
@ -1299,8 +1299,8 @@ static bool findPointKDopDisplacement(const glm::vec3& point, const AnimPose& sh
}
}
glm::vec3 Rig::deflectHandFromTorso(const glm::vec3& handPosition, const FBXJointShapeInfo& hipsShapeInfo, const FBXJointShapeInfo& spineShapeInfo,
const FBXJointShapeInfo& spine1ShapeInfo, const FBXJointShapeInfo& spine2ShapeInfo) const {
glm::vec3 Rig::deflectHandFromTorso(const glm::vec3& handPosition, const HFMJointShapeInfo& hipsShapeInfo, const HFMJointShapeInfo& spineShapeInfo,
const HFMJointShapeInfo& spine1ShapeInfo, const HFMJointShapeInfo& spine2ShapeInfo) const {
glm::vec3 position = handPosition;
glm::vec3 displacement;
int hipsJoint = indexOfJoint("Hips");
@ -1349,8 +1349,8 @@ glm::vec3 Rig::deflectHandFromTorso(const glm::vec3& handPosition, const FBXJoin
void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnabled, bool hipsEstimated,
bool leftArmEnabled, bool rightArmEnabled, bool headEnabled, float dt,
const AnimPose& leftHandPose, const AnimPose& rightHandPose,
const FBXJointShapeInfo& hipsShapeInfo, const FBXJointShapeInfo& spineShapeInfo,
const FBXJointShapeInfo& spine1ShapeInfo, const FBXJointShapeInfo& spine2ShapeInfo,
const HFMJointShapeInfo& hipsShapeInfo, const HFMJointShapeInfo& spineShapeInfo,
const HFMJointShapeInfo& spine1ShapeInfo, const HFMJointShapeInfo& spine2ShapeInfo,
const glm::mat4& rigToSensorMatrix, const glm::mat4& sensorToRigMatrix) {
const bool ENABLE_POLE_VECTORS = true;
@ -2008,7 +2008,7 @@ void Rig::computeExternalPoses(const glm::mat4& modelOffsetMat) {
}
void Rig::computeAvatarBoundingCapsule(
const FBXGeometry& geometry,
const HFMGeometry& geometry,
float& radiusOut,
float& heightOut,
glm::vec3& localOffsetOut) const {
@ -2041,7 +2041,7 @@ void Rig::computeAvatarBoundingCapsule(
// from the head to the hips when computing the rest of the bounding capsule.
int index = indexOfJoint("Head");
while (index != -1) {
const FBXJointShapeInfo& shapeInfo = geometry.joints.at(index).shapeInfo;
const HFMJointShapeInfo& shapeInfo = geometry.joints.at(index).shapeInfo;
AnimPose pose = _animSkeleton->getAbsoluteDefaultPose(index);
if (shapeInfo.points.size() > 0) {
for (auto& point : shapeInfo.points) {

View file

@ -86,10 +86,10 @@ public:
AnimPose secondaryControllerPoses[NumSecondaryControllerTypes]; // rig space
uint8_t secondaryControllerFlags[NumSecondaryControllerTypes];
bool isTalking;
FBXJointShapeInfo hipsShapeInfo;
FBXJointShapeInfo spineShapeInfo;
FBXJointShapeInfo spine1ShapeInfo;
FBXJointShapeInfo spine2ShapeInfo;
HFMJointShapeInfo hipsShapeInfo;
HFMJointShapeInfo spineShapeInfo;
HFMJointShapeInfo spine1ShapeInfo;
HFMJointShapeInfo spine2ShapeInfo;
};
struct EyeParameters {
@ -122,8 +122,8 @@ public:
void overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
void restoreRoleAnimation(const QString& role);
void initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOffset);
void reset(const FBXGeometry& geometry);
void initJointStates(const HFMGeometry& geometry, const glm::mat4& modelOffset);
void reset(const HFMGeometry& geometry);
bool jointStatesEmpty();
int getJointStateCount() const;
int indexOfJoint(const QString& jointName) const;
@ -210,7 +210,7 @@ public:
void copyJointsFromJointData(const QVector<JointData>& jointDataVec);
void computeExternalPoses(const glm::mat4& modelOffsetMat);
void computeAvatarBoundingCapsule(const FBXGeometry& geometry, float& radiusOut, float& heightOut, glm::vec3& offsetOut) const;
void computeAvatarBoundingCapsule(const HFMGeometry& geometry, float& radiusOut, float& heightOut, glm::vec3& offsetOut) const;
void setEnableInverseKinematics(bool enable);
void setEnableAnimations(bool enable);
@ -245,8 +245,8 @@ protected:
void updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnabled, bool hipsEstimated,
bool leftArmEnabled, bool rightArmEnabled, bool headEnabled, float dt,
const AnimPose& leftHandPose, const AnimPose& rightHandPose,
const FBXJointShapeInfo& hipsShapeInfo, const FBXJointShapeInfo& spineShapeInfo,
const FBXJointShapeInfo& spine1ShapeInfo, const FBXJointShapeInfo& spine2ShapeInfo,
const HFMJointShapeInfo& hipsShapeInfo, const HFMJointShapeInfo& spineShapeInfo,
const HFMJointShapeInfo& spine1ShapeInfo, const HFMJointShapeInfo& spine2ShapeInfo,
const glm::mat4& rigToSensorMatrix, const glm::mat4& sensorToRigMatrix);
void updateFeet(bool leftFootEnabled, bool rightFootEnabled, bool headEnabled,
const AnimPose& leftFootPose, const AnimPose& rightFootPose,
@ -257,8 +257,8 @@ protected:
bool calculateElbowPoleVector(int handIndex, int elbowIndex, int armIndex, int oppositeArmIndex, glm::vec3& poleVector) const;
glm::vec3 calculateKneePoleVector(int footJointIndex, int kneeJoint, int upLegIndex, int hipsIndex, const AnimPose& targetFootPose) const;
glm::vec3 deflectHandFromTorso(const glm::vec3& handPosition, const FBXJointShapeInfo& hipsShapeInfo, const FBXJointShapeInfo& spineShapeInfo,
const FBXJointShapeInfo& spine1ShapeInfo, const FBXJointShapeInfo& spine2ShapeInfo) const;
glm::vec3 deflectHandFromTorso(const glm::vec3& handPosition, const HFMJointShapeInfo& hipsShapeInfo, const HFMJointShapeInfo& spineShapeInfo,
const HFMJointShapeInfo& spine1ShapeInfo, const HFMJointShapeInfo& spine2ShapeInfo) const;
AnimPose _modelOffset; // model to rig space

View file

@ -244,13 +244,20 @@ AudioClient::AudioClient() :
// initialize wasapi; if getAvailableDevices is called from the CheckDevicesThread before this, it will crash
getAvailableDevices(QAudio::AudioInput);
getAvailableDevices(QAudio::AudioOutput);
// start a thread to detect any device changes
_checkDevicesTimer = new QTimer(this);
connect(_checkDevicesTimer, &QTimer::timeout, this, [this] {
QtConcurrent::run(QThreadPool::globalInstance(), [this] { checkDevices(); });
});
const unsigned long DEVICE_CHECK_INTERVAL_MSECS = 2 * 1000;
connect(_checkDevicesTimer, &QTimer::timeout, this, [=] {
QtConcurrent::run(QThreadPool::globalInstance(), [=] {
checkDevices();
// On some systems (Ubuntu) checking all the audio devices can take more than 2 seconds. To
// avoid consuming all of the thread pool, don't start the check interval until the previous
// check has completed.
QMetaObject::invokeMethod(_checkDevicesTimer, "start", Q_ARG(int, DEVICE_CHECK_INTERVAL_MSECS));
});
});
_checkDevicesTimer->setSingleShot(true);
_checkDevicesTimer->start(DEVICE_CHECK_INTERVAL_MSECS);
// start a thread to detect peak value changes

View file

@ -498,8 +498,8 @@ void Avatar::relayJointDataToChildren() {
glm::quat jointRotation;
glm::vec3 jointTranslation;
if (avatarJointIndex < 0) {
jointRotation = modelEntity->getAbsoluteJointRotationInObjectFrame(jointIndex);
jointTranslation = modelEntity->getAbsoluteJointTranslationInObjectFrame(jointIndex);
jointRotation = modelEntity->getLocalJointRotation(jointIndex);
jointTranslation = modelEntity->getLocalJointTranslation(jointIndex);
map.push_back(-1);
} else {
int jointIndex = getJointIndex(jointName);
@ -522,8 +522,8 @@ void Avatar::relayJointDataToChildren() {
jointRotation = getJointRotation(avatarJointIndex);
jointTranslation = getJointTranslation(avatarJointIndex);
} else {
jointRotation = modelEntity->getAbsoluteJointRotationInObjectFrame(jointIndex);
jointTranslation = modelEntity->getAbsoluteJointTranslationInObjectFrame(jointIndex);
jointRotation = modelEntity->getLocalJointRotation(jointIndex);
jointTranslation = modelEntity->getLocalJointTranslation(jointIndex);
}
modelEntity->setLocalJointRotation(jointIndex, jointRotation);
modelEntity->setLocalJointTranslation(jointIndex, jointTranslation);
@ -1311,7 +1311,7 @@ glm::quat Avatar::getAbsoluteJointRotationInObjectFrame(int index) const {
case CAMERA_MATRIX_INDEX: {
glm::quat rotation;
if (_skeletonModel && _skeletonModel->isActive()) {
int headJointIndex = _skeletonModel->getFBXGeometry().headJointIndex;
int headJointIndex = _skeletonModel->getHFMGeometry().headJointIndex;
if (headJointIndex >= 0) {
_skeletonModel->getAbsoluteJointRotationInRigFrame(headJointIndex, rotation);
}
@ -1360,7 +1360,7 @@ glm::vec3 Avatar::getAbsoluteJointTranslationInObjectFrame(int index) const {
case CAMERA_MATRIX_INDEX: {
glm::vec3 translation;
if (_skeletonModel && _skeletonModel->isActive()) {
int headJointIndex = _skeletonModel->getFBXGeometry().headJointIndex;
int headJointIndex = _skeletonModel->getHFMGeometry().headJointIndex;
if (headJointIndex >= 0) {
_skeletonModel->getAbsoluteJointTranslationInRigFrame(headJointIndex, translation);
}
@ -1416,7 +1416,7 @@ void Avatar::withValidJointIndicesCache(std::function<void()> const& worker) con
if (!_modelJointsCached) {
_modelJointIndicesCache.clear();
if (_skeletonModel && _skeletonModel->isActive()) {
_modelJointIndicesCache = _skeletonModel->getFBXGeometry().jointIndices;
_modelJointIndicesCache = _skeletonModel->getHFMGeometry().jointIndices;
_modelJointsCached = true;
}
}

View file

@ -54,7 +54,7 @@ void SkeletonModel::setTextures(const QVariantMap& textures) {
}
void SkeletonModel::initJointStates() {
const FBXGeometry& geometry = getFBXGeometry();
const HFMGeometry& geometry = getHFMGeometry();
glm::mat4 modelOffset = glm::scale(_scale) * glm::translate(_offset);
_rig.initJointStates(geometry, modelOffset);
@ -96,7 +96,7 @@ void SkeletonModel::initJointStates() {
// Called within Model::simulate call, below.
void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
assert(!_owningAvatar->isMyAvatar());
const FBXGeometry& geometry = getFBXGeometry();
const HFMGeometry& geometry = getHFMGeometry();
Head* head = _owningAvatar->getHead();
@ -259,22 +259,22 @@ bool SkeletonModel::getRightShoulderPosition(glm::vec3& position) const {
}
bool SkeletonModel::getHeadPosition(glm::vec3& headPosition) const {
return isActive() && getJointPositionInWorldFrame(getFBXGeometry().headJointIndex, headPosition);
return isActive() && getJointPositionInWorldFrame(getHFMGeometry().headJointIndex, headPosition);
}
bool SkeletonModel::getNeckPosition(glm::vec3& neckPosition) const {
return isActive() && getJointPositionInWorldFrame(getFBXGeometry().neckJointIndex, neckPosition);
return isActive() && getJointPositionInWorldFrame(getHFMGeometry().neckJointIndex, neckPosition);
}
bool SkeletonModel::getLocalNeckPosition(glm::vec3& neckPosition) const {
return isActive() && getJointPosition(getFBXGeometry().neckJointIndex, neckPosition);
return isActive() && getJointPosition(getHFMGeometry().neckJointIndex, neckPosition);
}
bool SkeletonModel::getEyeModelPositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const {
if (!isActive()) {
return false;
}
const FBXGeometry& geometry = getFBXGeometry();
const HFMGeometry& geometry = getHFMGeometry();
if (getJointPosition(geometry.leftEyeJointIndex, firstEyePosition) &&
getJointPosition(geometry.rightEyeJointIndex, secondEyePosition)) {
@ -330,7 +330,7 @@ void SkeletonModel::computeBoundingShape() {
return;
}
const FBXGeometry& geometry = getFBXGeometry();
const HFMGeometry& geometry = getHFMGeometry();
if (geometry.joints.isEmpty() || geometry.rootJointIndex == -1) {
// rootJointIndex == -1 if the avatar model has no skeleton
return;
@ -369,7 +369,7 @@ void SkeletonModel::renderBoundingCollisionShapes(RenderArgs* args, gpu::Batch&
}
bool SkeletonModel::hasSkeleton() {
return isActive() ? getFBXGeometry().rootJointIndex != -1 : false;
return isActive() ? getHFMGeometry().rootJointIndex != -1 : false;
}
void SkeletonModel::onInvalidate() {

View file

@ -41,10 +41,10 @@ public:
void updateAttitude(const glm::quat& orientation);
/// Returns the index of the left hand joint, or -1 if not found.
int getLeftHandJointIndex() const { return isActive() ? getFBXGeometry().leftHandJointIndex : -1; }
int getLeftHandJointIndex() const { return isActive() ? getHFMGeometry().leftHandJointIndex : -1; }
/// Returns the index of the right hand joint, or -1 if not found.
int getRightHandJointIndex() const { return isActive() ? getFBXGeometry().rightHandJointIndex : -1; }
int getRightHandJointIndex() const { return isActive() ? getHFMGeometry().rightHandJointIndex : -1; }
bool getLeftGrabPosition(glm::vec3& position) const;
bool getRightGrabPosition(glm::vec3& position) const;

View file

@ -206,7 +206,7 @@ void FBXBaker::importScene() {
}
#endif
_geometry = reader.extractFBXGeometry({}, _modelURL.toString());
_geometry = reader.extractHFMGeometry({}, _modelURL.toString());
_textureContentMap = reader._textureContent;
}
@ -329,7 +329,7 @@ void FBXBaker::rewriteAndBakeSceneTextures() {
for (FBXNode& textureChild : object->children) {
if (textureChild.name == "RelativeFilename") {
QString fbxTextureFileName { textureChild.properties.at(0).toString() };
QString hfmTextureFileName { textureChild.properties.at(0).toString() };
// grab the ID for this texture so we can figure out the
// texture type from the loaded materials
@ -337,7 +337,7 @@ void FBXBaker::rewriteAndBakeSceneTextures() {
auto textureType = textureTypes[textureID];
// Compress the texture information and return the new filename to be added into the FBX scene
auto bakedTextureFile = compressTexture(fbxTextureFileName, textureType);
auto bakedTextureFile = compressTexture(hfmTextureFileName, textureType);
// If no errors or warnings have occurred during texture compression add the filename to the FBX scene
if (!bakedTextureFile.isNull()) {

View file

@ -53,7 +53,7 @@ private:
void rewriteAndBakeSceneModels();
void rewriteAndBakeSceneTextures();
FBXGeometry* _geometry;
HFMGeometry* _geometry;
QHash<QString, int> _textureNameMatchCount;
QHash<QUrl, QString> _remappedTexturePaths;

View file

@ -75,7 +75,7 @@ void ModelBaker::abort() {
}
}
bool ModelBaker::compressMesh(FBXMesh& mesh, bool hasDeformers, FBXNode& dracoMeshNode, GetMaterialIDCallback materialIDCallback) {
bool ModelBaker::compressMesh(HFMMesh& mesh, bool hasDeformers, FBXNode& dracoMeshNode, GetMaterialIDCallback materialIDCallback) {
if (mesh.wasCompressed) {
handleError("Cannot re-bake a file that contains compressed mesh");
return false;

View file

@ -39,7 +39,7 @@ public:
const QString& bakedOutputDirectory, const QString& originalOutputDirectory = "");
virtual ~ModelBaker();
bool compressMesh(FBXMesh& mesh, bool hasDeformers, FBXNode& dracoMeshNode, GetMaterialIDCallback materialIDCallback = nullptr);
bool compressMesh(HFMMesh& mesh, bool hasDeformers, FBXNode& dracoMeshNode, GetMaterialIDCallback materialIDCallback = nullptr);
QString compressTexture(QString textureFileName, image::TextureUsage::Type = image::TextureUsage::Type::DEFAULT_TEXTURE);
virtual void setWasAborted(bool wasAborted) override;

View file

@ -153,7 +153,7 @@ void OBJBaker::bakeOBJ() {
checkIfTexturesFinished();
}
void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
void OBJBaker::createFBXNodeTree(FBXNode& rootNode, HFMGeometry& geometry) {
// Generating FBX Header Node
FBXNode headerNode;
headerNode.name = FBX_HEADER_EXTENSION;
@ -235,7 +235,7 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
auto size = meshParts.size();
for (int i = 0; i < size; i++) {
QString material = meshParts[i].materialID;
FBXMaterial currentMaterial = geometry.materials[material];
HFMMaterial currentMaterial = geometry.materials[material];
if (!currentMaterial.albedoTexture.filename.isEmpty() || !currentMaterial.specularTexture.filename.isEmpty()) {
auto textureID = nextNodeID();
_mapTextureMaterial.emplace_back(textureID, i);
@ -325,12 +325,12 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
}
// Set properties for material nodes
void OBJBaker::setMaterialNodeProperties(FBXNode& materialNode, QString material, FBXGeometry& geometry) {
void OBJBaker::setMaterialNodeProperties(FBXNode& materialNode, QString material, HFMGeometry& geometry) {
auto materialID = nextNodeID();
_materialIDs.push_back(materialID);
materialNode.properties = { materialID, material, MESH };
FBXMaterial currentMaterial = geometry.materials[material];
HFMMaterial currentMaterial = geometry.materials[material];
// Setting the hierarchy: Material -> Properties70 -> P -> Properties
FBXNode properties70Node;

View file

@ -39,8 +39,8 @@ private slots:
private:
void loadOBJ();
void createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry);
void setMaterialNodeProperties(FBXNode& materialNode, QString material, FBXGeometry& geometry);
void createFBXNodeTree(FBXNode& rootNode, HFMGeometry& geometry);
void setMaterialNodeProperties(FBXNode& materialNode, QString material, HFMGeometry& geometry);
NodeID nextNodeID() { return _nodeID++; }

View file

@ -268,7 +268,7 @@ EntityItemProperties RenderableModelEntityItem::getProperties(const EntityProper
if (model->isLoaded()) {
// TODO: improve naturalDimensions in the future,
// for now we've added this hack for setting natural dimensions of models
Extents meshExtents = model->getFBXGeometry().getUnscaledMeshExtents();
Extents meshExtents = model->getHFMGeometry().getUnscaledMeshExtents();
properties.setNaturalDimensions(meshExtents.maximum - meshExtents.minimum);
properties.calculateNaturalPosition(meshExtents.minimum, meshExtents.maximum);
}
@ -403,7 +403,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
// should never fall in here when collision model not fully loaded
// TODO: assert that all geometries exist and are loaded
//assert(_model && _model->isLoaded() && _compoundShapeResource && _compoundShapeResource->isLoaded());
const FBXGeometry& collisionGeometry = _compoundShapeResource->getFBXGeometry();
const HFMGeometry& collisionGeometry = _compoundShapeResource->getHFMGeometry();
ShapeInfo::PointCollection& pointCollection = shapeInfo.getPointCollection();
pointCollection.clear();
@ -411,15 +411,15 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
// the way OBJ files get read, each section under a "g" line is its own meshPart. We only expect
// to find one actual "mesh" (with one or more meshParts in it), but we loop over the meshes, just in case.
foreach (const FBXMesh& mesh, collisionGeometry.meshes) {
foreach (const HFMMesh& mesh, collisionGeometry.meshes) {
// each meshPart is a convex hull
foreach (const FBXMeshPart &meshPart, mesh.parts) {
foreach (const HFMMeshPart &meshPart, mesh.parts) {
pointCollection.push_back(QVector<glm::vec3>());
ShapeInfo::PointList& pointsInPart = pointCollection[i];
// run through all the triangles and (uniquely) add each point to the hull
uint32_t numIndices = (uint32_t)meshPart.triangleIndices.size();
// TODO: assert rather than workaround after we start sanitizing FBXMesh higher up
// TODO: assert rather than workaround after we start sanitizing HFMMesh higher up
//assert(numIndices % TRIANGLE_STRIDE == 0);
numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXReader
@ -440,7 +440,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
// run through all the quads and (uniquely) add each point to the hull
numIndices = (uint32_t)meshPart.quadIndices.size();
// TODO: assert rather than workaround after we start sanitizing FBXMesh higher up
// TODO: assert rather than workaround after we start sanitizing HFMMesh higher up
//assert(numIndices % QUAD_STRIDE == 0);
numIndices -= numIndices % QUAD_STRIDE; // WORKAROUND lack of sanity checking in FBXReader
@ -478,7 +478,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
// to the visual model and apply them to the collision model (without regard for the
// collision model's extents).
glm::vec3 scaleToFit = dimensions / model->getFBXGeometry().getUnscaledMeshExtents().size();
glm::vec3 scaleToFit = dimensions / model->getHFMGeometry().getUnscaledMeshExtents().size();
// multiply each point by scale before handing the point-set off to the physics engine.
// also determine the extents of the collision model.
glm::vec3 registrationOffset = dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint());
@ -498,14 +498,14 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
// compute meshPart local transforms
QVector<glm::mat4> localTransforms;
const FBXGeometry& fbxGeometry = model->getFBXGeometry();
int numFbxMeshes = fbxGeometry.meshes.size();
const HFMGeometry& hfmGeometry = model->getHFMGeometry();
int numHFMMeshes = hfmGeometry.meshes.size();
int totalNumVertices = 0;
glm::mat4 invRegistraionOffset = glm::translate(dimensions * (getRegistrationPoint() - ENTITY_ITEM_DEFAULT_REGISTRATION_POINT));
for (int i = 0; i < numFbxMeshes; i++) {
const FBXMesh& mesh = fbxGeometry.meshes.at(i);
for (int i = 0; i < numHFMMeshes; i++) {
const HFMMesh& mesh = hfmGeometry.meshes.at(i);
if (mesh.clusters.size() > 0) {
const FBXCluster& cluster = mesh.clusters.at(0);
const HFMCluster& cluster = mesh.clusters.at(0);
auto jointMatrix = model->getRig().getJointTransform(cluster.jointIndex);
// we backtranslate by the registration offset so we can apply that offset to the shapeInfo later
localTransforms.push_back(invRegistraionOffset * jointMatrix * cluster.inverseBindMatrix);
@ -524,10 +524,10 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
std::vector<std::shared_ptr<const graphics::Mesh>> meshes;
if (type == SHAPE_TYPE_SIMPLE_COMPOUND) {
auto& fbxMeshes = _compoundShapeResource->getFBXGeometry().meshes;
meshes.reserve(fbxMeshes.size());
for (auto& fbxMesh : fbxMeshes) {
meshes.push_back(fbxMesh._mesh);
auto& hfmMeshes = _compoundShapeResource->getHFMGeometry().meshes;
meshes.reserve(hfmMeshes.size());
for (auto& hfmMesh : hfmMeshes) {
meshes.push_back(hfmMesh._mesh);
}
} else {
meshes = model->getGeometry()->getMeshes();
@ -594,7 +594,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
while (partItr != parts.cend<const graphics::Mesh::Part>()) {
auto numIndices = partItr->_numIndices;
if (partItr->_topology == graphics::Mesh::TRIANGLES) {
// TODO: assert rather than workaround after we start sanitizing FBXMesh higher up
// TODO: assert rather than workaround after we start sanitizing HFMMesh higher up
//assert(numIndices % TRIANGLE_STRIDE == 0);
numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXReader
@ -605,7 +605,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
++indexItr;
}
} else if (partItr->_topology == graphics::Mesh::TRIANGLE_STRIP) {
// TODO: resurrect assert after we start sanitizing FBXMesh higher up
// TODO: resurrect assert after we start sanitizing HFMMesh higher up
//assert(numIndices > 2);
uint32_t approxNumIndices = TRIANGLE_STRIDE * numIndices;
@ -651,7 +651,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
std::set<int32_t> uniqueIndices;
auto numIndices = partItr->_numIndices;
if (partItr->_topology == graphics::Mesh::TRIANGLES) {
// TODO: assert rather than workaround after we start sanitizing FBXMesh higher up
// TODO: assert rather than workaround after we start sanitizing HFMMesh higher up
//assert(numIndices% TRIANGLE_STRIDE == 0);
numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXReader
@ -662,7 +662,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
++indexItr;
}
} else if (partItr->_topology == graphics::Mesh::TRIANGLE_STRIP) {
// TODO: resurrect assert after we start sanitizing FBXMesh higher up
// TODO: resurrect assert after we start sanitizing HFMMesh higher up
//assert(numIndices > TRIANGLE_STRIDE - 1);
auto indexItr = indices.cbegin<const gpu::BufferView::Index>() + partItr->_startIndex;
@ -755,7 +755,7 @@ int RenderableModelEntityItem::avatarJointIndex(int modelJointIndex) {
bool RenderableModelEntityItem::contains(const glm::vec3& point) const {
auto model = getModel();
if (EntityItem::contains(point) && model && _compoundShapeResource && _compoundShapeResource->isLoaded()) {
return _compoundShapeResource->getFBXGeometry().convexHullContains(worldToEntity(point));
return _compoundShapeResource->getHFMGeometry().convexHullContains(worldToEntity(point));
}
return false;
@ -1135,7 +1135,7 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) {
QVector<EntityJointData> jointsData;
const QVector<FBXAnimationFrame>& frames = _animation->getFramesReference(); // NOTE: getFrames() is too heavy
const QVector<HFMAnimationFrame>& frames = _animation->getFramesReference(); // NOTE: getFrames() is too heavy
int frameCount = frames.size();
if (frameCount <= 0) {
return;
@ -1160,10 +1160,10 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) {
}
QStringList animationJointNames = _animation->getGeometry().getJointNames();
auto& fbxJoints = _animation->getGeometry().joints;
auto& hfmJoints = _animation->getGeometry().joints;
auto& originalFbxJoints = _model->getFBXGeometry().joints;
auto& originalFbxIndices = _model->getFBXGeometry().jointIndices;
auto& originalHFMJoints = _model->getHFMGeometry().joints;
auto& originalHFMIndices = _model->getHFMGeometry().jointIndices;
bool allowTranslation = entity->getAnimationAllowTranslation();
@ -1182,22 +1182,22 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) {
translationMat = glm::translate(translations[index]);
}
} else if (index < animationJointNames.size()) {
QString jointName = fbxJoints[index].name; // Pushing this here so its not done on every entity, with the exceptions of those allowing for translation
if (originalFbxIndices.contains(jointName)) {
QString jointName = hfmJoints[index].name; // Pushing this here so its not done on every entity, with the exceptions of those allowing for translation
if (originalHFMIndices.contains(jointName)) {
// Making sure the joint names exist in the original model the animation is trying to apply onto. If they do, then remap and get it's translation.
int remappedIndex = originalFbxIndices[jointName] - 1; // JointIndeces seem to always start from 1 and the found index is always 1 higher than actual.
translationMat = glm::translate(originalFbxJoints[remappedIndex].translation);
int remappedIndex = originalHFMIndices[jointName] - 1; // JointIndeces seem to always start from 1 and the found index is always 1 higher than actual.
translationMat = glm::translate(originalHFMJoints[remappedIndex].translation);
}
}
glm::mat4 rotationMat;
if (index < rotations.size()) {
rotationMat = glm::mat4_cast(fbxJoints[index].preRotation * rotations[index] * fbxJoints[index].postRotation);
rotationMat = glm::mat4_cast(hfmJoints[index].preRotation * rotations[index] * hfmJoints[index].postRotation);
} else {
rotationMat = glm::mat4_cast(fbxJoints[index].preRotation * fbxJoints[index].postRotation);
rotationMat = glm::mat4_cast(hfmJoints[index].preRotation * hfmJoints[index].postRotation);
}
glm::mat4 finalMat = (translationMat * fbxJoints[index].preTransform *
rotationMat * fbxJoints[index].postTransform);
glm::mat4 finalMat = (translationMat * hfmJoints[index].preTransform *
rotationMat * hfmJoints[index].postTransform);
auto& jointData = jointsData[j];
jointData.translation = extractTranslation(finalMat);
jointData.translationSet = true;

View file

@ -70,8 +70,8 @@ public:
};
/// A single blendshape extracted from an FBX document.
class FBXBlendshape {
/// A single blendshape.
class HFMBlendshape {
public:
QVector<int> indices;
QVector<glm::vec3> vertices;
@ -79,19 +79,19 @@ public:
QVector<glm::vec3> tangents;
};
struct FBXJointShapeInfo {
// same units and frame as FBXJoint.translation
struct HFMJointShapeInfo {
// same units and frame as HFMJoint.translation
glm::vec3 avgPoint;
std::vector<float> dots;
std::vector<glm::vec3> points;
std::vector<glm::vec3> debugLines;
};
/// A single joint (transformation node) extracted from an FBX document.
class FBXJoint {
/// A single joint (transformation node).
class HFMJoint {
public:
FBXJointShapeInfo shapeInfo;
HFMJointShapeInfo shapeInfo;
QVector<int> freeLineage;
bool isFree;
int parentIndex;
@ -126,8 +126,8 @@ public:
};
/// A single binding to a joint in an FBX document.
class FBXCluster {
/// A single binding to a joint.
class HFMCluster {
public:
int jointIndex;
@ -137,8 +137,8 @@ public:
const int MAX_NUM_PIXELS_FOR_FBX_TEXTURE = 2048 * 2048;
/// A texture map in an FBX document.
class FBXTexture {
/// A texture map.
class HFMTexture {
public:
QString id;
QString name;
@ -156,7 +156,7 @@ public:
};
/// A single part of a mesh (with the same material).
class FBXMeshPart {
class HFMMeshPart {
public:
QVector<int> quadIndices; // original indices from the FBX mesh
@ -166,10 +166,10 @@ public:
QString materialID;
};
class FBXMaterial {
class HFMMaterial {
public:
FBXMaterial() {};
FBXMaterial(const glm::vec3& diffuseColor, const glm::vec3& specularColor, const glm::vec3& emissiveColor,
HFMMaterial() {};
HFMMaterial(const glm::vec3& diffuseColor, const glm::vec3& specularColor, const glm::vec3& emissiveColor,
float shininess, float opacity) :
diffuseColor(diffuseColor),
specularColor(specularColor),
@ -203,17 +203,17 @@ public:
QString shadingModel;
graphics::MaterialPointer _material;
FBXTexture normalTexture;
FBXTexture albedoTexture;
FBXTexture opacityTexture;
FBXTexture glossTexture;
FBXTexture roughnessTexture;
FBXTexture specularTexture;
FBXTexture metallicTexture;
FBXTexture emissiveTexture;
FBXTexture occlusionTexture;
FBXTexture scatteringTexture;
FBXTexture lightmapTexture;
HFMTexture normalTexture;
HFMTexture albedoTexture;
HFMTexture opacityTexture;
HFMTexture glossTexture;
HFMTexture roughnessTexture;
HFMTexture specularTexture;
HFMTexture metallicTexture;
HFMTexture emissiveTexture;
HFMTexture occlusionTexture;
HFMTexture scatteringTexture;
HFMTexture lightmapTexture;
glm::vec2 lightmapParams{ 0.0f, 1.0f };
@ -232,10 +232,10 @@ public:
};
/// A single mesh (with optional blendshapes) extracted from an FBX document.
class FBXMesh {
class HFMMesh {
public:
QVector<FBXMeshPart> parts;
QVector<HFMMeshPart> parts;
QVector<glm::vec3> vertices;
QVector<glm::vec3> normals;
@ -247,12 +247,12 @@ public:
QVector<uint16_t> clusterWeights;
QVector<int32_t> originalIndices;
QVector<FBXCluster> clusters;
QVector<HFMCluster> clusters;
Extents meshExtents;
glm::mat4 modelTransform;
QVector<FBXBlendshape> blendshapes;
QVector<HFMBlendshape> blendshapes;
unsigned int meshIndex; // the order the meshes appeared in the object file
@ -265,7 +265,7 @@ public:
class ExtractedMesh {
public:
FBXMesh mesh;
HFMMesh mesh;
QMultiHash<int, int> newIndices;
QVector<QHash<int, int> > blendshapeIndexMaps;
QVector<QPair<int, int> > partMaterialTextures;
@ -278,14 +278,14 @@ public:
* @property {Vec3[]} translations
*/
/// A single animation frame extracted from an FBX document.
class FBXAnimationFrame {
class HFMAnimationFrame {
public:
QVector<glm::quat> rotations;
QVector<glm::vec3> translations;
};
/// A light in an FBX document.
class FBXLight {
/// A light.
class HFMLight {
public:
QString name;
Transform transform;
@ -293,7 +293,7 @@ public:
float fogValue;
glm::vec3 color;
FBXLight() :
HFMLight() :
name(),
transform(),
intensity(1.0f),
@ -302,26 +302,26 @@ public:
{}
};
Q_DECLARE_METATYPE(FBXAnimationFrame)
Q_DECLARE_METATYPE(QVector<FBXAnimationFrame>)
Q_DECLARE_METATYPE(HFMAnimationFrame)
Q_DECLARE_METATYPE(QVector<HFMAnimationFrame>)
/// A set of meshes extracted from an FBX document.
class FBXGeometry {
class HFMGeometry {
public:
using Pointer = std::shared_ptr<FBXGeometry>;
using Pointer = std::shared_ptr<HFMGeometry>;
QString originalURL;
QString author;
QString applicationName; ///< the name of the application that generated the model
QVector<FBXJoint> joints;
QVector<HFMJoint> joints;
QHash<QString, int> jointIndices; ///< 1-based, so as to more easily detect missing indices
bool hasSkeletonJoints;
QVector<FBXMesh> meshes;
QVector<HFMMesh> meshes;
QVector<QString> scripts;
QHash<QString, FBXMaterial> materials;
QHash<QString, HFMMaterial> materials;
glm::mat4 offset; // This includes offset, rotation, and scale as specified by the FST file
@ -348,7 +348,7 @@ public:
Extents bindExtents;
Extents meshExtents;
QVector<FBXAnimationFrame> animationFrames;
QVector<HFMAnimationFrame> animationFrames;
int getJointIndex(const QString& name) const { return jointIndices.value(name) - 1; }
QStringList getJointNames() const;
@ -368,7 +368,7 @@ public:
QList<QString> blendshapeChannelNames;
};
Q_DECLARE_METATYPE(FBXGeometry)
Q_DECLARE_METATYPE(FBXGeometry::Pointer)
Q_DECLARE_METATYPE(HFMGeometry)
Q_DECLARE_METATYPE(HFMGeometry::Pointer)
#endif // hifi_FBX_h_

View file

@ -40,19 +40,19 @@
using namespace std;
int FBXGeometryPointerMetaTypeId = qRegisterMetaType<FBXGeometry::Pointer>();
int HFMGeometryPointerMetaTypeId = qRegisterMetaType<HFMGeometry::Pointer>();
QStringList FBXGeometry::getJointNames() const {
QStringList HFMGeometry::getJointNames() const {
QStringList names;
foreach (const FBXJoint& joint, joints) {
foreach (const HFMJoint& joint, joints) {
names.append(joint.name);
}
return names;
}
bool FBXGeometry::hasBlendedMeshes() const {
bool HFMGeometry::hasBlendedMeshes() const {
if (!meshes.isEmpty()) {
foreach (const FBXMesh& mesh, meshes) {
foreach (const HFMMesh& mesh, meshes) {
if (!mesh.blendshapes.isEmpty()) {
return true;
}
@ -61,7 +61,7 @@ bool FBXGeometry::hasBlendedMeshes() const {
return false;
}
Extents FBXGeometry::getUnscaledMeshExtents() const {
Extents HFMGeometry::getUnscaledMeshExtents() const {
const Extents& extents = meshExtents;
// even though our caller asked for "unscaled" we need to include any fst scaling, translation, and rotation, which
@ -74,12 +74,12 @@ Extents FBXGeometry::getUnscaledMeshExtents() const {
}
// TODO: Move to graphics::Mesh when Sam's ready
bool FBXGeometry::convexHullContains(const glm::vec3& point) const {
bool HFMGeometry::convexHullContains(const glm::vec3& point) const {
if (!getUnscaledMeshExtents().containsPoint(point)) {
return false;
}
auto checkEachPrimitive = [=](FBXMesh& mesh, QVector<int> indices, int primitiveSize) -> bool {
auto checkEachPrimitive = [=](HFMMesh& mesh, QVector<int> indices, int primitiveSize) -> bool {
// Check whether the point is "behind" all the primitives.
int verticesSize = mesh.vertices.size();
for (int j = 0;
@ -124,16 +124,16 @@ bool FBXGeometry::convexHullContains(const glm::vec3& point) const {
return false;
}
QString FBXGeometry::getModelNameOfMesh(int meshIndex) const {
QString HFMGeometry::getModelNameOfMesh(int meshIndex) const {
if (meshIndicesToModelNames.contains(meshIndex)) {
return meshIndicesToModelNames.value(meshIndex);
}
return QString();
}
int fbxGeometryMetaTypeId = qRegisterMetaType<FBXGeometry>();
int fbxAnimationFrameMetaTypeId = qRegisterMetaType<FBXAnimationFrame>();
int fbxAnimationFrameVectorMetaTypeId = qRegisterMetaType<QVector<FBXAnimationFrame> >();
int hfmGeometryMetaTypeId = qRegisterMetaType<HFMGeometry>();
int hfmAnimationFrameMetaTypeId = qRegisterMetaType<HFMAnimationFrame>();
int hfmAnimationFrameVectorMetaTypeId = qRegisterMetaType<QVector<HFMAnimationFrame> >();
glm::vec3 parseVec3(const QString& string) {
@ -303,7 +303,7 @@ glm::mat4 getGlobalTransform(const QMultiMap<QString, QString>& _connectionParen
class ExtractedBlendshape {
public:
QString id;
FBXBlendshape blendshape;
HFMBlendshape blendshape;
};
void printNode(const FBXNode& node, int indentLevel) {
@ -346,8 +346,8 @@ void appendModelIDs(const QString& parentID, const QMultiMap<QString, QString>&
}
}
FBXBlendshape extractBlendshape(const FBXNode& object) {
FBXBlendshape blendshape;
HFMBlendshape extractBlendshape(const FBXNode& object) {
HFMBlendshape blendshape;
foreach (const FBXNode& data, object.children) {
if (data.name == "Indexes") {
blendshape.indices = FBXReader::getIntVector(data);
@ -362,9 +362,9 @@ FBXBlendshape extractBlendshape(const FBXNode& object) {
return blendshape;
}
using IndexAccessor = std::function<glm::vec3*(const FBXMesh&, int, int, glm::vec3*, glm::vec3&)>;
using IndexAccessor = std::function<glm::vec3*(const HFMMesh&, int, int, glm::vec3*, glm::vec3&)>;
static void setTangents(const FBXMesh& mesh, const IndexAccessor& vertexAccessor, int firstIndex, int secondIndex,
static void setTangents(const HFMMesh& mesh, const IndexAccessor& vertexAccessor, int firstIndex, int secondIndex,
const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals, QVector<glm::vec3>& tangents) {
glm::vec3 vertex[2];
glm::vec3 normal;
@ -381,14 +381,14 @@ static void setTangents(const FBXMesh& mesh, const IndexAccessor& vertexAccessor
}
}
static void createTangents(const FBXMesh& mesh, bool generateFromTexCoords,
static void createTangents(const HFMMesh& mesh, bool generateFromTexCoords,
const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals, QVector<glm::vec3>& tangents,
IndexAccessor accessor) {
// if we have a normal map (and texture coordinates), we must compute tangents
if (generateFromTexCoords && !mesh.texCoords.isEmpty()) {
tangents.resize(vertices.size());
foreach(const FBXMeshPart& part, mesh.parts) {
foreach(const HFMMeshPart& part, mesh.parts) {
for (int i = 0; i < part.quadIndices.size(); i += 4) {
setTangents(mesh, accessor, part.quadIndices.at(i), part.quadIndices.at(i + 1), vertices, normals, tangents);
setTangents(mesh, accessor, part.quadIndices.at(i + 1), part.quadIndices.at(i + 2), vertices, normals, tangents);
@ -403,27 +403,27 @@ static void createTangents(const FBXMesh& mesh, bool generateFromTexCoords,
setTangents(mesh, accessor, part.triangleIndices.at(i + 2), part.triangleIndices.at(i), vertices, normals, tangents);
}
if ((part.triangleIndices.size() % 3) != 0) {
qCDebug(modelformat) << "Error in extractFBXGeometry part.triangleIndices.size() is not divisible by three ";
qCDebug(modelformat) << "Error in extractHFMGeometry part.triangleIndices.size() is not divisible by three ";
}
}
}
}
static void _createBlendShapeTangents(FBXMesh& mesh, bool generateFromTexCoords, FBXBlendshape& blendShape);
static void _createBlendShapeTangents(HFMMesh& mesh, bool generateFromTexCoords, HFMBlendshape& blendShape);
void FBXMesh::createBlendShapeTangents(bool generateTangents) {
void HFMMesh::createBlendShapeTangents(bool generateTangents) {
for (auto& blendShape : blendshapes) {
_createBlendShapeTangents(*this, generateTangents, blendShape);
}
}
void FBXMesh::createMeshTangents(bool generateFromTexCoords) {
FBXMesh& mesh = *this;
void HFMMesh::createMeshTangents(bool generateFromTexCoords) {
HFMMesh& mesh = *this;
// This is the only workaround I've found to trick the compiler into understanding that mesh.tangents isn't
// const in the lambda function.
auto& tangents = mesh.tangents;
createTangents(mesh, generateFromTexCoords, mesh.vertices, mesh.normals, mesh.tangents,
[&](const FBXMesh& mesh, int firstIndex, int secondIndex, glm::vec3* outVertices, glm::vec3& outNormal) {
[&](const HFMMesh& mesh, int firstIndex, int secondIndex, glm::vec3* outVertices, glm::vec3& outNormal) {
outVertices[0] = mesh.vertices[firstIndex];
outVertices[1] = mesh.vertices[secondIndex];
outNormal = mesh.normals[firstIndex];
@ -431,7 +431,7 @@ void FBXMesh::createMeshTangents(bool generateFromTexCoords) {
});
}
static void _createBlendShapeTangents(FBXMesh& mesh, bool generateFromTexCoords, FBXBlendshape& blendShape) {
static void _createBlendShapeTangents(HFMMesh& mesh, bool generateFromTexCoords, HFMBlendshape& blendShape) {
// Create lookup to get index in blend shape from vertex index in mesh
std::vector<int> reverseIndices;
reverseIndices.resize(mesh.vertices.size());
@ -443,7 +443,7 @@ static void _createBlendShapeTangents(FBXMesh& mesh, bool generateFromTexCoords,
}
createTangents(mesh, generateFromTexCoords, blendShape.vertices, blendShape.normals, blendShape.tangents,
[&](const FBXMesh& mesh, int firstIndex, int secondIndex, glm::vec3* outVertices, glm::vec3& outNormal) {
[&](const HFMMesh& mesh, int firstIndex, int secondIndex, glm::vec3* outVertices, glm::vec3& outNormal) {
const auto index1 = reverseIndices[firstIndex];
const auto index2 = reverseIndices[secondIndex];
@ -481,7 +481,7 @@ void addBlendshapes(const ExtractedBlendshape& extracted, const QList<WeightedIn
foreach (const WeightedIndex& index, indices) {
extractedMesh.mesh.blendshapes.resize(max(extractedMesh.mesh.blendshapes.size(), index.first + 1));
extractedMesh.blendshapeIndexMaps.resize(extractedMesh.mesh.blendshapes.size());
FBXBlendshape& blendshape = extractedMesh.mesh.blendshapes[index.first];
HFMBlendshape& blendshape = extractedMesh.mesh.blendshapes[index.first];
QHash<int, int>& blendshapeIndexMap = extractedMesh.blendshapeIndexMaps[index.first];
for (int i = 0; i < extracted.blendshape.indices.size(); i++) {
int oldIndex = extracted.blendshape.indices.at(i);
@ -539,7 +539,7 @@ public:
QVector<float> values;
};
bool checkMaterialsHaveTextures(const QHash<QString, FBXMaterial>& materials,
bool checkMaterialsHaveTextures(const QHash<QString, HFMMaterial>& materials,
const QHash<QString, QByteArray>& textureFilenames, const QMultiMap<QString, QString>& _connectionChildMap) {
foreach (const QString& materialID, materials.keys()) {
foreach (const QString& childID, _connectionChildMap.values(materialID)) {
@ -569,8 +569,8 @@ int matchTextureUVSetToAttributeChannel(const QString& texUVSetName, const QHash
}
FBXLight extractLight(const FBXNode& object) {
FBXLight light;
HFMLight extractLight(const FBXNode& object) {
HFMLight light;
foreach (const FBXNode& subobject, object.children) {
QString childname = QString(subobject.name);
if (subobject.name == "Properties70") {
@ -615,7 +615,7 @@ QByteArray fileOnUrl(const QByteArray& filepath, const QString& url) {
return filepath.mid(filepath.lastIndexOf('/') + 1);
}
FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QString& url) {
HFMGeometry* FBXReader::extractHFMGeometry(const QVariantHash& mapping, const QString& url) {
const FBXNode& node = _rootNode;
QMap<QString, ExtractedMesh> meshes;
QHash<QString, QString> modelIDsToNames;
@ -636,7 +636,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
QHash<QString, QString> yComponents;
QHash<QString, QString> zComponents;
std::map<QString, FBXLight> lights;
std::map<QString, HFMLight> lights;
QVariantHash joints = mapping.value("joint").toHash();
QString jointEyeLeftName = processID(getString(joints.value("jointEyeLeft", "jointEyeLeft")));
@ -689,8 +689,8 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
#if defined(DEBUG_FBXREADER)
int unknown = 0;
#endif
FBXGeometry* geometryPtr = new FBXGeometry;
FBXGeometry& geometry = *geometryPtr;
HFMGeometry* geometryPtr = new HFMGeometry;
HFMGeometry& geometry = *geometryPtr;
geometry.originalURL = url;
@ -944,7 +944,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
lightprop = vprop.toString();
}
FBXLight light = extractLight(object);
HFMLight light = extractLight(object);
}
}
} else {
@ -1102,7 +1102,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
_textureContent.insert(filepath, content);
}
} else if (object.name == "Material") {
FBXMaterial material;
HFMMaterial material;
material.name = (object.properties.at(1).toString());
foreach (const FBXNode& subobject, object.children) {
bool properties = false;
@ -1255,7 +1255,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
#endif
}
material.materialID = getID(object.properties);
_fbxMaterials.insert(material.materialID, material);
_hfmMaterials.insert(material.materialID, material);
} else if (object.name == "NodeAttribute") {
@ -1276,7 +1276,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
if (!attributetype.isEmpty()) {
if (attributetype == "Light") {
FBXLight light = extractLight(object);
HFMLight light = extractLight(object);
lights[attribID] = light;
}
}
@ -1345,7 +1345,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
QString parentID = getID(connection.properties, 2);
ooChildToParent.insert(childID, parentID);
if (!hifiGlobalNodeID.isEmpty() && (parentID == hifiGlobalNodeID)) {
std::map< QString, FBXLight >::iterator lightIt = lights.find(childID);
std::map< QString, HFMLight >::iterator lightIt = lights.find(childID);
if (lightIt != lights.end()) {
_lightmapLevel = (*lightIt).second.intensity;
if (_lightmapLevel <= 0.0f) {
@ -1504,7 +1504,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
frameCount = qMax(frameCount, curve.values.size());
}
for (int i = 0; i < frameCount; i++) {
FBXAnimationFrame frame;
HFMAnimationFrame frame;
frame.rotations.resize(modelIDs.size());
frame.translations.resize(modelIDs.size());
geometry.animationFrames.append(frame);
@ -1515,7 +1515,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
geometry.hasSkeletonJoints = false;
foreach (const QString& modelID, modelIDs) {
const FBXModel& model = models[modelID];
FBXJoint joint;
HFMJoint joint;
joint.isFree = freeJoints.contains(model.name);
joint.parentIndex = model.parentIndex;
@ -1553,7 +1553,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
joint.distanceToParent = 0.0f;
} else {
const FBXJoint& parentJoint = geometry.joints.at(joint.parentIndex);
const HFMJoint& parentJoint = geometry.joints.at(joint.parentIndex);
joint.transform = parentJoint.transform * glm::translate(joint.translation) *
joint.preTransform * glm::mat4_cast(combinedRotation) * joint.postTransform;
joint.inverseDefaultRotation = glm::inverse(combinedRotation) * parentJoint.inverseDefaultRotation;
@ -1631,7 +1631,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
geometry.meshExtents.reset();
// Create the Material Library
consolidateFBXMaterials(mapping);
consolidateHFMMaterials(mapping);
// We can't allow the scaling of a given image to different sizes, because the hash used for the KTX cache is based on the original image
// Allowing scaling of the same image to different sizes would cause different KTX files to target the same cache key
@ -1643,7 +1643,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
// 33 - 128 textures --> 512
// etc...
QSet<QString> uniqueTextures;
for (auto& material : _fbxMaterials) {
for (auto& material : _hfmMaterials) {
material.getTextureNames(uniqueTextures);
}
int numTextures = uniqueTextures.size();
@ -1659,15 +1659,15 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
} while (numTextureThreshold < numTextures && maxWidth > MIN_MIP_TEXTURE_WIDTH);
qCDebug(modelformat) << "Capped square texture width =" << maxWidth << "for model" << url << "with" << numTextures << "textures";
for (auto& material : _fbxMaterials) {
for (auto& material : _hfmMaterials) {
material.setMaxNumPixelsPerTexture(maxWidth * maxWidth);
}
}
#endif
geometry.materials = _fbxMaterials;
geometry.materials = _hfmMaterials;
// see if any materials have texture children
bool materialsHaveTextures = checkMaterialsHaveTextures(_fbxMaterials, _textureFilenames, _connectionChildMap);
bool materialsHaveTextures = checkMaterialsHaveTextures(_hfmMaterials, _textureFilenames, _connectionChildMap);
for (QMap<QString, ExtractedMesh>::iterator it = meshes.begin(); it != meshes.end(); it++) {
ExtractedMesh& extracted = it.value();
@ -1698,13 +1698,13 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
for (int i = children.size() - 1; i >= 0; i--) {
const QString& childID = children.at(i);
if (_fbxMaterials.contains(childID)) {
if (_hfmMaterials.contains(childID)) {
// the pure material associated with this part
FBXMaterial material = _fbxMaterials.value(childID);
HFMMaterial material = _hfmMaterials.value(childID);
for (int j = 0; j < extracted.partMaterialTextures.size(); j++) {
if (extracted.partMaterialTextures.at(j).first == materialIndex) {
FBXMeshPart& part = extracted.mesh.parts[j];
HFMMeshPart& part = extracted.mesh.parts[j];
part.materialID = material.materialID;
generateTangents |= material.needTangentSpace();
}
@ -1713,7 +1713,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
materialIndex++;
} else if (_textureFilenames.contains(childID)) {
FBXTexture texture = getTexture(childID);
HFMTexture texture = getTexture(childID);
for (int j = 0; j < extracted.partMaterialTextures.size(); j++) {
int partTexture = extracted.partMaterialTextures.at(j).second;
if (partTexture == textureIndex && !(partTexture == 0 && materialsHaveTextures)) {
@ -1736,34 +1736,34 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
if (!clusters.contains(clusterID)) {
continue;
}
FBXCluster fbxCluster;
HFMCluster hfmCluster;
const Cluster& cluster = clusters[clusterID];
clusterIDs.append(clusterID);
// see http://stackoverflow.com/questions/13566608/loading-skinning-information-from-fbx for a discussion
// of skinning information in FBX
QString jointID = _connectionChildMap.value(clusterID);
fbxCluster.jointIndex = modelIDs.indexOf(jointID);
if (fbxCluster.jointIndex == -1) {
hfmCluster.jointIndex = modelIDs.indexOf(jointID);
if (hfmCluster.jointIndex == -1) {
qCDebug(modelformat) << "Joint not in model list: " << jointID;
fbxCluster.jointIndex = 0;
hfmCluster.jointIndex = 0;
}
fbxCluster.inverseBindMatrix = glm::inverse(cluster.transformLink) * modelTransform;
hfmCluster.inverseBindMatrix = glm::inverse(cluster.transformLink) * modelTransform;
// slam bottom row to (0, 0, 0, 1), we KNOW this is not a perspective matrix and
// sometimes floating point fuzz can be introduced after the inverse.
fbxCluster.inverseBindMatrix[0][3] = 0.0f;
fbxCluster.inverseBindMatrix[1][3] = 0.0f;
fbxCluster.inverseBindMatrix[2][3] = 0.0f;
fbxCluster.inverseBindMatrix[3][3] = 1.0f;
hfmCluster.inverseBindMatrix[0][3] = 0.0f;
hfmCluster.inverseBindMatrix[1][3] = 0.0f;
hfmCluster.inverseBindMatrix[2][3] = 0.0f;
hfmCluster.inverseBindMatrix[3][3] = 1.0f;
fbxCluster.inverseBindTransform = Transform(fbxCluster.inverseBindMatrix);
hfmCluster.inverseBindTransform = Transform(hfmCluster.inverseBindMatrix);
extracted.mesh.clusters.append(fbxCluster);
extracted.mesh.clusters.append(hfmCluster);
// override the bind rotation with the transform link
FBXJoint& joint = geometry.joints[fbxCluster.jointIndex];
HFMJoint& joint = geometry.joints[hfmCluster.jointIndex];
joint.inverseBindRotation = glm::inverse(extractRotation(cluster.transformLink));
joint.bindTransform = cluster.transformLink;
joint.bindTransformFoundInCluster = true;
@ -1776,7 +1776,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
// if we don't have a skinned joint, parent to the model itself
if (extracted.mesh.clusters.isEmpty()) {
FBXCluster cluster;
HFMCluster cluster;
cluster.jointIndex = modelIDs.indexOf(modelID);
if (cluster.jointIndex == -1) {
qCDebug(modelformat) << "Model not in model list: " << modelID;
@ -1786,7 +1786,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
}
// whether we're skinned depends on how many clusters are attached
const FBXCluster& firstFBXCluster = extracted.mesh.clusters.at(0);
const HFMCluster& firstHFMCluster = extracted.mesh.clusters.at(0);
glm::mat4 inverseModelTransform = glm::inverse(modelTransform);
if (clusterIDs.size() > 1) {
// this is a multi-mesh joint
@ -1799,9 +1799,9 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
for (int i = 0; i < clusterIDs.size(); i++) {
QString clusterID = clusterIDs.at(i);
const Cluster& cluster = clusters[clusterID];
const FBXCluster& fbxCluster = extracted.mesh.clusters.at(i);
int jointIndex = fbxCluster.jointIndex;
FBXJoint& joint = geometry.joints[jointIndex];
const HFMCluster& hfmCluster = extracted.mesh.clusters.at(i);
int jointIndex = hfmCluster.jointIndex;
HFMJoint& joint = geometry.joints[jointIndex];
glm::mat4 transformJointToMesh = inverseModelTransform * joint.bindTransform;
glm::vec3 boneEnd = extractTranslation(transformJointToMesh);
glm::vec3 boneBegin = boneEnd;
@ -1881,8 +1881,8 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
}
} else {
// this is a single-mesh joint
int jointIndex = firstFBXCluster.jointIndex;
FBXJoint& joint = geometry.joints[jointIndex];
int jointIndex = firstHFMCluster.jointIndex;
HFMJoint& joint = geometry.joints[jointIndex];
// transform cluster vertices to joint-frame and save for later
glm::mat4 meshToJoint = glm::inverse(joint.bindTransform) * modelTransform;
@ -1924,7 +1924,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
// now that all joints have been scanned compute a k-Dop bounding volume of mesh
for (int i = 0; i < geometry.joints.size(); ++i) {
FBXJoint& joint = geometry.joints[i];
HFMJoint& joint = geometry.joints[i];
// NOTE: points are in joint-frame
ShapeVertices& points = shapeVertices.at(i);
@ -1994,13 +1994,13 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
return geometryPtr;
}
FBXGeometry* readFBX(const QByteArray& model, const QVariantHash& mapping, const QString& url, bool loadLightmaps, float lightmapLevel) {
HFMGeometry* readFBX(const QByteArray& model, const QVariantHash& mapping, const QString& url, bool loadLightmaps, float lightmapLevel) {
QBuffer buffer(const_cast<QByteArray*>(&model));
buffer.open(QIODevice::ReadOnly);
return readFBX(&buffer, mapping, url, loadLightmaps, lightmapLevel);
}
FBXGeometry* readFBX(QIODevice* device, const QVariantHash& mapping, const QString& url, bool loadLightmaps, float lightmapLevel) {
HFMGeometry* readFBX(QIODevice* device, const QVariantHash& mapping, const QString& url, bool loadLightmaps, float lightmapLevel) {
FBXReader reader;
reader._rootNode = FBXReader::parseFBX(device);
reader._loadLightmaps = loadLightmaps;
@ -2008,5 +2008,5 @@ FBXGeometry* readFBX(QIODevice* device, const QVariantHash& mapping, const QStri
qCDebug(modelformat) << "Reading FBX: " << url;
return reader.extractFBXGeometry(mapping, url);
return reader.extractHFMGeometry(mapping, url);
}

View file

@ -36,11 +36,11 @@ class FBXNode;
/// Reads FBX geometry from the supplied model and mapping data.
/// \exception QString if an error occurs in parsing
FBXGeometry* readFBX(const QByteArray& model, const QVariantHash& mapping, const QString& url = "", bool loadLightmaps = true, float lightmapLevel = 1.0f);
HFMGeometry* readFBX(const QByteArray& model, const QVariantHash& mapping, const QString& url = "", bool loadLightmaps = true, float lightmapLevel = 1.0f);
/// Reads FBX geometry from the supplied model and mapping data.
/// \exception QString if an error occurs in parsing
FBXGeometry* readFBX(QIODevice* device, const QVariantHash& mapping, const QString& url = "", bool loadLightmaps = true, float lightmapLevel = 1.0f);
HFMGeometry* readFBX(QIODevice* device, const QVariantHash& mapping, const QString& url = "", bool loadLightmaps = true, float lightmapLevel = 1.0f);
class TextureParam {
public:
@ -103,20 +103,20 @@ class ExtractedMesh;
class FBXReader {
public:
FBXGeometry* _fbxGeometry;
HFMGeometry* _hfmGeometry;
FBXNode _rootNode;
static FBXNode parseFBX(QIODevice* device);
FBXGeometry* extractFBXGeometry(const QVariantHash& mapping, const QString& url);
HFMGeometry* extractHFMGeometry(const QVariantHash& mapping, const QString& url);
static ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex, bool deduplicate = true);
QHash<QString, ExtractedMesh> meshes;
static void buildModelMesh(FBXMesh& extractedMesh, const QString& url);
static void buildModelMesh(HFMMesh& extractedMesh, const QString& url);
static glm::vec3 normalizeDirForPacking(const glm::vec3& dir);
FBXTexture getTexture(const QString& textureID);
HFMTexture getTexture(const QString& textureID);
QHash<QString, QString> _textureNames;
// Hashes the original RelativeFilename of textures
@ -142,9 +142,9 @@ public:
QHash<QString, QString> ambientFactorTextures;
QHash<QString, QString> occlusionTextures;
QHash<QString, FBXMaterial> _fbxMaterials;
QHash<QString, HFMMaterial> _hfmMaterials;
void consolidateFBXMaterials(const QVariantHash& mapping);
void consolidateHFMMaterials(const QVariantHash& mapping);
bool _loadLightmaps = true;
float _lightmapOffset = 0.0f;

View file

@ -27,7 +27,7 @@
#include "ModelFormatLogging.h"
void FBXMaterial::getTextureNames(QSet<QString>& textureList) const {
void HFMMaterial::getTextureNames(QSet<QString>& textureList) const {
if (!normalTexture.isNull()) {
textureList.insert(normalTexture.name);
}
@ -63,7 +63,7 @@ void FBXMaterial::getTextureNames(QSet<QString>& textureList) const {
}
}
void FBXMaterial::setMaxNumPixelsPerTexture(int maxNumPixels) {
void HFMMaterial::setMaxNumPixelsPerTexture(int maxNumPixels) {
normalTexture.maxNumPixels = maxNumPixels;
albedoTexture.maxNumPixels = maxNumPixels;
opacityTexture.maxNumPixels = maxNumPixels;
@ -77,12 +77,12 @@ void FBXMaterial::setMaxNumPixelsPerTexture(int maxNumPixels) {
lightmapTexture.maxNumPixels = maxNumPixels;
}
bool FBXMaterial::needTangentSpace() const {
bool HFMMaterial::needTangentSpace() const {
return !normalTexture.isNull();
}
FBXTexture FBXReader::getTexture(const QString& textureID) {
FBXTexture texture;
HFMTexture FBXReader::getTexture(const QString& textureID) {
HFMTexture texture;
const QByteArray& filepath = _textureFilepaths.value(textureID);
texture.content = _textureContent.value(filepath);
@ -123,7 +123,7 @@ FBXTexture FBXReader::getTexture(const QString& textureID) {
return texture;
}
void FBXReader::consolidateFBXMaterials(const QVariantHash& mapping) {
void FBXReader::consolidateHFMMaterials(const QVariantHash& mapping) {
QString materialMapString = mapping.value("materialMap").toString();
QJsonDocument materialMapDocument = QJsonDocument::fromJson(materialMapString.toUtf8());
@ -133,16 +133,16 @@ void FBXReader::consolidateFBXMaterials(const QVariantHash& mapping) {
qCDebug(modelformat) << "fbx Material Map found but did not produce valid JSON:" << materialMapString;
}
}
for (QHash<QString, FBXMaterial>::iterator it = _fbxMaterials.begin(); it != _fbxMaterials.end(); it++) {
FBXMaterial& material = (*it);
for (QHash<QString, HFMMaterial>::iterator it = _hfmMaterials.begin(); it != _hfmMaterials.end(); it++) {
HFMMaterial& material = (*it);
// Maya is the exporting the shading model and we are trying to use it
bool isMaterialLambert = (material.shadingModel.toLower() == "lambert");
// the pure material associated with this part
bool detectDifferentUVs = false;
FBXTexture diffuseTexture;
FBXTexture diffuseFactorTexture;
HFMTexture diffuseTexture;
HFMTexture diffuseFactorTexture;
QString diffuseTextureID = diffuseTextures.value(material.materialID);
QString diffuseFactorTextureID = diffuseFactorTextures.value(material.materialID);
@ -169,7 +169,7 @@ void FBXReader::consolidateFBXMaterials(const QVariantHash& mapping) {
detectDifferentUVs = (diffuseTexture.texcoordSet != 0) || (!diffuseTexture.transform.isIdentity());
}
FBXTexture transparentTexture;
HFMTexture transparentTexture;
QString transparentTextureID = transparentTextures.value(material.materialID);
// If PBS Material, systematically bind the albedo texture as transparency texture and check for the alpha channel
if (material.isPBSMaterial) {
@ -181,7 +181,7 @@ void FBXReader::consolidateFBXMaterials(const QVariantHash& mapping) {
detectDifferentUVs |= (transparentTexture.texcoordSet != 0) || (!transparentTexture.transform.isIdentity());
}
FBXTexture normalTexture;
HFMTexture normalTexture;
QString bumpTextureID = bumpTextures.value(material.materialID);
QString normalTextureID = normalTextures.value(material.materialID);
if (!normalTextureID.isNull()) {
@ -198,7 +198,7 @@ void FBXReader::consolidateFBXMaterials(const QVariantHash& mapping) {
detectDifferentUVs |= (normalTexture.texcoordSet != 0) || (!normalTexture.transform.isIdentity());
}
FBXTexture specularTexture;
HFMTexture specularTexture;
QString specularTextureID = specularTextures.value(material.materialID);
if (!specularTextureID.isNull()) {
specularTexture = getTexture(specularTextureID);
@ -206,7 +206,7 @@ void FBXReader::consolidateFBXMaterials(const QVariantHash& mapping) {
material.specularTexture = specularTexture;
}
FBXTexture metallicTexture;
HFMTexture metallicTexture;
QString metallicTextureID = metallicTextures.value(material.materialID);
if (!metallicTextureID.isNull()) {
metallicTexture = getTexture(metallicTextureID);
@ -214,7 +214,7 @@ void FBXReader::consolidateFBXMaterials(const QVariantHash& mapping) {
material.metallicTexture = metallicTexture;
}
FBXTexture roughnessTexture;
HFMTexture roughnessTexture;
QString roughnessTextureID = roughnessTextures.value(material.materialID);
if (!roughnessTextureID.isNull()) {
roughnessTexture = getTexture(roughnessTextureID);
@ -222,7 +222,7 @@ void FBXReader::consolidateFBXMaterials(const QVariantHash& mapping) {
detectDifferentUVs |= (roughnessTexture.texcoordSet != 0) || (!roughnessTexture.transform.isIdentity());
}
FBXTexture shininessTexture;
HFMTexture shininessTexture;
QString shininessTextureID = shininessTextures.value(material.materialID);
if (!shininessTextureID.isNull()) {
shininessTexture = getTexture(shininessTextureID);
@ -230,7 +230,7 @@ void FBXReader::consolidateFBXMaterials(const QVariantHash& mapping) {
detectDifferentUVs |= (shininessTexture.texcoordSet != 0) || (!shininessTexture.transform.isIdentity());
}
FBXTexture emissiveTexture;
HFMTexture emissiveTexture;
QString emissiveTextureID = emissiveTextures.value(material.materialID);
if (!emissiveTextureID.isNull()) {
emissiveTexture = getTexture(emissiveTextureID);
@ -245,7 +245,7 @@ void FBXReader::consolidateFBXMaterials(const QVariantHash& mapping) {
}
}
FBXTexture occlusionTexture;
HFMTexture occlusionTexture;
QString occlusionTextureID = occlusionTextures.value(material.materialID);
if (occlusionTextureID.isNull()) {
// 2nd chance
@ -265,7 +265,7 @@ void FBXReader::consolidateFBXMaterials(const QVariantHash& mapping) {
lightmapParams.x = _lightmapOffset;
lightmapParams.y = _lightmapLevel;
FBXTexture ambientTexture;
HFMTexture ambientTexture;
QString ambientTextureID = ambientTextures.value(material.materialID);
if (ambientTextureID.isNull()) {
// 2nd chance
@ -326,7 +326,7 @@ void FBXReader::consolidateFBXMaterials(const QVariantHash& mapping) {
if (materialOptions.contains("scatteringMap")) {
QByteArray scatteringMap = materialOptions.value("scatteringMap").toVariant().toByteArray();
material.scatteringTexture = FBXTexture();
material.scatteringTexture = HFMTexture();
material.scatteringTexture.name = material.name + ".scatteringMap";
material.scatteringTexture.filename = scatteringMap;
}

View file

@ -42,9 +42,9 @@
using vec2h = glm::tvec2<glm::detail::hdata>;
#define FBX_PACK_COLORS 1
#define HFM_PACK_COLORS 1
#if FBX_PACK_COLORS
#if HFM_PACK_COLORS
using ColorType = glm::uint32;
#define FBX_COLOR_ELEMENT gpu::Element::COLOR_RGBA_32
#else
@ -469,7 +469,7 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn
QPair<int, int> materialTexture(materialID, 0);
// grab or setup the FBXMeshPart for the part this face belongs to
// grab or setup the HFMMeshPart for the part this face belongs to
int& partIndexPlusOne = materialTextureParts[materialTexture];
if (partIndexPlusOne == 0) {
data.extracted.partMaterialTextures.append(materialTexture);
@ -478,7 +478,7 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn
}
// give the mesh part this index
FBXMeshPart& part = data.extracted.mesh.parts[partIndexPlusOne - 1];
HFMMeshPart& part = data.extracted.mesh.parts[partIndexPlusOne - 1];
part.triangleIndices.append(firstCorner.value());
part.triangleIndices.append(dracoFace[1].value());
part.triangleIndices.append(dracoFace[2].value());
@ -511,7 +511,7 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn
data.extracted.mesh.parts.resize(data.extracted.mesh.parts.size() + 1);
partIndex = data.extracted.mesh.parts.size();
}
FBXMeshPart& part = data.extracted.mesh.parts[partIndex - 1];
HFMMeshPart& part = data.extracted.mesh.parts[partIndex - 1];
if (endIndex - beginIndex == 4) {
appendIndex(data, part.quadIndices, beginIndex++, deduplicate);
@ -565,9 +565,9 @@ glm::vec3 FBXReader::normalizeDirForPacking(const glm::vec3& dir) {
return dir;
}
void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
void FBXReader::buildModelMesh(HFMMesh& extractedMesh, const QString& url) {
unsigned int totalSourceIndices = 0;
foreach(const FBXMeshPart& part, extractedMesh.parts) {
foreach(const HFMMeshPart& part, extractedMesh.parts) {
totalSourceIndices += (part.quadTrianglesIndices.size() + part.triangleIndices.size());
}
@ -583,17 +583,17 @@ void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
return;
}
FBXMesh& fbxMesh = extractedMesh;
HFMMesh& hfmMesh = extractedMesh;
graphics::MeshPointer mesh(new graphics::Mesh());
int numVerts = extractedMesh.vertices.size();
if (!fbxMesh.normals.empty() && fbxMesh.tangents.empty()) {
if (!hfmMesh.normals.empty() && hfmMesh.tangents.empty()) {
// Fill with a dummy value to force tangents to be present if there are normals
fbxMesh.tangents.reserve(fbxMesh.normals.size());
std::fill_n(std::back_inserter(fbxMesh.tangents), fbxMesh.normals.size(), Vectors::UNIT_X);
hfmMesh.tangents.reserve(hfmMesh.normals.size());
std::fill_n(std::back_inserter(hfmMesh.tangents), hfmMesh.normals.size(), Vectors::UNIT_X);
}
// Same thing with blend shapes
for (auto& blendShape : fbxMesh.blendshapes) {
for (auto& blendShape : hfmMesh.blendshapes) {
if (!blendShape.normals.empty() && blendShape.tangents.empty()) {
// Fill with a dummy value to force tangents to be present if there are normals
blendShape.tangents.reserve(blendShape.normals.size());
@ -609,8 +609,8 @@ void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
// Normal and tangent are always there together packed in normalized xyz32bits word (times 2)
const auto normalElement = FBX_NORMAL_ELEMENT;
const int normalsSize = fbxMesh.normals.size() * normalElement.getSize();
const int tangentsSize = fbxMesh.tangents.size() * normalElement.getSize();
const int normalsSize = hfmMesh.normals.size() * normalElement.getSize();
const int tangentsSize = hfmMesh.tangents.size() * normalElement.getSize();
// If there are normals then there should be tangents
assert(normalsSize <= tangentsSize);
if (tangentsSize > normalsSize) {
@ -620,22 +620,22 @@ void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
// Color attrib
const auto colorElement = FBX_COLOR_ELEMENT;
const int colorsSize = fbxMesh.colors.size() * colorElement.getSize();
const int colorsSize = hfmMesh.colors.size() * colorElement.getSize();
// Texture coordinates are stored in 2 half floats
const auto texCoordsElement = gpu::Element(gpu::VEC2, gpu::HALF, gpu::UV);
const int texCoordsSize = fbxMesh.texCoords.size() * texCoordsElement.getSize();
const int texCoords1Size = fbxMesh.texCoords1.size() * texCoordsElement.getSize();
const int texCoordsSize = hfmMesh.texCoords.size() * texCoordsElement.getSize();
const int texCoords1Size = hfmMesh.texCoords1.size() * texCoordsElement.getSize();
// Support for 4 skinning clusters:
// 4 Indices are uint8 ideally, uint16 if more than 256.
const auto clusterIndiceElement = (fbxMesh.clusters.size() < UINT8_MAX ? gpu::Element(gpu::VEC4, gpu::UINT8, gpu::XYZW) : gpu::Element(gpu::VEC4, gpu::UINT16, gpu::XYZW));
const auto clusterIndiceElement = (hfmMesh.clusters.size() < UINT8_MAX ? gpu::Element(gpu::VEC4, gpu::UINT8, gpu::XYZW) : gpu::Element(gpu::VEC4, gpu::UINT16, gpu::XYZW));
// 4 Weights are normalized 16bits
const auto clusterWeightElement = gpu::Element(gpu::VEC4, gpu::NUINT16, gpu::XYZW);
// Cluster indices and weights must be the same sizes
const int NUM_CLUSTERS_PER_VERT = 4;
const int numVertClusters = (fbxMesh.clusterIndices.size() == fbxMesh.clusterWeights.size() ? fbxMesh.clusterIndices.size() / NUM_CLUSTERS_PER_VERT : 0);
const int numVertClusters = (hfmMesh.clusterIndices.size() == hfmMesh.clusterWeights.size() ? hfmMesh.clusterIndices.size() / NUM_CLUSTERS_PER_VERT : 0);
const int clusterIndicesSize = numVertClusters * clusterIndiceElement.getSize();
const int clusterWeightsSize = numVertClusters * clusterWeightElement.getSize();
@ -660,9 +660,9 @@ void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
if (normalsSize > 0) {
std::vector<NormalType> normalsAndTangents;
normalsAndTangents.reserve(fbxMesh.normals.size() + fbxMesh.tangents.size());
for (auto normalIt = fbxMesh.normals.constBegin(), tangentIt = fbxMesh.tangents.constBegin();
normalIt != fbxMesh.normals.constEnd();
normalsAndTangents.reserve(hfmMesh.normals.size() + hfmMesh.tangents.size());
for (auto normalIt = hfmMesh.normals.constBegin(), tangentIt = hfmMesh.tangents.constBegin();
normalIt != hfmMesh.normals.constEnd();
++normalIt, ++tangentIt) {
#if FBX_PACK_NORMALS
const auto normal = normalizeDirForPacking(*normalIt);
@ -681,24 +681,24 @@ void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
// Pack colors
if (colorsSize > 0) {
#if FBX_PACK_COLORS
#if HFM_PACK_COLORS
std::vector<ColorType> colors;
colors.reserve(fbxMesh.colors.size());
for (const auto& color : fbxMesh.colors) {
colors.reserve(hfmMesh.colors.size());
for (const auto& color : hfmMesh.colors) {
colors.push_back(glm::packUnorm4x8(glm::vec4(color, 1.0f)));
}
vertBuffer->setSubData(colorsOffset, colorsSize, (const gpu::Byte*) colors.data());
#else
vertBuffer->setSubData(colorsOffset, colorsSize, (const gpu::Byte*) fbxMesh.colors.constData());
vertBuffer->setSubData(colorsOffset, colorsSize, (const gpu::Byte*) hfmMesh.colors.constData());
#endif
}
// Pack Texcoords 0 and 1 (if exists)
if (texCoordsSize > 0) {
QVector<vec2h> texCoordData;
texCoordData.reserve(fbxMesh.texCoords.size());
for (auto& texCoordVec2f : fbxMesh.texCoords) {
texCoordData.reserve(hfmMesh.texCoords.size());
for (auto& texCoordVec2f : hfmMesh.texCoords) {
vec2h texCoordVec2h;
texCoordVec2h.x = glm::detail::toFloat16(texCoordVec2f.x);
@ -709,8 +709,8 @@ void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
}
if (texCoords1Size > 0) {
QVector<vec2h> texCoordData;
texCoordData.reserve(fbxMesh.texCoords1.size());
for (auto& texCoordVec2f : fbxMesh.texCoords1) {
texCoordData.reserve(hfmMesh.texCoords1.size());
for (auto& texCoordVec2f : hfmMesh.texCoords1) {
vec2h texCoordVec2h;
texCoordVec2h.x = glm::detail::toFloat16(texCoordVec2f.x);
@ -722,22 +722,22 @@ void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
// Clusters data
if (clusterIndicesSize > 0) {
if (fbxMesh.clusters.size() < UINT8_MAX) {
if (hfmMesh.clusters.size() < UINT8_MAX) {
// yay! we can fit the clusterIndices within 8-bits
int32_t numIndices = fbxMesh.clusterIndices.size();
int32_t numIndices = hfmMesh.clusterIndices.size();
QVector<uint8_t> clusterIndices;
clusterIndices.resize(numIndices);
for (int32_t i = 0; i < numIndices; ++i) {
assert(fbxMesh.clusterIndices[i] <= UINT8_MAX);
clusterIndices[i] = (uint8_t)(fbxMesh.clusterIndices[i]);
assert(hfmMesh.clusterIndices[i] <= UINT8_MAX);
clusterIndices[i] = (uint8_t)(hfmMesh.clusterIndices[i]);
}
vertBuffer->setSubData(clusterIndicesOffset, clusterIndicesSize, (const gpu::Byte*) clusterIndices.constData());
} else {
vertBuffer->setSubData(clusterIndicesOffset, clusterIndicesSize, (const gpu::Byte*) fbxMesh.clusterIndices.constData());
vertBuffer->setSubData(clusterIndicesOffset, clusterIndicesSize, (const gpu::Byte*) hfmMesh.clusterIndices.constData());
}
}
if (clusterWeightsSize > 0) {
vertBuffer->setSubData(clusterWeightsOffset, clusterWeightsSize, (const gpu::Byte*) fbxMesh.clusterWeights.constData());
vertBuffer->setSubData(clusterWeightsOffset, clusterWeightsSize, (const gpu::Byte*) hfmMesh.clusterWeights.constData());
}
@ -856,7 +856,7 @@ void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
// Index and Part Buffers
unsigned int totalIndices = 0;
foreach(const FBXMeshPart& part, extractedMesh.parts) {
foreach(const HFMMeshPart& part, extractedMesh.parts) {
totalIndices += (part.quadTrianglesIndices.size() + part.triangleIndices.size());
}
@ -875,7 +875,7 @@ void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
if (extractedMesh.parts.size() > 1) {
indexNum = 0;
}
foreach(const FBXMeshPart& part, extractedMesh.parts) {
foreach(const HFMMeshPart& part, extractedMesh.parts) {
graphics::Mesh::Part modelPart(indexNum, 0, 0, graphics::Mesh::TRIANGLES);
if (part.quadTrianglesIndices.size()) {

View file

@ -697,7 +697,7 @@ glm::mat4 GLTFReader::getModelTransform(const GLTFNode& node) {
return tmat;
}
bool GLTFReader::buildGeometry(FBXGeometry& geometry, const QUrl& url) {
bool GLTFReader::buildGeometry(HFMGeometry& geometry, const QUrl& url) {
//Build dependencies
QVector<QVector<int>> nodeDependencies(_file.nodes.size());
@ -750,10 +750,10 @@ bool GLTFReader::buildGeometry(FBXGeometry& geometry, const QUrl& url) {
for (int i = 0; i < materialIDs.size(); i++) {
QString& matid = materialIDs[i];
geometry.materials[matid] = FBXMaterial();
FBXMaterial& fbxMaterial = geometry.materials[matid];
fbxMaterial._material = std::make_shared<graphics::Material>();
setFBXMaterial(fbxMaterial, _file.materials[i]);
geometry.materials[matid] = HFMMaterial();
HFMMaterial& hfmMaterial = geometry.materials[matid];
hfmMaterial._material = std::make_shared<graphics::Material>();
setHFMMaterial(hfmMaterial, _file.materials[i]);
}
@ -765,9 +765,9 @@ bool GLTFReader::buildGeometry(FBXGeometry& geometry, const QUrl& url) {
if (node.defined["mesh"]) {
qCDebug(modelformat) << "node_transforms" << node.transforms;
foreach(auto &primitive, _file.meshes[node.mesh].primitives) {
geometry.meshes.append(FBXMesh());
FBXMesh& mesh = geometry.meshes[geometry.meshes.size() - 1];
FBXCluster cluster;
geometry.meshes.append(HFMMesh());
HFMMesh& mesh = geometry.meshes[geometry.meshes.size() - 1];
HFMCluster cluster;
cluster.jointIndex = 0;
cluster.inverseBindMatrix = glm::mat4(1, 0, 0, 0,
0, 1, 0, 0,
@ -775,7 +775,7 @@ bool GLTFReader::buildGeometry(FBXGeometry& geometry, const QUrl& url) {
0, 0, 0, 1);
mesh.clusters.append(cluster);
FBXMeshPart part = FBXMeshPart();
HFMMeshPart part = HFMMeshPart();
int indicesAccessorIdx = primitive.indices;
@ -910,7 +910,7 @@ bool GLTFReader::buildGeometry(FBXGeometry& geometry, const QUrl& url) {
return true;
}
FBXGeometry* GLTFReader::readGLTF(QByteArray& model, const QVariantHash& mapping,
HFMGeometry* GLTFReader::readGLTF(QByteArray& model, const QVariantHash& mapping,
const QUrl& url, bool loadLightmaps, float lightmapLevel) {
_url = url;
@ -924,12 +924,12 @@ FBXGeometry* GLTFReader::readGLTF(QByteArray& model, const QVariantHash& mapping
parseGLTF(model);
//_file.dump();
FBXGeometry* geometryPtr = new FBXGeometry();
FBXGeometry& geometry = *geometryPtr;
HFMGeometry* geometryPtr = new HFMGeometry();
HFMGeometry& geometry = *geometryPtr;
buildGeometry(geometry, url);
//fbxDebugDump(geometry);
//hfmDebugDump(geometry);
return geometryPtr;
}
@ -997,8 +997,8 @@ QNetworkReply* GLTFReader::request(QUrl& url, bool isTest) {
return netReply; // trying to sync later on.
}
FBXTexture GLTFReader::getFBXTexture(const GLTFTexture& texture) {
FBXTexture fbxtex = FBXTexture();
HFMTexture GLTFReader::getHFMTexture(const GLTFTexture& texture) {
HFMTexture fbxtex = HFMTexture();
fbxtex.texcoordSet = 0;
if (texture.defined["source"]) {
@ -1014,7 +1014,7 @@ FBXTexture GLTFReader::getFBXTexture(const GLTFTexture& texture) {
return fbxtex;
}
void GLTFReader::setFBXMaterial(FBXMaterial& fbxmat, const GLTFMaterial& material) {
void GLTFReader::setHFMMaterial(HFMMaterial& fbxmat, const GLTFMaterial& material) {
if (material.defined["name"]) {
@ -1029,17 +1029,17 @@ void GLTFReader::setFBXMaterial(FBXMaterial& fbxmat, const GLTFMaterial& materia
}
if (material.defined["emissiveTexture"]) {
fbxmat.emissiveTexture = getFBXTexture(_file.textures[material.emissiveTexture]);
fbxmat.emissiveTexture = getHFMTexture(_file.textures[material.emissiveTexture]);
fbxmat.useEmissiveMap = true;
}
if (material.defined["normalTexture"]) {
fbxmat.normalTexture = getFBXTexture(_file.textures[material.normalTexture]);
fbxmat.normalTexture = getHFMTexture(_file.textures[material.normalTexture]);
fbxmat.useNormalMap = true;
}
if (material.defined["occlusionTexture"]) {
fbxmat.occlusionTexture = getFBXTexture(_file.textures[material.occlusionTexture]);
fbxmat.occlusionTexture = getHFMTexture(_file.textures[material.occlusionTexture]);
fbxmat.useOcclusionMap = true;
}
@ -1050,14 +1050,14 @@ void GLTFReader::setFBXMaterial(FBXMaterial& fbxmat, const GLTFMaterial& materia
fbxmat.metallic = material.pbrMetallicRoughness.metallicFactor;
}
if (material.pbrMetallicRoughness.defined["baseColorTexture"]) {
fbxmat.opacityTexture = getFBXTexture(_file.textures[material.pbrMetallicRoughness.baseColorTexture]);
fbxmat.albedoTexture = getFBXTexture(_file.textures[material.pbrMetallicRoughness.baseColorTexture]);
fbxmat.opacityTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.baseColorTexture]);
fbxmat.albedoTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.baseColorTexture]);
fbxmat.useAlbedoMap = true;
}
if (material.pbrMetallicRoughness.defined["metallicRoughnessTexture"]) {
fbxmat.roughnessTexture = getFBXTexture(_file.textures[material.pbrMetallicRoughness.metallicRoughnessTexture]);
fbxmat.roughnessTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.metallicRoughnessTexture]);
fbxmat.useRoughnessMap = true;
fbxmat.metallicTexture = getFBXTexture(_file.textures[material.pbrMetallicRoughness.metallicRoughnessTexture]);
fbxmat.metallicTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.metallicRoughnessTexture]);
fbxmat.useMetallicMap = true;
}
if (material.pbrMetallicRoughness.defined["roughnessFactor"]) {
@ -1181,37 +1181,37 @@ void GLTFReader::retriangulate(const QVector<int>& inIndices, const QVector<glm:
}
}
void GLTFReader::fbxDebugDump(const FBXGeometry& fbxgeo) {
qCDebug(modelformat) << "---------------- fbxGeometry ----------------";
qCDebug(modelformat) << " hasSkeletonJoints =" << fbxgeo.hasSkeletonJoints;
qCDebug(modelformat) << " offset =" << fbxgeo.offset;
void GLTFReader::hfmDebugDump(const HFMGeometry& hfmgeo) {
qCDebug(modelformat) << "---------------- hfmGeometry ----------------";
qCDebug(modelformat) << " hasSkeletonJoints =" << hfmgeo.hasSkeletonJoints;
qCDebug(modelformat) << " offset =" << hfmgeo.offset;
qCDebug(modelformat) << " leftEyeJointIndex =" << fbxgeo.leftEyeJointIndex;
qCDebug(modelformat) << " rightEyeJointIndex =" << fbxgeo.rightEyeJointIndex;
qCDebug(modelformat) << " neckJointIndex =" << fbxgeo.neckJointIndex;
qCDebug(modelformat) << " rootJointIndex =" << fbxgeo.rootJointIndex;
qCDebug(modelformat) << " leanJointIndex =" << fbxgeo.leanJointIndex;
qCDebug(modelformat) << " headJointIndex =" << fbxgeo.headJointIndex;
qCDebug(modelformat) << " leftHandJointIndex" << fbxgeo.leftHandJointIndex;
qCDebug(modelformat) << " rightHandJointIndex" << fbxgeo.rightHandJointIndex;
qCDebug(modelformat) << " leftToeJointIndex" << fbxgeo.leftToeJointIndex;
qCDebug(modelformat) << " rightToeJointIndex" << fbxgeo.rightToeJointIndex;
qCDebug(modelformat) << " leftEyeSize = " << fbxgeo.leftEyeSize;
qCDebug(modelformat) << " rightEyeSize = " << fbxgeo.rightEyeSize;
qCDebug(modelformat) << " leftEyeJointIndex =" << hfmgeo.leftEyeJointIndex;
qCDebug(modelformat) << " rightEyeJointIndex =" << hfmgeo.rightEyeJointIndex;
qCDebug(modelformat) << " neckJointIndex =" << hfmgeo.neckJointIndex;
qCDebug(modelformat) << " rootJointIndex =" << hfmgeo.rootJointIndex;
qCDebug(modelformat) << " leanJointIndex =" << hfmgeo.leanJointIndex;
qCDebug(modelformat) << " headJointIndex =" << hfmgeo.headJointIndex;
qCDebug(modelformat) << " leftHandJointIndex" << hfmgeo.leftHandJointIndex;
qCDebug(modelformat) << " rightHandJointIndex" << hfmgeo.rightHandJointIndex;
qCDebug(modelformat) << " leftToeJointIndex" << hfmgeo.leftToeJointIndex;
qCDebug(modelformat) << " rightToeJointIndex" << hfmgeo.rightToeJointIndex;
qCDebug(modelformat) << " leftEyeSize = " << hfmgeo.leftEyeSize;
qCDebug(modelformat) << " rightEyeSize = " << hfmgeo.rightEyeSize;
qCDebug(modelformat) << " palmDirection = " << fbxgeo.palmDirection;
qCDebug(modelformat) << " palmDirection = " << hfmgeo.palmDirection;
qCDebug(modelformat) << " neckPivot = " << fbxgeo.neckPivot;
qCDebug(modelformat) << " neckPivot = " << hfmgeo.neckPivot;
qCDebug(modelformat) << " bindExtents.size() = " << fbxgeo.bindExtents.size();
qCDebug(modelformat) << " meshExtents.size() = " << fbxgeo.meshExtents.size();
qCDebug(modelformat) << " bindExtents.size() = " << hfmgeo.bindExtents.size();
qCDebug(modelformat) << " meshExtents.size() = " << hfmgeo.meshExtents.size();
qCDebug(modelformat) << " jointIndices.size() =" << fbxgeo.jointIndices.size();
qCDebug(modelformat) << " joints.count() =" << fbxgeo.joints.count();
qCDebug(modelformat) << " jointIndices.size() =" << hfmgeo.jointIndices.size();
qCDebug(modelformat) << " joints.count() =" << hfmgeo.joints.count();
qCDebug(modelformat) << "---------------- Meshes ----------------";
qCDebug(modelformat) << " meshes.count() =" << fbxgeo.meshes.count();
qCDebug(modelformat) << " blendshapeChannelNames = " << fbxgeo.blendshapeChannelNames;
foreach(FBXMesh mesh, fbxgeo.meshes) {
qCDebug(modelformat) << " meshes.count() =" << hfmgeo.meshes.count();
qCDebug(modelformat) << " blendshapeChannelNames = " << hfmgeo.blendshapeChannelNames;
foreach(HFMMesh mesh, hfmgeo.meshes) {
qCDebug(modelformat) << "\n";
qCDebug(modelformat) << " meshpointer =" << mesh._mesh.get();
qCDebug(modelformat) << " meshindex =" << mesh.meshIndex;
@ -1227,7 +1227,7 @@ void GLTFReader::fbxDebugDump(const FBXGeometry& fbxgeo) {
qCDebug(modelformat) << " modelTransform =" << mesh.modelTransform;
qCDebug(modelformat) << " parts.count() =" << mesh.parts.count();
qCDebug(modelformat) << "---------------- Meshes (blendshapes)--------";
foreach(FBXBlendshape bshape, mesh.blendshapes) {
foreach(HFMBlendshape bshape, mesh.blendshapes) {
qCDebug(modelformat) << "\n";
qCDebug(modelformat) << " bshape.indices.count() =" << bshape.indices.count();
qCDebug(modelformat) << " bshape.vertices.count() =" << bshape.vertices.count();
@ -1235,7 +1235,7 @@ void GLTFReader::fbxDebugDump(const FBXGeometry& fbxgeo) {
qCDebug(modelformat) << "\n";
}
qCDebug(modelformat) << "---------------- Meshes (meshparts)--------";
foreach(FBXMeshPart meshPart, mesh.parts) {
foreach(HFMMeshPart meshPart, mesh.parts) {
qCDebug(modelformat) << "\n";
qCDebug(modelformat) << " quadIndices.count() =" << meshPart.quadIndices.count();
qCDebug(modelformat) << " triangleIndices.count() =" << meshPart.triangleIndices.count();
@ -1245,7 +1245,7 @@ void GLTFReader::fbxDebugDump(const FBXGeometry& fbxgeo) {
}
qCDebug(modelformat) << "---------------- Meshes (clusters)--------";
qCDebug(modelformat) << " clusters.count() =" << mesh.clusters.count();
foreach(FBXCluster cluster, mesh.clusters) {
foreach(HFMCluster cluster, mesh.clusters) {
qCDebug(modelformat) << "\n";
qCDebug(modelformat) << " jointIndex =" << cluster.jointIndex;
qCDebug(modelformat) << " inverseBindMatrix =" << cluster.inverseBindMatrix;
@ -1254,18 +1254,18 @@ void GLTFReader::fbxDebugDump(const FBXGeometry& fbxgeo) {
qCDebug(modelformat) << "\n";
}
qCDebug(modelformat) << "---------------- AnimationFrames ----------------";
foreach(FBXAnimationFrame anim, fbxgeo.animationFrames) {
foreach(HFMAnimationFrame anim, hfmgeo.animationFrames) {
qCDebug(modelformat) << " anim.translations = " << anim.translations;
qCDebug(modelformat) << " anim.rotations = " << anim.rotations;
}
QList<int> mitomona_keys = fbxgeo.meshIndicesToModelNames.keys();
QList<int> mitomona_keys = hfmgeo.meshIndicesToModelNames.keys();
foreach(int key, mitomona_keys) {
qCDebug(modelformat) << " meshIndicesToModelNames key =" << key << " val =" << fbxgeo.meshIndicesToModelNames[key];
qCDebug(modelformat) << " meshIndicesToModelNames key =" << key << " val =" << hfmgeo.meshIndicesToModelNames[key];
}
qCDebug(modelformat) << "---------------- Materials ----------------";
foreach(FBXMaterial mat, fbxgeo.materials) {
foreach(HFMMaterial mat, hfmgeo.materials) {
qCDebug(modelformat) << "\n";
qCDebug(modelformat) << " mat.materialID =" << mat.materialID;
qCDebug(modelformat) << " diffuseColor =" << mat.diffuseColor;
@ -1314,7 +1314,7 @@ void GLTFReader::fbxDebugDump(const FBXGeometry& fbxgeo) {
qCDebug(modelformat) << "---------------- Joints ----------------";
foreach(FBXJoint joint, fbxgeo.joints) {
foreach(HFMJoint joint, hfmgeo.joints) {
qCDebug(modelformat) << "\n";
qCDebug(modelformat) << " shapeInfo.avgPoint =" << joint.shapeInfo.avgPoint;
qCDebug(modelformat) << " shapeInfo.debugLines =" << joint.shapeInfo.debugLines;

View file

@ -706,7 +706,7 @@ class GLTFReader : public QObject {
Q_OBJECT
public:
GLTFReader();
FBXGeometry* readGLTF(QByteArray& model, const QVariantHash& mapping,
HFMGeometry* readGLTF(QByteArray& model, const QVariantHash& mapping,
const QUrl& url, bool loadLightmaps = true, float lightmapLevel = 1.0f);
private:
GLTFFile _file;
@ -714,7 +714,7 @@ private:
glm::mat4 getModelTransform(const GLTFNode& node);
bool buildGeometry(FBXGeometry& geometry, const QUrl& url);
bool buildGeometry(HFMGeometry& geometry, const QUrl& url);
bool parseGLTF(const QByteArray& model);
bool getStringVal(const QJsonObject& object, const QString& fieldname,
@ -778,9 +778,9 @@ private:
bool doesResourceExist(const QString& url);
void setFBXMaterial(FBXMaterial& fbxmat, const GLTFMaterial& material);
FBXTexture getFBXTexture(const GLTFTexture& texture);
void fbxDebugDump(const FBXGeometry& fbxgeo);
void setHFMMaterial(HFMMaterial& fbxmat, const GLTFMaterial& material);
HFMTexture getHFMTexture(const GLTFTexture& texture);
void hfmDebugDump(const HFMGeometry& hfmgeo);
};
#endif // hifi_GLTFReader_h

View file

@ -175,7 +175,7 @@ glm::vec2 OBJTokenizer::getVec2() {
}
void setMeshPartDefaults(FBXMeshPart& meshPart, QString materialID) {
void setMeshPartDefaults(HFMMeshPart& meshPart, QString materialID) {
meshPart.materialID = materialID;
}
@ -488,12 +488,12 @@ QNetworkReply* request(QUrl& url, bool isTest) {
}
bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mapping, FBXGeometry& geometry,
bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mapping, HFMGeometry& geometry,
float& scaleGuess, bool combineParts) {
FaceGroup faces;
FBXMesh& mesh = geometry.meshes[0];
mesh.parts.append(FBXMeshPart());
FBXMeshPart& meshPart = mesh.parts.last();
HFMMesh& mesh = geometry.meshes[0];
mesh.parts.append(HFMMeshPart());
HFMMeshPart& meshPart = mesh.parts.last();
bool sawG = false;
bool result = true;
int originalFaceCountForDebugging = 0;
@ -652,13 +652,13 @@ done:
}
FBXGeometry::Pointer OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, bool combineParts, const QUrl& url) {
HFMGeometry::Pointer OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, bool combineParts, const QUrl& url) {
PROFILE_RANGE_EX(resource_parse, __FUNCTION__, 0xffff0000, nullptr);
QBuffer buffer { &model };
buffer.open(QIODevice::ReadOnly);
auto geometryPtr { std::make_shared<FBXGeometry>() };
FBXGeometry& geometry { *geometryPtr };
auto geometryPtr { std::make_shared<HFMGeometry>() };
HFMGeometry& geometry { *geometryPtr };
OBJTokenizer tokenizer { &buffer };
float scaleGuess = 1.0f;
@ -666,14 +666,14 @@ FBXGeometry::Pointer OBJReader::readOBJ(QByteArray& model, const QVariantHash& m
_url = url;
geometry.meshExtents.reset();
geometry.meshes.append(FBXMesh());
geometry.meshes.append(HFMMesh());
try {
// call parseOBJGroup as long as it's returning true. Each successful call will
// add a new meshPart to the geometry's single mesh.
while (parseOBJGroup(tokenizer, mapping, geometry, scaleGuess, combineParts)) {}
FBXMesh& mesh = geometry.meshes[0];
HFMMesh& mesh = geometry.meshes[0];
mesh.meshIndex = 0;
geometry.joints.resize(1);
@ -688,7 +688,7 @@ FBXGeometry::Pointer OBJReader::readOBJ(QByteArray& model, const QVariantHash& m
geometry.jointIndices["x"] = 1;
FBXCluster cluster;
HFMCluster cluster;
cluster.jointIndex = 0;
cluster.inverseBindMatrix = glm::mat4(1, 0, 0, 0,
0, 1, 0, 0,
@ -697,20 +697,20 @@ FBXGeometry::Pointer OBJReader::readOBJ(QByteArray& model, const QVariantHash& m
mesh.clusters.append(cluster);
QMap<QString, int> materialMeshIdMap;
QVector<FBXMeshPart> fbxMeshParts;
QVector<HFMMeshPart> hfmMeshParts;
for (int i = 0, meshPartCount = 0; i < mesh.parts.count(); i++, meshPartCount++) {
FBXMeshPart& meshPart = mesh.parts[i];
HFMMeshPart& meshPart = mesh.parts[i];
FaceGroup faceGroup = faceGroups[meshPartCount];
bool specifiesUV = false;
foreach(OBJFace face, faceGroup) {
// Go through all of the OBJ faces and determine the number of different materials necessary (each different material will be a unique mesh).
// NOTE (trent/mittens 3/30/17): this seems hardcore wasteful and is slowed down a bit by iterating through the face group twice, but it's the best way I've thought of to hack multi-material support in an OBJ into this pipeline.
if (!materialMeshIdMap.contains(face.materialName)) {
// Create a new FBXMesh for this material mapping.
// Create a new HFMMesh for this material mapping.
materialMeshIdMap.insert(face.materialName, materialMeshIdMap.count());
fbxMeshParts.append(FBXMeshPart());
FBXMeshPart& meshPartNew = fbxMeshParts.last();
hfmMeshParts.append(HFMMeshPart());
HFMMeshPart& meshPartNew = hfmMeshParts.last();
meshPartNew.quadIndices = QVector<int>(meshPart.quadIndices); // Copy over quad indices [NOTE (trent/mittens, 4/3/17): Likely unnecessary since they go unused anyway].
meshPartNew.quadTrianglesIndices = QVector<int>(meshPart.quadTrianglesIndices); // Copy over quad triangulated indices [NOTE (trent/mittens, 4/3/17): Likely unnecessary since they go unused anyway].
meshPartNew.triangleIndices = QVector<int>(meshPart.triangleIndices); // Copy over triangle indices.
@ -745,14 +745,14 @@ FBXGeometry::Pointer OBJReader::readOBJ(QByteArray& model, const QVariantHash& m
// clean up old mesh parts.
int unmodifiedMeshPartCount = mesh.parts.count();
mesh.parts.clear();
mesh.parts = QVector<FBXMeshPart>(fbxMeshParts);
mesh.parts = QVector<HFMMeshPart>(hfmMeshParts);
for (int i = 0, meshPartCount = 0; i < unmodifiedMeshPartCount; i++, meshPartCount++) {
FaceGroup faceGroup = faceGroups[meshPartCount];
// Now that each mesh has been created with its own unique material mappings, fill them with data (vertex data is duplicated, face data is not).
foreach(OBJFace face, faceGroup) {
FBXMeshPart& meshPart = mesh.parts[materialMeshIdMap[face.materialName]];
HFMMeshPart& meshPart = mesh.parts[materialMeshIdMap[face.materialName]];
glm::vec3 v0 = checked_at(vertices, face.vertexIndices[0]);
glm::vec3 v1 = checked_at(vertices, face.vertexIndices[1]);
@ -824,7 +824,7 @@ FBXGeometry::Pointer OBJReader::readOBJ(QByteArray& model, const QVariantHash& m
// Build the single mesh.
FBXReader::buildModelMesh(mesh, url.toString());
// fbxDebugDump(geometry);
// hfmDebugDump(geometry);
} catch(const std::exception& e) {
qCDebug(modelformat) << "OBJ reader fail: " << e.what();
}
@ -885,38 +885,38 @@ FBXGeometry::Pointer OBJReader::readOBJ(QByteArray& model, const QVariantHash& m
if (!objMaterial.used) {
continue;
}
geometry.materials[materialID] = FBXMaterial(objMaterial.diffuseColor,
geometry.materials[materialID] = HFMMaterial(objMaterial.diffuseColor,
objMaterial.specularColor,
objMaterial.emissiveColor,
objMaterial.shininess,
objMaterial.opacity);
FBXMaterial& fbxMaterial = geometry.materials[materialID];
fbxMaterial.materialID = materialID;
fbxMaterial._material = std::make_shared<graphics::Material>();
graphics::MaterialPointer modelMaterial = fbxMaterial._material;
HFMMaterial& hfmMaterial = geometry.materials[materialID];
hfmMaterial.materialID = materialID;
hfmMaterial._material = std::make_shared<graphics::Material>();
graphics::MaterialPointer modelMaterial = hfmMaterial._material;
if (!objMaterial.diffuseTextureFilename.isEmpty()) {
fbxMaterial.albedoTexture.filename = objMaterial.diffuseTextureFilename;
hfmMaterial.albedoTexture.filename = objMaterial.diffuseTextureFilename;
}
if (!objMaterial.specularTextureFilename.isEmpty()) {
fbxMaterial.specularTexture.filename = objMaterial.specularTextureFilename;
hfmMaterial.specularTexture.filename = objMaterial.specularTextureFilename;
}
if (!objMaterial.emissiveTextureFilename.isEmpty()) {
fbxMaterial.emissiveTexture.filename = objMaterial.emissiveTextureFilename;
hfmMaterial.emissiveTexture.filename = objMaterial.emissiveTextureFilename;
}
if (!objMaterial.bumpTextureFilename.isEmpty()) {
fbxMaterial.normalTexture.filename = objMaterial.bumpTextureFilename;
fbxMaterial.normalTexture.isBumpmap = true;
fbxMaterial.bumpMultiplier = objMaterial.bumpTextureOptions.bumpMultiplier;
hfmMaterial.normalTexture.filename = objMaterial.bumpTextureFilename;
hfmMaterial.normalTexture.isBumpmap = true;
hfmMaterial.bumpMultiplier = objMaterial.bumpTextureOptions.bumpMultiplier;
}
if (!objMaterial.opacityTextureFilename.isEmpty()) {
fbxMaterial.opacityTexture.filename = objMaterial.opacityTextureFilename;
hfmMaterial.opacityTexture.filename = objMaterial.opacityTextureFilename;
}
modelMaterial->setEmissive(fbxMaterial.emissiveColor);
modelMaterial->setAlbedo(fbxMaterial.diffuseColor);
modelMaterial->setMetallic(glm::length(fbxMaterial.specularColor));
modelMaterial->setRoughness(graphics::Material::shininessToRoughness(fbxMaterial.shininess));
modelMaterial->setEmissive(hfmMaterial.emissiveColor);
modelMaterial->setAlbedo(hfmMaterial.diffuseColor);
modelMaterial->setMetallic(glm::length(hfmMaterial.specularColor));
modelMaterial->setRoughness(graphics::Material::shininessToRoughness(hfmMaterial.shininess));
bool applyTransparency = false;
bool applyShininess = false;
@ -971,7 +971,7 @@ FBXGeometry::Pointer OBJReader::readOBJ(QByteArray& model, const QVariantHash& m
}
if (applyTransparency) {
fbxMaterial.opacity = std::max(fbxMaterial.opacity, ILLUMINATION_MODEL_MIN_OPACITY);
hfmMaterial.opacity = std::max(hfmMaterial.opacity, ILLUMINATION_MODEL_MIN_OPACITY);
}
if (applyShininess) {
modelMaterial->setRoughness(ILLUMINATION_MODEL_APPLY_SHININESS);
@ -985,18 +985,18 @@ FBXGeometry::Pointer OBJReader::readOBJ(QByteArray& model, const QVariantHash& m
modelMaterial->setFresnel(glm::vec3(1.0f));
}
modelMaterial->setOpacity(fbxMaterial.opacity);
modelMaterial->setOpacity(hfmMaterial.opacity);
}
return geometryPtr;
}
void fbxDebugDump(const FBXGeometry& fbxgeo) {
qCDebug(modelformat) << "---------------- fbxGeometry ----------------";
qCDebug(modelformat) << " hasSkeletonJoints =" << fbxgeo.hasSkeletonJoints;
qCDebug(modelformat) << " offset =" << fbxgeo.offset;
qCDebug(modelformat) << " meshes.count() =" << fbxgeo.meshes.count();
foreach (FBXMesh mesh, fbxgeo.meshes) {
void hfmDebugDump(const HFMGeometry& hfmgeo) {
qCDebug(modelformat) << "---------------- hfmGeometry ----------------";
qCDebug(modelformat) << " hasSkeletonJoints =" << hfmgeo.hasSkeletonJoints;
qCDebug(modelformat) << " offset =" << hfmgeo.offset;
qCDebug(modelformat) << " meshes.count() =" << hfmgeo.meshes.count();
foreach (HFMMesh mesh, hfmgeo.meshes) {
qCDebug(modelformat) << " vertices.count() =" << mesh.vertices.count();
qCDebug(modelformat) << " colors.count() =" << mesh.colors.count();
qCDebug(modelformat) << " normals.count() =" << mesh.normals.count();
@ -1014,7 +1014,7 @@ void fbxDebugDump(const FBXGeometry& fbxgeo) {
qCDebug(modelformat) << " meshExtents =" << mesh.meshExtents;
qCDebug(modelformat) << " modelTransform =" << mesh.modelTransform;
qCDebug(modelformat) << " parts.count() =" << mesh.parts.count();
foreach (FBXMeshPart meshPart, mesh.parts) {
foreach (HFMMeshPart meshPart, mesh.parts) {
qCDebug(modelformat) << " quadIndices.count() =" << meshPart.quadIndices.count();
qCDebug(modelformat) << " triangleIndices.count() =" << meshPart.triangleIndices.count();
/*
@ -1031,16 +1031,16 @@ void fbxDebugDump(const FBXGeometry& fbxgeo) {
*/
}
qCDebug(modelformat) << " clusters.count() =" << mesh.clusters.count();
foreach (FBXCluster cluster, mesh.clusters) {
foreach (HFMCluster cluster, mesh.clusters) {
qCDebug(modelformat) << " jointIndex =" << cluster.jointIndex;
qCDebug(modelformat) << " inverseBindMatrix =" << cluster.inverseBindMatrix;
}
}
qCDebug(modelformat) << " jointIndices =" << fbxgeo.jointIndices;
qCDebug(modelformat) << " joints.count() =" << fbxgeo.joints.count();
qCDebug(modelformat) << " jointIndices =" << hfmgeo.jointIndices;
qCDebug(modelformat) << " joints.count() =" << hfmgeo.joints.count();
foreach (FBXJoint joint, fbxgeo.joints) {
foreach (HFMJoint joint, hfmgeo.joints) {
qCDebug(modelformat) << " isFree =" << joint.isFree;
qCDebug(modelformat) << " freeLineage" << joint.freeLineage;
qCDebug(modelformat) << " parentIndex" << joint.parentIndex;

View file

@ -42,7 +42,7 @@ public:
bool add(const QByteArray& vertexIndex, const QByteArray& textureIndex, const QByteArray& normalIndex,
const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& vertexColors);
// Return a set of one or more OBJFaces from this one, in which each is just a triangle.
// Even though FBXMeshPart can handle quads, it would be messy to try to keep track of mixed-size faces, so we treat everything as triangles.
// Even though HFMMeshPart can handle quads, it would be messy to try to keep track of mixed-size faces, so we treat everything as triangles.
QVector<OBJFace> triangulate();
private:
void addFrom(const OBJFace* face, int index);
@ -54,7 +54,7 @@ public:
}
;
// Materials and references to material names can come in any order, and different mesh parts can refer to the same material.
// Therefore it would get pretty hacky to try to use FBXMeshPart to store these as we traverse the files.
// Therefore it would get pretty hacky to try to use HFMMeshPart to store these as we traverse the files.
class OBJMaterial {
public:
float shininess;
@ -87,13 +87,13 @@ public:
QString currentMaterialName;
QHash<QString, OBJMaterial> materials;
FBXGeometry::Pointer readOBJ(QByteArray& model, const QVariantHash& mapping, bool combineParts, const QUrl& url = QUrl());
HFMGeometry::Pointer readOBJ(QByteArray& model, const QVariantHash& mapping, bool combineParts, const QUrl& url = QUrl());
private:
QUrl _url;
QHash<QByteArray, bool> librariesSeen;
bool parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mapping, FBXGeometry& geometry,
bool parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mapping, HFMGeometry& geometry,
float& scaleGuess, bool combineParts);
void parseMaterialLibrary(QIODevice* device);
void parseTextureLine(const QByteArray& textureLine, QByteArray& filename, OBJMaterialTextureOptions& textureOptions);
@ -103,5 +103,5 @@ private:
};
// What are these utilities doing here? One is used by fbx loading code in VHACD Utils, and the other a general debugging utility.
void setMeshPartDefaults(FBXMeshPart& meshPart, QString materialID);
void fbxDebugDump(const FBXGeometry& fbxgeo);
void setMeshPartDefaults(HFMMeshPart& meshPart, QString materialID);
void hfmDebugDump(const HFMGeometry& hfmgeo);

View file

@ -128,7 +128,7 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) {
void GeometryMappingResource::onGeometryMappingLoaded(bool success) {
if (success && _geometryResource) {
_fbxGeometry = _geometryResource->_fbxGeometry;
_hfmGeometry = _geometryResource->_hfmGeometry;
_meshParts = _geometryResource->_meshParts;
_meshes = _geometryResource->_meshes;
_materials = _geometryResource->_materials;
@ -193,38 +193,38 @@ void GeometryReader::run() {
_url.path().toLower().endsWith(".obj.gz") ||
_url.path().toLower().endsWith(".gltf"))) {
FBXGeometry::Pointer fbxGeometry;
HFMGeometry::Pointer hfmGeometry;
if (_url.path().toLower().endsWith(".fbx")) {
fbxGeometry.reset(readFBX(_data, _mapping, _url.path()));
if (fbxGeometry->meshes.size() == 0 && fbxGeometry->joints.size() == 0) {
hfmGeometry.reset(readFBX(_data, _mapping, _url.path()));
if (hfmGeometry->meshes.size() == 0 && hfmGeometry->joints.size() == 0) {
throw QString("empty geometry, possibly due to an unsupported FBX version");
}
} else if (_url.path().toLower().endsWith(".obj")) {
fbxGeometry = OBJReader().readOBJ(_data, _mapping, _combineParts, _url);
hfmGeometry = OBJReader().readOBJ(_data, _mapping, _combineParts, _url);
} else if (_url.path().toLower().endsWith(".obj.gz")) {
QByteArray uncompressedData;
if (gunzip(_data, uncompressedData)){
fbxGeometry = OBJReader().readOBJ(uncompressedData, _mapping, _combineParts, _url);
hfmGeometry = OBJReader().readOBJ(uncompressedData, _mapping, _combineParts, _url);
} else {
throw QString("failed to decompress .obj.gz");
}
} else if (_url.path().toLower().endsWith(".gltf")) {
std::shared_ptr<GLTFReader> glreader = std::make_shared<GLTFReader>();
fbxGeometry.reset(glreader->readGLTF(_data, _mapping, _url));
if (fbxGeometry->meshes.size() == 0 && fbxGeometry->joints.size() == 0) {
hfmGeometry.reset(glreader->readGLTF(_data, _mapping, _url));
if (hfmGeometry->meshes.size() == 0 && hfmGeometry->joints.size() == 0) {
throw QString("empty geometry, possibly due to an unsupported GLTF version");
}
} else {
throw QString("unsupported format");
}
// Add scripts to fbxgeometry
// Add scripts to hfmGeometry
if (!_mapping.value(SCRIPT_FIELD).isNull()) {
QVariantList scripts = _mapping.values(SCRIPT_FIELD);
for (auto &script : scripts) {
fbxGeometry->scripts.push_back(script.toString());
hfmGeometry->scripts.push_back(script.toString());
}
}
@ -234,7 +234,7 @@ void GeometryReader::run() {
qCWarning(modelnetworking) << "Abandoning load of" << _url << "; could not get strong ref";
} else {
QMetaObject::invokeMethod(resource.data(), "setGeometryDefinition",
Q_ARG(FBXGeometry::Pointer, fbxGeometry));
Q_ARG(HFMGeometry::Pointer, hfmGeometry));
}
} else {
throw QString("url is invalid");
@ -262,7 +262,7 @@ public:
virtual void downloadFinished(const QByteArray& data) override;
protected:
Q_INVOKABLE void setGeometryDefinition(FBXGeometry::Pointer fbxGeometry);
Q_INVOKABLE void setGeometryDefinition(HFMGeometry::Pointer hfmGeometry);
private:
QVariantHash _mapping;
@ -277,13 +277,13 @@ void GeometryDefinitionResource::downloadFinished(const QByteArray& data) {
QThreadPool::globalInstance()->start(new GeometryReader(_self, _effectiveBaseURL, _mapping, data, _combineParts));
}
void GeometryDefinitionResource::setGeometryDefinition(FBXGeometry::Pointer fbxGeometry) {
void GeometryDefinitionResource::setGeometryDefinition(HFMGeometry::Pointer hfmGeometry) {
// Assume ownership of the geometry pointer
_fbxGeometry = fbxGeometry;
_hfmGeometry = hfmGeometry;
// Copy materials
QHash<QString, size_t> materialIDAtlas;
for (const FBXMaterial& material : _fbxGeometry->materials) {
for (const HFMMaterial& material : _hfmGeometry->materials) {
materialIDAtlas[material.materialID] = _materials.size();
_materials.push_back(std::make_shared<NetworkMaterial>(material, _textureBaseUrl));
}
@ -291,11 +291,11 @@ void GeometryDefinitionResource::setGeometryDefinition(FBXGeometry::Pointer fbxG
std::shared_ptr<GeometryMeshes> meshes = std::make_shared<GeometryMeshes>();
std::shared_ptr<GeometryMeshParts> parts = std::make_shared<GeometryMeshParts>();
int meshID = 0;
for (const FBXMesh& mesh : _fbxGeometry->meshes) {
for (const HFMMesh& mesh : _hfmGeometry->meshes) {
// Copy mesh pointers
meshes->emplace_back(mesh._mesh);
int partID = 0;
for (const FBXMeshPart& part : mesh.parts) {
for (const HFMMeshPart& part : mesh.parts) {
// Construct local parts
parts->push_back(std::make_shared<MeshPart>(meshID, partID, (int)materialIDAtlas[part.materialID]));
partID++;
@ -371,7 +371,7 @@ const QVariantMap Geometry::getTextures() const {
// FIXME: The materials should only be copied when modified, but the Model currently caches the original
Geometry::Geometry(const Geometry& geometry) {
_fbxGeometry = geometry._fbxGeometry;
_hfmGeometry = geometry._hfmGeometry;
_meshes = geometry._meshes;
_meshParts = geometry._meshParts;
@ -444,8 +444,8 @@ void GeometryResource::deleter() {
}
void GeometryResource::setTextures() {
if (_fbxGeometry) {
for (const FBXMaterial& material : _fbxGeometry->materials) {
if (_hfmGeometry) {
for (const HFMMaterial& material : _hfmGeometry->materials) {
_materials.push_back(std::make_shared<NetworkMaterial>(material, _textureBaseUrl));
}
}
@ -512,7 +512,7 @@ const QString& NetworkMaterial::getTextureName(MapChannel channel) {
return NO_TEXTURE;
}
QUrl NetworkMaterial::getTextureUrl(const QUrl& baseUrl, const FBXTexture& texture) {
QUrl NetworkMaterial::getTextureUrl(const QUrl& baseUrl, const HFMTexture& texture) {
if (texture.content.isEmpty()) {
// External file: search relative to the baseUrl, in case filename is relative
return baseUrl.resolved(QUrl(texture.filename));
@ -529,22 +529,22 @@ QUrl NetworkMaterial::getTextureUrl(const QUrl& baseUrl, const FBXTexture& textu
}
}
graphics::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& baseUrl, const FBXTexture& fbxTexture,
graphics::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& baseUrl, const HFMTexture& hfmTexture,
image::TextureUsage::Type type, MapChannel channel) {
if (baseUrl.isEmpty()) {
return nullptr;
}
const auto url = getTextureUrl(baseUrl, fbxTexture);
const auto texture = DependencyManager::get<TextureCache>()->getTexture(url, type, fbxTexture.content, fbxTexture.maxNumPixels);
_textures[channel] = Texture { fbxTexture.name, texture };
const auto url = getTextureUrl(baseUrl, hfmTexture);
const auto texture = DependencyManager::get<TextureCache>()->getTexture(url, type, hfmTexture.content, hfmTexture.maxNumPixels);
_textures[channel] = Texture { hfmTexture.name, texture };
auto map = std::make_shared<graphics::TextureMap>();
if (texture) {
map->setTextureSource(texture->_textureSource);
}
map->setTextureTransform(fbxTexture.transform);
map->setTextureTransform(hfmTexture.transform);
return map;
}
@ -624,7 +624,7 @@ void NetworkMaterial::setLightmapMap(const QUrl& url) {
}
}
NetworkMaterial::NetworkMaterial(const FBXMaterial& material, const QUrl& textureBaseUrl) :
NetworkMaterial::NetworkMaterial(const HFMMaterial& material, const QUrl& textureBaseUrl) :
graphics::Material(*material._material),
_textures(MapChannel::NUM_MAP_CHANNELS)
{

View file

@ -45,9 +45,9 @@ public:
// Mutable, but must retain structure of vector
using NetworkMaterials = std::vector<std::shared_ptr<NetworkMaterial>>;
bool isGeometryLoaded() const { return (bool)_fbxGeometry; }
bool isGeometryLoaded() const { return (bool)_hfmGeometry; }
const FBXGeometry& getFBXGeometry() const { return *_fbxGeometry; }
const HFMGeometry& getHFMGeometry() const { return *_hfmGeometry; }
const GeometryMeshes& getMeshes() const { return *_meshes; }
const std::shared_ptr<NetworkMaterial> getShapeMaterial(int shapeID) const;
@ -62,7 +62,7 @@ protected:
friend class GeometryMappingResource;
// Shared across all geometries, constant throughout lifetime
std::shared_ptr<const FBXGeometry> _fbxGeometry;
std::shared_ptr<const HFMGeometry> _hfmGeometry;
std::shared_ptr<const GeometryMeshes> _meshes;
std::shared_ptr<const GeometryMeshParts> _meshParts;
@ -94,7 +94,7 @@ protected:
// Geometries may not hold onto textures while cached - that is for the texture cache
// Instead, these methods clear and reset textures from the geometry when caching/loading
bool shouldSetTextures() const { return _fbxGeometry && _materials.empty(); }
bool shouldSetTextures() const { return _hfmGeometry && _materials.empty(); }
void setTextures();
void resetTextures();
@ -165,7 +165,7 @@ public:
using MapChannel = graphics::Material::MapChannel;
NetworkMaterial() : _textures(MapChannel::NUM_MAP_CHANNELS) {}
NetworkMaterial(const FBXMaterial& material, const QUrl& textureBaseUrl);
NetworkMaterial(const HFMMaterial& material, const QUrl& textureBaseUrl);
NetworkMaterial(const NetworkMaterial& material);
void setAlbedoMap(const QUrl& url, bool useAlphaChannel);
@ -201,8 +201,8 @@ protected:
private:
// Helpers for the ctors
QUrl getTextureUrl(const QUrl& baseUrl, const FBXTexture& fbxTexture);
graphics::TextureMapPointer fetchTextureMap(const QUrl& baseUrl, const FBXTexture& fbxTexture,
QUrl getTextureUrl(const QUrl& baseUrl, const HFMTexture& hfmTexture);
graphics::TextureMapPointer fetchTextureMap(const QUrl& baseUrl, const HFMTexture& hfmTexture,
image::TextureUsage::Type type, MapChannel channel);
graphics::TextureMapPointer fetchTextureMap(const QUrl& url, image::TextureUsage::Type type, MapChannel channel);

View file

@ -45,8 +45,10 @@ public:
virtual void onTimeout() {}
virtual void onPacketSent(int wireSize, SequenceNumber seqNum, p_high_resolution_clock::time_point timePoint) {}
virtual void onPacketReSent(int wireSize, SequenceNumber seqNum, p_high_resolution_clock::time_point timePoint) {}
virtual int estimatedTimeout() const = 0;
protected:
void setMSS(int mss) { _mss = mss; }
virtual void setInitialSendSequenceNumber(SequenceNumber seqNum) = 0;

View file

@ -195,7 +195,7 @@ void Connection::recordSentPackets(int wireSize, int payloadSize,
void Connection::recordRetransmission(int wireSize, SequenceNumber seqNum, p_high_resolution_clock::time_point timePoint) {
_stats.record(ConnectionStats::Stats::Retransmission);
_congestionControl->onPacketSent(wireSize, seqNum, timePoint);
_congestionControl->onPacketReSent(wireSize, seqNum, timePoint);
}
void Connection::sendACK() {
@ -303,7 +303,7 @@ void Connection::processControl(ControlPacketPointer controlPacket) {
// where the other end expired our connection. Let's reset.
#ifdef UDT_CONNECTION_DEBUG
qCDebug(networking) << "Got HandshakeRequest from" << _destination << ", stopping SendQueue";
qCDebug(networking) << "Got HandshakeRequest from" << _destination << ", stopping SendQueue";
#endif
_hasReceivedHandshakeACK = false;
stopSendQueue();
@ -327,19 +327,19 @@ void Connection::processACK(ControlPacketPointer controlPacket) {
return;
}
if (ack <= _lastReceivedACK) {
if (ack < _lastReceivedACK) {
// this is an out of order ACK, bail
// or
// processing an already received ACK, bail
return;
}
_lastReceivedACK = ack;
// ACK the send queue so it knows what was received
getSendQueue().ack(ack);
if (ack > _lastReceivedACK) {
// this is not a repeated ACK, so update our member and tell the send queue
_lastReceivedACK = ack;
// ACK the send queue so it knows what was received
getSendQueue().ack(ack);
}
// give this ACK to the congestion control and update the send queue parameters
updateCongestionControlAndSendQueue([this, ack, &controlPacket] {
if (_congestionControl->onACK(ack, controlPacket->getReceiveTime())) {

View file

@ -481,6 +481,7 @@ bool SendQueue::isInactive(bool attemptedToSendPacket) {
auto cvStatus = _emptyCondition.wait_for(locker, EMPTY_QUEUES_INACTIVE_TIMEOUT);
if (cvStatus == std::cv_status::timeout && (_packets.isEmpty() || isFlowWindowFull()) && _naks.isEmpty()) {
#ifdef UDT_CONNECTION_DEBUG
qCDebug(networking) << "SendQueue to" << _destination << "has been empty for"
<< EMPTY_QUEUES_INACTIVE_TIMEOUT.count()

View file

@ -27,112 +27,106 @@ TCPVegasCC::TCPVegasCC() {
_baseRTT = std::numeric_limits<int>::max();
}
bool TCPVegasCC::calculateRTT(p_high_resolution_clock::time_point sendTime, p_high_resolution_clock::time_point receiveTime) {
// calculate the RTT (receive time - time ACK sent)
int lastRTT = duration_cast<microseconds>(receiveTime - sendTime).count();
const int MAX_RTT_SAMPLE_MICROSECONDS = 10000000;
if (lastRTT < 0) {
Q_ASSERT_X(false, __FUNCTION__, "calculated an RTT that is not > 0");
return false;
} else if (lastRTT == 0) {
// we do not allow a zero microsecond RTT (as per the UNIX kernel implementation of TCP Vegas)
lastRTT = 1;
} else if (lastRTT > MAX_RTT_SAMPLE_MICROSECONDS) {
// we cap the lastRTT to MAX_RTT_SAMPLE_MICROSECONDS to avoid overflows in window size calculations
lastRTT = MAX_RTT_SAMPLE_MICROSECONDS;
}
if (_ewmaRTT == -1) {
// first RTT sample - set _ewmaRTT to the value and set the variance to half the value
_ewmaRTT = lastRTT;
_rttVariance = lastRTT / 2;
} else {
// This updates the RTT using exponential weighted moving average
// This is the Jacobson's forumla for RTT estimation
// http://www.mathcs.emory.edu/~cheung/Courses/455/Syllabus/7-transport/Jacobson-88.pdf
// Estimated RTT = (1 - x)(estimatedRTT) + (x)(sampleRTT)
// (where x = 0.125 via Jacobson)
// Deviation = (1 - x)(deviation) + x |sampleRTT - estimatedRTT|
// (where x = 0.25 via Jacobson)
static const int RTT_ESTIMATION_ALPHA = 8;
static const int RTT_ESTIMATION_VARIANCE_ALPHA = 4;
_ewmaRTT = (_ewmaRTT * (RTT_ESTIMATION_ALPHA - 1) + lastRTT) / RTT_ESTIMATION_ALPHA;
_rttVariance = (_rttVariance * (RTT_ESTIMATION_VARIANCE_ALPHA- 1)
+ abs(lastRTT - _ewmaRTT)) / RTT_ESTIMATION_VARIANCE_ALPHA;
}
// keep track of the lowest RTT during connection
_baseRTT = std::min(_baseRTT, lastRTT);
// find the min RTT during the last RTT
_currentMinRTT = std::min(_currentMinRTT, lastRTT);
// add 1 to the number of RTT samples collected during this RTT window
++_numRTTs;
return true;
}
bool TCPVegasCC::onACK(SequenceNumber ack, p_high_resolution_clock::time_point receiveTime) {
auto it = _sentPacketTimes.find(ack);
auto previousAck = _lastACK;
_lastACK = ack;
if (it != _sentPacketTimes.end()) {
bool wasDuplicateACK = (ack == previousAck);
// calculate the RTT (receive time - time ACK sent)
int lastRTT = duration_cast<microseconds>(receiveTime - it->second).count();
auto it = std::find_if(_sentPacketDatas.begin(), _sentPacketDatas.end(), [ack](SentPacketData& packetTime){
return packetTime.sequenceNumber == ack;
});
const int MAX_RTT_SAMPLE_MICROSECONDS = 10000000;
if (!wasDuplicateACK && it != _sentPacketDatas.end()) {
// check if we can unambigiously calculate an RTT from this ACK
if (lastRTT < 0) {
Q_ASSERT_X(false, __FUNCTION__, "calculated an RTT that is not > 0");
// for that to be the case,
// any of the packets this ACK covers (from the current ACK back to our previous ACK)
// must not have been re-sent
bool canBeUsedForRTT = std::none_of(_sentPacketDatas.begin(), _sentPacketDatas.end(),
[ack, previousAck](SentPacketData& sentPacketData)
{
return sentPacketData.sequenceNumber > previousAck
&& sentPacketData.sequenceNumber <= ack
&& sentPacketData.wasResent;
});
auto sendTime = it->timePoint;
// remove all sent packet times up to this sequence number
it = _sentPacketDatas.erase(_sentPacketDatas.begin(), it + 1);
// if we can use this ACK for an RTT calculation then do so
// returning false if we calculate an invalid RTT
if (canBeUsedForRTT && !calculateRTT(sendTime, receiveTime)) {
return false;
} else if (lastRTT == 0) {
// we do not allow a zero microsecond RTT (as per the UNIX kernel implementation of TCP Vegas)
lastRTT = 1;
} else if (lastRTT > MAX_RTT_SAMPLE_MICROSECONDS) {
// we cap the lastRTT to MAX_RTT_SAMPLE_MICROSECONDS to avoid overflows in window size calculations
lastRTT = MAX_RTT_SAMPLE_MICROSECONDS;
}
}
if (_ewmaRTT == -1) {
// first RTT sample - set _ewmaRTT to the value and set the variance to half the value
_ewmaRTT = lastRTT;
_rttVariance = lastRTT / 2;
} else {
// This updates the RTT using exponential weighted moving average
// This is the Jacobson's forumla for RTT estimation
// http://www.mathcs.emory.edu/~cheung/Courses/455/Syllabus/7-transport/Jacobson-88.pdf
// Estimated RTT = (1 - x)(estimatedRTT) + (x)(sampleRTT)
// (where x = 0.125 via Jacobson)
// Deviation = (1 - x)(deviation) + x |sampleRTT - estimatedRTT|
// (where x = 0.25 via Jacobson)
static const int RTT_ESTIMATION_ALPHA = 8;
static const int RTT_ESTIMATION_VARIANCE_ALPHA = 4;
_ewmaRTT = (_ewmaRTT * (RTT_ESTIMATION_ALPHA - 1) + lastRTT) / RTT_ESTIMATION_ALPHA;
_rttVariance = (_rttVariance * (RTT_ESTIMATION_VARIANCE_ALPHA- 1)
+ abs(lastRTT - _ewmaRTT)) / RTT_ESTIMATION_VARIANCE_ALPHA;
}
// add 1 to the number of ACKs during this RTT
++_numACKs;
// keep track of the lowest RTT during connection
_baseRTT = std::min(_baseRTT, lastRTT);
// find the min RTT during the last RTT
_currentMinRTT = std::min(_currentMinRTT, lastRTT);
auto sinceLastAdjustment = duration_cast<microseconds>(p_high_resolution_clock::now() - _lastAdjustmentTime).count();
if (sinceLastAdjustment >= _ewmaRTT) {
performCongestionAvoidance(ack);
}
// remove this sent packet time from the hash
_sentPacketTimes.erase(it);
auto sinceLastAdjustment = duration_cast<microseconds>(p_high_resolution_clock::now() - _lastAdjustmentTime).count();
if (sinceLastAdjustment >= _ewmaRTT) {
performCongestionAvoidance(ack);
}
++_numACKSinceFastRetransmit;
// perform the fast re-transmit check if this is a duplicate ACK or if this is the first or second ACK
// after a previous fast re-transmit
if (ack == previousAck || _numACKSinceFastRetransmit < 3) {
// we may need to re-send ackNum + 1 if it has been more than our estimated timeout since it was sent
auto it = _sentPacketTimes.find(ack + 1);
if (it != _sentPacketTimes.end()) {
auto now = p_high_resolution_clock::now();
auto sinceSend = duration_cast<microseconds>(now - it->second).count();
if (sinceSend >= estimatedTimeout()) {
// break out of slow start, we've decided this is loss
_slowStart = false;
// reset the fast re-transmit counter
_numACKSinceFastRetransmit = 0;
// return true so the caller knows we needed a fast re-transmit
return true;
}
}
// if this is the 3rd duplicate ACK, we fallback to Reno's fast re-transmit
static const int RENO_FAST_RETRANSMIT_DUPLICATE_COUNT = 3;
++_duplicateACKCount;
if (ack == previousAck && _duplicateACKCount == RENO_FAST_RETRANSMIT_DUPLICATE_COUNT) {
// break out of slow start, we just hit loss
_slowStart = false;
// reset our fast re-transmit counters
_numACKSinceFastRetransmit = 0;
_duplicateACKCount = 0;
// return true so the caller knows we needed a fast re-transmit
return true;
}
if (wasDuplicateACK || _numACKSinceFastRetransmit < 3) {
return needsFastRetransmit(ack, wasDuplicateACK);
} else {
_duplicateACKCount = 0;
}
@ -141,6 +135,49 @@ bool TCPVegasCC::onACK(SequenceNumber ack, p_high_resolution_clock::time_point r
return false;
}
bool TCPVegasCC::needsFastRetransmit(SequenceNumber ack, bool wasDuplicateACK) {
// we may need to re-send ackNum + 1 if it has been more than our estimated timeout since it was sent
auto nextIt = std::find_if(_sentPacketDatas.begin(), _sentPacketDatas.end(), [ack](SentPacketData& packetTime){
return packetTime.sequenceNumber == ack + 1;
});
if (nextIt != _sentPacketDatas.end()) {
auto now = p_high_resolution_clock::now();
auto sinceSend = duration_cast<microseconds>(now - nextIt->timePoint).count();
if (sinceSend >= estimatedTimeout()) {
// break out of slow start, we've decided this is loss
_slowStart = false;
// reset the fast re-transmit counter
_numACKSinceFastRetransmit = 0;
// return true so the caller knows we needed a fast re-transmit
return true;
}
}
// if this is the 3rd duplicate ACK, we fallback to Reno's fast re-transmit
static const int RENO_FAST_RETRANSMIT_DUPLICATE_COUNT = 3;
++_duplicateACKCount;
if (wasDuplicateACK && _duplicateACKCount == RENO_FAST_RETRANSMIT_DUPLICATE_COUNT) {
// break out of slow start, we just hit loss
_slowStart = false;
// reset our fast re-transmit counters
_numACKSinceFastRetransmit = 0;
_duplicateACKCount = 0;
// return true so the caller knows we needed a fast re-transmit
return true;
}
return false;
}
void TCPVegasCC::performCongestionAvoidance(udt::SequenceNumber ack) {
static int VEGAS_ALPHA_SEGMENTS = 4;
static int VEGAS_BETA_SEGMENTS = 6;
@ -158,7 +195,7 @@ void TCPVegasCC::performCongestionAvoidance(udt::SequenceNumber ack) {
int64_t windowSizeDiff = (int64_t) _congestionWindowSize * (rtt - _baseRTT) / _baseRTT;
if (_numACKs <= 2) {
if (_numRTTs <= 2) {
performRenoCongestionAvoidance(ack);
} else {
if (_slowStart) {
@ -209,7 +246,7 @@ void TCPVegasCC::performCongestionAvoidance(udt::SequenceNumber ack) {
_currentMinRTT = std::numeric_limits<int>::max();
// reset our count of collected RTT samples
_numACKs = 0;
_numRTTs = 0;
}
@ -230,29 +267,29 @@ void TCPVegasCC::performRenoCongestionAvoidance(SequenceNumber ack) {
return;
}
int numAcked = _numACKs;
int numRTTCollected = _numRTTs;
if (_slowStart) {
// while in slow start we grow the congestion window by the number of ACKed packets
// allowing it to grow as high as the slow start threshold
int congestionWindow = _congestionWindowSize + numAcked;
int congestionWindow = _congestionWindowSize + numRTTCollected;
if (congestionWindow > udt::MAX_PACKETS_IN_FLIGHT) {
// we're done with slow start, set the congestion window to the slow start threshold
_congestionWindowSize = udt::MAX_PACKETS_IN_FLIGHT;
// figure out how many left over ACKs we should apply using the regular reno congestion avoidance
numAcked = congestionWindow - udt::MAX_PACKETS_IN_FLIGHT;
numRTTCollected = congestionWindow - udt::MAX_PACKETS_IN_FLIGHT;
} else {
_congestionWindowSize = congestionWindow;
numAcked = 0;
numRTTCollected = 0;
}
}
// grab the size of the window prior to reno additive increase
int preAIWindowSize = _congestionWindowSize;
if (numAcked > 0) {
if (numRTTCollected > 0) {
// Once we are out of slow start, we use additive increase to grow the window slowly.
// We grow the congestion window by a single packet everytime the entire congestion window is sent.
@ -263,7 +300,7 @@ void TCPVegasCC::performRenoCongestionAvoidance(SequenceNumber ack) {
}
// increase the window size by (1 / window size) for every ACK received
_ackAICount += numAcked;
_ackAICount += numRTTCollected;
if (_ackAICount >= preAIWindowSize) {
// when _ackAICount % preAIWindowSize == 0 then _ackAICount is 0
// when _ackAICount % preAIWindowSize != 0 then _ackAICount is _ackAICount - (_ackAICount % preAIWindowSize)
@ -277,8 +314,19 @@ void TCPVegasCC::performRenoCongestionAvoidance(SequenceNumber ack) {
}
void TCPVegasCC::onPacketSent(int wireSize, SequenceNumber seqNum, p_high_resolution_clock::time_point timePoint) {
if (_sentPacketTimes.find(seqNum) == _sentPacketTimes.end()) {
_sentPacketTimes[seqNum] = timePoint;
_sentPacketDatas.emplace_back(seqNum, timePoint);
}
void TCPVegasCC::onPacketReSent(int wireSize, SequenceNumber seqNum, p_high_resolution_clock::time_point timePoint) {
// look for our information for this sent packet
auto it = std::find_if(_sentPacketDatas.begin(), _sentPacketDatas.end(), [seqNum](SentPacketData& sentPacketInfo){
return sentPacketInfo.sequenceNumber == seqNum;
});
// if we found information for this packet (it hasn't been erased because it hasn't yet been ACKed)
// then mark it as re-sent so we know it cannot be used for RTT calculations
if (it != _sentPacketDatas.end()) {
it->wasResent = true;
}
}

View file

@ -30,6 +30,7 @@ public:
virtual void onTimeout() override {};
virtual void onPacketSent(int wireSize, SequenceNumber seqNum, p_high_resolution_clock::time_point timePoint) override;
virtual void onPacketReSent(int wireSize, SequenceNumber seqNum, p_high_resolution_clock::time_point timePoint) override;
virtual int estimatedTimeout() const override;
@ -37,11 +38,23 @@ protected:
virtual void performCongestionAvoidance(SequenceNumber ack);
virtual void setInitialSendSequenceNumber(SequenceNumber seqNum) override { _lastACK = seqNum - 1; }
private:
bool calculateRTT(p_high_resolution_clock::time_point sendTime, p_high_resolution_clock::time_point receiveTime);
bool needsFastRetransmit(SequenceNumber ack, bool wasDuplicateACK);
bool isCongestionWindowLimited();
void performRenoCongestionAvoidance(SequenceNumber ack);
using PacketTimeList = std::map<SequenceNumber, p_high_resolution_clock::time_point>;
PacketTimeList _sentPacketTimes; // Map of sequence numbers to sent time
struct SentPacketData {
SentPacketData(SequenceNumber seqNum, p_high_resolution_clock::time_point tPoint)
: sequenceNumber(seqNum), timePoint(tPoint) {};
SequenceNumber sequenceNumber;
p_high_resolution_clock::time_point timePoint;
bool wasResent { false };
};
using PacketTimeList = std::vector<SentPacketData>;
PacketTimeList _sentPacketDatas; // association of sequence numbers to sent time, for RTT calc
p_high_resolution_clock::time_point _lastAdjustmentTime; // Time of last congestion control adjustment
@ -56,7 +69,7 @@ private:
int _ewmaRTT { -1 }; // Exponential weighted moving average RTT
int _rttVariance { 0 }; // Variance in collected RTT values
int _numACKs { 0 }; // Number of ACKs received during the last RTT (since last performed congestion avoidance)
int _numRTTs { 0 }; // Number of RTTs calculated during the last RTT (since last performed congestion avoidance)
int _ackAICount { 0 }; // Counter for number of ACKs received for Reno additive increase
int _duplicateACKCount { 0 }; // Counter for duplicate ACKs received

View file

@ -32,8 +32,8 @@ bool CauterizedModel::updateGeometry() {
bool needsFullUpdate = Model::updateGeometry();
if (_isCauterized && needsFullUpdate) {
assert(_cauterizeMeshStates.empty());
const FBXGeometry& fbxGeometry = getFBXGeometry();
foreach (const FBXMesh& mesh, fbxGeometry.meshes) {
const HFMGeometry& hfmGeometry = getHFMGeometry();
foreach (const HFMMesh& mesh, hfmGeometry.meshes) {
Model::MeshState state;
if (_useDualQuaternionSkinning) {
state.clusterDualQuaternions.resize(mesh.clusters.size());
@ -76,7 +76,7 @@ void CauterizedModel::createRenderItemSet() {
// Run through all of the meshes, and place them into their segregated, but unsorted buckets
int shapeID = 0;
uint32_t numMeshes = (uint32_t)meshes.size();
const FBXGeometry& fbxGeometry = getFBXGeometry();
const HFMGeometry& hfmGeometry = getHFMGeometry();
for (uint32_t i = 0; i < numMeshes; i++) {
const auto& mesh = meshes.at(i);
if (!mesh) {
@ -86,7 +86,7 @@ void CauterizedModel::createRenderItemSet() {
// Create the render payloads
int numParts = (int)mesh->getNumParts();
for (int partIndex = 0; partIndex < numParts; partIndex++) {
initializeBlendshapes(fbxGeometry.meshes[i], i);
initializeBlendshapes(hfmGeometry.meshes[i], i);
auto ptr = std::make_shared<CauterizedMeshPartPayload>(shared_from_this(), i, partIndex, shapeID, transform, offset);
_modelMeshRenderItems << std::static_pointer_cast<ModelMeshPartPayload>(ptr);
@ -109,13 +109,13 @@ void CauterizedModel::updateClusterMatrices() {
return;
}
_needsUpdateClusterMatrices = false;
const FBXGeometry& geometry = getFBXGeometry();
const HFMGeometry& geometry = getHFMGeometry();
for (int i = 0; i < (int)_meshStates.size(); i++) {
Model::MeshState& state = _meshStates[i];
const FBXMesh& mesh = geometry.meshes.at(i);
const HFMMesh& mesh = geometry.meshes.at(i);
for (int j = 0; j < mesh.clusters.size(); j++) {
const FBXCluster& cluster = mesh.clusters.at(j);
const HFMCluster& cluster = mesh.clusters.at(j);
if (_useDualQuaternionSkinning) {
auto jointPose = _rig.getJointPose(cluster.jointIndex);
Transform jointTransform(jointPose.rot(), jointPose.scale(), jointPose.trans());
@ -145,10 +145,10 @@ void CauterizedModel::updateClusterMatrices() {
for (int i = 0; i < _cauterizeMeshStates.size(); i++) {
Model::MeshState& state = _cauterizeMeshStates[i];
const FBXMesh& mesh = geometry.meshes.at(i);
const HFMMesh& mesh = geometry.meshes.at(i);
for (int j = 0; j < mesh.clusters.size(); j++) {
const FBXCluster& cluster = mesh.clusters.at(j);
const HFMCluster& cluster = mesh.clusters.at(j);
if (_useDualQuaternionSkinning) {
if (_cauterizeBoneSet.find(cluster.jointIndex) == _cauterizeBoneSet.end()) {

View file

@ -260,8 +260,8 @@ void ModelMeshPartPayload::initCache(const ModelPointer& model) {
_hasColorAttrib = vertexFormat->hasAttribute(gpu::Stream::COLOR);
_isSkinned = vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT) && vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_INDEX);
const FBXGeometry& geometry = model->getFBXGeometry();
const FBXMesh& mesh = geometry.meshes.at(_meshIndex);
const HFMGeometry& geometry = model->getHFMGeometry();
const HFMMesh& mesh = geometry.meshes.at(_meshIndex);
_isBlendShaped = !mesh.blendshapes.isEmpty();
_hasTangents = !mesh.tangents.isEmpty();

View file

@ -183,7 +183,7 @@ bool Model::shouldInvalidatePayloadShapeKey(int meshIndex) {
return true;
}
const FBXGeometry& geometry = getFBXGeometry();
const HFMGeometry& geometry = getHFMGeometry();
const auto& networkMeshes = getGeometry()->getMeshes();
// if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown
// to false to rebuild out mesh groups.
@ -278,7 +278,7 @@ void Model::setRenderItemsNeedUpdate() {
void Model::reset() {
if (isLoaded()) {
const FBXGeometry& geometry = getFBXGeometry();
const HFMGeometry& geometry = getHFMGeometry();
_rig.reset(geometry);
emit rigReset();
emit rigReady();
@ -295,13 +295,13 @@ bool Model::updateGeometry() {
_needsReload = false;
// TODO: should all Models have a valid _rig?
if (_rig.jointStatesEmpty() && getFBXGeometry().joints.size() > 0) {
if (_rig.jointStatesEmpty() && getHFMGeometry().joints.size() > 0) {
initJointStates();
assert(_meshStates.empty());
const FBXGeometry& fbxGeometry = getFBXGeometry();
const HFMGeometry& hfmGeometry = getHFMGeometry();
int i = 0;
foreach (const FBXMesh& mesh, fbxGeometry.meshes) {
foreach (const HFMMesh& mesh, hfmGeometry.meshes) {
MeshState state;
state.clusterDualQuaternions.resize(mesh.clusters.size());
state.clusterMatrices.resize(mesh.clusters.size());
@ -319,7 +319,7 @@ bool Model::updateGeometry() {
// virtual
void Model::initJointStates() {
const FBXGeometry& geometry = getFBXGeometry();
const HFMGeometry& geometry = getHFMGeometry();
glm::mat4 modelOffset = glm::scale(_scale) * glm::translate(_offset);
_rig.initJointStates(geometry, modelOffset);
@ -363,7 +363,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g
int bestShapeID = 0;
int bestSubMeshIndex = 0;
const FBXGeometry& geometry = getFBXGeometry();
const HFMGeometry& geometry = getHFMGeometry();
if (!_triangleSetsValid) {
calculateTriangleSets(geometry);
}
@ -506,7 +506,7 @@ bool Model::findParabolaIntersectionAgainstSubMeshes(const glm::vec3& origin, co
int bestShapeID = 0;
int bestSubMeshIndex = 0;
const FBXGeometry& geometry = getFBXGeometry();
const HFMGeometry& geometry = getHFMGeometry();
if (!_triangleSetsValid) {
calculateTriangleSets(geometry);
}
@ -641,7 +641,7 @@ bool Model::convexHullContains(glm::vec3 point) {
QMutexLocker locker(&_mutex);
if (!_triangleSetsValid) {
calculateTriangleSets(getFBXGeometry());
calculateTriangleSets(getHFMGeometry());
}
// If we are inside the models box, then consider the submeshes...
@ -753,14 +753,14 @@ bool Model::replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointe
}
// update triangles for picking
{
FBXGeometry geometry;
HFMGeometry geometry;
for (const auto& newMesh : meshes) {
FBXMesh mesh;
HFMMesh mesh;
mesh._mesh = newMesh.getMeshPointer();
mesh.vertices = buffer_helpers::mesh::attributeToVector<glm::vec3>(mesh._mesh, gpu::Stream::POSITION);
int numParts = (int)newMesh.getMeshPointer()->getNumParts();
for (int partID = 0; partID < numParts; partID++) {
FBXMeshPart part;
HFMMeshPart part;
part.triangleIndices = buffer_helpers::bufferToVector<int>(mesh._mesh->getIndexBuffer(), "part.triangleIndices");
mesh.parts << part;
}
@ -789,12 +789,12 @@ scriptable::ScriptableModelBase Model::getScriptableModel() {
return result;
}
const FBXGeometry& geometry = getFBXGeometry();
const HFMGeometry& geometry = getHFMGeometry();
int numberOfMeshes = geometry.meshes.size();
int shapeID = 0;
for (int i = 0; i < numberOfMeshes; i++) {
const FBXMesh& fbxMesh = geometry.meshes.at(i);
if (auto mesh = fbxMesh._mesh) {
const HFMMesh& hfmMesh = geometry.meshes.at(i);
if (auto mesh = hfmMesh._mesh) {
result.append(mesh);
int numParts = (int)mesh->getNumParts();
@ -808,7 +808,7 @@ scriptable::ScriptableModelBase Model::getScriptableModel() {
return result;
}
void Model::calculateTriangleSets(const FBXGeometry& geometry) {
void Model::calculateTriangleSets(const HFMGeometry& geometry) {
PROFILE_RANGE(render, __FUNCTION__);
int numberOfMeshes = geometry.meshes.size();
@ -818,14 +818,14 @@ void Model::calculateTriangleSets(const FBXGeometry& geometry) {
_modelSpaceMeshTriangleSets.resize(numberOfMeshes);
for (int i = 0; i < numberOfMeshes; i++) {
const FBXMesh& mesh = geometry.meshes.at(i);
const HFMMesh& mesh = geometry.meshes.at(i);
const int numberOfParts = mesh.parts.size();
auto& meshTriangleSets = _modelSpaceMeshTriangleSets[i];
meshTriangleSets.resize(numberOfParts);
for (int j = 0; j < numberOfParts; j++) {
const FBXMeshPart& part = mesh.parts.at(j);
const HFMMeshPart& part = mesh.parts.at(j);
auto& partTriangleSet = meshTriangleSets[j];
@ -1114,7 +1114,7 @@ Extents Model::getBindExtents() const {
if (!isActive()) {
return Extents();
}
const Extents& bindExtents = getFBXGeometry().bindExtents;
const Extents& bindExtents = getHFMGeometry().bindExtents;
Extents scaledExtents = { bindExtents.minimum * _scale, bindExtents.maximum * _scale };
return scaledExtents;
}
@ -1128,12 +1128,12 @@ Extents Model::getMeshExtents() const {
if (!isActive()) {
return Extents();
}
const Extents& extents = getFBXGeometry().meshExtents;
const Extents& extents = getHFMGeometry().meshExtents;
// even though our caller asked for "unscaled" we need to include any fst scaling, translation, and rotation, which
// is captured in the offset matrix
glm::vec3 minimum = glm::vec3(getFBXGeometry().offset * glm::vec4(extents.minimum, 1.0f));
glm::vec3 maximum = glm::vec3(getFBXGeometry().offset * glm::vec4(extents.maximum, 1.0f));
glm::vec3 minimum = glm::vec3(getHFMGeometry().offset * glm::vec4(extents.minimum, 1.0f));
glm::vec3 maximum = glm::vec3(getHFMGeometry().offset * glm::vec4(extents.maximum, 1.0f));
Extents scaledExtents = { minimum * _scale, maximum * _scale };
return scaledExtents;
}
@ -1143,12 +1143,12 @@ Extents Model::getUnscaledMeshExtents() const {
return Extents();
}
const Extents& extents = getFBXGeometry().meshExtents;
const Extents& extents = getHFMGeometry().meshExtents;
// even though our caller asked for "unscaled" we need to include any fst scaling, translation, and rotation, which
// is captured in the offset matrix
glm::vec3 minimum = glm::vec3(getFBXGeometry().offset * glm::vec4(extents.minimum, 1.0f));
glm::vec3 maximum = glm::vec3(getFBXGeometry().offset * glm::vec4(extents.maximum, 1.0f));
glm::vec3 minimum = glm::vec3(getHFMGeometry().offset * glm::vec4(extents.minimum, 1.0f));
glm::vec3 maximum = glm::vec3(getHFMGeometry().offset * glm::vec4(extents.maximum, 1.0f));
Extents scaledExtents = { minimum, maximum };
return scaledExtents;
@ -1171,11 +1171,11 @@ void Model::setJointTranslation(int index, bool valid, const glm::vec3& translat
}
int Model::getParentJointIndex(int jointIndex) const {
return (isActive() && jointIndex != -1) ? getFBXGeometry().joints.at(jointIndex).parentIndex : -1;
return (isActive() && jointIndex != -1) ? getHFMGeometry().joints.at(jointIndex).parentIndex : -1;
}
int Model::getLastFreeJointIndex(int jointIndex) const {
return (isActive() && jointIndex != -1) ? getFBXGeometry().joints.at(jointIndex).freeLineage.last() : -1;
return (isActive() && jointIndex != -1) ? getHFMGeometry().joints.at(jointIndex).freeLineage.last() : -1;
}
void Model::setTextures(const QVariantMap& textures) {
@ -1275,7 +1275,7 @@ QStringList Model::getJointNames() const {
Q_RETURN_ARG(QStringList, result));
return result;
}
return isActive() ? getFBXGeometry().getJointNames() : QStringList();
return isActive() ? getHFMGeometry().getJointNames() : QStringList();
}
void Model::setScaleToFit(bool scaleToFit, const glm::vec3& dimensions, bool forceRescale) {
@ -1415,12 +1415,12 @@ void Model::updateClusterMatrices() {
}
_needsUpdateClusterMatrices = false;
const FBXGeometry& geometry = getFBXGeometry();
const HFMGeometry& geometry = getHFMGeometry();
for (int i = 0; i < (int) _meshStates.size(); i++) {
MeshState& state = _meshStates[i];
const FBXMesh& mesh = geometry.meshes.at(i);
const HFMMesh& mesh = geometry.meshes.at(i);
for (int j = 0; j < mesh.clusters.size(); j++) {
const FBXCluster& cluster = mesh.clusters.at(j);
const HFMCluster& cluster = mesh.clusters.at(j);
if (_useDualQuaternionSkinning) {
auto jointPose = _rig.getJointPose(cluster.jointIndex);
Transform jointTransform(jointPose.rot(), jointPose.scale(), jointPose.trans());
@ -1505,7 +1505,7 @@ void Model::createRenderItemSet() {
// Run through all of the meshes, and place them into their segregated, but unsorted buckets
int shapeID = 0;
uint32_t numMeshes = (uint32_t)meshes.size();
auto& fbxGeometry = getFBXGeometry();
auto& hfmGeometry = getHFMGeometry();
for (uint32_t i = 0; i < numMeshes; i++) {
const auto& mesh = meshes.at(i);
if (!mesh) {
@ -1515,7 +1515,7 @@ void Model::createRenderItemSet() {
// Create the render payloads
int numParts = (int)mesh->getNumParts();
for (int partIndex = 0; partIndex < numParts; partIndex++) {
initializeBlendshapes(fbxGeometry.meshes[i], i);
initializeBlendshapes(hfmGeometry.meshes[i], i);
_modelMeshRenderItems << std::make_shared<ModelMeshPartPayload>(shared_from_this(), i, partIndex, shapeID, transform, offset);
auto material = getGeometry()->getShapeMaterial(shapeID);
_modelMeshMaterialNames.push_back(material ? material->getName() : "");
@ -1600,7 +1600,7 @@ void Model::removeMaterial(graphics::MaterialPointer material, const std::string
class CollisionRenderGeometry : public Geometry {
public:
CollisionRenderGeometry(graphics::MeshPointer mesh) {
_fbxGeometry = std::make_shared<FBXGeometry>();
_hfmGeometry = std::make_shared<HFMGeometry>();
std::shared_ptr<GeometryMeshes> meshes = std::make_shared<GeometryMeshes>();
meshes->push_back(mesh);
_meshes = meshes;
@ -1656,9 +1656,9 @@ void Blender::run() {
if (_model && _model->isLoaded()) {
DETAILED_PROFILE_RANGE_EX(simulation_animation, __FUNCTION__, 0xFFFF0000, 0, { { "url", _model->getURL().toString() } });
int offset = 0;
auto meshes = _model->getFBXGeometry().meshes;
auto meshes = _model->getHFMGeometry().meshes;
int meshIndex = 0;
foreach(const FBXMesh& mesh, meshes) {
foreach(const HFMMesh& mesh, meshes) {
auto modelMeshBlendshapeOffsets = _model->_blendshapeOffsets.find(meshIndex++);
if (mesh.blendshapes.isEmpty() || modelMeshBlendshapeOffsets == _model->_blendshapeOffsets.end()) {
// Not blendshaped or not initialized
@ -1688,7 +1688,7 @@ void Blender::run() {
}
float normalCoefficient = vertexCoefficient * NORMAL_COEFFICIENT_SCALE;
const FBXBlendshape& blendshape = mesh.blendshapes.at(i);
const HFMBlendshape& blendshape = mesh.blendshapes.at(i);
tbb::parallel_for(tbb::blocked_range<int>(0, blendshape.indices.size()), [&](const tbb::blocked_range<int>& range) {
for (auto j = range.begin(); j < range.end(); j++) {
@ -1731,7 +1731,7 @@ bool Model::maybeStartBlender() {
return false;
}
void Model::initializeBlendshapes(const FBXMesh& mesh, int index) {
void Model::initializeBlendshapes(const HFMMesh& mesh, int index) {
if (mesh.blendshapes.empty()) {
// mesh doesn't have blendshape, did we allocate one though ?
if (_blendshapeOffsets.find(index) != _blendshapeOffsets.end()) {

View file

@ -185,7 +185,7 @@ public:
/// Provided as a convenience, will crash if !isLoaded()
// And so that getGeometry() isn't chained everywhere
const FBXGeometry& getFBXGeometry() const { assert(isLoaded()); return _renderGeometry->getFBXGeometry(); }
const HFMGeometry& getHFMGeometry() const { assert(isLoaded()); return _renderGeometry->getHFMGeometry(); }
bool isActive() const { return isLoaded(); }
@ -450,7 +450,7 @@ protected:
bool _overrideModelTransform { false };
bool _triangleSetsValid { false };
void calculateTriangleSets(const FBXGeometry& geometry);
void calculateTriangleSets(const HFMGeometry& geometry);
std::vector<std::vector<TriangleSet>> _modelSpaceMeshTriangleSets; // model space triangles for all sub meshes
virtual void createRenderItemSet();
@ -506,7 +506,7 @@ protected:
bool shouldInvalidatePayloadShapeKey(int meshIndex);
void initializeBlendshapes(const FBXMesh& mesh, int index);
void initializeBlendshapes(const HFMMesh& mesh, int index);
private:
float _loadingPriority { 0.0f };

View file

@ -41,14 +41,14 @@ void SoftAttachmentModel::updateClusterMatrices() {
_needsUpdateClusterMatrices = false;
const FBXGeometry& geometry = getFBXGeometry();
const HFMGeometry& geometry = getHFMGeometry();
for (int i = 0; i < (int) _meshStates.size(); i++) {
MeshState& state = _meshStates[i];
const FBXMesh& mesh = geometry.meshes.at(i);
const HFMMesh& mesh = geometry.meshes.at(i);
for (int j = 0; j < mesh.clusters.size(); j++) {
const FBXCluster& cluster = mesh.clusters.at(j);
const HFMCluster& cluster = mesh.clusters.at(j);
// TODO: cache these look-ups as an optimization
int jointIndexOverride = getJointIndexOverride(cluster.jointIndex);

View file

@ -74,10 +74,12 @@ void SpatiallyNestable::setParentID(const QUuid& parentID) {
}
});
bool success = false;
auto parent = getParentPointer(success);
if (success && parent) {
parent->updateQueryAACube();
if (!_parentKnowsMe) {
bool success = false;
auto parent = getParentPointer(success);
if (success && parent) {
parent->updateQueryAACube();
}
}
}

Some files were not shown because too many files have changed in this diff Show more