diff --git a/source/MaterialXGraphEditor/RenderView.cpp b/source/MaterialXGraphEditor/RenderView.cpp index 3c2e01dff9..2fe96e09b2 100644 --- a/source/MaterialXGraphEditor/RenderView.cpp +++ b/source/MaterialXGraphEditor/RenderView.cpp @@ -81,21 +81,6 @@ void applyModifiers(mx::DocumentPtr doc, const DocumentModifiers& modifiers) } } } - - // Remap unsupported texture coordinate indices. - for (mx::ElementPtr elem : doc->traverseTree()) - { - mx::NodePtr node = elem->asA(); - if (node && node->getCategory() == "texcoord") - { - mx::InputPtr index = node->getInput("index"); - mx::ValuePtr value = index ? index->getValue() : nullptr; - if (value && value->isA() && value->asA() != 0) - { - index->setValue(0); - } - } - } } void RenderView::setDocument(mx::DocumentPtr document) diff --git a/source/MaterialXRender/CgltfLoader.cpp b/source/MaterialXRender/CgltfLoader.cpp index fcc8831732..653c76a371 100644 --- a/source/MaterialXRender/CgltfLoader.cpp +++ b/source/MaterialXRender/CgltfLoader.cpp @@ -267,6 +267,7 @@ bool CgltfLoader::load(const FilePath& filePath, MeshList& meshList, bool texcoo MeshStreamPtr texcoordStream = nullptr; MeshStreamPtr vec4TangentStream = nullptr; int colorAttrIndex = 0; + int texcoordIndex = 0; // Read in vertex streams for (cgltf_size prim = 0; prim < primitive->attributes_count; prim++) @@ -277,12 +278,7 @@ bool CgltfLoader::load(const FilePath& filePath, MeshList& meshList, bool texcoo { continue; } - // Only load one stream of each type for now. cgltf_int streamIndex = attribute->index; - if (streamIndex != 0) - { - continue; - } // Get data as floats cgltf_size floatCount = cgltf_accessor_unpack_floats(accessor, NULL, 0); @@ -335,7 +331,7 @@ bool CgltfLoader::load(const FilePath& filePath, MeshList& meshList, bool texcoo } else if (isTexCoordStream) { - texcoordStream = MeshStream::create("i_" + MeshStream::TEXCOORD_ATTRIBUTE + "_0", MeshStream::TEXCOORD_ATTRIBUTE, 0); + texcoordStream = MeshStream::create("i_" + MeshStream::TEXCOORD_ATTRIBUTE + "_" + std::to_string(texcoordIndex), MeshStream::TEXCOORD_ATTRIBUTE, texcoordIndex); mesh->addStream(texcoordStream); if (vectorSize == 2) { @@ -343,6 +339,7 @@ bool CgltfLoader::load(const FilePath& filePath, MeshList& meshList, bool texcoo desiredVectorSize = 2; } geomStream = texcoordStream; + texcoordIndex++; } else { diff --git a/source/MaterialXRender/Mesh.cpp b/source/MaterialXRender/Mesh.cpp index bfa7dedd13..cb96796e52 100644 --- a/source/MaterialXRender/Mesh.cpp +++ b/source/MaterialXRender/Mesh.cpp @@ -4,6 +4,7 @@ // #include +#include #include #include @@ -42,8 +43,10 @@ Mesh::Mesh(const string& name) : MeshStreamPtr Mesh::generateNormals(MeshStreamPtr positionStream) { + const string normalStreamName = "i_" + MeshStream::NORMAL_ATTRIBUTE; + // Create the normal stream. - MeshStreamPtr normalStream = MeshStream::create("i_" + MeshStream::NORMAL_ATTRIBUTE, MeshStream::NORMAL_ATTRIBUTE, 0); + MeshStreamPtr normalStream = MeshStream::create(normalStreamName, MeshStream::NORMAL_ATTRIBUTE, 0); normalStream->resize(positionStream->getSize()); // Iterate through partitions. @@ -78,8 +81,11 @@ MeshStreamPtr Mesh::generateNormals(MeshStreamPtr positionStream) MeshStreamPtr Mesh::generateTextureCoordinates(MeshStreamPtr positionStream) { + const string texcoordStreamName = "i_" + MeshStream::TEXCOORD_ATTRIBUTE + "_0"; + + // Create stream from x,y of position stream + MeshStreamPtr texcoordStream = MeshStream::create(texcoordStreamName, MeshStream::TEXCOORD_ATTRIBUTE, 0); size_t vertexCount = positionStream->getData().size() / MeshStream::STRIDE_3D; - MeshStreamPtr texcoordStream = MeshStream::create("i_" + MeshStream::TEXCOORD_ATTRIBUTE + "_0", MeshStream::TEXCOORD_ATTRIBUTE, 0); texcoordStream->setStride(MeshStream::STRIDE_2D); texcoordStream->resize(vertexCount); std::fill(texcoordStream->getData().begin(), texcoordStream->getData().end(), 0.0f); @@ -89,6 +95,8 @@ MeshStreamPtr Mesh::generateTextureCoordinates(MeshStreamPtr positionStream) MeshStreamPtr Mesh::generateTangents(MeshStreamPtr positionStream, MeshStreamPtr normalStream, MeshStreamPtr texcoordStream) { + const string tangentStreamName = "i_" + MeshStream::TANGENT_ATTRIBUTE; + size_t vertexCount = positionStream->getData().size() / positionStream->getStride(); size_t normalCount = normalStream->getData().size() / normalStream->getStride(); size_t texcoordCount = texcoordStream->getData().size() / texcoordStream->getStride(); @@ -98,7 +106,7 @@ MeshStreamPtr Mesh::generateTangents(MeshStreamPtr positionStream, MeshStreamPtr } // Create the tangent stream. - MeshStreamPtr tangentStream = MeshStream::create("i_" + MeshStream::TANGENT_ATTRIBUTE, MeshStream::TANGENT_ATTRIBUTE, 0); + MeshStreamPtr tangentStream = MeshStream::create(tangentStreamName, MeshStream::TANGENT_ATTRIBUTE, 0); tangentStream->resize(positionStream->getSize()); std::fill(tangentStream->getData().begin(), tangentStream->getData().end(), 0.0f); @@ -173,12 +181,14 @@ MeshStreamPtr Mesh::generateTangents(MeshStreamPtr positionStream, MeshStreamPtr MeshStreamPtr Mesh::generateBitangents(MeshStreamPtr normalStream, MeshStreamPtr tangentStream) { + const string bitangentStreamName = "i_" + MeshStream::BITANGENT_ATTRIBUTE; + if (normalStream->getSize() != tangentStream->getSize()) { return nullptr; } - MeshStreamPtr bitangentStream = MeshStream::create("i_" + MeshStream::BITANGENT_ATTRIBUTE, MeshStream::BITANGENT_ATTRIBUTE, 0); + MeshStreamPtr bitangentStream = MeshStream::create(bitangentStreamName, MeshStream::BITANGENT_ATTRIBUTE, 0); bitangentStream->resize(normalStream->getSize()); for (size_t i = 0; i < normalStream->getSize(); i++) @@ -218,7 +228,8 @@ void Mesh::mergePartitions() void Mesh::splitByUdims() { - MeshStreamPtr texcoords = getStream(MeshStream::TEXCOORD_ATTRIBUTE, 0); + const unsigned int texcoord_stream = 0; + MeshStreamPtr texcoords = getStream(MeshStream::TEXCOORD_ATTRIBUTE, texcoord_stream); if (!texcoords) { return; @@ -312,4 +323,116 @@ void MeshStream::transform(const Matrix44& matrix) } } +MeshStreamPtr Mesh::getStream(const string& name, bool allowFallback) +{ + for (const auto& stream : _streams) + { + if (stream->getName() == name) + { + return stream; + } + } + if (allowFallback) + { + const std::string POSITION_NAME("i_" + MeshStream::POSITION_ATTRIBUTE); + MeshStreamPtr positionStream = getStream(POSITION_NAME); + // Fail if there are no positions. + if (!positionStream) + { + return MeshStreamPtr(); + } + + MeshStreamPtr returnStream = nullptr; + bool needTexCoords = stringStartsWith(name, "i_" + MeshStream::TEXCOORD_ATTRIBUTE); + bool needNormals = stringStartsWith(name, "i_" + MeshStream::NORMAL_ATTRIBUTE); + bool needTangents = stringStartsWith(name, "i_" + MeshStream::TANGENT_ATTRIBUTE); + if (needTangents) + { + needNormals = true; + needTexCoords = true; + } + bool needBiTangents = stringStartsWith(name, "i_" + MeshStream::BITANGENT_ATTRIBUTE); + if (needBiTangents) + { + needNormals = true; + needTangents = true; + needTexCoords = true; + } + + // Return texcoord 0. If it does not exist then create it. + MeshStreamPtr texcoordStream = getStream("i_" + MeshStream::TEXCOORD_ATTRIBUTE + "_0"); + if (needTexCoords) + { + if (!texcoordStream) + { + texcoordStream = generateTextureCoordinates(positionStream); + if (texcoordStream) + { + addStream(texcoordStream); + } + } + returnStream = texcoordStream; + } + + MeshStreamPtr normalStream = getStream("i_" + MeshStream::NORMAL_ATTRIBUTE); + if (needNormals) + { + if (!normalStream) + { + normalStream = generateNormals(positionStream); + if (normalStream) + { + addStream(normalStream); + } + } + returnStream = normalStream; + } + + MeshStreamPtr tangentStream = getStream("i_" + MeshStream::TANGENT_ATTRIBUTE); + if (needTangents) + { + if (!tangentStream) + { + tangentStream = generateTangents(positionStream, normalStream, texcoordStream); + if (tangentStream) + { + addStream(tangentStream); + } + } + returnStream = tangentStream; + } + + if (needBiTangents) + { + MeshStreamPtr bitangentStream = getStream("i_" + MeshStream::BITANGENT_ATTRIBUTE); + if (!!bitangentStream) + { + bitangentStream = generateBitangents(normalStream, tangentStream); + if (bitangentStream) + { + addStream(bitangentStream); + } + } + returnStream = bitangentStream; + } + + // Return position as fallback color stream + if (stringStartsWith(name, "i_" + MeshStream::COLOR_ATTRIBUTE)) + { + returnStream = positionStream; + } + + return returnStream; + } + + return MeshStreamPtr(); +} + +MeshStreamPtr Mesh::getStream(const string& type, unsigned int index, bool allowFallback) +{ + const string streamName = "i_" + type + "_" + std::to_string(index); + return getStream(streamName, allowFallback); +} + MATERIALX_NAMESPACE_END + diff --git a/source/MaterialXRender/Mesh.h b/source/MaterialXRender/Mesh.h index 987b9cd69f..eebf6db014 100644 --- a/source/MaterialXRender/Mesh.h +++ b/source/MaterialXRender/Mesh.h @@ -275,39 +275,25 @@ class MX_RENDER_API Mesh /// Get a mesh stream by name /// @param name Name of stream + /// @param allowFallback If true will attempt to return fallback stream if it does not exist. Default is false. /// @return Reference to a mesh stream if found - MeshStreamPtr getStream(const string& name) const - { - for (const auto& stream : _streams) - { - if (stream->getName() == name) - { - return stream; - } - } - return MeshStreamPtr(); - } + MeshStreamPtr getStream(const string& name, bool allowFallback = false); /// Get a mesh stream by type and index /// @param type Type of stream /// @param index Index of stream + /// @param allowFallback If true will attempt to return a fallback stream if it does not exist. Default is false. /// @return Reference to a mesh stream if found - MeshStreamPtr getStream(const string& type, unsigned int index) const - { - for (const auto& stream : _streams) - { - if (stream->getType() == type && - stream->getIndex() == index) - { - return stream; - } - } - return MeshStreamPtr(); - } + MeshStreamPtr getStream(const string& type, unsigned int index, bool allowFallback = false); /// Add a mesh stream void addStream(MeshStreamPtr stream) { + for (MeshStreamPtr s : _streams) + { + if (s->getName() == stream->getName()) + return; + } _streams.push_back(stream); } diff --git a/source/MaterialXRenderGlsl/GlslProgram.cpp b/source/MaterialXRenderGlsl/GlslProgram.cpp index 5da89c63b4..198bd57563 100644 --- a/source/MaterialXRenderGlsl/GlslProgram.cpp +++ b/source/MaterialXRenderGlsl/GlslProgram.cpp @@ -255,7 +255,7 @@ void GlslProgram::bindAttribute(const GlslProgram::InputMap& inputs, MeshPtr mes unsigned int index = input.second->value ? input.second->value->asA() : 0; unsigned int stride = 0; - MeshStreamPtr stream = mesh->getStream(input.first); + MeshStreamPtr stream = mesh->getStream(input.first, true); if (!stream) { throw ExceptionRenderError("Geometry buffer could not be retrieved for binding: " + input.first + ". Index: " + std::to_string(index)); @@ -1065,10 +1065,7 @@ int GlslProgram::mapTypeToOpenGLType(TypeDesc type) const GlslProgram::InputMap& GlslProgram::updateAttributesList() { - if (_attributeList.size() > 0) - { - return _attributeList; - } + _attributeList.clear(); if (_programId == UNDEFINED_OPENGL_RESOURCE_ID) { diff --git a/source/MaterialXRenderMsl/MslPipelineStateObject.mm b/source/MaterialXRenderMsl/MslPipelineStateObject.mm index 2704f78d4b..813a724a06 100644 --- a/source/MaterialXRenderMsl/MslPipelineStateObject.mm +++ b/source/MaterialXRenderMsl/MslPipelineStateObject.mm @@ -372,7 +372,7 @@ int GetStrideOfMetalType(MTLDataType type) unsigned int index = input.second->value ? input.second->value->asA() : 0; unsigned int stride = 0; - MeshStreamPtr stream = mesh->getStream(input.first); + MeshStreamPtr stream = mesh->getStream(input.first, true); if (!stream) { errors.push_back("Geometry buffer could not be retrieved for binding: " + input.first + ". Index: " + std::to_string(index)); diff --git a/source/MaterialXView/Viewer.cpp b/source/MaterialXView/Viewer.cpp index a9b66dd452..70eb23f752 100644 --- a/source/MaterialXView/Viewer.cpp +++ b/source/MaterialXView/Viewer.cpp @@ -120,21 +120,6 @@ void applyModifiers(mx::DocumentPtr doc, const DocumentModifiers& modifiers) } } } - - // Remap unsupported texture coordinate indices. - for (mx::ElementPtr elem : doc->traverseTree()) - { - mx::NodePtr node = elem->asA(); - if (node && node->getCategory() == "texcoord") - { - mx::InputPtr index = node->getInput("index"); - mx::ValuePtr value = index ? index->getValue() : nullptr; - if (value && value->isA() && value->asA() != 0) - { - index->setValue(0); - } - } - } } } // anonymous namespace diff --git a/source/PyMaterialX/PyMaterialXRender/PyMesh.cpp b/source/PyMaterialX/PyMaterialXRender/PyMesh.cpp index 5c26821436..3eb1937463 100644 --- a/source/PyMaterialX/PyMaterialXRender/PyMesh.cpp +++ b/source/PyMaterialX/PyMaterialXRender/PyMesh.cpp @@ -52,8 +52,8 @@ void bindPyMesh(py::module& mod) .def("setSourceUri", &mx::Mesh::setSourceUri) .def("hasSourceUri", &mx::Mesh::hasSourceUri) .def("getSourceUri", &mx::Mesh::getSourceUri) - .def("getStream", static_cast(&mx::Mesh::getStream)) - .def("getStream", static_cast (&mx::Mesh::getStream)) + .def("getStream", static_cast (&mx::Mesh::getStream)) + .def("getStream", static_cast (&mx::Mesh::getStream)) .def("addStream", &mx::Mesh::addStream) .def("setVertexCount", &mx::Mesh::setVertexCount) .def("getVertexCount", &mx::Mesh::getVertexCount)