0
我需要在C#中的两个模型之间执行布尔减法。其中一个网格完全位于另一个网格内,所以我希望能够扭转一个模型的法线并将两个模型相加。尽管如此,我仍然对如何改变法线方向感到迷茫。C#翻转曲面法线
这是我如何计算的表面法线:
//creates surface normals
Vector3D CalculateSurfaceNormal(Point3D p1, Point3D p2, Point3D p3)
{
Vector3D v1 = new Vector3D(0, 0, 0); // Vector 1 (x,y,z) & Vector 2 (x,y,z)
Vector3D v2 = new Vector3D(0, 0, 0);
Vector3D normal = new Vector3D(0, 0, 0);
// Finds The Vector Between 2 Points By Subtracting
// The x,y,z Coordinates From One Point To Another.
// Calculate The Vector From Point 2 To Point 1
v1.X = p1.X - p2.X;
v1.Y = p1.Y - p2.Y;
v1.Z = p1.Z - p2.Z;
// Calculate The Vector From Point 3 To Point 2
v2.X = p2.X - p3.X;
v2.Y = p2.Y - p3.Y;
v2.Z = p2.Z - p3.Z;
// Compute The Cross Product To Give Us A Surface Normal
normal.X = v1.Y * v2.Z - v1.Z * v2.Y; // Cross Product For Y - Z
normal.Y = v1.Z * v2.X - v1.X * v2.Z; // Cross Product For X - Z
normal.Z = v1.X * v2.Y - v1.Y * v2.X; // Cross Product For X - Y
normal.Normalize();
return normal;
}
我被告知通过否定它扭转了正常:
n = CalculateSurfaceNormal(p1, p2, p3);
n = new Vector3D(-1 * n.X, -1 * n.Y, -1 * n.Z);
我觉得值被否定,但是当我在3D程序中查看模型,模型中没有改变。
另一个建议是通过改变向量的顺序来尝试背面剔除。我试图通过交换v1和v2的顺序:
//creates invertedsurface normals
Vector3D CalculateInvertedSurfaceNormal(Point3D p1, Point3D p2, Point3D p3)
{
Vector3D v1 = new Vector3D(0, 0, 0); // Vector 1 (x,y,z) & Vector 2 (x,y,z)
Vector3D v2 = new Vector3D(0, 0, 0);
Vector3D normal = new Vector3D(0, 0, 0);
// Finds The Vector Between 2 Points By Subtracting
// The x,y,z Coordinates From One Point To Another.
// Calculate The Vector From Point 2 To Point 1
v2.X = p1.X - p2.X;
v2.Y = p1.Y - p2.Y;
v2.Z = p1.Z - p2.Z;
// Calculate The Vector From Point 3 To Point 2
v1.X = p2.X - p3.X;
v1.Y = p2.Y - p3.Y;
v1.Z = p2.Z - p3.Z;
// Compute The Cross Product To Give Us A Surface Normal
normal.X = v1.Y * v2.Z - v1.Z * v2.Y; // Cross Product For Y - Z
normal.Y = v1.Z * v2.X - v1.X * v2.Z; // Cross Product For X - Z
normal.Z = v1.X * v2.Y - v1.Y * v2.X; // Cross Product For X - Y
normal.Normalize();
return normal;
}
模型没有变化。
这里是整个代码:
private void SaveMoldMeshtoStlFile(MeshGeometry3D mesh, string filename)
{
if (mesh == null)
return;
if (File.Exists(filename))
{
File.SetAttributes(filename, FileAttributes.Normal);
File.Delete(filename);
}
Point3DCollection vertexes = mesh.Positions;
Int32Collection indexes = mesh.TriangleIndices;
Point3D p1, p2, p3;
Vector3D n;
string text;
using (TextWriter writer = new StreamWriter(filename))
{
writer.WriteLine("solid Bolus");
for (int v = 0; v < mesh.TriangleIndices.Count(); v += 3)
{
//gather the 3 points for the face and the normal
p1 = vertexes[indexes[v]];
p2 = vertexes[indexes[v + 1]];
p3 = vertexes[indexes[v + 2]];
n = CalculateInvertedSurfaceNormal(p1, p2, p3);
text = string.Format("facet normal {0} {1} {2}", n.X,n.Y, n.Z);
writer.WriteLine(text);
writer.WriteLine("outer loop");
text = String.Format("vertex {0} {1} {2}", p1.X, p1.Y, p1.Z);
writer.WriteLine(text);
text = String.Format("vertex {0} {1} {2}", p2.X, p2.Y, p2.Z);
writer.WriteLine(text);
text = String.Format("vertex {0} {1} {2}", p3.X, p3.Y, p3.Z);
writer.WriteLine(text);
writer.WriteLine("endloop");
writer.WriteLine("endfacet");
}
}
}
//creates inverted surface normals
Vector3D CalculateInvertedSurfaceNormal(Point3D p1, Point3D p2, Point3D p3)
{
Vector3D v1 = new Vector3D(0, 0, 0); // Vector 1 (x,y,z) & Vector 2 (x,y,z)
Vector3D v2 = new Vector3D(0, 0, 0);
Vector3D normal = new Vector3D(0, 0, 0);
// Finds The Vector Between 2 Points By Subtracting
// The x,y,z Coordinates From One Point To Another.
// Calculate The Vector From Point 2 To Point 1
v2.X = p1.X - p2.X;
v2.Y = p1.Y - p2.Y;
v2.Z = p1.Z - p2.Z;
// Calculate The Vector From Point 3 To Point 2
v1.X = p2.X - p3.X;
v1.Y = p2.Y - p3.Y;
v1.Z = p2.Z - p3.Z;
// Compute The Cross Product To Give Us A Surface Normal
normal.X = v1.Y * v2.Z - v1.Z * v2.Y; // Cross Product For Y - Z
normal.Y = v1.Z * v2.X - v1.X * v2.Z; // Cross Product For X - Z
normal.Z = v1.X * v2.Y - v1.Y * v2.X; // Cross Product For X - Y
normal.Normalize();
return normal;
}
是否有我的代码错误?我错过了什么吗?我已经在几个不同的程序中试用了导出的模型,并且都显示导出的模型仍然具有向外的法线。我尝试翻转Blender中的法线,发现其他程序也显示法线翻转,所以我相当确定这是我的程序的问题。