Skip to content

Commit

Permalink
common: support culling on/off in rasterization
Browse files Browse the repository at this point in the history
  • Loading branch information
cdcseacave committed Nov 8, 2023
1 parent 88765f6 commit b7adc80
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 44 deletions.
2 changes: 1 addition & 1 deletion libs/Common/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -2188,7 +2188,7 @@ class TImage : public TDMatrix<TYPE>

template <typename T, typename PARSER>
static void RasterizeTriangle(const TPoint2<T>& v1, const TPoint2<T>& v2, const TPoint2<T>& v3, PARSER& parser);
template <typename T, typename PARSER>
template <typename T, typename PARSER, bool CULL=true>
static void RasterizeTriangleBary(const TPoint2<T>& v1, const TPoint2<T>& v2, const TPoint2<T>& v3, PARSER& parser);
template <typename T, typename PARSER>
static void RasterizeTriangleDepth(TPoint3<T> p1, TPoint3<T> p2, TPoint3<T> p3, PARSER& parser);
Expand Down
14 changes: 8 additions & 6 deletions libs/Common/Types.inl
Original file line number Diff line number Diff line change
Expand Up @@ -2625,7 +2625,7 @@ void TImage<TYPE>::RasterizeTriangle(const TPoint2<T>& v1, const TPoint2<T>& v2,
// same as above, but raster a triangle using barycentric coordinates:
// https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation
template <typename TYPE>
template <typename T, typename PARSER>
template <typename T, typename PARSER, bool CULL>
void TImage<TYPE>::RasterizeTriangleBary(const TPoint2<T>& v1, const TPoint2<T>& v2, const TPoint2<T>& v3, PARSER& parser)
{
// compute bounding-box fully containing the triangle
Expand All @@ -2642,7 +2642,7 @@ void TImage<TYPE>::RasterizeTriangleBary(const TPoint2<T>& v1, const TPoint2<T>&
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);
Expand All @@ -2653,17 +2653,17 @@ void TImage<TYPE>::RasterizeTriangleBary(const TPoint2<T>& v1, const TPoint2<T>&
// 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<T>(b1, b2, b3) * invArea);
parser(pt, TPoint3<T>(b1, b2, b3));
}
}
}
Expand Down Expand Up @@ -3047,6 +3047,8 @@ bool TImage<TYPE>::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);
Expand Down
92 changes: 56 additions & 36 deletions libs/MVS/Mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1011,53 +1011,73 @@ 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

// 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
Expand Down
3 changes: 2 additions & 1 deletion libs/MVS/Mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit b7adc80

Please sign in to comment.