mirror of
https://github.com/overte-org/overte.git
synced 2025-04-14 14:47:19 +02:00
Merge remote-tracking branch 'upstream/master' into materialMap
This commit is contained in:
commit
b9934bce70
25 changed files with 166 additions and 127 deletions
|
@ -52,6 +52,9 @@ else()
|
|||
set(MOBILE 0)
|
||||
endif()
|
||||
|
||||
# Use default time server if none defined in environment
|
||||
set_from_env(TIMESERVER_URL TIMESERVER_URL "http://sha256timestamp.ws.symantec.com/sha256/timestamp")
|
||||
|
||||
set(HIFI_USE_OPTIMIZED_IK OFF)
|
||||
set(BUILD_CLIENT_OPTION ON)
|
||||
set(BUILD_SERVER_OPTION ON)
|
||||
|
|
|
@ -22,7 +22,7 @@ macro(optional_win_executable_signing)
|
|||
# setup a post build command to sign the executable
|
||||
add_custom_command(
|
||||
TARGET ${TARGET_NAME} POST_BUILD
|
||||
COMMAND ${SIGNTOOL_EXECUTABLE} sign /fd sha256 /f %HF_PFX_FILE% /p %HF_PFX_PASSPHRASE% /tr http://sha256timestamp.ws.symantec.com/sha256/timestamp /td SHA256 ${EXECUTABLE_PATH}
|
||||
COMMAND ${SIGNTOOL_EXECUTABLE} sign /fd sha256 /f %HF_PFX_FILE% /p %HF_PFX_PASSPHRASE% /tr ${TIMESERVER_URL} /td SHA256 ${EXECUTABLE_PATH}
|
||||
)
|
||||
else ()
|
||||
message(FATAL_ERROR "HF_PFX_PASSPHRASE must be set for executables to be signed.")
|
||||
|
|
|
@ -9320,6 +9320,3 @@ void Application::toggleAwayMode(){
|
|||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "Application.moc"
|
||||
|
|
|
@ -707,8 +707,7 @@ Menu::Menu() {
|
|||
// Developer > Timing >>>
|
||||
MenuWrapper* timingMenu = developerMenu->addMenu("Timing");
|
||||
MenuWrapper* perfTimerMenu = timingMenu->addMenu("Performance Timer");
|
||||
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::DisplayDebugTimingDetails, 0, false,
|
||||
qApp, SLOT(enablePerfStats(bool)));
|
||||
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::DisplayDebugTimingDetails);
|
||||
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::OnlyDisplayTopTen, 0, true);
|
||||
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandUpdateTiming, 0, false);
|
||||
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandSimulationTiming, 0, false);
|
||||
|
|
|
@ -910,6 +910,9 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) {
|
|||
});
|
||||
_layerIndex = 0;
|
||||
addIncludeItemsToMallets();
|
||||
|
||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
scaleKeyboard(myAvatar->getSensorToWorldScale());
|
||||
});
|
||||
|
||||
request->send();
|
||||
|
|
|
@ -98,6 +98,7 @@ public:
|
|||
bool isPassword() const;
|
||||
void setPassword(bool password);
|
||||
void enableRightMallet();
|
||||
void scaleKeyboard(float sensorToWorldScale);
|
||||
void enableLeftMallet();
|
||||
void disableRightMallet();
|
||||
void disableLeftMallet();
|
||||
|
@ -122,7 +123,6 @@ public slots:
|
|||
void handleTriggerContinue(const QUuid& id, const PointerEvent& event);
|
||||
void handleHoverBegin(const QUuid& id, const PointerEvent& event);
|
||||
void handleHoverEnd(const QUuid& id, const PointerEvent& event);
|
||||
void scaleKeyboard(float sensorToWorldScale);
|
||||
|
||||
private:
|
||||
struct Anchor {
|
||||
|
|
|
@ -104,13 +104,15 @@ void FBXBaker::rewriteAndBakeSceneModels(const QVector<hfm::Mesh>& meshes, const
|
|||
int meshIndex = 0;
|
||||
for (FBXNode& rootChild : _rootNode.children) {
|
||||
if (rootChild.name == "Objects") {
|
||||
for (auto object = rootChild.children.begin(); object != rootChild.children.end(); object++) {
|
||||
auto object = rootChild.children.begin();
|
||||
while (object != rootChild.children.end()) {
|
||||
if (object->name == "Geometry") {
|
||||
if (object->properties.at(2) == "Mesh") {
|
||||
int meshNum = meshIndexToRuntimeOrder[meshIndex];
|
||||
replaceMeshNodeWithDraco(*object, dracoMeshes[meshNum], dracoMaterialLists[meshNum]);
|
||||
meshIndex++;
|
||||
}
|
||||
object++;
|
||||
} else if (object->name == "Model") {
|
||||
for (FBXNode& modelChild : object->children) {
|
||||
if (modelChild.name == "Properties60" || modelChild.name == "Properties70") {
|
||||
|
@ -136,9 +138,12 @@ void FBXBaker::rewriteAndBakeSceneModels(const QVector<hfm::Mesh>& meshes, const
|
|||
meshIndex++;
|
||||
}
|
||||
}
|
||||
object++;
|
||||
} else if (object->name == "Texture" || object->name == "Video") {
|
||||
// this is an embedded texture, we need to remove it from the FBX
|
||||
object = rootChild.children.erase(object);
|
||||
} else {
|
||||
object++;
|
||||
}
|
||||
|
||||
if (hasErrors()) {
|
||||
|
|
|
@ -27,9 +27,10 @@ std::function<QThread*()> MaterialBaker::_getNextOvenWorkerThreadOperator;
|
|||
|
||||
static int materialNum = 0;
|
||||
|
||||
MaterialBaker::MaterialBaker(const QString& materialData, bool isURL, const QString& bakedOutputDir) :
|
||||
MaterialBaker::MaterialBaker(const QString& materialData, bool isURL, const QString& bakedOutputDir, QUrl destinationPath) :
|
||||
_materialData(materialData),
|
||||
_isURL(isURL),
|
||||
_destinationPath(destinationPath),
|
||||
_bakedOutputDir(bakedOutputDir),
|
||||
_textureOutputDir(bakedOutputDir + "/materialTextures/" + QString::number(materialNum++))
|
||||
{
|
||||
|
@ -177,6 +178,10 @@ void MaterialBaker::handleFinishedTextureBaker() {
|
|||
auto newURL = QUrl(_textureOutputDir).resolved(baker->getMetaTextureFileName());
|
||||
auto relativeURL = QDir(_bakedOutputDir).relativeFilePath(newURL.toString());
|
||||
|
||||
if (!_destinationPath.isEmpty()) {
|
||||
relativeURL = _destinationPath.resolved(relativeURL).toDisplayString();
|
||||
}
|
||||
|
||||
// Replace the old texture URLs
|
||||
for (auto networkMaterial : _materialsNeedingRewrite.values(textureKey)) {
|
||||
networkMaterial->getTextureMap(baker->getMapChannel())->getTextureSource()->setUrl(relativeURL);
|
||||
|
|
|
@ -24,7 +24,7 @@ static const QString BAKED_MATERIAL_EXTENSION = ".baked.json";
|
|||
class MaterialBaker : public Baker {
|
||||
Q_OBJECT
|
||||
public:
|
||||
MaterialBaker(const QString& materialData, bool isURL, const QString& bakedOutputDir);
|
||||
MaterialBaker(const QString& materialData, bool isURL, const QString& bakedOutputDir, QUrl destinationPath = QUrl());
|
||||
|
||||
QString getMaterialData() const { return _materialData; }
|
||||
bool isURL() const { return _isURL; }
|
||||
|
@ -51,6 +51,7 @@ private:
|
|||
|
||||
QString _materialData;
|
||||
bool _isURL;
|
||||
QUrl _destinationPath;
|
||||
|
||||
NetworkMaterialResourcePointer _materialResource;
|
||||
|
||||
|
|
|
@ -167,6 +167,10 @@ void ModelBaker::saveSourceModel() {
|
|||
|
||||
connect(networkReply, &QNetworkReply::finished, this, &ModelBaker::handleModelNetworkReply);
|
||||
}
|
||||
|
||||
if (_mappingURL.isEmpty()) {
|
||||
outputUnbakedFST();
|
||||
}
|
||||
}
|
||||
|
||||
void ModelBaker::handleModelNetworkReply() {
|
||||
|
@ -314,6 +318,37 @@ void ModelBaker::handleFinishedMaterialBaker() {
|
|||
outputBakedFST();
|
||||
}
|
||||
|
||||
void ModelBaker::outputUnbakedFST() {
|
||||
// Output an unbaked FST file in the original output folder to make it easier for FSTBaker to rebake this model
|
||||
// TODO: Consider a more robust method that does not depend on FSTBaker navigating to a hardcoded relative path
|
||||
QString outputFSTFilename = _modelURL.fileName();
|
||||
auto extensionStart = outputFSTFilename.indexOf(".");
|
||||
if (extensionStart != -1) {
|
||||
outputFSTFilename.resize(extensionStart);
|
||||
}
|
||||
outputFSTFilename += FST_EXTENSION;
|
||||
QString outputFSTURL = _originalOutputDir + "/" + outputFSTFilename;
|
||||
|
||||
hifi::VariantHash outputMapping;
|
||||
outputMapping[FST_VERSION_FIELD] = FST_VERSION;
|
||||
outputMapping[FILENAME_FIELD] = _modelURL.fileName();
|
||||
outputMapping[COMMENT_FIELD] = "This FST file was generated by Oven for use during rebaking. It is not part of the original model. This file's existence is subject to change.";
|
||||
hifi::ByteArray fstOut = FSTReader::writeMapping(outputMapping);
|
||||
|
||||
QFile fstOutputFile { outputFSTURL };
|
||||
if (fstOutputFile.exists()) {
|
||||
handleWarning("The file '" + outputFSTURL + "' already exists. Should that be baked instead of '" + _modelURL.toString() + "'?");
|
||||
return;
|
||||
}
|
||||
if (!fstOutputFile.open(QIODevice::WriteOnly)) {
|
||||
handleWarning("Failed to open file '" + outputFSTURL + "' for writing. Rebaking may fail on the associated model.");
|
||||
return;
|
||||
}
|
||||
if (fstOutputFile.write(fstOut) == -1) {
|
||||
handleWarning("Failed to write to file '" + outputFSTURL + "'. Rebaking may fail on the associated model.");
|
||||
}
|
||||
}
|
||||
|
||||
void ModelBaker::outputBakedFST() {
|
||||
// Output FST file, copying over input mappings if available
|
||||
QString outputFSTFilename = !_mappingURL.isEmpty() ? _mappingURL.fileName() : _modelURL.fileName();
|
||||
|
@ -328,6 +363,7 @@ void ModelBaker::outputBakedFST() {
|
|||
outputMapping[FST_VERSION_FIELD] = FST_VERSION;
|
||||
outputMapping[FILENAME_FIELD] = _bakedModelURL.fileName();
|
||||
outputMapping.remove(TEXDIR_FIELD);
|
||||
outputMapping.remove(COMMENT_FIELD);
|
||||
hifi::ByteArray fstOut = FSTReader::writeMapping(outputMapping);
|
||||
|
||||
QFile fstOutputFile { outputFSTURL };
|
||||
|
|
|
@ -82,6 +82,7 @@ protected slots:
|
|||
void handleFinishedMaterialBaker();
|
||||
|
||||
private:
|
||||
void outputUnbakedFST();
|
||||
void outputBakedFST();
|
||||
|
||||
bool _hasBeenBaked { false };
|
||||
|
|
|
@ -358,7 +358,7 @@ ExtractedMesh FBXSerializer::extractMesh(const FBXNode& object, unsigned int& me
|
|||
std::vector<QString> dracoMaterialList;
|
||||
for (const auto& dracoChild : child.children) {
|
||||
if (dracoChild.name == "FBXDracoMeshVersion") {
|
||||
if (!dracoChild.children.isEmpty()) {
|
||||
if (!dracoChild.properties.isEmpty()) {
|
||||
dracoMeshNodeVersion = dracoChild.properties[0].toUInt();
|
||||
}
|
||||
} else if (dracoChild.name == "MaterialList") {
|
||||
|
@ -492,7 +492,7 @@ ExtractedMesh FBXSerializer::extractMesh(const FBXNode& object, unsigned int& me
|
|||
// Figure out what material this part is
|
||||
if (dracoMeshNodeVersion >= 2) {
|
||||
// Define the materialID now
|
||||
if (dracoMaterialList.size() - 1 <= materialID) {
|
||||
if (materialID < dracoMaterialList.size()) {
|
||||
part.materialID = dracoMaterialList[materialID];
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -33,6 +33,7 @@ static const QString BLENDSHAPE_FIELD = "bs";
|
|||
static const QString SCRIPT_FIELD = "script";
|
||||
static const QString JOINT_NAME_MAPPING_FIELD = "jointMap";
|
||||
static const QString MATERIAL_MAPPING_FIELD = "materialMap";
|
||||
static const QString COMMENT_FIELD = "comment";
|
||||
|
||||
class FSTReader {
|
||||
public:
|
||||
|
|
|
@ -751,107 +751,95 @@ void GLTFSerializer::getSkinInverseBindMatrices(std::vector<std::vector<float>>&
|
|||
}
|
||||
}
|
||||
|
||||
void GLTFSerializer::getNodeQueueByDepthFirstChildren(std::vector<int>& children, int stride, std::vector<int>& result) {
|
||||
int startingIndex = 0;
|
||||
int finalIndex = (int)children.size();
|
||||
if (stride == -1) {
|
||||
startingIndex = (int)children.size() - 1;
|
||||
finalIndex = -1;
|
||||
}
|
||||
for (int index = startingIndex; index != finalIndex; index += stride) {
|
||||
int c = children[index];
|
||||
result.push_back(c);
|
||||
std::vector<int> nested = _file.nodes[c].children.toStdVector();
|
||||
if (nested.size() != 0) {
|
||||
std::sort(nested.begin(), nested.end());
|
||||
for (int r : nested) {
|
||||
if (result.end() == std::find(result.begin(), result.end(), r)) {
|
||||
getNodeQueueByDepthFirstChildren(nested, stride, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) {
|
||||
int numNodes = _file.nodes.size();
|
||||
|
||||
//Build dependencies
|
||||
QVector<QVector<int>> nodeDependencies(numNodes);
|
||||
// Build dependencies
|
||||
QVector<int> parents;
|
||||
QVector<int> sortedNodes;
|
||||
parents.fill(-1, numNodes);
|
||||
sortedNodes.reserve(numNodes);
|
||||
int nodecount = 0;
|
||||
foreach(auto &node, _file.nodes) {
|
||||
//nodes_transforms.push_back(getModelTransform(node));
|
||||
foreach(int child, node.children) nodeDependencies[child].push_back(nodecount);
|
||||
foreach(int child, node.children) {
|
||||
parents[child] = nodecount;
|
||||
}
|
||||
sortedNodes.push_back(nodecount);
|
||||
nodecount++;
|
||||
}
|
||||
|
||||
|
||||
// Build transforms
|
||||
nodecount = 0;
|
||||
foreach(auto &node, _file.nodes) {
|
||||
// collect node transform
|
||||
_file.nodes[nodecount].transforms.push_back(getModelTransform(node));
|
||||
if (nodeDependencies[nodecount].size() == 1) {
|
||||
int parentidx = nodeDependencies[nodecount][0];
|
||||
while (true) { // iterate parents
|
||||
// collect parents transforms
|
||||
_file.nodes[nodecount].transforms.push_back(getModelTransform(_file.nodes[parentidx]));
|
||||
if (nodeDependencies[parentidx].size() == 1) {
|
||||
parentidx = nodeDependencies[parentidx][0];
|
||||
} else break;
|
||||
}
|
||||
_file.nodes[nodecount].transforms.push_back(getModelTransform(node));
|
||||
int parentIndex = parents[nodecount];
|
||||
while (parentIndex != -1) {
|
||||
const auto& parentNode = _file.nodes[parentIndex];
|
||||
// collect transforms for a node's parents, grandparents, etc.
|
||||
_file.nodes[nodecount].transforms.push_back(getModelTransform(parentNode));
|
||||
parentIndex = parents[parentIndex];
|
||||
}
|
||||
|
||||
nodecount++;
|
||||
}
|
||||
|
||||
|
||||
// since parent indices must exist in the sorted list before any of their children, sortedNodes might not be initialized in the correct order
|
||||
// therefore we need to re-initialize the order in which nodes will be parsed
|
||||
QVector<bool> hasBeenSorted;
|
||||
hasBeenSorted.fill(false, numNodes);
|
||||
int i = 0; // initial index
|
||||
while (i < numNodes) {
|
||||
int currentNode = sortedNodes[i];
|
||||
int parentIndex = parents[currentNode];
|
||||
if (parentIndex == -1 || hasBeenSorted[parentIndex]) {
|
||||
hasBeenSorted[currentNode] = true;
|
||||
i++;
|
||||
} else {
|
||||
int j = i + 1; // index of node to be sorted
|
||||
while (j < numNodes) {
|
||||
int nextNode = sortedNodes[j];
|
||||
parentIndex = parents[nextNode];
|
||||
if (parentIndex == -1 || hasBeenSorted[parentIndex]) {
|
||||
// swap with currentNode
|
||||
hasBeenSorted[nextNode] = true;
|
||||
sortedNodes[i] = nextNode;
|
||||
sortedNodes[j] = currentNode;
|
||||
i++;
|
||||
currentNode = sortedNodes[i];
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// initialize order in which nodes will be parsed
|
||||
std::vector<int> nodeQueue;
|
||||
nodeQueue.reserve(numNodes);
|
||||
int rootNode = 0;
|
||||
int finalNode = numNodes;
|
||||
if (!_file.scenes[_file.scene].nodes.contains(0)) {
|
||||
rootNode = numNodes - 1;
|
||||
finalNode = -1;
|
||||
}
|
||||
bool rootAtStartOfList = rootNode < finalNode;
|
||||
int nodeListStride = 1;
|
||||
if (!rootAtStartOfList) { nodeListStride = -1; }
|
||||
|
||||
QVector<int> initialSceneNodes = _file.scenes[_file.scene].nodes;
|
||||
std::sort(initialSceneNodes.begin(), initialSceneNodes.end());
|
||||
int sceneRootNode = 0;
|
||||
int sceneFinalNode = initialSceneNodes.size();
|
||||
if (!rootAtStartOfList) {
|
||||
sceneRootNode = initialSceneNodes.size() - 1;
|
||||
sceneFinalNode = -1;
|
||||
}
|
||||
for (int index = sceneRootNode; index != sceneFinalNode; index += nodeListStride) {
|
||||
int i = initialSceneNodes[index];
|
||||
nodeQueue.push_back(i);
|
||||
std::vector<int> children = _file.nodes[i].children.toStdVector();
|
||||
std::sort(children.begin(), children.end());
|
||||
getNodeQueueByDepthFirstChildren(children, nodeListStride, nodeQueue);
|
||||
// Build map from original to new indices
|
||||
QVector<int> originalToNewNodeIndexMap;
|
||||
originalToNewNodeIndexMap.fill(-1, numNodes);
|
||||
for (int i = 0; i < numNodes; i++) {
|
||||
originalToNewNodeIndexMap[sortedNodes[i]] = i;
|
||||
}
|
||||
|
||||
|
||||
// Build joints
|
||||
HFMJoint joint;
|
||||
joint.distanceToParent = 0;
|
||||
hfmModel.jointIndices["x"] = numNodes;
|
||||
hfmModel.hasSkeletonJoints = false;
|
||||
|
||||
for (int nodeIndex : nodeQueue) {
|
||||
for (int nodeIndex : sortedNodes) {
|
||||
auto& node = _file.nodes[nodeIndex];
|
||||
|
||||
joint.parentIndex = -1;
|
||||
if (!_file.scenes[_file.scene].nodes.contains(nodeIndex)) {
|
||||
joint.parentIndex = std::distance(nodeQueue.begin(), std::find(nodeQueue.begin(), nodeQueue.end(), nodeDependencies[nodeIndex][0]));
|
||||
joint.parentIndex = parents[nodeIndex];
|
||||
if (joint.parentIndex != -1) {
|
||||
joint.parentIndex = originalToNewNodeIndexMap[joint.parentIndex];
|
||||
}
|
||||
joint.transform = node.transforms.first();
|
||||
joint.translation = extractTranslation(joint.transform);
|
||||
joint.rotation = glmExtractRotation(joint.transform);
|
||||
glm::vec3 scale = extractScale(joint.transform);
|
||||
joint.postTransform = glm::scale(glm::mat4(), scale);
|
||||
joint.postTransform = glm::scale(glm::mat4(), scale);
|
||||
|
||||
joint.name = node.name;
|
||||
joint.isSkeletonJoint = false;
|
||||
|
@ -862,24 +850,25 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) {
|
|||
// Build skeleton
|
||||
std::vector<glm::mat4> jointInverseBindTransforms;
|
||||
jointInverseBindTransforms.resize(numNodes);
|
||||
if (!_file.skins.isEmpty()) {
|
||||
hfmModel.hasSkeletonJoints = !_file.skins.isEmpty();
|
||||
if (hfmModel.hasSkeletonJoints) {
|
||||
hfmModel.hasSkeletonJoints = true;
|
||||
std::vector<std::vector<float>> inverseBindValues;
|
||||
getSkinInverseBindMatrices(inverseBindValues);
|
||||
|
||||
int jointIndex = finalNode;
|
||||
while (jointIndex != rootNode) {
|
||||
rootAtStartOfList ? jointIndex-- : jointIndex++;
|
||||
int jOffset = nodeQueue[jointIndex];
|
||||
for (int jointIndex = 0; jointIndex < numNodes; jointIndex++) {
|
||||
int nodeIndex = sortedNodes[jointIndex];
|
||||
auto joint = hfmModel.joints[jointIndex];
|
||||
|
||||
hfmModel.hasSkeletonJoints = true;
|
||||
for (int s = 0; s < _file.skins.size(); s++) {
|
||||
auto skin = _file.skins[s];
|
||||
joint.isSkeletonJoint = skin.joints.contains(jOffset);
|
||||
const auto& skin = _file.skins[s];
|
||||
int matrixIndex = skin.joints.indexOf(nodeIndex);
|
||||
joint.isSkeletonJoint = skin.joints.contains(nodeIndex);
|
||||
|
||||
// build inverse bind matrices
|
||||
if (joint.isSkeletonJoint) {
|
||||
std::vector<float> value = inverseBindValues[s];
|
||||
int matrixCount = 16 * skin.joints.indexOf(jOffset);
|
||||
std::vector<float>& value = inverseBindValues[s];
|
||||
int matrixCount = 16 * matrixIndex;
|
||||
jointInverseBindTransforms[jointIndex] =
|
||||
glm::mat4(value[matrixCount], value[matrixCount + 1], value[matrixCount + 2], value[matrixCount + 3],
|
||||
value[matrixCount + 4], value[matrixCount + 5], value[matrixCount + 6], value[matrixCount + 7],
|
||||
|
@ -896,7 +885,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) {
|
|||
}
|
||||
|
||||
|
||||
//Build materials
|
||||
// Build materials
|
||||
QVector<QString> materialIDs;
|
||||
QString unknown = "Default";
|
||||
int ukcount = 0;
|
||||
|
@ -916,7 +905,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) {
|
|||
|
||||
// Build meshes
|
||||
nodecount = 0;
|
||||
for (int nodeIndex = rootNode; nodeIndex != finalNode; nodeIndex += nodeListStride) {
|
||||
for (int nodeIndex : sortedNodes) {
|
||||
auto& node = _file.nodes[nodeIndex];
|
||||
|
||||
if (node.defined["mesh"]) {
|
||||
|
@ -924,14 +913,14 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) {
|
|||
foreach(auto &primitive, _file.meshes[node.mesh].primitives) {
|
||||
hfmModel.meshes.append(HFMMesh());
|
||||
HFMMesh& mesh = hfmModel.meshes[hfmModel.meshes.size() - 1];
|
||||
if (!hfmModel.hasSkeletonJoints) {
|
||||
if (!hfmModel.hasSkeletonJoints) {
|
||||
HFMCluster cluster;
|
||||
cluster.jointIndex = nodecount;
|
||||
cluster.inverseBindMatrix = glm::mat4();
|
||||
cluster.inverseBindTransform = Transform(cluster.inverseBindMatrix);
|
||||
mesh.clusters.append(cluster);
|
||||
} else {
|
||||
for (int j = rootNode; j != finalNode; j += nodeListStride) {
|
||||
} else { // skinned model
|
||||
for (int j = 0; j < numNodes; j++) {
|
||||
HFMCluster cluster;
|
||||
cluster.jointIndex = j;
|
||||
cluster.inverseBindMatrix = jointInverseBindTransforms[j];
|
||||
|
@ -940,10 +929,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) {
|
|||
}
|
||||
}
|
||||
HFMCluster root;
|
||||
root.jointIndex = rootNode;
|
||||
if (root.jointIndex == -1) {
|
||||
root.jointIndex = 0;
|
||||
}
|
||||
root.jointIndex = 0;
|
||||
root.inverseBindMatrix = jointInverseBindTransforms[root.jointIndex];
|
||||
root.inverseBindTransform = Transform(root.inverseBindMatrix);
|
||||
mesh.clusters.append(root);
|
||||
|
@ -1043,6 +1029,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) {
|
|||
qWarning(modelformat) << "There was a problem reading glTF TANGENT data for model " << _url;
|
||||
continue;
|
||||
}
|
||||
// tangents can be a vec3 or a vec4 which includes a w component (of -1 or 1)
|
||||
int stride = (accessor.type == GLTFAccessorType::VEC4) ? 4 : 3;
|
||||
for (int n = 0; n < tangents.size() - 3; n += stride) {
|
||||
float tanW = stride == 4 ? tangents[n + 3] : 1;
|
||||
|
@ -1111,7 +1098,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) {
|
|||
}
|
||||
}
|
||||
|
||||
// adapted from FBXSerializer.cpp
|
||||
// Build weights (adapted from FBXSerializer.cpp)
|
||||
if (hfmModel.hasSkeletonJoints) {
|
||||
int numClusterIndices = clusterJoints.size();
|
||||
const int WEIGHTS_PER_VERTEX = 4;
|
||||
|
@ -1121,7 +1108,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) {
|
|||
mesh.clusterWeights.fill(0, numClusterIndices);
|
||||
|
||||
for (int c = 0; c < clusterJoints.size(); c++) {
|
||||
mesh.clusterIndices[c] = _file.skins[node.skin].joints[clusterJoints[c]];
|
||||
mesh.clusterIndices[c] = originalToNewNodeIndexMap[_file.skins[node.skin].joints[clusterJoints[c]]];
|
||||
}
|
||||
|
||||
// normalize and compress to 16-bits
|
||||
|
@ -1160,12 +1147,10 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) {
|
|||
|
||||
mesh.meshIndex = hfmModel.meshes.size();
|
||||
}
|
||||
|
||||
}
|
||||
nodecount++;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -713,7 +713,6 @@ private:
|
|||
|
||||
glm::mat4 getModelTransform(const GLTFNode& node);
|
||||
void getSkinInverseBindMatrices(std::vector<std::vector<float>>& inverseBindMatrixValues);
|
||||
void getNodeQueueByDepthFirstChildren(std::vector<int>& children, int stride, std::vector<int>& result);
|
||||
|
||||
bool buildGeometry(HFMModel& hfmModel, const hifi::URL& url);
|
||||
bool parseGLTF(const hifi::ByteArray& data);
|
||||
|
|
|
@ -318,6 +318,7 @@ public:
|
|||
void setTextureTransforms(const Transform& transform, MaterialMappingMode mode, bool repeat);
|
||||
|
||||
const std::string& getName() const { return _name; }
|
||||
void setName(const std::string& name) { _name = name; }
|
||||
|
||||
const std::string& getModel() const { return _model; }
|
||||
void setModel(const std::string& model) { _model = model; }
|
||||
|
|
|
@ -184,6 +184,7 @@ std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource
|
|||
auto nameJSON = materialJSON.value(key);
|
||||
if (nameJSON.isString()) {
|
||||
name = nameJSON.toString().toStdString();
|
||||
material->setName(name);
|
||||
}
|
||||
} else if (key == "model") {
|
||||
auto modelJSON = materialJSON.value(key);
|
||||
|
|
|
@ -1572,9 +1572,13 @@ void Model::applyMaterialMapping() {
|
|||
|
||||
auto& materialMapping = getMaterialMapping();
|
||||
for (auto& mapping : materialMapping) {
|
||||
std::set<unsigned int> shapeIDs = getMeshIDsFromMaterialID(QString(mapping.first.c_str()));
|
||||
auto networkMaterialResource = mapping.second;
|
||||
if (!networkMaterialResource || shapeIDs.size() == 0) {
|
||||
if (!networkMaterialResource) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::set<unsigned int> shapeIDs = getMeshIDsFromMaterialID(QString(mapping.first.c_str()));
|
||||
if (shapeIDs.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,8 +21,8 @@ endfunction()
|
|||
if (BUILD_TOOLS)
|
||||
# Allow different tools for stable builds
|
||||
if (STABLE_BUILD)
|
||||
set(ALL_TOOLS
|
||||
udt-test
|
||||
set(ALL_TOOLS
|
||||
udt-test
|
||||
vhacd-util
|
||||
frame-optimizer
|
||||
gpu-frame-player
|
||||
|
@ -34,8 +34,8 @@ if (BUILD_TOOLS)
|
|||
oven
|
||||
)
|
||||
else()
|
||||
set(ALL_TOOLS
|
||||
udt-test
|
||||
set(ALL_TOOLS
|
||||
udt-test
|
||||
vhacd-util
|
||||
frame-optimizer
|
||||
gpu-frame-player
|
||||
|
@ -48,7 +48,7 @@ if (BUILD_TOOLS)
|
|||
nitpick
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
foreach(TOOL ${ALL_TOOLS})
|
||||
check_test(${TOOL})
|
||||
if (${BUILD_TOOL_RESULT})
|
||||
|
|
|
@ -61,7 +61,7 @@ protected:
|
|||
|
||||
QString _workingFolder;
|
||||
|
||||
const QString DEV_BUILD_XML_URL{ "https://highfidelity.com/dev-builds.xml" };
|
||||
const QString DEV_BUILD_XML_URL{ "https://metaverse.highfidelity.com/dev-builds.xml" };
|
||||
const QString DEV_BUILD_XML_FILENAME{ "dev-builds.xml" };
|
||||
|
||||
bool buildXMLDownloaded;
|
||||
|
|
|
@ -60,5 +60,5 @@ const double R_Y = 0.212655f;
|
|||
const double G_Y = 0.715158f;
|
||||
const double B_Y = 0.072187f;
|
||||
|
||||
const QString nitpickVersion{ "v3.2.0" };
|
||||
const QString nitpickVersion{ "v3.2.1" };
|
||||
#endif // hifi_common_h
|
|
@ -18,6 +18,4 @@ elseif (APPLE)
|
|||
set_target_properties(${TARGET_NAME} PROPERTIES INSTALL_RPATH "@executable_path/../Frameworks")
|
||||
endif()
|
||||
|
||||
if (BUILD_SERVER)
|
||||
install_beside_console()
|
||||
endif ()
|
||||
install_beside_console()
|
||||
|
|
|
@ -258,7 +258,7 @@ void DomainBaker::addScriptBaker(const QString& property, const QString& url, co
|
|||
_entitiesNeedingRewrite.insert(scriptURL, { property, jsonRef });
|
||||
}
|
||||
|
||||
void DomainBaker::addMaterialBaker(const QString& property, const QString& data, bool isURL, const QJsonValueRef& jsonRef) {
|
||||
void DomainBaker::addMaterialBaker(const QString& property, const QString& data, bool isURL, const QJsonValueRef& jsonRef, QUrl destinationPath) {
|
||||
// grab a clean version of the URL without a query or fragment
|
||||
QString materialData;
|
||||
if (isURL) {
|
||||
|
@ -272,7 +272,7 @@ void DomainBaker::addMaterialBaker(const QString& property, const QString& data,
|
|||
|
||||
// setup a baker for this material
|
||||
QSharedPointer<MaterialBaker> materialBaker {
|
||||
new MaterialBaker(data, isURL, _contentOutputPath),
|
||||
new MaterialBaker(data, isURL, _contentOutputPath, destinationPath),
|
||||
&MaterialBaker::deleteLater
|
||||
};
|
||||
|
||||
|
@ -412,13 +412,9 @@ void DomainBaker::enumerateEntities() {
|
|||
if (entity.contains(MATERIAL_URL_KEY)) {
|
||||
addMaterialBaker(MATERIAL_URL_KEY, entity[MATERIAL_URL_KEY].toString(), true, *it);
|
||||
}
|
||||
// FIXME: Disabled for now because relative texture URLs are not supported for embedded materials in material entities
|
||||
// We need to make texture URLs absolute in this particular case only, keeping in mind that FSTBaker also uses embedded materials
|
||||
/*
|
||||
if (entity.contains(MATERIAL_DATA_KEY)) {
|
||||
addMaterialBaker(MATERIAL_DATA_KEY, entity[MATERIAL_DATA_KEY].toString(), false, *it);
|
||||
addMaterialBaker(MATERIAL_DATA_KEY, entity[MATERIAL_DATA_KEY].toString(), false, *it, _destinationPath);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ private:
|
|||
void addModelBaker(const QString& property, const QString& url, const QJsonValueRef& jsonRef);
|
||||
void addTextureBaker(const QString& property, const QString& url, image::TextureUsage::Type type, const QJsonValueRef& jsonRef);
|
||||
void addScriptBaker(const QString& property, const QString& url, const QJsonValueRef& jsonRef);
|
||||
void addMaterialBaker(const QString& property, const QString& data, bool isURL, const QJsonValueRef& jsonRef);
|
||||
void addMaterialBaker(const QString& property, const QString& data, bool isURL, const QJsonValueRef& jsonRef, QUrl destinationPath = QUrl());
|
||||
};
|
||||
|
||||
#endif // hifi_DomainBaker_h
|
||||
|
|
|
@ -12,7 +12,9 @@ target_link_libraries(${TARGET_NAME} ${VHACD_LIBRARIES})
|
|||
|
||||
setup_memory_debugger()
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
if (WIN32)
|
||||
package_libraries_for_deployment()
|
||||
elseif (UNIX AND NOT APPLE)
|
||||
include(FindOpenMP)
|
||||
if(OPENMP_FOUND)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
|
||||
|
@ -20,3 +22,5 @@ if (UNIX AND NOT APPLE)
|
|||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
install_beside_console()
|
||||
|
|
Loading…
Reference in a new issue