Skip to content

Commit

Permalink
mesh: make TRasterMesh multithread-safe
Browse files Browse the repository at this point in the history
(cherry picked from commit bbfae87948dc0fa128b1a42c040c5d5e58e4ec0c)
  • Loading branch information
cdcseacave committed Nov 8, 2024
1 parent 9609fd9 commit 384da63
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 72 deletions.
39 changes: 21 additions & 18 deletions libs/MVS/DepthMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1107,18 +1107,17 @@ bool MVS::TriangulatePoints2DepthMap(
// rasterize triangles onto depthmap
struct RasterDepth : TRasterMeshBase<RasterDepth> {
typedef TRasterMeshBase<RasterDepth> Base;
using Base::Triangle;
using Base::camera;
using Base::depthMap;
using Base::ptc;
using Base::pti;
const Mesh::NormalArr& vertexNormals;
NormalMap& normalMap;
Mesh::Face face;
RasterDepth(const Mesh::NormalArr& _vertexNormals, const Camera& _camera, DepthMap& _depthMap, NormalMap& _normalMap)
: Base(_camera, _depthMap), vertexNormals(_vertexNormals), normalMap(_normalMap) {}
inline void operator()(const ImageRef& pt, const Point3f& bary) {
const Point3f pbary(PerspectiveCorrectBarycentricCoordinates(bary));
const Depth z(ComputeDepth(pbary));
inline void Raster(const ImageRef& pt, const Triangle& t, const Point3f& bary) {
const Point3f pbary(PerspectiveCorrectBarycentricCoordinates(t, bary));
const Depth z(ComputeDepth(t, pbary));
ASSERT(z > Depth(0));
depthMap(pt) = z;
normalMap(pt) = normalized(
Expand All @@ -1128,16 +1127,18 @@ bool MVS::TriangulatePoints2DepthMap(
);
}
};
RasterDepth rasterer = {mesh.vertexNormals, camera, depthMap, normalMap};
RasterDepth rasterer {mesh.vertexNormals, camera, depthMap, normalMap};
RasterDepth::Triangle triangle;
RasterDepth::TriangleRasterizer triangleRasterizer(triangle, rasterer);
for (const Mesh::Face& face : mesh.faces) {
rasterer.face = face;
rasterer.ptc[0].z = mesh.vertices[face[0]].z;
rasterer.ptc[1].z = mesh.vertices[face[1]].z;
rasterer.ptc[2].z = mesh.vertices[face[2]].z;
triangle.ptc[0].z = mesh.vertices[face[0]].z;
triangle.ptc[1].z = mesh.vertices[face[1]].z;
triangle.ptc[2].z = mesh.vertices[face[2]].z;
Image8U::RasterizeTriangleBary(
projs[face[0]],
projs[face[1]],
projs[face[2]], rasterer);
projs[face[2]], triangleRasterizer);
}
}
return true;
Expand Down Expand Up @@ -1181,22 +1182,24 @@ bool MVS::TriangulatePoints2DepthMap(
using Base::depthMap;
RasterDepth(const Camera& _camera, DepthMap& _depthMap)
: Base(_camera, _depthMap) {}
inline void operator()(const ImageRef& pt, const Point3f& bary) {
const Point3f pbary(PerspectiveCorrectBarycentricCoordinates(bary));
const Depth z(ComputeDepth(pbary));
inline void Raster(const ImageRef& pt, const Triangle& t, const Point3f& bary) {
const Point3f pbary(PerspectiveCorrectBarycentricCoordinates(t, bary));
const Depth z(ComputeDepth(t, pbary));
ASSERT(z > Depth(0));
depthMap(pt) = z;
}
};
RasterDepth rasterer = {camera, depthMap};
RasterDepth rasterer {camera, depthMap};
RasterDepth::Triangle triangle;
RasterDepth::TriangleRasterizer triangleRasterizer(triangle, rasterer);
for (const Mesh::Face& face : mesh.faces) {
rasterer.ptc[0].z = mesh.vertices[face[0]].z;
rasterer.ptc[1].z = mesh.vertices[face[1]].z;
rasterer.ptc[2].z = mesh.vertices[face[2]].z;
triangle.ptc[0].z = mesh.vertices[face[0]].z;
triangle.ptc[1].z = mesh.vertices[face[1]].z;
triangle.ptc[2].z = mesh.vertices[face[2]].z;
Image8U::RasterizeTriangleBary(
projs[face[0]],
projs[face[1]],
projs[face[2]], rasterer);
projs[face[2]], triangleRasterizer);
}
}
return true;
Expand Down
56 changes: 33 additions & 23 deletions libs/MVS/Mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4078,9 +4078,11 @@ void Mesh::Project(const Camera& camera, DepthMap& depthMap) const
: Base(_vertices, _camera, _depthMap) {}
};
RasterMesh rasterer(vertices, camera, depthMap);
RasterMesh::Triangle triangle;
RasterMesh::TriangleRasterizer triangleRasterizer(triangle, rasterer);
rasterer.Clear();
for (const Face& facet: faces)
rasterer.Project(facet);
rasterer.Project(facet, triangleRasterizer);
}
void Mesh::Project(const Camera& camera, DepthMap& depthMap, Image8U3& image) const
{
Expand All @@ -4097,9 +4099,9 @@ void Mesh::Project(const Camera& camera, DepthMap& depthMap, Image8U3& image) co
Base::Clear();
image.memset(0);
}
void Raster(const ImageRef& pt, const Point3f& bary) {
const Point3f pbary(PerspectiveCorrectBarycentricCoordinates(bary));
const Depth z(ComputeDepth(pbary));
void Raster(const ImageRef& pt, const Triangle& t, const Point3f& bary) {
const Point3f pbary(PerspectiveCorrectBarycentricCoordinates(t, bary));
const Depth z(ComputeDepth(t, pbary));
ASSERT(z > Depth(0));
Depth& depth = depthMap(pt);
if (depth == 0 || depth > z) {
Expand All @@ -4115,11 +4117,13 @@ void Mesh::Project(const Camera& camera, DepthMap& depthMap, Image8U3& image) co
if (image.size() != depthMap.size())
image.create(depthMap.size());
RasterMesh rasterer(*this, camera, depthMap, image);
RasterMesh::Triangle triangle;
RasterMesh::TriangleRasterizer triangleRasterizer(triangle, rasterer);
rasterer.Clear();
FOREACH(idxFace, faces) {
const Face& facet = faces[idxFace];
rasterer.idxFaceTex = idxFace*3;
rasterer.Project(facet);
rasterer.Project(facet, triangleRasterizer);
}
}
// project mesh to the given camera plane, computing also the normal-map (in camera space)
Expand All @@ -4138,13 +4142,13 @@ void Mesh::Project(const Camera& camera, DepthMap& depthMap, NormalMap& normalMa
Base::Clear();
normalMap.memset(0);
}
inline void Project(const Face& facet) {
inline void Project(const Face& facet, TriangleRasterizer& tr) {
idxVerts = facet.ptr();
Base::Project(facet);
Base::Project(facet, tr);
}
void Raster(const ImageRef& pt, const Point3f& bary) {
const Point3f pbary(PerspectiveCorrectBarycentricCoordinates(bary));
const Depth z(ComputeDepth(pbary));
void Raster(const ImageRef& pt, const Triangle& t, const Point3f& bary) {
const Point3f pbary(PerspectiveCorrectBarycentricCoordinates(t, bary));
const Depth z(ComputeDepth(t, pbary));
ASSERT(z > Depth(0));
Depth& depth = depthMap(pt);
if (depth == Depth(0) || depth > z) {
Expand All @@ -4160,10 +4164,12 @@ void Mesh::Project(const Camera& camera, DepthMap& depthMap, NormalMap& normalMa
if (normalMap.size() != depthMap.size())
normalMap.create(depthMap.size());
RasterMesh rasterer(*this, camera, depthMap, normalMap);
RasterMesh::Triangle triangle;
RasterMesh::TriangleRasterizer triangleRasterizer(triangle, rasterer);
rasterer.Clear();
// render the entire mesh
for (const Face& facet: faces)
rasterer.Project(facet);
rasterer.Project(facet, triangleRasterizer);
}
// project mesh to the given camera plane using orthographic projection
void Mesh::ProjectOrtho(const Camera& camera, DepthMap& depthMap) const
Expand All @@ -4172,22 +4178,24 @@ void Mesh::ProjectOrtho(const Camera& camera, DepthMap& depthMap) const
typedef TRasterMesh<RasterMesh> Base;
RasterMesh(const VertexArr& _vertices, const Camera& _camera, DepthMap& _depthMap)
: Base(_vertices, _camera, _depthMap) {}
inline bool ProjectVertex(const Mesh::Vertex& pt, int v) {
return (ptc[v] = camera.TransformPointW2C(Cast<REAL>(pt))).z > 0 &&
depthMap.isInsideWithBorder<float,3>(pti[v] = camera.TransformPointOrthoC2I(ptc[v]));
inline bool ProjectVertex(const Mesh::Vertex& pt, int v, Triangle& t) {
return (t.ptc[v] = camera.TransformPointW2C(Cast<REAL>(pt))).z > 0 &&
depthMap.isInsideWithBorder<float,3>(t.pti[v] = camera.TransformPointOrthoC2I(t.ptc[v]));
}
void Raster(const ImageRef& pt, const Point3f& bary) {
const Depth z(ComputeDepth(bary));
void Raster(const ImageRef& pt, const Triangle& t, const Point3f& bary) {
const Depth z(ComputeDepth(t, bary));
ASSERT(z > Depth(0));
Depth& depth = depthMap(pt);
if (depth == 0 || depth > z)
depth = z;
}
};
RasterMesh rasterer(vertices, camera, depthMap);
RasterMesh::Triangle triangle;
RasterMesh::TriangleRasterizer triangleRasterizer(triangle, rasterer);
rasterer.Clear();
for (const Face& facet: faces)
rasterer.Project(facet);
rasterer.Project(facet, triangleRasterizer);
}
void Mesh::ProjectOrtho(const Camera& camera, DepthMap& depthMap, Image8U3& image) const
{
Expand All @@ -4204,12 +4212,12 @@ void Mesh::ProjectOrtho(const Camera& camera, DepthMap& depthMap, Image8U3& imag
Base::Clear();
image.memset(0);
}
inline bool ProjectVertex(const Mesh::Vertex& pt, int v) {
return (ptc[v] = camera.TransformPointW2C(Cast<REAL>(pt))).z > 0 &&
depthMap.isInsideWithBorder<float,3>(pti[v] = camera.TransformPointOrthoC2I(ptc[v]));
inline bool ProjectVertex(const Mesh::Vertex& pt, int v, Triangle& t) {
return (t.ptc[v] = camera.TransformPointW2C(Cast<REAL>(pt))).z > 0 &&
depthMap.isInsideWithBorder<float,3>(t.pti[v] = camera.TransformPointOrthoC2I(t.ptc[v]));
}
void Raster(const ImageRef& pt, const Point3f& bary) {
const Depth z(ComputeDepth(bary));
void Raster(const ImageRef& pt, const Triangle& t, const Point3f& bary) {
const Depth z(ComputeDepth(t, bary));
ASSERT(z > Depth(0));
Depth& depth = depthMap(pt);
if (depth == 0 || depth > z) {
Expand All @@ -4225,11 +4233,13 @@ void Mesh::ProjectOrtho(const Camera& camera, DepthMap& depthMap, Image8U3& imag
if (image.size() != depthMap.size())
image.create(depthMap.size());
RasterMesh rasterer(*this, camera, depthMap, image);
RasterMesh::Triangle triangle;
RasterMesh::TriangleRasterizer triangleRasterizer(triangle, rasterer);
rasterer.Clear();
FOREACH(idxFace, faces) {
const Face& facet = faces[idxFace];
rasterer.idxFaceTex = idxFace*3;
rasterer.Project(facet);
rasterer.Project(facet, triangleRasterizer);
}
}
// assuming the mesh is properly oriented, ortho-project it to a camera looking from top to down
Expand Down
62 changes: 40 additions & 22 deletions libs/MVS/Mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -287,13 +287,16 @@ class MVS_API Mesh
// used to render a 3D triangle
template <typename DERIVED>
struct TRasterMeshBase {
const Camera& camera;
typedef DERIVED Rasterizer;

struct Triangle {
Point3 ptc[3];
Point2f pti[3];
};

const Camera& camera;
DepthMap& depthMap;

Point3 ptc[3];
Point2f pti[3];

TRasterMeshBase(const Camera& _camera, DepthMap& _depthMap)
: camera(_camera), depthMap(_depthMap) {}

Expand All @@ -304,55 +307,70 @@ struct TRasterMeshBase {
return depthMap.size();
}

inline bool ProjectVertex(const Point3f& pt, int v) {
return (ptc[v] = camera.TransformPointW2C(Cast<REAL>(pt))).z > 0 &&
depthMap.isInsideWithBorder<float,3>(pti[v] = camera.TransformPointC2I(ptc[v]));
inline bool ProjectVertex(const Point3f& pt, int v, Triangle& t) {
return (t.ptc[v] = camera.TransformPointW2C(Cast<REAL>(pt))).z > 0 &&
depthMap.isInsideWithBorder<float,3>(t.pti[v] = camera.TransformPointC2I(t.ptc[v]));
}

inline Point3f PerspectiveCorrectBarycentricCoordinates(const Point3f& bary) {
return SEACAVE::PerspectiveCorrectBarycentricCoordinates(bary, (float)ptc[0].z, (float)ptc[1].z, (float)ptc[2].z);
inline Point3f PerspectiveCorrectBarycentricCoordinates(const Triangle& t, const Point3f& bary) {
return SEACAVE::PerspectiveCorrectBarycentricCoordinates(bary, (float)t.ptc[0].z, (float)t.ptc[1].z, (float)t.ptc[2].z);
}
inline float ComputeDepth(const Point3f& pbary) {
return pbary[0]*(float)ptc[0].z + pbary[1]*(float)ptc[1].z + pbary[2]*(float)ptc[2].z;
inline float ComputeDepth(const Triangle& t, const Point3f& pbary) {
return pbary[0]*(float)t.ptc[0].z + pbary[1]*(float)t.ptc[1].z + pbary[2]*(float)t.ptc[2].z;
}
void Raster(const ImageRef& pt, const Point3f& bary) {
const Point3f pbary(PerspectiveCorrectBarycentricCoordinates(bary));
const Depth z(ComputeDepth(pbary));
void Raster(const ImageRef& pt, const Triangle& t, const Point3f& bary) {
const Point3f pbary(PerspectiveCorrectBarycentricCoordinates(t, bary));
const Depth z(ComputeDepth(t, pbary));
ASSERT(z > Depth(0));
Depth& depth = depthMap(pt);
if (depth == 0 || depth > z)
depth = z;
}
inline void operator()(const ImageRef& pt, const Point3f& bary) {
static_cast<DERIVED*>(this)->Raster(pt, bary);

struct TriangleRasterizer {
Triangle& triangle;
Rasterizer& rasterizer;
TriangleRasterizer(Triangle& t, Rasterizer& r) : triangle(t), rasterizer(r) {}
inline cv::Size Size() const {
return rasterizer.Size();
}
inline void operator()(const ImageRef& pt, const Point3f& bary) const {
rasterizer.Raster(pt, triangle, bary);
}
};
inline TriangleRasterizer CreateTriangleRasterizer(Triangle& triangle) {
return TriangleRasterizer(triangle, *static_cast<DERIVED*>(this));
}
};

// used to render a mesh
template <typename DERIVED>
struct TRasterMesh : TRasterMeshBase<DERIVED> {
typedef TRasterMeshBase<DERIVED> Base;
using typename Base::Triangle;
using typename Base::TriangleRasterizer;

using Base::camera;
using Base::depthMap;

using Base::ptc;
using Base::pti;

const Mesh::VertexArr& vertices;

TRasterMesh(const Mesh::VertexArr& _vertices, const Camera& _camera, DepthMap& _depthMap)
: Base(_camera, _depthMap), vertices(_vertices) {}

void Project(const Mesh::Face& facet) {
void Project(const Mesh::Face& facet, TriangleRasterizer& tr) {
// project face vertices to image plane
for (int v=0; v<3; ++v) {
// skip face if not completely inside
if (!static_cast<DERIVED*>(this)->ProjectVertex(vertices[facet[v]], v))
if (!static_cast<DERIVED*>(this)->ProjectVertex(vertices[facet[v]], v, tr.triangle))
return;
}
// draw triangle
Image8U3::RasterizeTriangleBary(pti[0], pti[1], pti[2], *this);
Image8U3::RasterizeTriangleBary(tr.triangle.pti[0], tr.triangle.pti[1], tr.triangle.pti[2], tr);
}
void Project(const Mesh::Face& facet) {
Triangle triangle;
Project(facet, this->CreateTriangleRasterizer(triangle));
}
};
/*----------------------------------------------------------------*/
Expand Down
10 changes: 6 additions & 4 deletions libs/MVS/SceneRefine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,9 @@ class MeshRefine {
faceMap.memset((uint8_t)NO_ID);
baryMap.memset(0);
}
void Raster(const ImageRef& pt, const Point3f& bary) {
const Point3f pbary(PerspectiveCorrectBarycentricCoordinates(bary));
const Depth z(ComputeDepth(pbary));
void Raster(const ImageRef& pt, const Triangle& t, const Point3f& bary) {
const Point3f pbary(PerspectiveCorrectBarycentricCoordinates(t, bary));
const Depth z(ComputeDepth(t, pbary));
ASSERT(z > Depth(0));
Depth& depth = depthMap(pt);
if (depth == 0 || depth > z) {
Expand Down Expand Up @@ -734,11 +734,13 @@ void MeshRefine::ProjectMesh(
baryMap.create(size);
// project all triangles on this image and keep the closest ones
RasterMesh rasterer(vertices, camera, depthMap, faceMap, baryMap);
RasterMesh::Triangle triangle;
RasterMesh::TriangleRasterizer triangleRasterizer(triangle, rasterer);
rasterer.Clear();
for (auto idxFace : cameraFaces) {
const Face& facet = faces[idxFace];
rasterer.idxFace = idxFace;
rasterer.Project(facet);
rasterer.Project(facet, triangleRasterizer);
}
}

Expand Down
12 changes: 7 additions & 5 deletions libs/MVS/SceneTexture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,9 @@ struct MeshTexture {
Base::Clear();
faceMap.memset((uint8_t)NO_ID);
}
void Raster(const ImageRef& pt, const Point3f& bary) {
const Point3f pbary(PerspectiveCorrectBarycentricCoordinates(bary));
const Depth z(ComputeDepth(pbary));
void Raster(const ImageRef& pt, const Triangle& t, const Point3f& bary) {
const Point3f pbary(PerspectiveCorrectBarycentricCoordinates(t, bary));
const Depth z(ComputeDepth(t, pbary));
ASSERT(z > Depth(0));
Depth& depth = depthMap(pt);
if (depth == 0 || depth > z) {
Expand Down Expand Up @@ -496,6 +496,8 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr
faceMap.create(imageData.GetSize());
depthMap.create(imageData.GetSize());
RasterMesh rasterer(vertices, imageData.camera, depthMap, faceMap);
RasterMesh::Triangle triangle;
RasterMesh::TriangleRasterizer triangleRasterizer(triangle, rasterer);
if (nIgnoreMaskLabel >= 0) {
// import mask
BitMatrix bmask;
Expand All @@ -513,9 +515,9 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr
rasterer.validFace = true;
const Face& facet = faces[idxFace];
rasterer.idxFace = idxFace;
rasterer.Project(facet);
rasterer.Project(facet, triangleRasterizer);
if (!rasterer.validFace)
rasterer.Project(facet);
rasterer.Project(facet, triangleRasterizer);
}
// compute the projection area of visible faces
#if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA
Expand Down

0 comments on commit 384da63

Please sign in to comment.