How can I use something like NativeList<NativeList<Vector3Int>>? or any other alternative ways?

Hi guys I am trying to code a class that calculates the normals of a mesh. I am trying to use the job system to enhance the performance. In my solution I am trying to use something like NativeList>. But when I compiled I got an error says that:

ArgumentException: Unity.Collections.NativeList`1[UnityEngine.Vector3Int] used in native collection is not blittable or primitive

I’ve tried other ways like using NativeList<List> (error: List is nullable type) List<NativeList> (error: It wont work with the job system.)

Is there anyway I can do this?

Thank you guys!

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Collections;
using Unity.Burst;
using Unity.Jobs;
using UnityEngine.Jobs;

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

NativeArray nativeIndices;
NativeList<NativeList> nativeVerticesAdjFaces;
NativeList nativeNormals;
NativeArray nativeVertices;

InitAdjacentFacesJob initAdjacentFacesJob;
JobHandle initAdjacentFacesJobHandle;

CalculateNormalsJob calculateNormalsJob;
JobHandle calculateNormalsJobHandle;

public void Init(Mesh _mesh)
{
mesh = _mesh;
verticesAdjFaces = new List<List>();
nativeIndices = new NativeArray(mesh.triangles, Allocator.Temp);
nativeVerticesAdjFaces = new NativeList<NativeList>(mesh.vertexCount,Allocator.Temp);
nativeNormals = new NativeList(mesh.normals.Length, Allocator.Temp);
nativeVertices = new NativeArray(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 indices;
public NativeList<NativeList> verticesAdjFaces;
public void Execute(int i)
{
NativeList list = new NativeList();
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(nativeNormals.ToArray());
mesh.SetNormals(normals);
}

public struct CalculateNormalsJob : IJobParallelFor {
public NativeArray vertices;
public NativeList<NativeList> verticesAdjFaces;
public NativeList normals;
public void Execute(int i)
{
NativeList adjFaces = verticesAdjFaces*;*
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);
}
}
}

Use this button for code snippets:

For your case:
NativeMultiHashMap
NativeList of entities with DynamicBuffer

Thank you sir. I will use the button next time. And I have decided to use NativeMultiHashMap for my code but I am having issue of getting the values from the map by using one key. I dont find any method under the NativeMultiHashMap. Can you please help me with it?

I added the vertices to the map here:

    public struct InitAdjacentFacesJob : IJobParallelFor
    {
        public NativeArray<int> indices;
        public NativeMultiHashMap<int, Vector3Int> verticesAdjFaces;
        public void Execute(int i)
        {

            for (int j = 0; j < indices.Length; j += 3)
            {
                if (i == indices[j] || i == indices[j + 1] || i == indices[j + 2])
                {
                    Vector3Int triangle = new Vector3Int(indices[j], indices[j + 1], indices[j + 2]);
                    verticesAdjFaces.Add(i, triangle);
                }
            }
        }
    }

and i am trying to get all the triangles of one of the vertices here:

    public struct CalculateNormalsJob : IJobParallelFor {
        public NativeArray<Vector3> vertices;
        public NativeMultiHashMap<int, Vector3Int> verticesAdjFaces;
        public NativeList<Vector3> normals;
        public void Execute(int i)
        {
            //this line. which method should i use to get the adjFaces?????? confused
            NativeList<Vector3Int> adjFaces = verticesAdjFaces.GetValueArray(Allocator.Temp);
            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);
        }
    }

TryGetFirstValue, TryGetNextValue

1 Like

Instead of having vertices in sub lists, put them all in one big list and have a separate list with the indexes into this big list. No need for any other data format.

2 Likes