

= Пользовательские Сетки Фигуры

Английская версия: <<jme3/advanced/custom_meshes#,Custom Meshes>>



image::http///img821.imageshack.us/img821/1829/hellomesh.png[hellomesh.png,with="200",height="150",align="left"]

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


*Примечание:* В этом уроке, мы (пере)создадим очень простую прямоугольную сетки (четырехугольник), и мы рассмотрим различные способы окраски. Кодирование пользовательского четырехугольника может быть не очень полезно, потому что это точно тоже же что и встроенный `com.jme3.scene.shape.Quad`. Мы выбрали простой четырехугольник, чтобы научить вас, как построить любые фигуры из треугольников, не отвлекаясь на более сложных фигур.


*  Полный пример кода: link:http://jmonkeyengine.googlecode.com/svn/branches/stable-alpha4/engine/src/test/jme3test/model/shape/TestCustomMesh.java[TestCustomMesh.java]


== Полигональные Сетки

Полигональные <<документация/jme3_ru/расширенная/сетка#,Сетки>> состоят из треугольников. Углы треугольников называются вершинами. Когда вы создаете новую фигуру, вы можете разбить её на треугольники.


*Пример:* Давайте посмотрим на куб. Куб состоит из 6 прямоугольников. Каждый прямоугольник можно разбить на два треугольника. Это означает, что вам нужно 12 треугольников, чтобы описать сетку куба. Для этого вы должны предоставить координаты 8 углов треугольников (называемых вершинами).


Главное, что вы должны указать вершины каждого треугольника в правильном порядке: каждый треугольник отдельно, против часовой стрелки. 


Звучит сложнее, чем это – давайте создадим простую пользовательскую (сетку), четырехугольника.



== Создание Сетки Четырехугольник

В этом уроке мы хотим создать четырехугольник 3х3. Четырехугольник имеет четыре вершины, и состоит из двух треугольников. В нашем примере мы выберем для нижнего левого угла значение 0/0/0 а верхнему правому 3/3/0. 


[source]

----
0,3,0--3,3,0
| \        |
|   \      |
|     \    |
|       \  |
|         \|
0,0,0--3,0,0
----


=== Объект Сетка

Базовый класс для создания сеток является `com.jme3.scene.Mesh`.


[source,java]

----
Mesh mesh = new Mesh();
----

Совет: Если вы создаете свои собственные сетки на основе базового-Mesh класса (`public class MyMesh extends Mesh {  }`), замените переменную `mesh` на `this` как в следующих примерах.



=== Координаты Вершин

Чтобы определить собственную фигуру, определите фигуру в *координатами вершин* в 3D-пространстве.  Хранить список положения вершин в массиве `com.jme3.math.Vector3f`. Для Четырехугольника, нам нужны четыре вершины: левая нижняя, правая нижняя, левая верхняя, правая верхняя. Мы назавем массив `vertices[]`.


[source,java]

----

Vector3f [] vertices = new Vector3f[4];
vertices[0] = new Vector3f(0,0,0);
vertices[1] = new Vector3f(3,0,0);
vertices[2] = new Vector3f(0,3,0);
vertices[3] = new Vector3f(3,3,0);

----


=== Координаты Текстуры

Далее, мы определяем 2D *координаты текстур* для четырехугольника для каждой вершины, в том же порядке, как и вершины: левый нижний, правый нижний, левый верхний, правый верхний. Мы называем этот Vector2f массив `texCoord[]`


[source,java]

----

Vector2f[] texCoord = new Vector2f[4];
texCoord[0] = new Vector2f(0,0);
texCoord[1] = new Vector2f(1,0);
texCoord[2] = new Vector2f(0,1);
texCoord[3] = new Vector2f(1,1);

----

Этот синтаксис означает, когда вы применить текстуру к этой сетке, текстура заполнит четырехугольник из угла в угол в 100% размера. Особенно, когда вы сшить вместе большую сетку, можно использовать это, чтобы сказать визуализации ли, и как именно, вы хотите, чтобы покрыть всю сетку. Например если вы используете 0.5f или 2f как текстурные координаты, а не 1f, текстура будет растягиваться или сжиматься соответственно.



=== Соединим точки

Далее мы обратимся эти несвязанные координаты в *треугольники*: Мы определить порядок, в котором каждый треугольник построен. Думаю, что эти индексы как поступающие в группы по три. Каждая группа показателей описывает один треугольник. Если углы совпадают, вы можете (и должны!) повторно использовать индекс для нескольких треугольников.


Помните, что вы должны указать вершины против часовой стрелки.


[source,java]

----

int [] indexes = { 2,0,1, 1,3,2 };

----

Этот синтаксис означает:


*  Индексы 0,1,2,3 стоять на четырех вершинах, указанных для четырехугольника в `vertices[]`.
*  2,0,1 треугольник начинается в левом верхнем углу экрана, по-прежнему внизу слева, и заканчивается в правом нижнем углу.
*  1,3,2 треугольник начало в правом нижнем углу, по-прежнему в правом верхнем углу, и заканчивается в левом верхнем углу.

[source]

----

2\2--3
| \  | Против часовой стрелки
|  \ |
0--1\1

----

Если фигура более сложная, в ней больше треугольников, и поэтому также несколько вершин/индексов. Просто продолжаем расширять список, добавляя группы из трех показателей для каждого треугольника. (Например три-треугольника “дом фигура имеет 5 вершин/индексов, и вы бы указали на три группы: `int [] indexes = { 2,0,1, 1,3,2, 2,3,4 };`.) 


<<документация/jme3_ru/расширенная/spatial_ru#,Spatial>>`FaceCullMode.Back`“



=== Setting the Mesh Buffer

Вы храните данные сетки в буфере.


.  С помощью `com.jme3.util.BufferUtils`, мы создаем три буфера для трех типов информации:
**  координаты вершин,
**  координаты текстур,
**  индексы.

.  Мы присваиваем данные соответствующего типа буфера внутри объекта `Mesh`. Три буферных типа (`Position`, `TextCoord`, `Index`) взяты из перечисленных в `com.jme3.scene.VertexBuffer.Type`.
.  Целочисленный параметр описывает количество значений компонентов. Vertex postions 3 float значения, текстурных координат 2 float значения, а индексы находятся 3 целых чисел, представляющий 3-х вершин треугольника.
.  Для отображения сетки в сцене, мы должны предварительно рассчитать bounding volume нашей новой сетки: Вызовем метод `updateBound()`.

[source,java]

----

mesh.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(vertices));
mesh.setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoord));
mesh.setBuffer(Type.Index,    3, BufferUtils.createIntBuffer(indexes));
mesh.updateBound();

----

Наша сетка готова! Теперь мы хотим увидеть её.



== Использование сетки в сцене

Мы создаем `com.jme3.scene.Geometry` и `com.jme3.material.Material`от нашей `mesh`, применить простой цвет материала к нему, и прикрепить его к rootNode, и он появится в сцене


[source,java]

----

Geometry geo = new Geometry("OurMesh", mesh); //с помощью нашего пользовательского объекта сетки
Material mat = new Material(assetManager, 
    "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.Blue);
geo.setMaterial(mat);
rootNode.attachChild(geo);

----

Библиотека для assetManager?
Ta-daa!



== Using a Quad instead

Мы создали сетку четырехугольник(Quad) её можно заменить на четырехугольник, таких как :


[source,java]

----

Quad quad = new Quad(1,1); // replace the definition of Vertex and Textures Coordinates plus indexes
Geometry geo = new Geometry("OurQuad", quad); // с помощью Quad объекта
Material mat = new Material(assetManager, 
    "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.Blue);
geo.setMaterial(mat);
rootNode.attachChild(geo);

----

Если вы хотите изменить координаты текстуры, чтобы изменить масштаб текстуры, используйте:


[source,java]

----

Quad quad = new Quad(1,1);
quad.scaleTextureCoordinates(new Vector2f(width , height));

----


== Динамические Сетки

При изменении сетки динамически в путях, который изменяют границы модели, вам нужно обновить ее:


.  Вызовите `updateBound()` у объекта mesh, а затем 
.  Вызовите `updateModelBound()` у объекта геометрии, содержащий сетку. 

The updateModelBound() method warns you about not usually needing to use it, but that can be ignored in this special case.


_N.B.: Это не работает на TerrainQuad. Пожалуйста, используйте функцию TerrainQuad.adjustHeight() чтобы изменить сетки TerrainQuad вместо этого.  Кроме того, если вы хотите в последствии использовать столкновения на них, вам нужно вызвать TerrainPatch.getMesh().createCollisionData(); обновление данных столкновений, иначе они будут сталкиваться с иллюзией старой сетки. _



== Необязательно Особенности Сетки

Есть больше буферов вершин сетки, чем три показанных выше. Общие сведения см. также в <<документация/jme3_ru/расширенная/сетка#,Сетка>>.



=== Пример: Vertex Colors

Vertex coloring это простой способ окраски сетки. Вместо того чтобы просто присвоить один сплошной цвет, каждая вершина (угол) имеет присвоенный цвет. Грани между вершинами окрашиваются с градиентом. Для этой демонстрации, вы можете использовать те же сетки “mesh объект, который был определен выше.


[source,java]

----
Geometry geo = new Geometry ("ColoredMesh", mesh); // используем пользовательскую сетку
Material matVC = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
matVC.setBoolean("VertexColor", true);
----

Вы создаете  float массив буфер цвета:


*  Назначить 4 значения Цвет RGBA, для каждой вершины.
**  Цикл по 4 значения цвета, использовать цветовой индекс 
[source,java]

----
int colorIndex = 0;
----


*   Буфер цвета содержит четыре значения цвета для каждой вершины.
**  Quad в данном примере, имеет 4 вершины. 
[source,java]

----
float[] colorArray = new float[4*4];

----

**  Совет: Если сетка имеет разное количество вершин, вы должны написать: 
[source,java]

----
float[] colorArray = new float[yourVertexCount * 4]
----



Цикл по буферу colorArray быстро установить какие-то значения RGBA для каждой вершины. Как обычно, цветовые значения RGBA в диапазоне от 0.0f до 1.0f. *Обратите внимание, что значения цвета в этом примере выбраны произвольно.* Это просто быстрый цикл, чтобы дать каждой вершины другое значение RGBA (фиолетово-серый, фиолетовый, зеленовато-серый, зеленый, см. скриншот), без написания большого количества кода. Для вашей собственной сетки, вы назначите осмысленные значения для цветового буфера в зависимости от, какой цвет вы хотите, чтобы ваш сетка, имела.


[source,java]

----

// Примечание: красным и зеленым значения arbitray в этом примере
for(int i = 0; i < 4; i++){
   // Значение Красного (увеличивается .2 на каждой следующей вершины здесь)
   colorArray[colorIndex++]= 0.1f+(.2f*i);
   // Значение зеленого (снижается .2 на каждой следующей вершины)
   colorArray[colorIndex++]= 0.9f-(0.2f*i);
   // Значение синего (остается неизменным в нашем случае)
   colorArray[colorIndex++]= 0.5f;
   // Значение альфа (без прозрачности установить здесь)
   colorArray[colorIndex++]= 1.0f;
}
----

Далее, установите цветовой буфер. RGBA значение цвета содержит четыре float компонента таким образом, параметр `4`.


[source,java]

----
mesh.setBuffer(Type.Color, 4, colorArray);
geo.setMaterial(matVC);

----

Когда вы запустите этот код, вы увидите градиент цвета простирающийся от каждой вершины.



=== Пример: Использование Сетки с Lighting.j3md

Предыдущие примеры использовали сетку с материалом `Unshaded.j3md`. Если вы хотите использовать сетку с Phong подсветкой материалов (таких, как `Lighting.j3md`), сетка должна включать в себя информацию о ее нормалях. (Нормальные векторы кодируют в каком направлении полигоны сетки сталкиваются, что важно для расчета света и тени!)


[source,java]

----

float[] normals = new float[12];
normals = new float[]{0,0,1, 0,0,1, 0,0,1, 0,0,1};
mesh.setBuffer(Type.Normal, 3, BufferUtils.createFloatBuffer(normals));

----

Вы должны указать, как много нормалей в качестве вершин многоугольника.  Для плоского quad, четыре нормали указывают в одном направлении. В этом случае, направление Z единичный вектор (0,0,1), это означает, что наша quad смотрит в камеру.


Если сетка является более сложным или округлые, рассчитать cross products соседних вершин, чтобы определить векторы нормали!



=== Пример: В Режиме Точки

Кроме того для окраски граней, как описано выше, вы можете скрыть грани и показать только вершины в виде цветных угловых точек.


[source,java]

----
Geometry coloredMesh = new Geometry ("ColoredMesh", cMesh);
...
mesh.setMode(Mesh.Mode.Points);
mesh.setPointSize(10f);
mesh.updateBound();
mesh.setStatic();
Geometry points = new Geometry("Points", mesh);
points.setMaterial(mat);
rootNode.attachChild(points);
rootNode.attachChild(geo);

----

В результате в 10 px точек будут рендерины для каждой из четырех вершин. Точки имеют цвет вершины, указанной выше. Грани Quad не отображаются в этом режиме. Вы можете использовать это, чтобы визуализировать специальную отладку или для режима редактирования в игре.



== Отладка Совет: Выбраковка

По умолчанию, jME3 оптимизирует сетку “backface culling, это означает не рисуем внутри. Он определяет сторону треугольника по заказу вершин: frontface это грани, где вершины задаются против часовой стрелки.


Для вас это означает, что по умолчанию, пользовательские сетки является невидимым, если смотреть от “за или изнутри. Это может не быть проблемой, обычно даже так задумано, потому что так быстрее. Игрок не будет заглядывать внутрь и большинства вещей в любом случае. Например, если ваша пользовательская сетка замкнутый многогранник, или или плоский обои, как объект рендерить backfaces (внутри колонны, обратной стороне картины и т.д.) действительно будет пустой тратой ресурсов.


Однако в случае, когда ваш usecase требует backfaces быть видимым, у вас есть два варианта:


*  Если у вас есть очень простая сцена, вы можете просто отключить backface выбраковку невидимой поверхности для материала этой сетки. 
[source]

----
mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off);
----

*  Еще одно решение для по-настоящему двусторонней сетки является указание каждого треугольника дважды, второй раз с противоположной последовательностью вершин. Второй (обратный) треугольник-это второй frontface, который покрывает выбраковку на торцах. 
[source]

----
int[] indexes = { 2,0,1, 1,3,2, 2,3,1, 1,0,2 };
----

'''

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


*  <<документация/jme3_ru/расширенная/spatial_ru#,Spatial>> – содержит дополнительные сведения об отладке пользовательских сеток (которые не отображаются, как и ожидалось), изменяя значение по умолчанию выбраковки поведения.
*  <<документация/jme3_ru/расширенная/сетка#,Сетка>> – более подробную информацию о свойствах расширенной сетки
<tags><tag target="spatial" /><tag target="node" /><tag target="mesh" /><tag target="geometry" /><tag target="scenegraph" /></tags>
