From 80e06ad223c7d26611e303fa2615c69bf227534f Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Thu, 15 Oct 2020 12:30:39 -0700 Subject: [PATCH 1/9] fix frame number in video encoding Signed-off-by: Ian Chen --- av/src/VideoEncoder.cc | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/av/src/VideoEncoder.cc b/av/src/VideoEncoder.cc index 47948288b..f1a02026d 100644 --- a/av/src/VideoEncoder.cc +++ b/av/src/VideoEncoder.cc @@ -76,6 +76,9 @@ class ignition::common::VideoEncoderPrivate /// \brief Previous time when the frame is added. public: std::chrono::steady_clock::time_point timePrev; + /// \brief Time when the first frame is added. + public: std::chrono::steady_clock::time_point timeStart; + /// \brief Number of frames in the video public: uint64_t frameCount = 0; @@ -505,9 +508,13 @@ bool VideoEncoder::AddFrame(const unsigned char *_frame, auto dt = _timestamp - this->dataPtr->timePrev; // Skip frames that arrive faster than the video's fps - if (dt < std::chrono::duration(1.0/this->dataPtr->fps)) + double period = 1.0/this->dataPtr->fps; + if (dt < std::chrono::duration(period)) return false; + if (this->dataPtr->frameCount == 0u) + this->dataPtr->timeStart = _timestamp; + this->dataPtr->timePrev = _timestamp; // Cause the sws to be recreated on image resize @@ -575,7 +582,14 @@ bool VideoEncoder::AddFrame(const unsigned char *_frame, this->dataPtr->avOutFrame->data, this->dataPtr->avOutFrame->linesize); - this->dataPtr->avOutFrame->pts = this->dataPtr->frameCount++; + // compute frame number based on timestamp of current image + auto timeSinceStart = std::chrono::duration_cast( + _timestamp - this->dataPtr->timeStart); + double durationSec = timeSinceStart.count() / 1000.0; + uint64_t frameNumber = durationSec / period; + + this->dataPtr->avOutFrame->pts = frameNumber; + this->dataPtr->frameCount++; #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 40, 101) int gotOutput = 0; From fc60fbe280a9b14eb5e2b15e3de4d1828766690a Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Thu, 15 Oct 2020 18:45:09 -0700 Subject: [PATCH 2/9] encode duplicate frames to ensure continuous pts Signed-off-by: Ian Chen --- av/src/VideoEncoder.cc | 143 +++++++++++++++++++++-------------------- 1 file changed, 75 insertions(+), 68 deletions(-) diff --git a/av/src/VideoEncoder.cc b/av/src/VideoEncoder.cc index f1a02026d..87f56f86e 100644 --- a/av/src/VideoEncoder.cc +++ b/av/src/VideoEncoder.cc @@ -588,98 +588,105 @@ bool VideoEncoder::AddFrame(const unsigned char *_frame, double durationSec = timeSinceStart.count() / 1000.0; uint64_t frameNumber = durationSec / period; - this->dataPtr->avOutFrame->pts = frameNumber; - this->dataPtr->frameCount++; + uint64_t frameDiff = frameNumber + 1 - this->dataPtr->frameCount; -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 40, 101) - int gotOutput = 0; - AVPacket avPacket; - av_init_packet(&avPacket); - avPacket.data = nullptr; - avPacket.size = 0; + // make sure we have continuous pts (frame number) otherwise some decoders + // may not be happy. So encode more (duplicate) frames until the current frame + // number + for (uint64_t i = 0u; i < frameDiff; ++i) + { + this->dataPtr->avOutFrame->pts = this->dataPtr->frameCount++; - int ret = avcodec_encode_video2(this->dataPtr->codecCtx, &avPacket, - this->dataPtr->avOutFrame, &gotOutput); +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 40, 101) + int gotOutput = 0; + AVPacket avPacket; + av_init_packet(&avPacket); + avPacket.data = nullptr; + avPacket.size = 0; - if (ret >= 0 && gotOutput == 1) - { - avPacket.stream_index = this->dataPtr->videoStream->index; + int ret = avcodec_encode_video2(this->dataPtr->codecCtx, &avPacket, + this->dataPtr->avOutFrame, &gotOutput); - // Scale timestamp appropriately. - if (avPacket.pts != static_cast(AV_NOPTS_VALUE)) + if (ret >= 0 && gotOutput == 1) { - avPacket.pts = av_rescale_q(avPacket.pts, - this->dataPtr->codecCtx->time_base, - this->dataPtr->videoStream->time_base); - } + avPacket.stream_index = this->dataPtr->videoStream->index; - if (avPacket.dts != static_cast(AV_NOPTS_VALUE)) - { - avPacket.dts = av_rescale_q( - avPacket.dts, - this->dataPtr->codecCtx->time_base, - this->dataPtr->videoStream->time_base); - } + // Scale timestamp appropriately. + if (avPacket.pts != static_cast(AV_NOPTS_VALUE)) + { + avPacket.pts = av_rescale_q(avPacket.pts, + this->dataPtr->codecCtx->time_base, + this->dataPtr->videoStream->time_base); + } - // Write frame to disk - ret = av_interleaved_write_frame(this->dataPtr->formatCtx, &avPacket); + if (avPacket.dts != static_cast(AV_NOPTS_VALUE)) + { + avPacket.dts = av_rescale_q( + avPacket.dts, + this->dataPtr->codecCtx->time_base, + this->dataPtr->videoStream->time_base); + } - if (ret < 0) - { - ignerr << "Error writing frame" << std::endl; - return false; + // Write frame to disk + ret = av_interleaved_write_frame(this->dataPtr->formatCtx, &avPacket); + + if (ret < 0) + { + ignerr << "Error writing frame" << std::endl; + return false; + } } - } - av_free_packet(&avPacket); + av_free_packet(&avPacket); -// #else for libavcodec version check + // #else for libavcodec version check #else - AVPacket *avPacket = av_packet_alloc(); - av_init_packet(avPacket); - - avPacket->data = nullptr; - avPacket->size = 0; + AVPacket *avPacket = av_packet_alloc(); + av_init_packet(avPacket); - int ret = avcodec_send_frame(this->dataPtr->codecCtx, - this->dataPtr->avOutFrame); + avPacket->data = nullptr; + avPacket->size = 0; - // This loop will retrieve and write available packets - while (ret >= 0) - { - ret = avcodec_receive_packet(this->dataPtr->codecCtx, avPacket); + int ret = avcodec_send_frame(this->dataPtr->codecCtx, + this->dataPtr->avOutFrame); - // Potential performance improvement: Queue the packets and write in - // a separate thread. - if (ret >= 0) + // This loop will retrieve and write available packets + while (ret >= 0) { - avPacket->stream_index = this->dataPtr->videoStream->index; + ret = avcodec_receive_packet(this->dataPtr->codecCtx, avPacket); - // Scale timestamp appropriately. - if (avPacket->pts != static_cast(AV_NOPTS_VALUE)) + // Potential performance improvement: Queue the packets and write in + // a separate thread. + if (ret >= 0) { - avPacket->pts = av_rescale_q(avPacket->pts, - this->dataPtr->codecCtx->time_base, - this->dataPtr->videoStream->time_base); - } + avPacket->stream_index = this->dataPtr->videoStream->index; - if (avPacket->dts != static_cast(AV_NOPTS_VALUE)) - { - avPacket->dts = av_rescale_q( - avPacket->dts, - this->dataPtr->codecCtx->time_base, - this->dataPtr->videoStream->time_base); - } + // Scale timestamp appropriately. + if (avPacket->pts != static_cast(AV_NOPTS_VALUE)) + { + avPacket->pts = av_rescale_q(avPacket->pts, + this->dataPtr->codecCtx->time_base, + this->dataPtr->videoStream->time_base); + } - // Write frame to disk - if (av_interleaved_write_frame(this->dataPtr->formatCtx, avPacket) < 0) - ignerr << "Error writing frame" << std::endl; + if (avPacket->dts != static_cast(AV_NOPTS_VALUE)) + { + avPacket->dts = av_rescale_q( + avPacket->dts, + this->dataPtr->codecCtx->time_base, + this->dataPtr->videoStream->time_base); + } + + // Write frame to disk + if (av_interleaved_write_frame(this->dataPtr->formatCtx, avPacket) < 0) + ignerr << "Error writing frame" << std::endl; + } } - } - av_packet_unref(avPacket); + av_packet_unref(avPacket); #endif + } return true; } From 6eeff9c888486614d720813a7855c76f2ddbfb02 Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Thu, 15 Oct 2020 22:00:04 -0700 Subject: [PATCH 3/9] fix resetting video recording Signed-off-by: Ian Chen --- av/src/VideoEncoder.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/av/src/VideoEncoder.cc b/av/src/VideoEncoder.cc index 87f56f86e..0935c4d75 100644 --- a/av/src/VideoEncoder.cc +++ b/av/src/VideoEncoder.cc @@ -128,7 +128,8 @@ bool VideoEncoder::Start(const std::string &_format, // This will be true if Stop has been called, but not reset. We will reset // automatically to prevent any errors. if (this->dataPtr->formatCtx || this->dataPtr->avInFrame || - this->dataPtr->avOutFrame || this->dataPtr->swsCtx) + this->dataPtr->avOutFrame || this->dataPtr->swsCtx || + this->dataPtr->frameCount > 0u) { this->Reset(); } From ceb15a568f5eb8496f56b8f9c0ea2d64d29b0bba Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Mon, 9 Nov 2020 22:57:14 -0800 Subject: [PATCH 4/9] support multiple texcoord set Signed-off-by: Ian Chen --- graphics/include/ignition/common/SubMesh.hh | 56 +++++++ graphics/src/ColladaLoader.cc | 146 ++++++++++++------ graphics/src/ColladaLoader_TEST.cc | 54 ++++++- graphics/src/SubMesh.cc | 104 +++++++++++-- .../multiple_texture_coordinates_triangle.dae | 63 ++++++++ 5 files changed, 356 insertions(+), 67 deletions(-) diff --git a/graphics/include/ignition/common/SubMesh.hh b/graphics/include/ignition/common/SubMesh.hh index b7d64bc82..5f303c00f 100644 --- a/graphics/include/ignition/common/SubMesh.hh +++ b/graphics/include/ignition/common/SubMesh.hh @@ -124,6 +124,20 @@ namespace ignition /// \param[in] _uv The texture coordinate public: void AddTexCoord(const ignition::math::Vector2d &_uv); + /// \brief Add a texture coord to a texture coordinate set of the mesh + /// \param[in] _u Position along u + /// \param[in] _v Position along v + /// \param[in] _setIndex Texture coordinate set index + public: void AddTexCoordBySet(double _u, double _v, + unsigned int _setIndex); + + /// \brief Add a texture coord to a texture coordinate set of the mesh + /// \param[in] _u Position along u + /// \param[in] _v Position along v + /// \param[in] _setIndex Texture coordinate set index + public: void AddTexCoordBySet(const ignition::math::Vector2d &_uv, + unsigned int _setIndex); + /// \brief Add a vertex - skeleton node assignment /// \param[in] _vertex The vertex index /// \param[in] _node The node index @@ -165,12 +179,31 @@ namespace ignition public: ignition::math::Vector2d TexCoord( const unsigned int _index) const; + /// \brief Get a texture coordinate for a texture coordinate set + /// \param[in] _index the texture index + /// \return The texture coordinate or ignition::math::Vector2d::Zero + /// if index is out of bounds. + /// \param[in] _setIndex Texture coordinate set index + /// \sa bool HasTexCoordBySet(unsigned int _index, unsigned int _setIndex) + /// const + public: ignition::math::Vector2d TexCoordBySet( + unsigned int _index, + unsigned int _setIndex) const; + /// \brief Set a texture coordinate /// \param[in] _index Index of the texture coordinate that will be set. /// \param[in] _uv The new texture coordinate public: void SetTexCoord(const unsigned int _index, const ignition::math::Vector2d &_uv); + /// \brief Set a texture coordinate for a texture coordinate set + /// \param[in] _index Index of the texture coordinate that will be set. + /// \param[in] _uv The new texture coordinate + /// \param[in] _setIndex Texture coordinate set index + public: void SetTexCoordBySet(unsigned int _index, + const ignition::math::Vector2d &_uv, + unsigned int _setIdex); + /// \brief Get an index value from the index array /// \param[in] _index Array index. /// \return The index, or -1 if the _index is out of bounds. @@ -215,6 +248,12 @@ namespace ignition /// \return The number of texture coordinates. public: unsigned int TexCoordCount() const; + /// \brief Return the number of texture coordinates for a texture + /// coordinate set + /// \param[in] _setIndex Texture coordinate set index + /// \return The number of texture coordinates. + public: unsigned int TexCoordCountBySet(unsigned int _setIndex) const; + /// \brief Get the number of vertex-skeleton node assignments /// \return The number of vertex-skeleton node assignments public: unsigned int NodeAssignmentsCount() const; @@ -258,6 +297,15 @@ namespace ignition /// the given _index. public: bool HasTexCoord(const unsigned int _index) const; + /// \brief Return true if this submesh has the texture coordinate with + /// the given index in a texture coordinate set + /// \param[in] _index Texture coordinate index + /// \param[in] _setIndex Texture coordinate set index + /// \return Return true if this submesh has the texture coordinate with + /// the given _index. + public: bool HasTexCoordBySet(unsigned int _index, unsigned int _setIndex) + const; + /// \brief Return true if this submesh has the node assignment with /// the given index /// \param[in] _index Node assignment index @@ -284,6 +332,14 @@ namespace ignition public: void GenSphericalTexCoord( const ignition::math::Vector3d &_center); + /// \brief Generate texture coordinates for a texture coordinate set + /// using spherical projection from center + /// \param[in] _center Center of the projection. + /// \param[in] _setIndex Texture coordinate set index + public: void GenSphericalTexCoordBySet( + const ignition::math::Vector3d &_center, + unsigned int _setIndex); + /// \brief Scale all vertices by _factor /// \param[in] _factor Scaling factor public: void Scale(const ignition::math::Vector3d &_factor); diff --git a/graphics/src/ColladaLoader.cc b/graphics/src/ColladaLoader.cc index 7bf473576..e5190bb22 100644 --- a/graphics/src/ColladaLoader.cc +++ b/graphics/src/ColladaLoader.cc @@ -316,8 +316,9 @@ namespace ignition /// \brief Index of a normal in the collada

element public: unsigned int normalIndex; - /// \brief Index of a texture coordinate in the collada

element - public: unsigned int texcoordIndex; + /// \brief A map of texture coordinate set index to index of a texture + /// coordinate in the collada

element + public: std::map texcoordIndex; /// \brief Index of a vertex in the Gazebo mesh public: unsigned int mappedIndex; @@ -1992,7 +1993,8 @@ void ColladaLoaderPrivate::LoadPolylist(tinyxml2::XMLElement *_polylistXml, std::vector verts; std::vector norms; - std::vector texcoords; + std::map> texcoords; + std::map texcoordsOffsetToSet; const unsigned int VERTEX = 0; const unsigned int NORMAL = 1; @@ -2000,7 +2002,7 @@ void ColladaLoaderPrivate::LoadPolylist(tinyxml2::XMLElement *_polylistXml, unsigned int otherSemantics = TEXCOORD + 1; // look up table of position/normal/texcoord duplicate indices - std::map texDupMap; + std::map> texDupMap; std::map normalDupMap; std::map positionDupMap; @@ -2034,8 +2036,14 @@ void ColladaLoaderPrivate::LoadPolylist(tinyxml2::XMLElement *_polylistXml, } else if (semantic == "TEXCOORD") { - this->LoadTexCoords(source, texcoords, texDupMap); - inputs[TEXCOORD].insert(ignition::math::parseInt(offset)); + int offsetInt = ignition::math::parseInt(offset); + if (inputs[TEXCOORD].find(offsetInt) == inputs[TEXCOORD].end()) + { + int set = ignition::math::parseInt(polylistInputXml->Attribute("set")); + this->LoadTexCoords(source, texcoords[set], texDupMap[set]); + inputs[TEXCOORD].insert(offsetInt); + texcoordsOffsetToSet[offsetInt] = set; + } } else { @@ -2153,16 +2161,26 @@ void ColladaLoaderPrivate::LoadPolylist(tinyxml2::XMLElement *_polylistXml, if (!inputs[TEXCOORD].empty()) { - // Get the vertex texcoord index value. If the texcoord is a - // duplicate then reset the index to the first instance of the - // duplicated texcoord - unsigned int remappedTexcoordIndex = - values[*inputs[TEXCOORD].begin()]; - - if (texDupMap.find(remappedTexcoordIndex) != texDupMap.end()) - remappedTexcoordIndex = texDupMap[remappedTexcoordIndex]; - - texEqual = iv.texcoordIndex == remappedTexcoordIndex; + texEqual = true; + for (auto offset : inputs[TEXCOORD]) + { + int set = texcoordsOffsetToSet[offset]; + // Get the vertex texcoord index value. If the texcoord is a + // duplicate then reset the index to the first instance of the + // duplicated texcoord + unsigned int remappedTexcoordIndex = + values[offset]; + auto &texDupMapSet = texDupMap[set]; + auto texDupMapSetIt = texDupMapSet.find( + remappedTexcoordIndex); + if (texDupMapSetIt != texDupMapSet.end()) + remappedTexcoordIndex = texDupMapSetIt->second; + if (iv.texcoordIndex[set] != remappedTexcoordIndex) + { + texEqual = false; + break; + } + } } // if the vertex has matching normal and texcoord index values @@ -2228,17 +2246,25 @@ void ColladaLoaderPrivate::LoadPolylist(tinyxml2::XMLElement *_polylistXml, if (!inputs[TEXCOORD].empty()) { - unsigned int inputRemappedTexcoordIndex = - values[*inputs[TEXCOORD].begin()]; - - if (texDupMap.find(inputRemappedTexcoordIndex) != texDupMap.end()) + for (auto offset : inputs[TEXCOORD]) { - inputRemappedTexcoordIndex = - texDupMap[inputRemappedTexcoordIndex]; + unsigned int inputRemappedTexcoordIndex = + // values[*inputs[TEXCOORD].begin()]; + values[offset]; + + int set = texcoordsOffsetToSet[offset]; + + auto texDupMapSet = texDupMap[set]; + auto texDupMapSetIt = texDupMapSet.find( + inputRemappedTexcoordIndex); + if (texDupMapSetIt != texDupMapSet.end()) + inputRemappedTexcoordIndex = texDupMapSetIt->second; + auto &texcoordsSet = texcoords[set]; + subMesh->AddTexCoordBySet( + texcoordsSet[inputRemappedTexcoordIndex].X(), + texcoordsSet[inputRemappedTexcoordIndex].Y(), set); + input.texcoordIndex[set] = inputRemappedTexcoordIndex; } - subMesh->AddTexCoord(texcoords[inputRemappedTexcoordIndex].X(), - texcoords[inputRemappedTexcoordIndex].Y()); - input.texcoordIndex = inputRemappedTexcoordIndex; } // add the new ignition submesh vertex index to the map @@ -2293,7 +2319,8 @@ void ColladaLoaderPrivate::LoadTriangles(tinyxml2::XMLElement *_trianglesXml, std::vector verts; std::vector norms; - std::vector texcoords; + std::map> texcoords; + std::map texcoordsOffsetToSet; const unsigned int VERTEX = 0; const unsigned int NORMAL = 1; @@ -2309,7 +2336,7 @@ void ColladaLoaderPrivate::LoadTriangles(tinyxml2::XMLElement *_trianglesXml, std::map> inputs; // look up table of position/normal/texcoord duplicate indices - std::map texDupMap; + std::map> texDupMap; std::map normalDupMap; std::map positionDupMap; @@ -2337,9 +2364,15 @@ void ColladaLoaderPrivate::LoadTriangles(tinyxml2::XMLElement *_trianglesXml, } else if (semantic == "TEXCOORD") { - // we currently only support one set of UVs - this->LoadTexCoords(source, texcoords, texDupMap); - inputs[TEXCOORD].insert(ignition::math::parseInt(offset)); + int offsetInt = ignition::math::parseInt(offset); + if (inputs[TEXCOORD].find(offsetInt) == inputs[TEXCOORD].end()) + { + unsigned int set = ignition::math::parseInt( + trianglesInputXml->Attribute("set")); + this->LoadTexCoords(source, texcoords[set], texDupMap[set]); + inputs[TEXCOORD].insert(offsetInt); + texcoordsOffsetToSet[offsetInt] = set; + } hasTexcoords = true; } else @@ -2451,16 +2484,26 @@ void ColladaLoaderPrivate::LoadTriangles(tinyxml2::XMLElement *_trianglesXml, } if (hasTexcoords) { - // Get the vertex texcoord index value. If the texcoord is a - // duplicate then reset the index to the first instance of the - // duplicated texcoord - unsigned int remappedTexcoordIndex = - values.at(*inputs[TEXCOORD].begin()); - if (texDupMap.find(remappedTexcoordIndex) != texDupMap.end()) - remappedTexcoordIndex = texDupMap[remappedTexcoordIndex]; - - if (iv.texcoordIndex == remappedTexcoordIndex) - texEqual = true; + texEqual = true; + for (auto offset : inputs[TEXCOORD]) + { + // Get the vertex texcoord index value. If the texcoord is a + // duplicate then reset the index to the first instance of the + // duplicated texcoord + unsigned int remappedTexcoordIndex = + values.at(offset); + int set = texcoordsOffsetToSet[offset]; + auto texDupMapSet = texDupMap[set]; + auto texDupMapSetIt = texDupMapSet.find(remappedTexcoordIndex); + if (texDupMapSetIt != texDupMapSet.end()) + remappedTexcoordIndex = texDupMapSetIt->second; + + if (iv.texcoordIndex[set] != remappedTexcoordIndex) + { + texEqual = false; + break; + } + } } // if the vertex has matching normal and texcoord index values then @@ -2524,13 +2567,22 @@ void ColladaLoaderPrivate::LoadTriangles(tinyxml2::XMLElement *_trianglesXml, } if (hasTexcoords) { - unsigned int inputRemappedTexcoordIndex = - values.at(*inputs[TEXCOORD].begin()); - if (texDupMap.find(inputRemappedTexcoordIndex) != texDupMap.end()) - inputRemappedTexcoordIndex = texDupMap[inputRemappedTexcoordIndex]; - subMesh->AddTexCoord(texcoords[inputRemappedTexcoordIndex].X(), - texcoords[inputRemappedTexcoordIndex].Y()); - input.texcoordIndex = inputRemappedTexcoordIndex; + for (auto offset : inputs[TEXCOORD]) + { + unsigned int inputRemappedTexcoordIndex = + values.at(offset); + + int set = texcoordsOffsetToSet[offset]; + auto &texDupMapSet = texDupMap[set]; + auto texDupMapSetIt = texDupMapSet.find(inputRemappedTexcoordIndex); + if (texDupMapSetIt != texDupMapSet.end()) + inputRemappedTexcoordIndex = texDupMapSetIt->second; + auto &texcoordsSet = texcoords[set]; + subMesh->AddTexCoordBySet( + texcoordsSet[inputRemappedTexcoordIndex].X(), + texcoordsSet[inputRemappedTexcoordIndex].Y(), set); + input.texcoordIndex[set] = inputRemappedTexcoordIndex; + } } // add the new ignition submesh vertex index to the map diff --git a/graphics/src/ColladaLoader_TEST.cc b/graphics/src/ColladaLoader_TEST.cc index 45eca5228..a9a9a447a 100644 --- a/graphics/src/ColladaLoader_TEST.cc +++ b/graphics/src/ColladaLoader_TEST.cc @@ -191,11 +191,11 @@ TEST_F(ColladaLoader, TexCoordSets) "/test/data/multiple_texture_coordinates_triangle.dae"); ASSERT_TRUE(mesh); - EXPECT_EQ(3u, mesh->VertexCount()); - EXPECT_EQ(3u, mesh->NormalCount()); - EXPECT_EQ(3u, mesh->IndexCount()); - EXPECT_EQ(3u, mesh->TexCoordCount()); - EXPECT_EQ(1u, mesh->SubMeshCount()); + EXPECT_EQ(6u, mesh->VertexCount()); + EXPECT_EQ(6u, mesh->NormalCount()); + EXPECT_EQ(6u, mesh->IndexCount()); + EXPECT_EQ(6u, mesh->TexCoordCount()); + EXPECT_EQ(2u, mesh->SubMeshCount()); EXPECT_EQ(0u, mesh->MaterialCount()); auto sm = mesh->SubMeshByIndex(0u); @@ -210,6 +210,50 @@ TEST_F(ColladaLoader, TexCoordSets) EXPECT_EQ(math::Vector2d(0, 1), subMesh->TexCoord(0u)); EXPECT_EQ(math::Vector2d(0, 1), subMesh->TexCoord(1u)); EXPECT_EQ(math::Vector2d(0, 1), subMesh->TexCoord(2u)); + + auto smb = mesh->SubMeshByIndex(1u); + auto subMeshB = smb.lock(); + EXPECT_NE(nullptr, subMeshB); + EXPECT_EQ(math::Vector3d(10, 0, 0), subMeshB->Vertex(0u)); + EXPECT_EQ(math::Vector3d(20, 0, 0), subMeshB->Vertex(1u)); + EXPECT_EQ(math::Vector3d(20, 10, 0), subMeshB->Vertex(2u)); + EXPECT_EQ(math::Vector3d(0, 0, 1), subMeshB->Normal(0u)); + EXPECT_EQ(math::Vector3d(0, 0, 1), subMeshB->Normal(1u)); + EXPECT_EQ(math::Vector3d(0, 0, 1), subMeshB->Normal(2u)); + EXPECT_EQ(math::Vector2d(0, 1), subMeshB->TexCoord(0u)); + EXPECT_EQ(math::Vector2d(0, 1), subMeshB->TexCoord(1u)); + EXPECT_EQ(math::Vector2d(0, 1), subMeshB->TexCoord(2u)); + + EXPECT_TRUE(subMeshB->HasTexCoord(0u)); + EXPECT_TRUE(subMeshB->HasTexCoord(1u)); + EXPECT_TRUE(subMeshB->HasTexCoord(2u)); + EXPECT_FALSE(subMeshB->HasTexCoord(3u)); + + // test texture coordinate set API + EXPECT_EQ(3u, subMeshB->TexCoordCountBySet(0u)); + EXPECT_EQ(math::Vector2d(0, 1), subMeshB->TexCoordBySet(0u, 0u)); + EXPECT_EQ(math::Vector2d(0, 1), subMeshB->TexCoordBySet(1u, 0u)); + EXPECT_EQ(math::Vector2d(0, 1), subMeshB->TexCoordBySet(2u, 0u)); + EXPECT_EQ(math::Vector2d(0, 1), subMeshB->TexCoordBySet(1u, 0u)); + EXPECT_EQ(math::Vector2d(0, 1), subMeshB->TexCoordBySet(2u, 0u)); + + EXPECT_TRUE(subMeshB->HasTexCoordBySet(0u, 0u)); + EXPECT_TRUE(subMeshB->HasTexCoordBySet(1u, 0u)); + EXPECT_TRUE(subMeshB->HasTexCoordBySet(2u, 0u)); + EXPECT_FALSE(subMeshB->HasTexCoordBySet(3u, 0u)); + + EXPECT_EQ(3u, subMeshB->TexCoordCountBySet(1u)); + EXPECT_EQ(math::Vector2d(0, 0.5), subMeshB->TexCoordBySet(0u, 1u)); + EXPECT_EQ(math::Vector2d(0, 0.4), subMeshB->TexCoordBySet(1u, 1u)); + EXPECT_EQ(math::Vector2d(0, 0.3), subMeshB->TexCoordBySet(2u, 1u)); + + EXPECT_TRUE(subMeshB->HasTexCoordBySet(0u, 1u)); + EXPECT_TRUE(subMeshB->HasTexCoordBySet(1u, 1u)); + EXPECT_TRUE(subMeshB->HasTexCoordBySet(2u, 1u)); + EXPECT_FALSE(subMeshB->HasTexCoordBySet(3u, 1u)); + + subMeshB->SetTexCoordBySet(2u, math::Vector2d(0.1, 0.2), 1u); + EXPECT_EQ(math::Vector2d(0.1, 0.2), subMeshB->TexCoordBySet(2u, 1u)); } ///////////////////////////////////////////////// diff --git a/graphics/src/SubMesh.cc b/graphics/src/SubMesh.cc index 6bdbd05a0..8e2272679 100644 --- a/graphics/src/SubMesh.cc +++ b/graphics/src/SubMesh.cc @@ -35,8 +35,9 @@ class ignition::common::SubMeshPrivate /// \brief the normal array public: std::vector normals; - /// \brief the texture coordinate array - public: std::vector texCoords; + /// \brief A map of texcoord set index to texture coordinate array + public: std::map> + texCoords; /// \brief the vertex index array public: std::vector indices; @@ -86,9 +87,12 @@ SubMesh::SubMesh(const SubMesh &_submesh) std::copy(_submesh.dataPtr->normals.begin(), _submesh.dataPtr->normals.end(), std::back_inserter(this->dataPtr->normals)); - std::copy(_submesh.dataPtr->texCoords.begin(), - _submesh.dataPtr->texCoords.end(), - std::back_inserter(this->dataPtr->texCoords)); + + for (const auto &set : _submesh.dataPtr->texCoords) + { + std::copy(set.second.begin(), set.second.end(), + std::back_inserter(this->dataPtr->texCoords[set.first])); + } std::copy(_submesh.dataPtr->vertices.begin(), _submesh.dataPtr->vertices.end(), std::back_inserter(this->dataPtr->vertices)); @@ -147,13 +151,30 @@ void SubMesh::AddNormal(const double _x, const double _y, const double _z) ////////////////////////////////////////////////// void SubMesh::AddTexCoord(const double _u, const double _v) { - this->dataPtr->texCoords.push_back(ignition::math::Vector2d(_u, _v)); + unsigned firstSetIndex = 0u; + if (!this->dataPtr->texCoords.empty()) + firstSetIndex = this->dataPtr->texCoords.begin()->first; + this->AddTexCoordBySet(_u, _v, firstSetIndex); } ////////////////////////////////////////////////// void SubMesh::AddTexCoord(const ignition::math::Vector2d &_uv) { - this->dataPtr->texCoords.push_back(_uv); + this->AddTexCoord(_uv.X(), _uv.Y()); +} + +////////////////////////////////////////////////// +void SubMesh::AddTexCoordBySet(double _u, double _v, unsigned int _setIndex) +{ + this->dataPtr->texCoords[_setIndex].push_back( + ignition::math::Vector2d(_u, _v)); +} + +////////////////////////////////////////////////// +void SubMesh::AddTexCoordBySet(const ignition::math::Vector2d &_uv, + unsigned int _setIndex) +{ + this->AddTexCoordBySet(_uv.X(), _uv.Y(), _setIndex); } ////////////////////////////////////////////////// @@ -220,7 +241,17 @@ bool SubMesh::HasNormal(const unsigned int _index) const ////////////////////////////////////////////////// bool SubMesh::HasTexCoord(const unsigned int _index) const { - return _index < this->dataPtr->texCoords.size(); + if (this->dataPtr->texCoords.empty()) + return false; + unsigned firstSetIndex = this->dataPtr->texCoords.begin()->first; + return this->HasTexCoordBySet(_index, firstSetIndex); +} + +////////////////////////////////////////////////// +bool SubMesh::HasTexCoordBySet(unsigned int _index, + unsigned int _setIndex) const +{ + return _index < this->dataPtr->texCoords[_setIndex].size(); } ////////////////////////////////////////////////// @@ -245,26 +276,49 @@ void SubMesh::SetNormal(const unsigned int _index, ////////////////////////////////////////////////// ignition::math::Vector2d SubMesh::TexCoord(const unsigned int _index) const { - if (_index >= this->dataPtr->texCoords.size()) + if (this->dataPtr->texCoords.empty()) + { + ignerr << "Texture coordinate sets are empty" << std::endl; + return math::Vector2d::Zero; + } + unsigned firstSetIndex = this->dataPtr->texCoords.begin()->first; + return this->TexCoordBySet(_index, firstSetIndex); +} + +////////////////////////////////////////////////// +ignition::math::Vector2d SubMesh::TexCoordBySet(unsigned int _index, + unsigned int _setIndex) const +{ + if (_index >= this->dataPtr->texCoords[_setIndex].size()) { ignerr << "Index too large" << std::endl; return math::Vector2d::Zero; } - return this->dataPtr->texCoords[_index]; + return this->dataPtr->texCoords[_setIndex][_index]; } ////////////////////////////////////////////////// void SubMesh::SetTexCoord(const unsigned int _index, const ignition::math::Vector2d &_t) { - if (_index >= this->dataPtr->texCoords.size()) + unsigned firstSetIndex = 0u; + if (!this->dataPtr->texCoords.empty()) + firstSetIndex = this->dataPtr->texCoords.begin()->first; + this->SetTexCoordBySet(_index, _t, firstSetIndex); +} + +////////////////////////////////////////////////// +void SubMesh::SetTexCoordBySet(unsigned int _index, + const ignition::math::Vector2d &_t, unsigned int _setIndex) +{ + if (_index >= this->dataPtr->texCoords[_setIndex].size()) { ignerr << "Index too large" << std::endl; return; } - this->dataPtr->texCoords[_index] = _t; + this->dataPtr->texCoords[_setIndex][_index] = _t; } ////////////////////////////////////////////////// @@ -369,7 +423,16 @@ unsigned int SubMesh::IndexCount() const ////////////////////////////////////////////////// unsigned int SubMesh::TexCoordCount() const { - return this->dataPtr->texCoords.size(); + if (this->dataPtr->texCoords.empty()) + return 0u; + unsigned firstSetIndex = this->dataPtr->texCoords.begin()->first; + return this->TexCoordCountBySet(firstSetIndex); +} + +////////////////////////////////////////////////// +unsigned int SubMesh::TexCoordCountBySet(unsigned int _setIndex) const +{ + return this->dataPtr->texCoords[_setIndex].size(); } ////////////////////////////////////////////////// @@ -501,7 +564,18 @@ void SubMesh::RecalculateNormals() ////////////////////////////////////////////////// void SubMesh::GenSphericalTexCoord(const ignition::math::Vector3d &_center) { - this->dataPtr->texCoords.clear(); + if (this->dataPtr->texCoords.empty()) + return; + + unsigned firstSetIndex = this->dataPtr->texCoords.begin()->first; + this->GenSphericalTexCoordBySet(_center, firstSetIndex); +} + +////////////////////////////////////////////////// +void SubMesh::GenSphericalTexCoordBySet(const ignition::math::Vector3d &_center, + unsigned int _setIndex) +{ + this->dataPtr->texCoords[_setIndex].clear(); for (const auto &vert : this->dataPtr->vertices) { @@ -516,7 +590,7 @@ void SubMesh::GenSphericalTexCoord(const ignition::math::Vector3d &_center) double t = std::min(1.0, std::max(-1.0, y/r)); double u = acos(s) / IGN_PI; double v = acos(t) / IGN_PI; - this->AddTexCoord(u, v); + this->AddTexCoordBySet(u, v, _setIndex); } } diff --git a/test/data/multiple_texture_coordinates_triangle.dae b/test/data/multiple_texture_coordinates_triangle.dae index df352927c..d3c13b8f3 100644 --- a/test/data/multiple_texture_coordinates_triangle.dae +++ b/test/data/multiple_texture_coordinates_triangle.dae @@ -68,6 +68,64 @@ + + + + + +0 0 0 +10 0 0 +10 10 0 + + + + + + + + + + + 0 0 1 + + + + + + + + + + 0 0 0 0 0 0 + + + + + + + + + 0 0.5 0 0.6 0 0.7 + + + + + + + + + + + + + + + +

0 0 0 0 1 0 1 1 2 0 2 2

+ + + + @@ -76,6 +134,11 @@ 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 + + 1 0 0 10 0 1 0 0 0 0 1 0 0 0 0 1 + + + From 060d06bda4024105a5d719f1d7d6aa781857a2b1 Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Thu, 19 Nov 2020 17:20:00 -0800 Subject: [PATCH 5/9] add tex coord set count Signed-off-by: Ian Chen --- graphics/include/ignition/common/SubMesh.hh | 4 ++++ graphics/src/ColladaLoader_TEST.cc | 1 + graphics/src/SubMesh.cc | 6 ++++++ 3 files changed, 11 insertions(+) diff --git a/graphics/include/ignition/common/SubMesh.hh b/graphics/include/ignition/common/SubMesh.hh index 5f303c00f..f7db4c5ab 100644 --- a/graphics/include/ignition/common/SubMesh.hh +++ b/graphics/include/ignition/common/SubMesh.hh @@ -254,6 +254,10 @@ namespace ignition /// \return The number of texture coordinates. public: unsigned int TexCoordCountBySet(unsigned int _setIndex) const; + /// \brief Return the number of texture coordinate sets + /// \return The number of texture coordinates sets. + public: unsigned int TexCoordSetCount() const; + /// \brief Get the number of vertex-skeleton node assignments /// \return The number of vertex-skeleton node assignments public: unsigned int NodeAssignmentsCount() const; diff --git a/graphics/src/ColladaLoader_TEST.cc b/graphics/src/ColladaLoader_TEST.cc index a9a9a447a..66346cd7e 100644 --- a/graphics/src/ColladaLoader_TEST.cc +++ b/graphics/src/ColladaLoader_TEST.cc @@ -230,6 +230,7 @@ TEST_F(ColladaLoader, TexCoordSets) EXPECT_FALSE(subMeshB->HasTexCoord(3u)); // test texture coordinate set API + EXPECT_EQ(2u, subMeshB->TexCoordSetCount()); EXPECT_EQ(3u, subMeshB->TexCoordCountBySet(0u)); EXPECT_EQ(math::Vector2d(0, 1), subMeshB->TexCoordBySet(0u, 0u)); EXPECT_EQ(math::Vector2d(0, 1), subMeshB->TexCoordBySet(1u, 0u)); diff --git a/graphics/src/SubMesh.cc b/graphics/src/SubMesh.cc index 8e2272679..2c317e95e 100644 --- a/graphics/src/SubMesh.cc +++ b/graphics/src/SubMesh.cc @@ -435,6 +435,12 @@ unsigned int SubMesh::TexCoordCountBySet(unsigned int _setIndex) const return this->dataPtr->texCoords[_setIndex].size(); } +////////////////////////////////////////////////// +unsigned int SubMesh::TexCoordSetCount() const +{ + return this->dataPtr->texCoords.size(); +} + ////////////////////////////////////////////////// unsigned int SubMesh::NodeAssignmentsCount() const { From fa9ed9378f131c639d09049a1efb828e04a3c08c Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Thu, 19 Nov 2020 22:35:43 -0800 Subject: [PATCH 6/9] add lightmap to material Signed-off-by: Ian Chen --- graphics/include/ignition/common/Pbr.hh | 15 +++++++++++++++ graphics/src/Pbr.cc | 25 +++++++++++++++++++++++++ graphics/src/Pbr_TEST.cc | 18 ++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/graphics/include/ignition/common/Pbr.hh b/graphics/include/ignition/common/Pbr.hh index cd84c8573..68afde020 100644 --- a/graphics/include/ignition/common/Pbr.hh +++ b/graphics/include/ignition/common/Pbr.hh @@ -166,6 +166,21 @@ namespace common /// \param[in] _map Filename of the emissive map. public: void SetEmissiveMap(const std::string &_map); + /// \brief Get the light map filename. This will be an empty string + /// if an light map has not been set. + /// \return Filename of the light map, or empty string if a light + /// map has not been specified. + public: std::string LightMap() const; + + /// \brief Set the light map filename. + /// \param[in] _map Filename of the light map. + /// \param[in] _uvSet Index of the texture coordinate set + public: void SetLightMap(const std::string &_map, unsigned int _uvSet = 0u); + + /// \brief Get the light map texture coordinate set. + /// \return Index of the light map texture coordinate set + public: unsigned int LightMapTexCoordSet() const; + /// \brief Get the metalness value of the material for metal workflow /// \return metalness value of the material public: double Metalness() const; diff --git a/graphics/src/Pbr.cc b/graphics/src/Pbr.cc index f3024a303..cd96bda6a 100644 --- a/graphics/src/Pbr.cc +++ b/graphics/src/Pbr.cc @@ -50,6 +50,12 @@ class ignition::common::PbrPrivate /// \brief Emissive map public: std::string emissiveMap = ""; + /// \brief Light map + public: std::string lightMap; + + /// \brief Light map texture coordinate set + public: unsigned int lightMapUvSet = 0u; + /// \brief Roughness value (metal workflow only) public: double roughness = 0.5; @@ -293,6 +299,25 @@ void Pbr::SetEmissiveMap(const std::string &_map) this->dataPtr->emissiveMap = _map; } +////////////////////////////////////////////////// +std::string Pbr::LightMap() const +{ + return this->dataPtr->lightMap; +} + +////////////////////////////////////////////////// +void Pbr::SetLightMap(const std::string &_map, unsigned int _uvSet) +{ + this->dataPtr->lightMap = _map; + this->dataPtr->lightMapUvSet = _uvSet; +} + +////////////////////////////////////////////////// +unsigned int Pbr::LightMapTexCoordSet() const +{ + return this->dataPtr->lightMapUvSet; +} + ////////////////////////////////////////////////// PbrType Pbr::Type() const { diff --git a/graphics/src/Pbr_TEST.cc b/graphics/src/Pbr_TEST.cc index b7e89b072..de9a923d2 100644 --- a/graphics/src/Pbr_TEST.cc +++ b/graphics/src/Pbr_TEST.cc @@ -32,6 +32,8 @@ TEST(Pbr, BasicAPI) EXPECT_EQ(std::string(), pbr.RoughnessMap()); EXPECT_EQ(std::string(), pbr.MetalnessMap()); EXPECT_EQ(std::string(), pbr.EmissiveMap()); + EXPECT_EQ(std::string(), pbr.LightMap()); + EXPECT_EQ(0u, pbr.LightMapTexCoordSet()); EXPECT_DOUBLE_EQ(0.5, pbr.Roughness()); EXPECT_DOUBLE_EQ(0.0, pbr.Metalness()); EXPECT_EQ(std::string(), pbr.SpecularMap()); @@ -60,6 +62,10 @@ TEST(Pbr, BasicAPI) pbr.SetEmissiveMap("metal_emissive_map.png"); EXPECT_EQ("metal_emissive_map.png", pbr.EmissiveMap()); + pbr.SetLightMap("metal_light_map.png", 1u); + EXPECT_EQ("metal_light_map.png", pbr.LightMap()); + EXPECT_EQ(1u, pbr.LightMapTexCoordSet()); + pbr.SetRoughnessMap("roughness_map.png"); EXPECT_EQ("roughness_map.png", pbr.RoughnessMap()); @@ -89,6 +95,7 @@ TEST(Pbr, MoveCopy) pbr.SetEnvironmentMap("specular_env_map.png"); pbr.SetAmbientOcclusionMap("specular_ambient_occlusion_map.png"); pbr.SetEmissiveMap("specular_emissive_map.png"); + pbr.SetLightMap("specular_light_map.png", 2u); pbr.SetGlossinessMap("glossiness_map.png"); pbr.SetSpecularMap("specular_map.png"); pbr.SetGlossiness(0.1); @@ -102,6 +109,8 @@ TEST(Pbr, MoveCopy) EXPECT_EQ("specular_ambient_occlusion_map.png", pbr2.AmbientOcclusionMap()); EXPECT_EQ("specular_emissive_map.png", pbr2.EmissiveMap()); + EXPECT_EQ("specular_light_map.png", pbr2.LightMap()); + EXPECT_EQ(2u, pbr2.LightMapTexCoordSet()); EXPECT_EQ("specular_map.png", pbr2.SpecularMap()); EXPECT_EQ("glossiness_map.png", pbr2.GlossinessMap()); EXPECT_DOUBLE_EQ(0.1, pbr2.Glossiness()); @@ -122,6 +131,7 @@ TEST(Pbr, MoveCopy) pbr.SetEnvironmentMap("metal_env_map.png"); pbr.SetAmbientOcclusionMap("metal_ambient_occlusion_map.png"); pbr.SetEmissiveMap("metal_emissive_map.png"); + pbr.SetLightMap("metal_light_map.png", 3u); pbr.SetRoughnessMap("roughness_map.png"); pbr.SetMetalnessMap("metalness_map.png"); pbr.SetRoughness(0.8); @@ -136,6 +146,8 @@ TEST(Pbr, MoveCopy) EXPECT_EQ("metal_ambient_occlusion_map.png", pbr2.AmbientOcclusionMap()); EXPECT_EQ("metal_emissive_map.png", pbr2.EmissiveMap()); + EXPECT_EQ("metal_light_map.png", pbr2.LightMap()); + EXPECT_EQ(3u, pbr2.LightMapTexCoordSet()); EXPECT_EQ("roughness_map.png", pbr2.RoughnessMap()); EXPECT_EQ("metalness_map.png", pbr2.MetalnessMap()); EXPECT_DOUBLE_EQ(0.8, pbr2.Roughness()); @@ -156,6 +168,7 @@ TEST(Pbr, MoveCopy) pbr.SetEnvironmentMap("metal_env_map.png"); pbr.SetAmbientOcclusionMap("metal_ambient_occlusion_map.png"); pbr.SetEmissiveMap("metal_emissive_map.png"); + pbr.SetLightMap("metal_light_map.png", 1u); pbr.SetRoughnessMap("roughness_map.png"); pbr.SetMetalnessMap("metalness_map.png"); pbr.SetRoughness(0.8); @@ -171,6 +184,8 @@ TEST(Pbr, MoveCopy) EXPECT_EQ("metal_ambient_occlusion_map.png", pbr2.AmbientOcclusionMap()); EXPECT_EQ("metal_emissive_map.png", pbr2.EmissiveMap()); + EXPECT_EQ("metal_light_map.png", pbr2.LightMap()); + EXPECT_EQ(1u, pbr2.LightMapTexCoordSet()); EXPECT_EQ("roughness_map.png", pbr2.RoughnessMap()); EXPECT_EQ("metalness_map.png", pbr2.MetalnessMap()); EXPECT_DOUBLE_EQ(0.8, pbr2.Roughness()); @@ -191,6 +206,7 @@ TEST(Pbr, MoveCopy) pbr.SetEnvironmentMap("metal_env_map.png"); pbr.SetAmbientOcclusionMap("metal_ambient_occlusion_map.png"); pbr.SetEmissiveMap("metal_emissive_map.png"); + pbr.SetLightMap("metal_light_map.png", 2u); pbr.SetRoughnessMap("roughness_map.png"); pbr.SetMetalnessMap("metalness_map.png"); pbr.SetRoughness(0.18); @@ -205,6 +221,8 @@ TEST(Pbr, MoveCopy) EXPECT_EQ("metal_ambient_occlusion_map.png", pbr2.AmbientOcclusionMap()); EXPECT_EQ("metal_emissive_map.png", pbr2.EmissiveMap()); + EXPECT_EQ("metal_light_map.png", pbr2.LightMap()); + EXPECT_EQ(2u, pbr2.LightMapTexCoordSet()); EXPECT_EQ("roughness_map.png", pbr2.RoughnessMap()); EXPECT_EQ("metalness_map.png", pbr2.MetalnessMap()); EXPECT_DOUBLE_EQ(0.18, pbr2.Roughness()); From 48598a218312b32b82461fd6cb69df7785826b2d Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Fri, 20 Nov 2020 14:33:32 -0800 Subject: [PATCH 7/9] fixing load time Signed-off-by: Ian Chen --- graphics/src/ColladaLoader.cc | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/graphics/src/ColladaLoader.cc b/graphics/src/ColladaLoader.cc index e5190bb22..04ac46639 100644 --- a/graphics/src/ColladaLoader.cc +++ b/graphics/src/ColladaLoader.cc @@ -2484,6 +2484,19 @@ void ColladaLoaderPrivate::LoadTriangles(tinyxml2::XMLElement *_trianglesXml, } if (hasTexcoords) { + // Get the vertex texcoord index value. If the texcoord is a + // duplicate then reset the index to the first instance of the + // duplicated texcoord + // unsigned int offset = *inputs[TEXCOORD].begin(); + // unsigned int remappedTexcoordIndex = + // values.at(offset); + // int set = texcoordsOffsetToSet[offset]; + // auto &texDupMapSet = texDupMap[set]; + // auto texDupMapSetIt = texDupMapSet.find(remappedTexcoordIndex); + // if (texDupMapSetIt != texDupMapSet.end()) + // remappedTexcoordIndex = texDupMapSetIt->second; + // texEqual = iv.texcoordIndex[set] == remappedTexcoordIndex; + texEqual = true; for (auto offset : inputs[TEXCOORD]) { @@ -2493,7 +2506,7 @@ void ColladaLoaderPrivate::LoadTriangles(tinyxml2::XMLElement *_trianglesXml, unsigned int remappedTexcoordIndex = values.at(offset); int set = texcoordsOffsetToSet[offset]; - auto texDupMapSet = texDupMap[set]; + auto &texDupMapSet = texDupMap[set]; auto texDupMapSetIt = texDupMapSet.find(remappedTexcoordIndex); if (texDupMapSetIt != texDupMapSet.end()) remappedTexcoordIndex = texDupMapSetIt->second; @@ -2504,6 +2517,7 @@ void ColladaLoaderPrivate::LoadTriangles(tinyxml2::XMLElement *_trianglesXml, break; } } + } // if the vertex has matching normal and texcoord index values then From bc17fe4749c3f1dfa027940f88b9aa0011bc025e Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Fri, 20 Nov 2020 14:40:12 -0800 Subject: [PATCH 8/9] more fixes Signed-off-by: Ian Chen --- graphics/src/ColladaLoader.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/graphics/src/ColladaLoader.cc b/graphics/src/ColladaLoader.cc index 04ac46639..8b1a8a851 100644 --- a/graphics/src/ColladaLoader.cc +++ b/graphics/src/ColladaLoader.cc @@ -2249,12 +2249,11 @@ void ColladaLoaderPrivate::LoadPolylist(tinyxml2::XMLElement *_polylistXml, for (auto offset : inputs[TEXCOORD]) { unsigned int inputRemappedTexcoordIndex = - // values[*inputs[TEXCOORD].begin()]; values[offset]; int set = texcoordsOffsetToSet[offset]; - auto texDupMapSet = texDupMap[set]; + auto &texDupMapSet = texDupMap[set]; auto texDupMapSetIt = texDupMapSet.find( inputRemappedTexcoordIndex); if (texDupMapSetIt != texDupMapSet.end()) From 2dfeb5443d30c7cfaeabc14dfa890c68b284b588 Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Mon, 30 Nov 2020 17:30:21 -0800 Subject: [PATCH 9/9] fix codecheck Signed-off-by: Ian Chen --- graphics/src/ColladaLoader.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/graphics/src/ColladaLoader.cc b/graphics/src/ColladaLoader.cc index 8b1a8a851..428773b89 100644 --- a/graphics/src/ColladaLoader.cc +++ b/graphics/src/ColladaLoader.cc @@ -2516,7 +2516,6 @@ void ColladaLoaderPrivate::LoadTriangles(tinyxml2::XMLElement *_trianglesXml, break; } } - } // if the vertex has matching normal and texcoord index values then