1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-31 08:13:04 +04:00

Merge pull request #25382 from savuor:rv/fix_mesh_load

Fix mesh loading for texture coordinates and face indices #25382

### This PR changes

* Texture coordinates were stored incorrectly (3-channel array is read as if there were 2 channels), fixed
* Faces were pushed back to the output array instead of indexed writing which produced a lot of empty faces, fixed
* A set of ground truth tests were added to cover these issues
* `std::vector<cv::Mat>` support added for `saveMesh()` which is required for Python bindings
* More command line args were added to rasterization test data generator

### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [x] There is a reference to the original bug report and related work
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
Rostislav Vasilikhin
2024-04-16 09:20:44 +02:00
committed by GitHub
parent 3e561d8353
commit 6699ca1a40
6 changed files with 320 additions and 163 deletions
+26 -31
View File
@@ -140,7 +140,7 @@ void loadMesh(const String &filename, OutputArray vertices, OutputArrayOfArrays
std::vector<std::vector<int32_t>> vec_indices;
std::vector<Point3f> vec_texCoords;
int nTexCoords;
int nTexCoords = 0;
decoder->readData(vec_vertices, vec_normals, vec_rgb, vec_texCoords, nTexCoords, vec_indices, 0);
@@ -210,32 +210,30 @@ void loadMesh(const String &filename, OutputArray vertices, OutputArrayOfArrays
if (texCoords.needed())
{
int ch = texCoords.empty() ? 0 : texCoords.channels();
Mat texMat = Mat(1, static_cast<int>(vec_texCoords.size()), CV_MAKETYPE(CV_32F, nTexCoords), vec_texCoords.data());
if (ch == nTexCoords)
if (nTexCoords)
{
texMat.copyTo(texCoords);
CV_Assert(!texCoords.fixedType() || (texCoords.type() == CV_MAKE_TYPE(CV_32F, nTexCoords)));
Mat tex3(vec_texCoords);
if (nTexCoords == 3)
{
tex3.copyTo(texCoords);
}
else if (nTexCoords == 2)
{
// if texCoords is empty then channels() can be any number
bool has3ch = texCoords.channels() == 3;
int ch = has3ch ? 3 : 2;
std::vector<int> permut = has3ch ? std::vector<int>{ 0, 0, 1, 1, -1, 2 } : std::vector<int>{ 0, 0, 1, 1 };
texCoords.createSameSize(vec_texCoords, CV_MAKE_TYPE(CV_32F, ch));
Mat out = texCoords.getMat();
cv::mixChannels(tex3, out, permut);
}
}
else
{
Mat newTexMat;
std::vector<Mat> varr;
cv::split(texMat, varr);
if (ch == 2 && nTexCoords == 3)
{
std::vector<Mat> marr = { varr[0], varr[1] };
cv::merge(marr, newTexMat);
}
else if (ch == 3 && nTexCoords == 2)
{
std::vector<Mat> marr = { varr[0], varr[1], Mat::zeros(varr[0].size(), CV_32F) };
cv::merge(marr, newTexMat);
}
else
{
newTexMat = texMat;
}
newTexMat.copyTo(texCoords);
texCoords.clear();
}
}
@@ -280,7 +278,8 @@ void saveMesh(const String &filename, InputArray vertices, InputArrayOfArrays in
std::vector<std::vector<int32_t>> vec_indices;
CV_Assert(indices.depth() == CV_32S);
if (indices.kind() == _InputArray::KindFlag::STD_VECTOR_VECTOR)
if (indices.kind() == _InputArray::KindFlag::STD_VECTOR_VECTOR ||
indices.kind() == _InputArray::KindFlag::STD_VECTOR_MAT)
{
std::vector<Mat> mat_indices;
indices.getMatVector(mat_indices);
@@ -312,13 +311,9 @@ void saveMesh(const String &filename, InputArray vertices, InputArrayOfArrays in
}
if (nTexCoords == 2)
{
std::vector<Point2f> vec2_texCoords;
texCoords.copyTo(vec2_texCoords);
for (size_t i = 0; i < vec2_texCoords.size(); i++)
{
Point2f p = vec2_texCoords[i];
vec_texCoords.push_back({p.x, p.y, 0});
}
// extend by 3rd zero channel
vec_texCoords.resize(texCoords.total());
cv::mixChannels(texCoords, vec_texCoords, {0, 0, 1, 1, -1, 2});
}
if (nTexCoords == 3)
{