如何使用类似NativeList <nativelist <vector3int >>的东西?或任何其他替代方式?

时间:2019-04-30 07:48:12

标签: unity3d jobs primitive

我正在尝试使用作业系统手动计算网格的法线以获得更好的性能。在我的解决方案中,我尝试使用类似NativeList>的方法。但是当我编译时,我收到一条错误消息:

ArgumentException:本机集合中使用的Unity.Collections.NativeList`1 [UnityEngine.Vector3Int]不可变本白或原始的

反正我可以解决这个问题吗?

谢谢你们!

public class NormalCalculatorJobSystem
{
List<List<Vector3Int>> verticesAdjFaces;
List<Vector3> normals;
Mesh mesh = null;

NativeArray<int> nativeIndices;
NativeList<NativeList<Vector3Int>> nativeVerticesAdjFaces;
NativeList<Vector3> nativeNormals;
NativeArray<Vector3> nativeVertices;

InitAdjacentFacesJob initAdjacentFacesJob;
JobHandle initAdjacentFacesJobHandle;

CalculateNormalsJob calculateNormalsJob;
JobHandle calculateNormalsJobHandle;

public void Init(Mesh _mesh)
{
    mesh = _mesh;
    verticesAdjFaces = new List<List<Vector3Int>>();


    nativeIndices = new NativeArray<int>(mesh.triangles, Allocator.Temp);

    //ArgumentException: Unity.Collections.NativeList`1[UnityEngine.Vector3Int] used in native collection is not blittable or primitive
    nativeVerticesAdjFaces = new NativeList<NativeList<Vector3Int>>(mesh.vertexCount,Allocator.Temp);


    nativeNormals = new NativeList<Vector3>(mesh.normals.Length, Allocator.Temp);
    nativeVertices = new NativeArray<Vector3>(mesh.vertices, Allocator.Temp);

    InitAdjacentFaces();
}

public void InitAdjacentFaces() {

    initAdjacentFacesJob = new InitAdjacentFacesJob
    {
        indices = nativeIndices,
        verticesAdjFaces = nativeVerticesAdjFaces,
    };

    initAdjacentFacesJobHandle = initAdjacentFacesJob.Schedule(mesh.vertexCount, 64);
    initAdjacentFacesJobHandle.Complete();
}

public struct InitAdjacentFacesJob : IJobParallelFor
{
    public NativeArray<int> indices;
    public NativeList<NativeList<Vector3Int>> verticesAdjFaces;
    public void Execute(int i)
    {
        NativeList<Vector3Int> list = new NativeList<Vector3Int>();
        for (int j = 0; j < indices.Length; j += 3)
        {
            if (list.Length > 6)
                continue;
            if (i == indices[j] || i == indices[j + 1] || i == indices[j + 2])
            {
                Vector3Int triangle = new Vector3Int(indices[j], indices[j + 1], indices[j + 2]);
                list.Add(triangle);
            }
        }
        verticesAdjFaces.Add(list);
    }
}


public void CalculateNormals(Mesh mesh)
{
    nativeNormals.Clear();
    calculateNormalsJob = new CalculateNormalsJob
    {
        vertices = nativeVertices,
        verticesAdjFaces = nativeVerticesAdjFaces,
        normals = nativeNormals
    };
    calculateNormalsJobHandle = calculateNormalsJob.Schedule(nativeVerticesAdjFaces.Length, 64,initAdjacentFacesJobHandle);
    calculateNormalsJobHandle.Complete();
    normals = new List<Vector3>(nativeNormals.ToArray());
    mesh.SetNormals(normals);
}

public struct CalculateNormalsJob : IJobParallelFor {
    public NativeArray<Vector3> vertices;
    public NativeList<NativeList<Vector3Int>> verticesAdjFaces;
    public NativeList<Vector3> normals;
    public void Execute(int i)
    {
        NativeList<Vector3Int> adjFaces = verticesAdjFaces[i];
        Vector3 normal = Vector3.zero;
        for (int j = 0; j < adjFaces.Length; j++)
        {
            Vector3Int triangle = adjFaces[j];
            Vector3 vec0 = vertices[triangle.y] - vertices[triangle.x];
            Vector3 vec1 = vertices[triangle.z] - vertices[triangle.x];
            normal += Vector3.Cross(vec0, vec1);
        }
        normal.Normalize();
        normals.Add(normal);
    }
}

}

1 个答案:

答案 0 :(得分:0)

可blittable类型是在托管和非托管代码中均具有规范表示形式的类型。您可以阅读有关here的更多信息。

对于DOTS,Unity发明了自己的可着色值类型,其与您在像HLSL这样的着色语言中看到的类型更加相似。对于矢量,您具有float2,float3,float4等。对于矩阵,您也具有float4x4。在您的情况下,您需要int3而不是Vector3Int。使用这些新类型的好处之一是它们可以利用SIMD运算(单指令,多数据),该运算允许在单个指令中对所有3个值使用算术运算。

这些新类型还对诸如交叉和点积之类的东西具有自己的固有操作。您可以在GitHub上找到数学库。