Класс RenderMesh позволяет создавать, загружать и использовать в любом типе рендера произвольные трехмерные модели, созданные из полигонов.
3D модель представлена как набор вершин, цветов, текстурных координат и полигонов, последние объединяют первые 3 в треугольники (каждая вершина треугольника является ссылкой на вершину, цвет и текстурные координаты). Из треугольников и создается модель.
Формат файлов .obj является достаточно распространенным не бинарным форматом 3D моделей, который поддерживают многие редакторы. RenderMesh позволяет одной функцией загружать модели из файлов с таким форматом. Загружаются данные о вершинах, текстурных координатах и полигонах, остальные данные избыточны и игнорируются.
Создание: var mesh = new RenderMesh() - создает пустую модель
Основные методы для модификации:
mesh.addVertex(x, y, z, u, v) - добавляет вершину в модель, x, y, z - координаты в пространстве, u, v - координаты текстуры (от 0 до 1). Каждые 3 последовательно идущие вершины объединяются в треугольник, кол-во вершин обязательно должно быть кратно 3.
mesh.setColor(r, g, b) - устанавливает цвет, который будет использован для всех добавленных далее вершин, пока цвет не изменится (по умолчанию белый)
mesh.resetColor() - сбрасывает цвет обратно до белого
mesh.setBlockTexture("name", index) - данный метод нужен в случае, когда модель используется для блока. После вызова этого метода все текстурные координаты будут заданы для конкретной текстуры блока.
mesh.resetTexture() - сбрасывает состояние, полученное вызовом метода setBlockTexture.
mesh.clear() - очищает модель
mesh.translate(x, y, z) - смещает всю модель на вектор x, y, z
mesh.scale(x, y, z) - изменяет размер модели по каждой координате соответственно в x, y, z раз
mesh.rebuild() - пересчитывает нормали всех треугольников, нужные для корректного освещения, нужно вызвать это после завершения модификации модели.Для импорта модели из файла используется метод mesh.importFromFile(path, type, params) или конструктор с такими же аргументами. Импорт автоматически вызовет метод rebuild() после завершения.
Аргументы:
Формат объекта настроек и их значения по умолчанию:
{
clear: false, // очищать ли модель перед импортом
invertV: false, // в некоторых моделях вторая текстурная координатаинвертирована, это инвертирует ее обратно.
translate: [0, 0, 0], // аналогичен по действию метода translate, но происходит прямо во время импорта, что ускоряет процесс
scale: [1, 1, 1] // аналогичен методу scale, вызывается после примененияпараметра translate
}
Пример:
var mesh = new RenderMesh(__dir__ + "models/barrel.obj", "obj", null); // импортирует модель из "директория мода/models/barrel.obj"
Модель RenderMesh может быть установлена для конкретной части рендера моба и тогда она будет отрисовываться в ее системе координат. Модель заменит остальные элементы этой части рендера, и они не будут отрисовываться.
Для того, чтобы установить модель в объекте ModelPart есть метод setMesh(mesh), который может принимать объект модели или null.
Пример:
var mesh = new RenderMesh(__dir__ + "models/barrel.obj", "obj", null); // создать модель из файла (см. прошлый пример)
var render = new Render(); // создать пустой рендер
var bodyPart = render.getPart("body"); // получить часть (ModelPart) с именем "body"
bodyPart.setMesh(mesh); // установить модель для полученной части рендера моба
После установки мобу текстуры для этой модели и созданного в примере рендера был получен следующий результат:
Использование для модели блока:
Модель RenderMesh может быть добавлена в модель объекта блока (BlockModel), при этом ее текстурой будет текстура всех блоков (см метод setBlockTexture). В одну модель блока может быть добавлено несколько моделей RenderMesh и они не будут заменять друг друга и другие части модели блока.
Для добавления RenderMesh в BlockModel используется метод последнего addMesh(mesh), который добавляет RenderMesh в модель блока, или конструктор new BlockModel(mesh), который создает модель блока из переданного RenderMesh.
В отличии от рендера мобов, рендер блоков имеет такую механику как culling (треугольники будут видны только с той стороны, с которой их вершины идут по часовой стрелке), это сделано в самом MCPE для оптимизации и при создании моделей для блоков это стоит учитывать.
Пример:
var mesh = new RenderMesh(); // создать пустую модель
mesh.setBlockTexture("quartz_block_side", 0); // установить текстуру кварца (можно добавить произвольную текстуру, как текстуру блока и использовать ее)
mesh.importFromFile(__dir__ + "models/barrel.obj", "obj", null); // загрузить из файла с использованием текстуры кварца
var blockModel = new BlockRenderer.Model(mesh); // создать модель для рендера
После установки нашей модели блоку (к примеру с помощью ICRender), получаем результат:
Заменяя текстуру кварца на развертку бочки, которая была использована до этого и добавляя ее в текстуры блоков получаем ту же самую модель, но для блока (подобные текстуры стоит изменять до квадрата размера степени 2, это оптимальнее и развертка при этом сохраняется):
Для моделей блоков актуальны настройки освещения моделей (для мобов оно рассчитывается самим MCPE). Они задаются следующими методами:setLightParams(min, max, smooth) - задает значения освещения, рассчитанного по нормалям, min, max - минимальное и максимальное (от 0 до 1), smooth - значение сглаживания (больше 0, 1 является нейтральным элементом, по умолчанию 1.9)
setLightDir(x, y, z) - устанавливает направление света, нужное для рассчета освещения по нормалям.
setLightIgnore(ignoreBlockLight, ignoreSkyLight) - задает игнорирование разных типов освещения мира (если тип игнорируется, то освещение всегда максимальное)
Одна и та же модель при значениях по умолчанию и после вызова setLightParams(0, 1,1):