Mesh Converter

From Ciliz|W4
This page contains changes which are not marked for translation.
Other languages:
English • ‎русский

Scope

Игровой движок W4 использует собственный формат хранения ассетов. Следовательно, прежде чем использовать сторонний ассет, его необходимо преобразовать в наш формат. Сделать это можно с помощью инструмента Mesh Converter, который поставляется вместе с нашим SDK.

Mesh Converter позволяет преобразовывать ассеты из формата Autodesk FBX (.fbx). Другие форматы не поддерживаются.

Technical limitations

Конвертер может преобразовать любой fbx со следующими ограничениями:

1. В связи с аппаратными и программными особенностями некоторых популярных моделей устройств skinned mesh может содержать:

  • не более 28 костей
  • не более 8 вершин на кость

How to use

Загрузка репозитория проекта описана в статье Quick Start. Файл конвертера W4MeshConverter.bin находится в каталоге w4framework/tools . Конвертация запускается из командной строки, как это описано на следующем примере и в разделе Short manual.

Mesh Exmple

Preparing

Возьмем для примера Utah teapot. Если посмотрите файл с помощью утилиты Autodesk FBX Review, увидите примерно то же, что на рисунке.

cb84552c-5001-4127-9d9d-1e93f9c96696.png

Обратите внимание на положение носика чайника при просмотре fbx, мы вернемся к этому чуть позже.

Converting

Скопируем файл модели в директорию конвертера.

Далее, для преобразования модели в формат нашего движка (asset) необходимо выполнить:

./W4MeshConverter utah-teapot.fbx teapot

В результате появится директория teapot содержащая данные ассета.

Adding to the project structure

Для работы с ассетом необходимо скопировать его директорию (в нашем случае это teapot) в директорию resources проекта. Директория resources располагается на том же уровне структуры проекта, что и sources. Таким образом, структура проекта станет подобна следующей:

.
└── W4TemplateGame
    ├── resources
    │   └── teapot
    │       ├── Animations
    │       ├── BoneInfo
    │       ├── Materials
    │       │   ├── defaultMaterial.matInst
    │       │   └── defaultSkinnedMaterial.matInst
    │       ├── Splines
    │       ├── teapot.asset
    │       └── VertexData
    │           ├── Utah Teapot Quads_0.ib
    │           └── Utah Teapot Quads.vb
    └── sources
        └── main.cpp

Code example

Загрузка:

 auto asset = Asset::load(Path("resources/teapot", "teapot.asset"));

Добавление в Render (отображение на экране):

 auto root = RootNode::make();
 root->addChild(asset->getRoot());
 Render::instance().getPass(0)->setRoot(root);

Полный код примера:

 #include "W4Framework.h"
 
 W4_USE_UNSTRICT_INTERFACE
 
 class AssetSample : public w4::IGame
 {
 public:
 
     AssetSample() = default;
     ~AssetSample() = default; 
 
     void onStart() override
     {
         auto cam = Render::instance().getScreenCamera();
         cam->setWorldTranslation({0.f, 0, -50.f});
 
         auto asset = Asset::load(Path("resources/teapot", "teapot.asset"));
 
         auto root =  RootNode::make();
         root->addChild(asset->getRoot());
         Render::instance().getPass(0)->setRoot(root);
     }
 };
 
 W4_RUN(AssetSample)

Result

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

3aa4d02a-5152-44d6-9168-13a155f1b049.png

Если сравнить рисунки, можно заметить, что нос чайника в FBX Review смотрит в одну сторону, а в результате выполнения программы в другую. Это происходит из-за различий в системах координат.

Система координат FBX Scene Axis and Unit Conversion является правосторонней (с осью Y направленной верх), тогда как Система координат W4 левосторонняя (ось Y также направлена верх).

Animated mesh Exmple

Для анимированных мешей порядок работы не сильно отличается от описанного выше.

Preparing

Анимированную модель можно найти в интернете. Возьмем, например, Rigged Hand. Просмотр с помощью Autodesk FBX Review покажет примерно следующее:

http://demo.w4-dev.ciliz.com/wiki-files/Hand.mov

Converting

Так же как в примере выше (с обычным мешем), скопируем модель в папку конвертера и преобразуем в формат W4 Engine:

./W4MeshConverter Hand_rigged.FBX hand

В результате выполнения в текущей папке будет получена директория hand, содержащая данные ассета.

Adding to the project structure

Скопируем полученный каталог ассета hand в каталог resources нашего проекта. Примерная структура проекта после этого:

.
└── W4TemplateGame
    ├── resources
    │   └── hand
    │       ├── Animations
    │       │   └── Take 001.ssa
    │       ├── BoneInfo
    │       │   ├── bone_main_hande.skeleton
    │       │   └── Hand_rigged.skin
    │       ├── hand.asset
    │       ├── Materials
    │       │   ├── defaultMaterial.matInst
    │       │   └── defaultSkinnedMaterial.matInst
    │       ├── Splines
    │       └── VertexData
    │           ├── Hand_rigged_0.ib
    │           └── Hand_rigged.vb
    └── sources
        └── main.cpp

Code example

Загрузим asset и добавим его в дерево отрисовки:

 auto asset = Asset::load(Path("resources/hand", "hand.asset"));
 render::getRoot()->addChild(asset->getRoot());

Если мы попробуем сейчас собрать проект, то ничего не увидим. Потому что камера попала “внутрь” asset’a.

Возьмем камеру и передвинем её подальше (возможно, придется задать другие значения, в зависимости от размера окна браузера, размера объекта и т.п.):

 auto cam = render::getScreenCamera();
 cam->setWorldTranslation({0.f, 125.f, -300.f});

Если сейчас собрать проект, то на экране появится рука, но она не будет двигаться.

Чтобы она задвигалась, нужно запустить аниматор у соответствующего skinned mesh’a. Известно, что skinned mesh у нас один и у него одна анимация, поэтому в цикле пройдем по всему дереву asset’a и всем skinned mesh’ам в нём и будем проигрывать анимацию (в нашем примере - первую):

 asset->getRoot()->traversal([&](Node& node)
 {
   if(node.is<SkinnedMesh>())
   {
     auto skinned = node.as<SkinnedMesh>();
     skinned->getAnimator(0).setIsLooped(true);
     skinned->play(0);
   }
 });

Полный код примера:

 #include "W4Framework.h"
 
 W4_USE_UNSTRICT_INTERFACE
 
 class MeshAnimatedSample : public w4::IGame
 {
 public:
     MeshAnimatedSample() = default;
 
     void onStart() override
     {
         auto asset = Asset::load(Path("resources/hand", "hand.asset"));
         render::getRoot()->addChild(asset->getRoot());
 
         auto cam = render::getScreenCamera();
         cam->setWorldTranslation({0.f, 150.f, -300.f});
 
         asset->getRoot()->traversal([&](Node &node)
         {
             if (node.is<SkinnedMesh>())
             {
                 auto skinned = node.as<SkinnedMesh>();
                 skinned->getAnimator(0).setIsLooped(true);
                 skinned->play(0);
             }
         });
     }
 };
 
 W4_RUN(MeshAnimatedSample)

Result

В результате выполнения вышеописанной программы отобразится следующая анимация:

http://demo.w4-dev.ciliz.com/wiki-files/Hand_engine.mov

Short manual

Basics

Конвертация utah-teapot.fbx в ассет с именем asset в текущей директории:

./W4MeshConverter utah-teapot.fbx

Конвертация utah-teapot.fbx в ассет с именем teapot в текущей директории:

./W4MeshConverter utah-teapot.fbx teapot

Конвертация utah-teapot.fbx в ассет с именем teapot, который будет сохранен в директории ~/some/dir:

./W4MeshConverter utah-teapot.fbx teapot ~/some/dir 

Common keys

Справка:

-h, --help

Вывод статистики сцены:

-v, --verbose

Пример статистики:

(DEBUG) ==================== Scene statistics ====================
(DEBUG) Nodes: 2
(DEBUG) Geometries: 1
(DEBUG) Poses: 0
(DEBUG) Materials: 1
(DEBUG) Textures: 0
(DEBUG) ====================== Axis & Scale ======================
(DEBUG) Up: +Y, Front: +ParityOdd, System: RightHanded
(DEBUG) Scale: 1.000000
(DEBUG) ================ Mesh: Red_label ================
(DEBUG) Vertex count: 404
(DEBUG) Index count: 2118
(DEBUG) All polygons are triangles: 1
(DEBUG) ==========================================================
(DEBUG) create default material...
(DEBUG) create default skinned material...

Управление размером (scale) на конвертации, где arg - значение, например (10, 1, 0.1):

--scale arg

Переворот вертикальной оси V текстурных координат, если флаг указан, то к текстурным координатам будет применено преобразование вида V = 1.0 - V:

--uv-flip

Setting limitations

Для всех Mesh'ей могут быть заданы ограничения на максимальное количество вершин и индексов. Для Skinned Mesh'ей могут быть заданы ограничения на максимальное количество костей и максимальное количество костей на вершину.

Модель, которая не соответствует заданным ограничениям, можно принудительно сконвертировать с помощью флага force, однако работоспособность в таком случае не гарантируется:

-f, --force

Установка ограничения на максимальное количество вершин на объект, где arg - значение, по умолчанию не задано:

--max-vertex arg

Установка ограничения на максимальное количество индексов на объект, где arg - значение, по умолчанию не задано:

--max-index arg

Установка ограничения на максимальное количество костей для Skinned Mesh, где arg - значение, по умолчанию 28, при установке значения выше, чем значение по умолчанию, работоспособность не гарантируется:

--max-bones arg

Установка ограничения на максимальное количество костей на вершину для Skinned Mesh, где arg - значение, по умолчанию 8, при установке значения выше, чем значение по умолчанию, работоспособность не гарантируется:

--max-bones-per-vertex arg