Докуметация Cтарт Статьи Форум Лента Вход
Не официальное русскоязычное сообщество
Главная
    Документация jMonkeyEngine
        jMonkeyEngine Уроки и Документация
            Вклады
                Проект JUnion
                    Возможности

Возможности

Опубликованно: 29.05.2018, 20:52
Последняя редакция, Andry: 30.05.2018 21:44

Типы структур

Типы структур позволяют реализовывать типы данных, которые используют наименьшее колличество памяти.

Вы можете реализовать тип структуры, задав ему аннотацию @Struct.

@Struct
public class Vec3 {
    public float x,y,z;
}

Структура Vec3 имеет размер 12 байт. Вы можете проверить это двумя способами, выполнив:

System.out.println("Size: " + Mem.sizeOf(Vec3.class));
System.out.println(Mem.layoutString(Vec3.class));

Выведется

Size: 12
~Struct test.HelloStruct$Vec3(12/12/12) Align: 4 ~
|0:x FLOAT(4), -1|
|4:y FLOAT(4), -1|
|8:z FLOAT(4), -1|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Автоматическое выравнивание данных

Для получения информации о выравнивании данных смотрите здесь.

@Struct
public class MixedData {
    byte Data1;
    short Data2;
    int Data3;
    byte Data4;
}

Структура MixedData не имеет выровненных данных. JUnion обнаруживает это и автоматически перестраивает данные. Мы можем еще раз использовать код ниже, чтобы проверить размер и компоновку структуры.

System.out.println ("Размер:" + Mem.sizeOf (MixedData.class));
System.out.println (Mem.layoutString (MixedData.class));

Выведется

Size: 8
~Struct test.HelloStruct$MixedData(8/8/8) Align: 4 ~
|0:Data3 INT(4), -1|
|4:Data2 SHORT(2), -1|
|6:Data1 BYTE(1), -1|
|7:Data4 BYTE(1), -1|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Первое Data3 с индексом 0, кратно четырем, выравнивается. Аналогично, Data2 начинается с индексом 4, оно кратно 2, также выравнивается.

Ручное выравнивание данных

Если ваш код зависит от компоновки данных внутри структуры, используйте autopad в свойствах аннотации.

@Struct(autopad=false)
public class Manual {
    public byte b;
    private byte padding;
    public char ch;
}

Установив autopad в false, вы должны реализовать свои данные так, чтобы они были выровнены. Компилятор выдаст ошибку, если структура выровнена не правильно.

Создание Массивов Типов Структур

Массивы структур выделяются в куче и автоматически высвобождаются.

Vec3[] arr = new Vec3[12];
arr[5].y = 10;
		
System.out.println("arr[5].y = " + arr[5].y );

64-битные long адреса массива

Массивы структур поддерживают адресацию с long-ами.

Vec3[] arr = new Vec3[Mem.li(1000000000L)];
arr[Mem.li(900000000L)].y = 10;
		
System.out.println("y = " + arr[Mem.li(900000000L)].y );

Изменение Native DirectByteBuffer-ов

Мало того, что доступ к/изменение bytebuffer-ов более читабельно с помощью синтаксиса структуры, оно также повышает производительность.

ByteBuffer a = ByteBuffer.allocateDirect(num*vec3Size).order(ByteOrder.nativeOrder());

Vec3[] av = Mem.wrap(a, Mem.sizeOf(Vec3.class));

Проверка Индексов

Vec3[] arr = new Vec3[12];

arr[-1].x = 5; //throws IndexOutOfBoundsException
arr[12].x = 5; //throws IndexOutOfBoundsException

Вложенные структуры

@Struct
public class Line2 {
    public Vec3 a, b;
}

Компоновка

Size: 24
~Struct test.HelloStruct$Line2(24/24/24) Align: 4 ~
|0:a STRUCT(4), -1|
|12:b STRUCT(4), -1|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Ссылки Структур

При сборке древа структур вы можете написать что-то вроде этого.

@Struct
public class Node {
    public Node left, right;
}

Однако структура не может содержать себя. JUnion обнаруживает эту ошибку как Круговую Зависимость(Circular Dependence).

Чтобы собрать древо структур, мы можем написать:

@Struct
public class Node {
    @Reference public Node left, right;
}

Проверка нулевой ссылки

Node[] n = new Node[10];
Node a = n[0].left; //throws NullPointerDereference

Чтобы проверить, является ли ссылка нулевой(null) , используйте Mem.isNull

Node[] n = new Node[10];
if(!Mem.isNull(n[0].left)) {
    Node a = n[0].left;
}

Срез Массива

Вы можете создавать срезы массива. Срезы обмениваются данными, поэтому изменения в срезе отражаются и в исходном массиве.

Vec3[] arr = new Vec3[10];
for(int i = 0; i < arr.length; i++) arr[i].x = i;
		
Vec3[] a = Mem.slice(arr, 5, arr.length);
Vec3[] b = Mem.slice(arr, 5, arr.length, 2);
Vec3[] reversed = Mem.slice(arr, 0, arr.length, -1);
		
System.out.print("a:\t");
for(int i = 0; i < a.length; i++) System.out.print(a[i].x + ",");
System.out.print("\nb:\t");
for(int i = 0; i < b.length; i++) System.out.print(b[i].x+",");
System.out.print("\nrev:\t");
for(int i = 0; i < reversed.length; i++) System.out.print(reversed[i].x+",");

Выведется

a:	5.0,6.0,7.0,8.0,9.0,
b:      5.0,7.0,
rev:	9.0,8.0,7.0,6.0,5.0,4.0,3.0,2.0,1.0,0.0,

Обобщения

Vec3[] arr = new Vec3[10];
for(int i = 0; i < arr.length; i++) arr[i].x = i;

ArrayList<Vec3> list = new ArrayList<>();
list.add(arr[5]);
list.add(arr[1]);
list.add(arr[7]);

for(Vec3 v : list) {
    System.out.println(v.x);
}

Выведется

5.0
1.0
7.0

Размещение в стеке

Существует два способа размещения структур в стеке. Первый безопасный путь требует инициализации всех переменных структуры со следующим синтаксисом.

Vec3 v = Mem.stack(Vec3.class); {
    v.x = 1; v.y = 2; v.z = 3;
}

Если инициализация нежелательна, например когда вы хотите инициализировать структуру из вызова функции. Сейчас это возможно сделать так как указанно ниже. Этот способ небезопасен, если вы читаете данные, прежде чем их инициализировать.

Vec3 v = Mem0.stackRaw(Vec3.class);

Смотрите так же:


Переведено для jmonkeyengine.ru, оригинал
Автор перевода: Andry

Добавить комментарий

jMonkeyEngine.ru © 2017. Все права сохранены.