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:
committed by
GitHub
parent
3e561d8353
commit
6699ca1a40
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user