diff --git a/libs/Common/Types.h b/libs/Common/Types.h index 6d27cbc34..0047424a6 100644 --- a/libs/Common/Types.h +++ b/libs/Common/Types.h @@ -2188,7 +2188,7 @@ class TImage : public TDMatrix template static void RasterizeTriangle(const TPoint2& v1, const TPoint2& v2, const TPoint2& v3, PARSER& parser); - template + template static void RasterizeTriangleBary(const TPoint2& v1, const TPoint2& v2, const TPoint2& v3, PARSER& parser); template static void RasterizeTriangleDepth(TPoint3 p1, TPoint3 p2, TPoint3 p3, PARSER& parser); diff --git a/libs/Common/Types.inl b/libs/Common/Types.inl index 5854e337f..f2fdb27b2 100644 --- a/libs/Common/Types.inl +++ b/libs/Common/Types.inl @@ -2625,7 +2625,7 @@ void TImage::RasterizeTriangle(const TPoint2& v1, const TPoint2& v2, // same as above, but raster a triangle using barycentric coordinates: // https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation template -template +template void TImage::RasterizeTriangleBary(const TPoint2& v1, const TPoint2& v2, const TPoint2& v3, PARSER& parser) { // compute bounding-box fully containing the triangle @@ -2642,7 +2642,7 @@ void TImage::RasterizeTriangleBary(const TPoint2& v1, const TPoint2& Base::clip(boxMinI, boxMaxI, size); // ignore back oriented triangles (negative area) const T area(EdgeFunction(v1, v2, v3)); - if (area <= 0) + if (CULL && area <= 0) return; // parse all pixels inside the bounding-box const T invArea(T(1) / area); @@ -2653,17 +2653,17 @@ void TImage::RasterizeTriangleBary(const TPoint2& v1, const TPoint2& // discard point if not in triangle; // testing only for negative barycentric coordinates // guarantees all will be in [0,1] at the end of all checks - const T b1(EdgeFunction(v2, v3, p)); + const T b1(EdgeFunction(v2, v3, p) * invArea); if (b1 < 0) continue; - const T b2(EdgeFunction(v3, v1, p)); + const T b2(EdgeFunction(v3, v1, p) * invArea); if (b2 < 0) continue; - const T b3(EdgeFunction(v1, v2, p)); + const T b3(EdgeFunction(v1, v2, p) * invArea); if (b3 < 0) continue; // output pixel - parser(pt, TPoint3(b1, b2, b3) * invArea); + parser(pt, TPoint3(b1, b2, b3)); } } } @@ -3047,6 +3047,8 @@ bool TImage::Load(const String& fileName) cv::cvtColor(img, img, cv::COLOR_BGRA2GRAY); else if (img.channels() == 1 && Base::channels() == 4) cv::cvtColor(img, img, cv::COLOR_GRAY2BGRA); + else if (img.channels() == 4 && Base::channels() == 3) + cv::cvtColor(img, img, cv::COLOR_BGRA2BGR); } if (img.type() == Base::type()) cv::swap(img, *this); diff --git a/libs/MVS/Mesh.cpp b/libs/MVS/Mesh.cpp index a479c5e33..fb582abf0 100644 --- a/libs/MVS/Mesh.cpp +++ b/libs/MVS/Mesh.cpp @@ -1011,26 +1011,36 @@ static const Mesh::TexCoord halfPixel(0.5f, 0.5f); // translate, normalize and flip Y axis of the texture coordinates void Mesh::FaceTexcoordsNormalize(TexCoordArr& newFaceTexcoords, bool flipY) const { - ASSERT(HasTexture()); - TexCoordArr invNorms(texturesDiffuse.size()); - FOREACH(i, texturesDiffuse) { - ASSERT(!texturesDiffuse[i].empty()); - invNorms[i] = TexCoord(1.f/(float)texturesDiffuse[i].cols, 1.f/(float)texturesDiffuse[i].rows); - } + ASSERT(HasTextureCoordinates()); newFaceTexcoords.resize(faceTexcoords.size()); - if (flipY) { - FOREACH(i, faceTexcoords) { - const TexCoord& texcoord = faceTexcoords[i]; - const TexCoord& invNorm = invNorms[GetFaceTextureIndex(i/3)]; - newFaceTexcoords[i] = TexCoord( - (texcoord.x+halfPixel.x)*invNorm.x, - 1.f-(texcoord.y+halfPixel.y)*invNorm.y - ); - } + if (texturesDiffuse.empty()) { + if (flipY) { + FOREACH(i, faceTexcoords) { + const TexCoord& texcoord = faceTexcoords[i]; + newFaceTexcoords[i] = TexCoord(texcoord.x, 1.f-texcoord.y); + } + } else + newFaceTexcoords = faceTexcoords; } else { - FOREACH(i, faceTexcoords) { - const TexCoord& invNorm = invNorms[GetFaceTextureIndex(i/3)]; - newFaceTexcoords[i] = (faceTexcoords[i]+halfPixel)*invNorm; + TexCoordArr invNorms(texturesDiffuse.size()); + FOREACH(i, texturesDiffuse) { + ASSERT(!texturesDiffuse[i].empty()); + invNorms[i] = TexCoord(1.f/(float)texturesDiffuse[i].cols, 1.f/(float)texturesDiffuse[i].rows); + } + if (flipY) { + FOREACH(i, faceTexcoords) { + const TexCoord& texcoord = faceTexcoords[i]; + const TexCoord& invNorm = invNorms[GetFaceTextureIndex(i/3)]; + newFaceTexcoords[i] = TexCoord( + (texcoord.x+halfPixel.x)*invNorm.x, + 1.f-(texcoord.y+halfPixel.y)*invNorm.y + ); + } + } else { + FOREACH(i, faceTexcoords) { + const TexCoord& invNorm = invNorms[GetFaceTextureIndex(i/3)]; + newFaceTexcoords[i] = (faceTexcoords[i]+halfPixel)*invNorm; + } } } } // FaceTexcoordsNormalize @@ -1038,26 +1048,36 @@ void Mesh::FaceTexcoordsNormalize(TexCoordArr& newFaceTexcoords, bool flipY) con // flip Y axis, unnormalize and translate back texture coordinates void Mesh::FaceTexcoordsUnnormalize(TexCoordArr& newFaceTexcoords, bool flipY) const { - ASSERT(HasTexture()); - TexCoordArr scales(texturesDiffuse.size()); - FOREACH(i, texturesDiffuse) { - ASSERT(!texturesDiffuse[i].empty()); - scales[i] = TexCoord((float)texturesDiffuse[i].cols, (float)texturesDiffuse[i].rows); - } + ASSERT(HasTextureCoordinates()); newFaceTexcoords.resize(faceTexcoords.size()); - if (flipY) { - FOREACH(i, faceTexcoords) { - const TexCoord& texcoord = faceTexcoords[i]; - const TexCoord& scale = scales[GetFaceTextureIndex(i/3)]; - newFaceTexcoords[i] = TexCoord( - texcoord.x*scale.x-halfPixel.x, - (1.f-texcoord.y)*scale.y-halfPixel.y - ); - } + if (texturesDiffuse.empty()) { + if (flipY) { + FOREACH(i, faceTexcoords) { + const TexCoord& texcoord = faceTexcoords[i]; + newFaceTexcoords[i] = TexCoord(texcoord.x, 1.f-texcoord.y); + } + } else + newFaceTexcoords = faceTexcoords; } else { - FOREACH(i, faceTexcoords) { - const TexCoord& scale = scales[GetFaceTextureIndex(i/3)]; - newFaceTexcoords[i] = faceTexcoords[i]*scale - halfPixel; + TexCoordArr scales(texturesDiffuse.size()); + FOREACH(i, texturesDiffuse) { + ASSERT(!texturesDiffuse[i].empty()); + scales[i] = TexCoord((float)texturesDiffuse[i].cols, (float)texturesDiffuse[i].rows); + } + if (flipY) { + FOREACH(i, faceTexcoords) { + const TexCoord& texcoord = faceTexcoords[i]; + const TexCoord& scale = scales[GetFaceTextureIndex(i/3)]; + newFaceTexcoords[i] = TexCoord( + texcoord.x*scale.x-halfPixel.x, + (1.f-texcoord.y)*scale.y-halfPixel.y + ); + } + } else { + FOREACH(i, faceTexcoords) { + const TexCoord& scale = scales[GetFaceTextureIndex(i/3)]; + newFaceTexcoords[i] = faceTexcoords[i]*scale - halfPixel; + } } } } // FaceTexcoordsUnnormalize diff --git a/libs/MVS/Mesh.h b/libs/MVS/Mesh.h index 5298e132f..5f14e8f5c 100644 --- a/libs/MVS/Mesh.h +++ b/libs/MVS/Mesh.h @@ -154,7 +154,8 @@ class MVS_API Mesh void Join(const Mesh&); bool IsEmpty() const { return vertices.empty(); } bool IsWatertight(); - bool HasTexture() const { ASSERT(faces.size()*3 == faceTexcoords.size() || vertices.size() == faceTexcoords.size()); return !faceTexcoords.empty() && !texturesDiffuse.empty(); } + bool HasTexture() const { return HasTextureCoordinates() && !texturesDiffuse.empty(); } + bool HasTextureCoordinates() const { ASSERT(faces.size()*3 == faceTexcoords.size() || vertices.size() == faceTexcoords.size()); return !faceTexcoords.empty(); } bool HasTextureCoordinatesPerVertex() const { return !faceTexcoords.empty() && vertices.size() == faceTexcoords.size(); } Box GetAABB() const;