From 30012babbbd8386b67f6b1a3fa5ec6fa7b016888 Mon Sep 17 00:00:00 2001
From: Nicolas Pope <nwpope@utu.fi>
Date: Tue, 3 Nov 2020 09:54:20 +0200
Subject: [PATCH] Fix problem with normals

---
 components/operators/src/mls.cu             | 60 +++++++++++----------
 components/renderers/cpp/src/CUDARender.cpp | 22 ++++++++
 components/renderers/cpp/src/carver.cu      |  9 ++--
 3 files changed, 59 insertions(+), 32 deletions(-)

diff --git a/components/operators/src/mls.cu b/components/operators/src/mls.cu
index d677de67f..1293e6d9a 100644
--- a/components/operators/src/mls.cu
+++ b/components/operators/src/mls.cu
@@ -47,7 +47,7 @@ using ftl::cuda::TextureObject;
 		const float3 Ni = make_float3(normals_in.tex2D((int)(x)+u, (int)(y)+v));
 
 		// Gauss approx weighting function using point distance
-		const float w = ftl::cuda::spatialWeighting(X,Xi,smoothing);
+		const float w = (Ni.x+Ni.y+Ni.z == 0.0f) ? 0.0f : ftl::cuda::spatialWeighting(X,Xi,smoothing);
 
 		aX += Xi*w;
 		nX += Ni*w;
@@ -55,22 +55,24 @@ using ftl::cuda::TextureObject;
     }
 	}
 	
-	nX /= contrib;  // Weighted average normal
-	aX /= contrib;  // Weighted average point (centroid)
+	if (contrib > 0.0f) {
+		nX /= contrib;  // Weighted average normal
+		aX /= contrib;  // Weighted average point (centroid)
 
-	// Signed-Distance Field function
-	float fX = nX.x * (X.x - aX.x) + nX.y * (X.y - aX.y) + nX.z * (X.z - aX.z);
+		// Signed-Distance Field function
+		float fX = nX.x * (X.x - aX.x) + nX.y * (X.y - aX.y) + nX.z * (X.z - aX.z);
 
-	// Calculate new point using SDF function to adjust depth (and position)
-	X = X - nX * fX;
-	
-	//uint2 screen = camera.camToScreen<uint2>(X);
+		// Calculate new point using SDF function to adjust depth (and position)
+		X = X - nX * fX;
+		
+		//uint2 screen = camera.camToScreen<uint2>(X);
 
-    //if (screen.x < depth_out.width() && screen.y < depth_out.height()) {
-    //    depth_out(screen.x,screen.y) = X.z;
-	//}
-	depth_out(x,y) = X.z;
-	normals_out(x,y) = make_half4(nX / length(nX), 0.0f);
+		//if (screen.x < depth_out.width() && screen.y < depth_out.height()) {
+		//    depth_out(screen.x,screen.y) = X.z;
+		//}
+		depth_out(x,y) = X.z;
+		normals_out(x,y) = make_half4(nX / length(nX), 0.0f);
+	}
 }
 
 void ftl::cuda::mls_smooth(
@@ -137,7 +139,7 @@ void ftl::cuda::mls_smooth(
 		const float3 Ni = make_float3(normals_in.tex2D((int)(x)+u, (int)(y)+v));
 
 		// Gauss approx weighting function using point distance
-		const float w = ftl::cuda::spatialWeighting(X,Xi,smoothing);
+		const float w = (Ni.x+Ni.y+Ni.z == 0.0f) ? 0.0f : ftl::cuda::spatialWeighting(X,Xi,smoothing);
 
 		aX += Xi*w;
 		nX += Ni*w;
@@ -145,22 +147,24 @@ void ftl::cuda::mls_smooth(
     }
 	}
 	
-	nX /= contrib;  // Weighted average normal
-	aX /= contrib;  // Weighted average point (centroid)
+	if (contrib > 0.0f) {
+		nX /= contrib;  // Weighted average normal
+		aX /= contrib;  // Weighted average point (centroid)
 
-	// Signed-Distance Field function
-	float fX = nX.x * (X.x - aX.x) + nX.y * (X.y - aX.y) + nX.z * (X.z - aX.z);
+		// Signed-Distance Field function
+		float fX = nX.x * (X.x - aX.x) + nX.y * (X.y - aX.y) + nX.z * (X.z - aX.z);
 
-	// Calculate new point using SDF function to adjust depth (and position)
-	X = X - nX * fX;
-	
-	//uint2 screen = camera.camToScreen<uint2>(X);
+		// Calculate new point using SDF function to adjust depth (and position)
+		X = X - nX * fX;
+		
+		//uint2 screen = camera.camToScreen<uint2>(X);
 
-    //if (screen.x < depth_out.width() && screen.y < depth_out.height()) {
-    //    depth_out(screen.x,screen.y) = X.z;
-	//}
-	//depth_out(x,y) = X.z;
-	normals_out(x,y) = make_half4(nX / length(nX), 0.0f);
+		//if (screen.x < depth_out.width() && screen.y < depth_out.height()) {
+		//    depth_out(screen.x,screen.y) = X.z;
+		//}
+		//depth_out(x,y) = X.z;
+		normals_out(x,y) = make_half4(nX / length(nX), 0.0f);
+	}
 }
 
 void ftl::cuda::mls_smooth(
diff --git a/components/renderers/cpp/src/CUDARender.cpp b/components/renderers/cpp/src/CUDARender.cpp
index 6d6fccf6a..ec4a59239 100644
--- a/components/renderers/cpp/src/CUDARender.cpp
+++ b/components/renderers/cpp/src/CUDARender.cpp
@@ -508,6 +508,28 @@ void CUDARender::_mesh(ftl::rgbd::Frame &out, const Eigen::Matrix4d &t, cudaStre
 				params_.camera,
 				stream_
 			);
+
+			ftl::cuda::mls_smooth(
+				out.createTexture<half4>(_getNormalsChannel()),
+				temp_.createTexture<half4>(Channel::Normals),
+				out.getTexture<float>(_getDepthChannel()),
+				//out.getTexture<float>(_getDepthChannel()),
+				value("mls_smooth", 0.01f),
+				value("mls_radius", 2),
+				params_.camera,
+				stream_
+			);
+
+			ftl::cuda::mls_smooth(
+				temp_.createTexture<half4>(Channel::Normals),
+				out.createTexture<half4>(_getNormalsChannel()),
+				out.getTexture<float>(_getDepthChannel()),
+				//out.getTexture<float>(_getDepthChannel()),
+				value("mls_smooth", 0.01f),
+				value("mls_radius", 2),
+				params_.camera,
+				stream_
+			);
 		}
 	}
 
diff --git a/components/renderers/cpp/src/carver.cu b/components/renderers/cpp/src/carver.cu
index 12faea329..f804c1e27 100644
--- a/components/renderers/cpp/src/carver.cu
+++ b/components/renderers/cpp/src/carver.cu
@@ -221,13 +221,13 @@ void ftl::cuda::depth_carve(
 
 		// Point and normal of neighbour
 		const float3 Xi = in_2_o * camera_in.screenToCam(s.x+u, s.y+v, d);
-		const float3 Ni = in_2_o33 * make_float3(normals_in[s.x+u+(s.y+v)*npitch_in]);
+		const float3 Ni = make_float3(normals_in[s.x+u+(s.y+v)*npitch_in]);
 
 		// Gauss approx weighting function using point distance
-		const float w = (Ni.x+Ni.y+Ni.z > 0.0f) ? ftl::cuda::spatialWeighting(X,Xi,smoothing) : 0.0f;
+		const float w = (length(Ni) > 0.0f) ? ftl::cuda::spatialWeighting(X,Xi,smoothing) : 0.0f;
 
 		aX += Xi*w;
-		nX += Ni*w;
+		nX += (in_2_o33 * Ni)*w;
 		contrib += w;
     }
 	}
@@ -265,7 +265,8 @@ __global__ void mls_reduce_kernel(
 		normals_out[x+y*npitch] = make_half4(0.0f, 0.0f, 0.0f, 0.0f);
 
 		float d0 = depth[x+y*dpitch];
-		if (d0 < camera.minDepth || d0 > camera.maxDepth || contrib == 0.0f) return;
+		//depth[x+y*dpitch] = 0.0f;
+		if (d0 <= camera.minDepth || d0 >= camera.maxDepth || contrib == 0.0f) return;
 		float3 X = camera.screenToCam((int)(x),(int)(y),d0);
 		
 		nX /= contrib;  // Weighted average normal
-- 
GitLab