Difference between revisions of "Mesh Converter/ru"

From Ciliz|W4
(Updating to match new version of source page)
 
(Updating to match new version of source page)
 
(One intermediate revision by the same user not shown)
Line 18: Line 18:
 
=== Mesh Exmple ===
 
=== Mesh Exmple ===
 
==== Preparing ====
 
==== Preparing ====
Возьмем для примера Utah teapot.
+
Возьмем для примера [http://demo.w4-dev.ciliz.com/wiki-files/utah-teapot.fbx Utah teapot].
 
Если посмотрите файл с помощью утилиты [https://www.autodesk.com/products/fbx/fbx-review Autodesk FBX Review], увидите примерно то же, что на рисунке.
 
Если посмотрите файл с помощью утилиты [https://www.autodesk.com/products/fbx/fbx-review Autodesk FBX Review], увидите примерно то же, что на рисунке.
  
[[File:D1b94d56-cb70-428b-ac1c-65701c690238.png|500px]]
+
http://demo.w4-dev.ciliz.com/wiki-files/cb84552c-5001-4127-9d9d-1e93f9c96696.png
  
 
Обратите внимание на положение носика чайника при просмотре fbx, мы вернемся к этому чуть позже.
 
Обратите внимание на положение носика чайника при просмотре fbx, мы вернемся к этому чуть позже.
Line 56: Line 56:
 
Загрузка:
 
Загрузка:
  
 +
<syntaxhighlight lang="c++">
 
  auto asset = Asset::load(Path("resources/teapot", "teapot.asset"));
 
  auto asset = Asset::load(Path("resources/teapot", "teapot.asset"));
 +
</syntaxhighlight>
  
 
Добавление в Render (отображение на экране):
 
Добавление в Render (отображение на экране):
  
 +
<syntaxhighlight lang="c++">
 
  auto root = RootNode::make();
 
  auto root = RootNode::make();
 
  root->addChild(asset->getRoot());
 
  root->addChild(asset->getRoot());
 
  Render::instance().getPass(0)->setRoot(root);
 
  Render::instance().getPass(0)->setRoot(root);
 +
</syntaxhighlight>
  
 
Полный код примера:
 
Полный код примера:
  
 +
<syntaxhighlight lang="c++">
 
  #include "W4Framework.h"
 
  #include "W4Framework.h"
 
   
 
   
Line 91: Line 96:
 
   
 
   
 
  W4_RUN(AssetSample)
 
  W4_RUN(AssetSample)
 +
</syntaxhighlight>
  
 
==== Result ====
 
==== Result ====
 
В результате выполнения должен отобразиться тот же чайник, но с небольшим отличием.
 
В результате выполнения должен отобразиться тот же чайник, но с небольшим отличием.
  
[[File:1b952599-fc03-428f-96e8-ae86935b46d8.png|500px]]
+
http://demo.w4-dev.ciliz.com/wiki-files/3aa4d02a-5152-44d6-9168-13a155f1b049.png
  
 
Если сравнить рисунки, можно заметить, что нос чайника в FBX Review смотрит в одну сторону, а в результате выполнения программы в другую. Это происходит из-за различий в системах координат.
 
Если сравнить рисунки, можно заметить, что нос чайника в FBX Review смотрит в одну сторону, а в результате выполнения программы в другую. Это происходит из-за различий в системах координат.
Line 104: Line 110:
 
Для анимированных мешей порядок работы не сильно отличается от описанного [http://wiki.w4-dev.ciliz.com/index.php/Mesh_Converter#Mesh_Exmple выше].
 
Для анимированных мешей порядок работы не сильно отличается от описанного [http://wiki.w4-dev.ciliz.com/index.php/Mesh_Converter#Mesh_Exmple выше].
 
==== Preparing ====
 
==== Preparing ====
Анимированную модель можно найти в интернете. Возьмем, например, Rigged Hand.
+
Анимированную модель можно найти в интернете. Возьмем, например, [http://demo.w4-dev.ciliz.com/wiki-files/Hand_rigged.FBX Rigged Hand].
 
Просмотр с помощью [https://www.autodesk.com/products/fbx/fbx-review Autodesk FBX Review] покажет примерно следующее:
 
Просмотр с помощью [https://www.autodesk.com/products/fbx/fbx-review Autodesk FBX Review] покажет примерно следующее:
  
 
[[file:hand.mov|500px]]
 
[[file:hand.mov|500px]]
 +
 +
http://demo.w4-dev.ciliz.com/wiki-files/Hand.mov
  
 
==== Converting ====
 
==== Converting ====
Line 141: Line 149:
 
Загрузим asset и добавим его в дерево отрисовки:
 
Загрузим asset и добавим его в дерево отрисовки:
  
 +
<syntaxhighlight lang="c++">
 
  auto asset = Asset::load(Path("resources/hand", "hand.asset"));
 
  auto asset = Asset::load(Path("resources/hand", "hand.asset"));
 
  render::getRoot()->addChild(asset->getRoot());
 
  render::getRoot()->addChild(asset->getRoot());
 +
</syntaxhighlight>
  
 
Если мы попробуем сейчас собрать проект, то ничего не увидим. Потому что камера попала “внутрь” asset’a.
 
Если мы попробуем сейчас собрать проект, то ничего не увидим. Потому что камера попала “внутрь” asset’a.
Line 148: Line 158:
 
Возьмем камеру и передвинем её подальше (возможно, придется задать другие значения, в зависимости от размера окна браузера, размера объекта и т.п.):
 
Возьмем камеру и передвинем её подальше (возможно, придется задать другие значения, в зависимости от размера окна браузера, размера объекта и т.п.):
  
 +
<syntaxhighlight lang="c++">
 
  auto cam = render::getScreenCamera();
 
  auto cam = render::getScreenCamera();
 
  cam->setWorldTranslation({0.f, 125.f, -300.f});
 
  cam->setWorldTranslation({0.f, 125.f, -300.f});
 
+
</syntaxhighlight>
 +
 
 
Если сейчас собрать проект, то на экране появится рука, но она не будет двигаться.
 
Если сейчас собрать проект, то на экране появится рука, но она не будет двигаться.
  
 
Чтобы она задвигалась, нужно запустить аниматор у соответствующего skinned mesh’a. Известно, что skinned mesh у нас один и у него одна анимация, поэтому в цикле пройдем по всему дереву asset’a и всем skinned mesh’ам в нём и будем проигрывать анимацию (в нашем примере - первую):
 
Чтобы она задвигалась, нужно запустить аниматор у соответствующего skinned mesh’a. Известно, что skinned mesh у нас один и у него одна анимация, поэтому в цикле пройдем по всему дереву asset’a и всем skinned mesh’ам в нём и будем проигрывать анимацию (в нашем примере - первую):
  
 +
<syntaxhighlight lang="c++">
 
  asset->getRoot()->traversal([&](Node& node)
 
  asset->getRoot()->traversal([&](Node& node)
 
  {
 
  {
Line 164: Line 177:
 
   }
 
   }
 
  });
 
  });
 +
</syntaxhighlight>
  
 
Полный код примера:
 
Полный код примера:
  
 +
<syntaxhighlight lang="c++">
 
  #include "W4Framework.h"
 
  #include "W4Framework.h"
 
   
 
   
Line 197: Line 212:
 
   
 
   
 
  W4_RUN(MeshAnimatedSample)
 
  W4_RUN(MeshAnimatedSample)
 +
</syntaxhighlight>
  
 
==== Result ====
 
==== Result ====
Line 202: Line 218:
  
 
[[File:Hand engine.mov|500px]]
 
[[File:Hand engine.mov|500px]]
 +
 +
http://demo.w4-dev.ciliz.com/wiki-files/Hand_engine.mov
  
 
== Short manual ==
 
== Short manual ==

Latest revision as of 13:23, 1 June 2020

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