在接缝结束了2网格之间计算法线法线、网格、结束了

2023-09-07 22:43:52 作者:「像迯跑の賊」

我目前正在创建的Unity3D地形这是专门为低内存正在运行的应用程序的移动设备。允许与一个尺寸的15.000 x 15.000公里和从-1.000米的高度10.000米的地形和它的唯一的限制是在硬盘上的空间中。

I currently creating a terrain for Unity3D which is specialized for mobile-devices with low memory for a running app. Allowing a terrain with a size of 15.000 x 15.000 kilometers and a height from -1.000 meters to 10.000 meters and it's only limits are the space on the hard disk.

一切都很好,只是不同的网格之间的法线(每个网格都有一个细分级别)不正确计算运行现在。这里有两个画面而形象化的问题:

Everything is running fine right now except that the normals between different meshes ( each mesh has a subdivision level ) are not calculated correctly. Here are two pictures which visualize the problem:

该问题只发生在从一个细分级别到另一个过渡。如果这两个网格具有相同级别的效果很好。我首先想到的计算法线时,我错过了一些面孔,但他们似乎都纳入计算。

The problem only occurs on a transition from one subdivision level to another. If both mesh have the same level it works well. I first thought i miss some faces when calculating the normals but it seems they are all included into the calculation.

每个面的正常计算:

Vector3 u = vertices[item.Face1] - vertices[item.Face0];
Vector3 v = vertices[item.Face2] - vertices[item.Face0];

Vector3 fn = new Vector3((u.Y * v.Z) - (u.Z * v.Y), (u.Z * v.X) - (u.X * v.Z), (u.X * v.Y) - (u.Y * v.X));
fn.Normalize();

在计算正常的每个面围绕一个顶点之后,我添加的所有面法线顶点正常和规范它。其结果显示在画面,并作为可以在后台并在网格本身它工作看到只要没有不同细分级别

After calculating the normal of each face around a vertex i add all the face-normals to the vertex-normal and normalize it. The result is shown in the pictures, and as you can see in the background and on the meshes itself it works as long there is no different subdivision level.

/// <summary>
/// This is a static indicies array which contains all indicies
/// for all possible meshes.
/// </summary>
private static readonly Int32[] // Subdivision
                             [] // All borders
                             [] Indicies = new Int32[8][][]; // Indicies

计算每个正常当前网格的:

Calculate each normal of the current mesh:

Int32 count = 0;
for (int y = 0; y < length; y++)
{
    for (int x = 0; x < length; x++)
    {
        ns[count++] = GetNormal(x, y, faces, vs);
    }
}

GetNormal -method:

The GetNormal-method:

private unsafe Vector3 GetNormal(Int32 x, Int32 y, Int32[] indicies, Vector3* vertices)
{
    Vector3 normal = new Vector3();
    CalculateNormal(x, y, indicies, vertices, ref normal);
    normal.Normalize();
    // Calculate all face normals and normalize
    return normal;
}

CalculateNormal -method:

The CalculateNormal-method:

private unsafe void CalculateNormal(Int32 x, Int32 y, Int32[] indicies, Vector3* vertices, ref Vector3 normal)
{
    Int32 p = ((y * Length) + x);
    Int32 length = Length - 1;

    foreach (Face item in FindFaces(this, indicies, p))
    {
        Vector3 u = vertices[item.Face1] - vertices[item.Face0];
        Vector3 v = vertices[item.Face2] - vertices[item.Face0];

        Vector3 fn = new Vector3((u.Y * v.Z) - (u.Z * v.Y), (u.Z * v.X) - (u.X * v.Z), (u.X * v.Y) - (u.Y * v.X));
        fn.Normalize();
        normal += fn;
    }

    SegmentHeighmap heightmap;
    if (x == 0 && y == 0)
    {
        foreach (Face item in FindFaces(Neighbor.Left, out heightmap, TranslateLeftX, TranslateLeftY, x, y))
        {
            Face f = item;
            AddFaceNormal(ref f, ref normal, heightmap);
        }

... /* A lot of more code here for each possible combination */

AddFaceNormal -method:

The AddFaceNormal-method:

private static void AddFaceNormal(ref Face face, ref Vector3 normal, SegmentHeighmap heightmap)
{
    Vector3 v0;
    Vector3 v1;
    Vector3 v2;
    heightmap.CalculateVertex(face.Face0, out v0);
    heightmap.CalculateVertex(face.Face1, out v1);
    heightmap.CalculateVertex(face.Face2, out v2);

    Vector3 u = v1 - v0;
    Vector3 v = v2 - v0;

    Vector3 fn = new Vector3((u.Y * v.Z) - (u.Z * v.Y), (u.Z * v.X) - (u.X * v.Z), (u.X * v.Y) - (u.Y * v.X));
    fn.Normalize();
    normal += fn;
}

FindFaces - 方法:

private IEnumerable<Face> FindFaces(Neighbor neighbor, out SegmentHeighmap heightmap, TranslationHandler translateX, TranslationHandler translateY, Int32 x, Int32 y)
{
    Segment segment = Segment.GetNeighbor(neighbor);
    if (segment != null)
    {
        heightmap = segment.Heighmap;
        Int32 point = ((translateY(this, heightmap, y) * Length) + translateX(this, heightmap, x));

        return FindFaces(heightmap, null, point);
    }
    heightmap = null;
    return Enumerable.Empty<Face>();
}
private IEnumerable<Face> FindFaces(SegmentHeighmap heightmap, Int32[] indicies, Int32 point)
{
    indicies = indicies ?? Indicies[heightmap.Segment.SubdivisionLevel][heightmap.SideFlag];

    for (int i = 0; i < indicies.Length; i += 3)
    {
        Int32 a = indicies[i], b = indicies[i + 1], c = indicies[i + 2];
        if (a == point || b == point || c == point)
        {
            yield return new Face(a, b, c);
        }
    }
}

TransformPoint -method:

The TransformPoint-method:

private Int32 TranslatePoint(Int32 point, Segment segment)
{
    Int32 subdiv = segment.SubdivisionLevel - Parent.SubdivisionLevel;
    if (subdiv == 0)
    {
        return point;
    }
    if (Math.Abs(subdiv) == 1)
    {
        if (subdiv > 0)
        {
            return point * 2;
        }
        return point / 2;
    }

    throw new InvalidOperationException("Subdivision difference is greater than 1");
}

最后的 TranslationHandler -delegate和2样品处理:

And finally the TranslationHandler-delegate and 2 sample handlers:

/// <summary>
/// Handles the translation from one coordinate space into another
/// This handler is used internal only
/// </summary>
private delegate Int32 TranslationHandler(SegmentHeighmap @this, SegmentHeighmap other, Int32 v);

private static readonly TranslationHandler TranslateLeftX = (t, o, v) => o.Length - 1;
private static readonly TranslationHandler TranslateLeftY = (t, o, v) => t.TranslatePoint(v, o.Segment);

问题

的问题很简单的?为什么它不工作的不同层次,我怀念的东西在我的计算。

Question

The question is simple: Why is it not working for different levels, do i miss something in my calculation?

推荐答案

我仍然不知道为什么会发生,但用这个当....

I still don't know why it happens but when replacing this....

Vector3 u = vertices[item.Face1] - vertices[item.Face0];
Vector3 v = vertices[item.Face2] - vertices[item.Face0];

Vector3 fn = new Vector3((u.Y * v.Z) - (u.Z * v.Y), (u.Z * v.X) - (u.X * v.Z), (u.X * v.Y) - (u.Y * v.X));
fn.Normalize();
normal += fn;

另一个 AddFaceNormal - 方法很有效。我不知道为什么这happend,但现在它的工作原理。

with another AddFaceNormal-method it works. I don't know why this happend but now it works.