Обновление массива Vector3 из собственного плагина C ++ - PullRequest
0 голосов
/ 06 ноября 2018

Marshal.Copy() Метод поддерживает только несколько типов массивов. Теперь я знаю только, как копировать из IntPtr (указывая на массив с плавающей точкой из кода C ++) в float[].

IntPtr pvertices = GetVerticesFromCPP();
float[] vertices = new float[nVertices * 3];
Marshal.Copy(pvertices, vertices, 0, nVertices * 3);

Но то, что я действительно хочу, это UnityEngine.Vector3[].

Нужно ли вручную конвертировать float[] в UnityEngine.Vector3[]? Или есть более простой и быстрый способ сделать это напрямую?

1 Ответ

0 голосов
/ 06 ноября 2018

Нужно ли вручную конвертировать float [] в UnityEngine.Vector3 []? Или Есть более простой и быстрый способ, который напрямую это делает?

Да, вы должны сделать это вручную, но есть лучший способ сделать это.

Я предполагаю, что вам нужно изменить Vector3 на нативной стороне, а затем вернуть результат. Для этого нет необходимости использовать массив float. Просто создайте структуру Vector3 на стороне C ++, а затем используйте указатель для передачи его между C ++ и C #. Не возвращайте массив Vector3 из C ++ , создайте его на стороне C #, затем передайте его функции C ++ для изменения и применения изменений к аргументу.

C ++:

Для этого необходимо, чтобы вы включили небезопасное ключевое слово в Unity.

struct Vector3
{
     float x;
     float y;
     float z;
};

тогда ваша функция:

extern "C" void UpdateVectorArray(Vector3* vecArray, int vecSize)
{
    for(int i = 0; i < vecSize; ++i)
    {
        //Simply modify each Vector reference
        Vector3 &vec = vecArray[i];
        vec.x = 11;
        vec.y = 20;
        vec.z = 55;
    }
}

C #:

[DllImport("Plugin Name")]
static unsafe extern void UpdateVectorArray(Vector3* vecArray, int vecSize);


void UpdateVectorArray(Vector3[] vecArray)
{
    unsafe
    {
        //Pin array then send to C++
        fixed (Vector3* vecPtr = vecArray)
        {
            UpdateVectorArray(vecPtr, vecArray.Length);
        }
    }
}

Использование:

Получить вершины из модели, отправить в C ++ и изменить его, переназначить измененную сетку:

void Start()
{
    Mesh mesh = GetComponent<MeshFilter>().mesh;

    Vector3[] vertices = mesh.vertices;
    UpdateVectorArray(vertices);

    //Re-assign the modified mesh
    mesh.vertices = vertices;
    mesh.RecalculateBounds();
}

Чтобы не использовать ключевое слово unsafe в Unity, используйте атрибут [In, Out].

[DllImport("Plugin Name")]
static extern void UpdateVectorArray([In, Out] Vector3[] vecArray, int vecSize);

void Start()
{
    Mesh mesh = GetComponent<MeshFilter>().mesh;

    Vector3[] vertices = mesh.vertices;
    UpdateVectorArray(vertices, vertices.Length);

    mesh.vertices = vertices;
    mesh.RecalculateBounds();
}

Сторона C ++ остается прежней. Вы также можете использовать GCHandle для закрепления массива и избегать использования ключевого слова unsafe, но решение для ключевого слова unsafe лучше и быстрее.

...