Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multiple texture coordinate sets #131

Merged
merged 21 commits into from
Dec 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 86 additions & 5 deletions graphics/include/ignition/common/SubMesh.hh
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,37 @@ namespace ignition
/// \param[in] _z Position along z
public: void AddNormal(const double _x, const double _y, const double _z);

/// \brief Add a texture coord to the mesh
/// \brief Add a texture coord to the mesh. If multiple texture
/// coordinate sets exist, this function adds it to the first texture
/// coordinate set in the submesh. If no previous texture coordinates
/// exist, it is added to set 0.
/// \param[in] _u Position along u
/// \param[in] _v Position along v
/// \sa AddTexCoordBySet
public: void AddTexCoord(const double _u, const double _v);

/// \brief Add a texture coordinate to the mesh
/// \brief Add a texture coordinate to the mesh. If multiple texture
/// coordinate sets exist, this function adds it to the first texture
/// coordinate set in the submesh. If no previous texture coordinates
/// exist, it is added to set 0.
/// \param[in] _uv The texture coordinate
/// \sa AddTexCoordBySet
public: void AddTexCoord(const ignition::math::Vector2d &_uv);
chapulina marked this conversation as resolved.
Show resolved Hide resolved

/// \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
Expand Down Expand Up @@ -165,12 +187,34 @@ namespace ignition
public: ignition::math::Vector2d TexCoord(
const unsigned int _index) const;

/// \brief Set a texture coordinate
/// \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. If multiple texture
/// coordinate sets exist, this function sets the texture
/// coordinate in the first texture coordinate set in the submesh.
/// \param[in] _index Index of the texture coordinate that will be set.
/// \param[in] _uv The new texture coordinate
/// \sa SetTexCoordBySet
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.
Expand Down Expand Up @@ -211,10 +255,25 @@ namespace ignition
/// \return The number of indices.
public: unsigned int IndexCount() const;

/// \brief Return the number of texture coordinates
/// \brief Return the number of texture coordinates. If multiple
/// texture coordinate sets exist, this function checks the first
/// texture coordinate set in the submesh, which by default is set 0,
/// unless AddTexCoordBySet is called with a different set index number
/// the first time a texture coordinate is added.
/// \return The number of texture coordinates.
/// \sa TexCoordCountBySet
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 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;
Expand Down Expand Up @@ -252,12 +311,26 @@ namespace ignition
public: bool HasNormal(const unsigned int _index) const;

/// \brief Return true if this submesh has the texture coordinate with
/// the given index
/// the given index. If multiple texture coordinate sets exist, this
/// function checks the first texture coordinate set in the submesh,
/// which by default is set 0 unless AddTexCoordBySet is called with
/// a different set index number the first time a texture coordinate is
/// added.
/// \param[in] _index Texture coordinate index
/// \return Return true if this submesh has the texture coordinate with
/// the given _index.
/// \sa HasTexCoordBySet
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
Expand All @@ -284,6 +357,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);
Expand Down
152 changes: 105 additions & 47 deletions graphics/src/ColladaLoader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,9 @@ namespace ignition
/// \brief Index of a normal in the collada <p> element
public: unsigned int normalIndex;

/// \brief Index of a texture coordinate in the collada <p> element
public: unsigned int texcoordIndex;
/// \brief A map of texture coordinate set index to index of a texture
/// coordinate in the collada <p> element
public: std::map<unsigned int, unsigned int> texcoordIndex;

/// \brief Index of a vertex in the Gazebo mesh
public: unsigned int mappedIndex;
Expand Down Expand Up @@ -1992,15 +1993,17 @@ void ColladaLoaderPrivate::LoadPolylist(tinyxml2::XMLElement *_polylistXml,

std::vector<ignition::math::Vector3d> verts;
std::vector<ignition::math::Vector3d> norms;
std::vector<ignition::math::Vector2d> texcoords;
std::map<unsigned int, std::vector<ignition::math::Vector2d>> texcoords;
std::map<unsigned int, unsigned int> texcoordsOffsetToSet;

const unsigned int VERTEX = 0;
const unsigned int NORMAL = 1;
const unsigned int TEXCOORD = 2;
unsigned int otherSemantics = TEXCOORD + 1;

// look up table of position/normal/texcoord duplicate indices
std::map<unsigned int, unsigned int> texDupMap;
std::unordered_map<unsigned int, std::map<unsigned int, unsigned int>>
texDupMap;
std::map<unsigned int, unsigned int> normalDupMap;
std::map<unsigned int, unsigned int> positionDupMap;

Expand Down Expand Up @@ -2034,8 +2037,17 @@ 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())
{
unsigned int set = 0u;
auto setStr = polylistInputXml->Attribute("set");
if (setStr)
set = ignition::math::parseInt(setStr);
this->LoadTexCoords(source, texcoords[set], texDupMap[set]);
inputs[TEXCOORD].insert(offsetInt);
texcoordsOffsetToSet[offsetInt] = set;
}
}
else
{
Expand Down Expand Up @@ -2153,16 +2165,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
Expand Down Expand Up @@ -2228,17 +2250,24 @@ 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[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
Expand Down Expand Up @@ -2293,7 +2322,8 @@ void ColladaLoaderPrivate::LoadTriangles(tinyxml2::XMLElement *_trianglesXml,

std::vector<ignition::math::Vector3d> verts;
std::vector<ignition::math::Vector3d> norms;
std::vector<ignition::math::Vector2d> texcoords;
std::map<unsigned int, std::vector<ignition::math::Vector2d>> texcoords;
std::map<unsigned int, unsigned int> texcoordsOffsetToSet;

const unsigned int VERTEX = 0;
const unsigned int NORMAL = 1;
Expand All @@ -2309,7 +2339,8 @@ void ColladaLoaderPrivate::LoadTriangles(tinyxml2::XMLElement *_trianglesXml,
std::map<const unsigned int, std::set<int>> inputs;

// look up table of position/normal/texcoord duplicate indices
std::map<unsigned int, unsigned int> texDupMap;
std::unordered_map<unsigned int, std::map<unsigned int, unsigned int>>
texDupMap;
std::map<unsigned int, unsigned int> normalDupMap;
std::map<unsigned int, unsigned int> positionDupMap;

Expand Down Expand Up @@ -2337,9 +2368,17 @@ 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 = 0u;
auto setStr = trianglesInputXml->Attribute("set");
if (setStr)
set = ignition::math::parseInt(setStr);
this->LoadTexCoords(source, texcoords[set], texDupMap[set]);
inputs[TEXCOORD].insert(offsetInt);
texcoordsOffsetToSet[offsetInt] = set;
}
hasTexcoords = true;
}
else
Expand Down Expand Up @@ -2451,16 +2490,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
Expand Down Expand Up @@ -2524,13 +2573,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
Expand Down
Loading