Jelajahi Sumber

Fixing normals on mesh loader

Panagiotis Christopoulos Charitos 13 tahun lalu
induk
melakukan
68736bc33a

+ 11 - 0
include/anki/gl/Fbo.h

@@ -71,6 +71,17 @@ public:
 	void setOtherAttachment(GLenum attachment, const Texture& tex, 
 		const I32 layer = -1, const I32 face = -1);
 
+	/// Blit framebuffer
+	void blit(const Fbo& source, U32 srcX0, U32 srcY0, U32 srcX1, U32 srcY1, 
+		U32 dstX0, U32 dstY0, U32 dstX1, U32 dstY1, GLbitfield mask,
+		GLenum filter)
+	{
+		source.bind(FT_READ);
+		bind(FT_DRAW);
+		glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, 
+			dstY1, mask, filter);
+	}
+
 	/// Creates a new FBO
 	void create();
 

+ 7 - 0
include/anki/resource/MeshLoader.h

@@ -42,6 +42,10 @@ namespace anki {
 class MeshLoader
 {
 public:
+	/// If two vertices have the same position and normals under the angle 
+	/// specified by this constant then combine those normals
+	static constexpr F32 NORMALS_ANGLE_MERGE = getPi<F32>() / 6.0;
+
 	/// Vertex weight for skeletal animation
 	struct VertexWeight
 	{
@@ -182,6 +186,9 @@ private:
 	/// tangents, VBOs etc
 	/// @exception Exception
 	void doPostLoad();
+
+	/// It iterates all verts and fixes the normals on seams
+	void fixNormals();
 };
 
 } // end namespace anki

+ 1 - 3
src/renderer/Ssao.cpp

@@ -177,9 +177,7 @@ void Ssao::run()
 	// Blit from main pass FBO to vertical pass FBO
 	if(blit())
 	{
-		mpFbo.bind(Fbo::FT_READ);
-		vblurFbo.bind(Fbo::FT_DRAW);
-		glBlitFramebuffer(
+		vblurFbo.blit(mpFbo,
 			0, 0, mpWidth, mpHeight,
 			0, 0, bWidth, bHeight,
 			GL_COLOR_BUFFER_BIT, GL_LINEAR);

+ 36 - 0
src/resource/MeshLoader.cpp

@@ -145,6 +145,7 @@ void MeshLoader::doPostLoad()
 	}
 
 	createAllNormals();
+	fixNormals();
 	if(texCoords.size() > 0)
 	{
 		createVertTangents();
@@ -266,4 +267,39 @@ void MeshLoader::createVertTangents()
 	}
 }
 
+//==============================================================================
+void MeshLoader::fixNormals()
+{
+	const F32 positionsDistanceThresh = getEpsilon<F32>() * getEpsilon<F32>();
+	const F32 normalsDotThresh = cos(NORMALS_ANGLE_MERGE);
+
+	for(U i = 1; i < vertCoords.size(); i++)
+	{
+		const Vec3& crntPos = vertCoords[i];
+		Vec3& crntNormal = vertNormals[i];
+
+		// Check the previous
+		for(U j = 0; j < i; j++)
+		{
+			const Vec3& otherPos = vertCoords[j];
+			Vec3& otherNormal = vertNormals[j];
+
+			F32 distanceSq = crntPos.getDistanceSquared(otherPos);
+
+			if(distanceSq <= positionsDistanceThresh)
+			{
+				F32 dot = crntNormal.dot(otherNormal);
+
+				if(dot <= normalsDotThresh)
+				{
+					Vec3 newNormal = (crntNormal + otherNormal) * 0.5;
+					newNormal.normalize();
+
+					newNormal = otherNormal = newNormal;
+				}
+			}
+		}
+	}
+}
+
 } // end namespace anki