mirror of
https://github.com/enduro2d/enduro2d-toolset.git
synced 2025-12-12 19:26:13 +07:00
move model_converter from main e2d repo
This commit is contained in:
11
.appveyor.yml
Normal file
11
.appveyor.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
version: "{build}"
|
||||
image:
|
||||
- Visual Studio 2015
|
||||
- Visual Studio 2017
|
||||
platform:
|
||||
- Win32
|
||||
- x64
|
||||
build_script:
|
||||
- git submodule update --init --recursive
|
||||
- scripts\build_all.bat
|
||||
test: off
|
||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
build/*
|
||||
CMakeLists.txt.user
|
||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "model_converter/modules/assimp"]
|
||||
path = model_converter/modules/assimp
|
||||
url = https://github.com/assimp/assimp/
|
||||
82
.travis.yml
Normal file
82
.travis.yml
Normal file
@@ -0,0 +1,82 @@
|
||||
language: cpp
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
dist: trusty
|
||||
addons: { apt: { sources: ubuntu-toolchain-r-test, packages: ["xorg-dev", "g++-4.9"] } }
|
||||
env: MATRIX_EVAL="CC=gcc-4.9 && CXX=g++-4.9"
|
||||
- os: linux
|
||||
dist: trusty
|
||||
addons: { apt: { sources: ubuntu-toolchain-r-test, packages: ["xorg-dev", "g++-5"] } }
|
||||
env: MATRIX_EVAL="CC=gcc-5 && CXX=g++-5"
|
||||
- os: linux
|
||||
dist: trusty
|
||||
addons: { apt: { sources: ubuntu-toolchain-r-test, packages: ["xorg-dev", "g++-6"] } }
|
||||
env: MATRIX_EVAL="CC=gcc-6 && CXX=g++-6"
|
||||
- os: linux
|
||||
dist: trusty
|
||||
addons: { apt: { sources: ubuntu-toolchain-r-test, packages: ["xorg-dev", "g++-7"] } }
|
||||
env: MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
|
||||
- os: linux
|
||||
dist: trusty
|
||||
addons: { apt: { sources: ubuntu-toolchain-r-test, packages: ["xorg-dev", "g++-8"] } }
|
||||
env: MATRIX_EVAL="CC=gcc-8 && CXX=g++-8"
|
||||
- os: linux
|
||||
dist: trusty
|
||||
addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-precise-3.8"], packages: ["xorg-dev", "clang-3.8", "g++-5"] } }
|
||||
env: MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8"
|
||||
- os: linux
|
||||
dist: trusty
|
||||
addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-precise-3.9"], packages: ["xorg-dev", "clang-3.9", "g++-5"] } }
|
||||
env: MATRIX_EVAL="CC=clang-3.9 && CXX=clang++-3.9"
|
||||
- os: linux
|
||||
dist: trusty
|
||||
addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-trusty-4.0"], packages: ["xorg-dev", "clang-4.0", "g++-5"] } }
|
||||
env: MATRIX_EVAL="CC=clang-4.0 && CXX=clang++-4.0"
|
||||
- os: linux
|
||||
dist: trusty
|
||||
addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-trusty-5.0"], packages: ["xorg-dev", "clang-5.0", "g++-7"] } }
|
||||
env: MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0"
|
||||
- os: linux
|
||||
dist: trusty
|
||||
addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-trusty-6.0"], packages: ["xorg-dev", "clang-6.0", "g++-7"] } }
|
||||
env: MATRIX_EVAL="CC=clang-6.0 && CXX=clang++-6.0"
|
||||
- os: osx
|
||||
osx_image: xcode8.3
|
||||
compiler: clang
|
||||
- os: osx
|
||||
osx_image: xcode9
|
||||
compiler: clang
|
||||
- os: osx
|
||||
osx_image: xcode9.1
|
||||
compiler: clang
|
||||
- os: osx
|
||||
osx_image: xcode9.2
|
||||
compiler: clang
|
||||
- os: osx
|
||||
osx_image: xcode9.3
|
||||
compiler: clang
|
||||
- os: osx
|
||||
osx_image: xcode9.4
|
||||
compiler: clang
|
||||
- os: osx
|
||||
osx_image: xcode10
|
||||
compiler: clang
|
||||
before_install:
|
||||
- eval "${MATRIX_EVAL}"
|
||||
- if [ "$TRAVIS_OS_NAME" == 'osx' ]; then
|
||||
brew update;
|
||||
brew upgrade cmake;
|
||||
brew install git-lfs;
|
||||
fi
|
||||
- if [ "$TRAVIS_OS_NAME" == 'linux' ]; then
|
||||
mkdir $HOME/cmake;
|
||||
export PATH="$HOME/cmake/bin:$PATH";
|
||||
travis_retry wget -q https://cmake.org/files/v3.11/cmake-3.11.4-Linux-x86_64.sh;
|
||||
sh cmake-3.11.4-Linux-x86_64.sh --prefix=$HOME/cmake --exclude-subdir --skip-license;
|
||||
fi
|
||||
script:
|
||||
- git submodule update --init --recursive
|
||||
- git lfs install
|
||||
- git lfs pull
|
||||
- ./scripts/build_all.sh
|
||||
39
BUILD_INSTRUCTIONS.md
Normal file
39
BUILD_INSTRUCTIONS.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Build Instructions
|
||||
|
||||
## * Requirements
|
||||
|
||||
- [git](https://git-scm.com/)
|
||||
- [git-lfs](https://git-lfs.github.com/)
|
||||
- [cmake](https://cmake.org/) **>= 3.11**
|
||||
- [gcc](https://www.gnu.org/software/gcc/) **>= 4.9** or [clang](https://clang.llvm.org/) **>= 3.8** or [msvc](https://visualstudio.microsoft.com/) **>= 2015**
|
||||
|
||||
## * Cloning
|
||||
|
||||
```bash
|
||||
$ git clone --recursive git://github.com/enduro2d/enduro2d-toolset.git
|
||||
$ cd enduro2d-toolset
|
||||
$ git lfs install
|
||||
$ git lfs pull
|
||||
```
|
||||
|
||||
## * Building
|
||||
|
||||
```bash
|
||||
$ cd your_toolset_repository_directory
|
||||
$ mkdir build && cd build
|
||||
$ cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
$ cmake --build . -- -j8
|
||||
```
|
||||
|
||||
## * Running
|
||||
|
||||
```bash
|
||||
$ cd your_toolset_build_directory
|
||||
$ ./model_converter/model_converter
|
||||
```
|
||||
|
||||
## * Links
|
||||
|
||||
- CMake: https://cmake.org/
|
||||
- CMake documentation: https://cmake.org/documentation/
|
||||
- CMake FAQ: https://gitlab.kitware.com/cmake/community/wikis/FAQ
|
||||
7
CMakeLists.txt
Normal file
7
CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.11 FATAL_ERROR)
|
||||
project(enduro2d-toolset)
|
||||
|
||||
option(E2D_BUILD_MODEL_CONVERTER "Build model converter" ON)
|
||||
if(E2D_BUILD_MODEL_CONVERTER)
|
||||
add_subdirectory(model_converter)
|
||||
endif()
|
||||
21
LICENSE.md
Normal file
21
LICENSE.md
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018-2019 Matvey Cherevko
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
23
README.md
Normal file
23
README.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Enduro2D-toolset (work in progress)
|
||||
|
||||
[![travis][badge.travis]][travis]
|
||||
[![appveyor][badge.appveyor]][appveyor]
|
||||
[![language][badge.language]][language]
|
||||
[![license][badge.license]][license]
|
||||
[![paypal][badge.paypal]][paypal]
|
||||
|
||||
## [Build Instructions](./BUILD_INSTRUCTIONS.md)
|
||||
|
||||
## [License (MIT)](./LICENSE.md)
|
||||
|
||||
[badge.travis]: https://img.shields.io/travis/enduro2d/enduro2d-toolset/master.svg?logo=travis
|
||||
[badge.appveyor]: https://img.shields.io/appveyor/ci/BlackMATov/enduro2d-toolset/master.svg?logo=appveyor
|
||||
[badge.language]: https://img.shields.io/badge/language-C%2B%2B14-red.svg
|
||||
[badge.license]: https://img.shields.io/badge/license-MIT-blue.svg
|
||||
[badge.paypal]: https://img.shields.io/badge/donate-PayPal-orange.svg?logo=paypal&colorA=00457C
|
||||
|
||||
[travis]: https://travis-ci.org/enduro2d/enduro2d-toolset
|
||||
[appveyor]: https://ci.appveyor.com/project/BlackMATov/enduro2d-toolset
|
||||
[language]: https://en.wikipedia.org/wiki/C%2B%2B14
|
||||
[license]: https://en.wikipedia.org/wiki/MIT_License
|
||||
[paypal]: https://www.paypal.me/matov
|
||||
29
model_converter/CMakeLists.txt
Normal file
29
model_converter/CMakeLists.txt
Normal file
@@ -0,0 +1,29 @@
|
||||
#
|
||||
# external 3rd party
|
||||
#
|
||||
|
||||
set(ASSIMP_NO_EXPORT ON CACHE BOOL "" FORCE)
|
||||
set(ASSIMP_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
||||
set(ASSIMP_BUILD_ASSIMP_TOOLS OFF CACHE BOOL "" FORCE)
|
||||
add_subdirectory(modules/assimp)
|
||||
|
||||
#
|
||||
# model converter executable
|
||||
#
|
||||
|
||||
file(GLOB MODEL_CONVERTER_SOURCES
|
||||
sources/*.*)
|
||||
|
||||
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES
|
||||
${MODEL_CONVERTER_SOURCES})
|
||||
|
||||
add_executable(model_converter
|
||||
${MODEL_CONVERTER_SOURCES})
|
||||
|
||||
target_link_libraries(model_converter
|
||||
assimp)
|
||||
|
||||
set_target_properties(model_converter PROPERTIES
|
||||
CXX_STANDARD 14
|
||||
CXX_STANDARD_REQUIRED YES
|
||||
CXX_EXTENSIONS NO)
|
||||
1
model_converter/modules/assimp
Submodule
1
model_converter/modules/assimp
Submodule
Submodule model_converter/modules/assimp added at bc0064d3b0
406
model_converter/sources/main.cpp
Normal file
406
model_converter/sources/main.cpp
Normal file
@@ -0,0 +1,406 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "Enduro2D"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2018-2019 Matvey Cherevko
|
||||
******************************************************************************/
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
|
||||
#include <assimp/Importer.hpp>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/postprocess.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
const std::uint32_t mesh_file_version = 1;
|
||||
const std::string mesh_file_signature = "e2d_mesh";
|
||||
|
||||
struct opts {
|
||||
bool timers = false;
|
||||
bool verbose = false;
|
||||
|
||||
opts(int argc, char *argv[]) {
|
||||
timers = has_flag("-t", argc, argv) || has_flag("--timers", argc, argv);
|
||||
verbose = has_flag("-v", argc, argv) || has_flag("--verbose", argc, argv);
|
||||
}
|
||||
|
||||
private:
|
||||
static bool has_flag(const char* flag, int argc, char *argv[]) noexcept {
|
||||
for ( int i = 0; i < argc; ++i ) {
|
||||
if ( 0 == std::strcmp(argv[i], flag) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class timer {
|
||||
public:
|
||||
timer()
|
||||
: tp_(std::chrono::high_resolution_clock::now()) {}
|
||||
|
||||
void done() const {
|
||||
const auto duration_us = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::high_resolution_clock::now() - tp_);
|
||||
std::cout << duration_us.count() << "us" << std::endl;
|
||||
}
|
||||
private:
|
||||
std::chrono::high_resolution_clock::time_point tp_;
|
||||
};
|
||||
|
||||
struct v2f {
|
||||
float x = 0.f;
|
||||
float y = 0.f;
|
||||
|
||||
v2f(float nx, float ny)
|
||||
: x(nx), y(ny) {}
|
||||
};
|
||||
|
||||
struct v3f {
|
||||
float x = 0.f;
|
||||
float y = 0.f;
|
||||
float z = 0.f;
|
||||
|
||||
v3f(float nx, float ny, float nz)
|
||||
: x(nx), y(ny), z(nz) {}
|
||||
};
|
||||
|
||||
struct mesh {
|
||||
std::vector<v3f> vertices;
|
||||
std::vector<std::uint32_t> indices;
|
||||
|
||||
std::vector<std::vector<v2f>> uvs_channels;
|
||||
std::vector<std::vector<std::uint32_t>> colors_channels;
|
||||
|
||||
std::vector<v3f> normals;
|
||||
std::vector<v3f> tangents;
|
||||
std::vector<v3f> bitangents;
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
T saturate(T v) noexcept {
|
||||
return std::min(std::max(v, T(0)), T(1));
|
||||
}
|
||||
|
||||
std::uint8_t pack_color_component(float c) noexcept {
|
||||
return static_cast<std::uint8_t>(std::round(saturate(c) * 255.f));
|
||||
}
|
||||
|
||||
std::uint32_t pack_color(float r, float g, float b, float a) noexcept {
|
||||
std::uint8_t rr = pack_color_component(r);
|
||||
std::uint8_t gg = pack_color_component(g);
|
||||
std::uint8_t bb = pack_color_component(b);
|
||||
std::uint8_t aa = pack_color_component(a);
|
||||
return
|
||||
static_cast<std::uint32_t>(aa) << 24 |
|
||||
static_cast<std::uint32_t>(rr) << 16 |
|
||||
static_cast<std::uint32_t>(gg) << 8 |
|
||||
static_cast<std::uint32_t>(bb) << 0;
|
||||
}
|
||||
|
||||
void write_u32_to_ofstream(std::ofstream& s, const std::uint32_t v) {
|
||||
s.write(
|
||||
reinterpret_cast<const char*>(&v),
|
||||
sizeof(v));
|
||||
}
|
||||
|
||||
void write_str_to_ofstream(std::ofstream& s, const std::string& v) {
|
||||
s.write(v.data(), static_cast<std::ptrdiff_t>(v.length()));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
std::size_t write_vector_to_ofstream(std::ofstream& s, const std::vector<T>& v) {
|
||||
if ( !v.empty() ) {
|
||||
std::size_t data_size = v.size() * sizeof(T);
|
||||
s.write(
|
||||
reinterpret_cast<const char*>(v.data()),
|
||||
static_cast<std::ptrdiff_t>(data_size));
|
||||
return data_size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool validate_mesh(const mesh& mesh) noexcept {
|
||||
if ( mesh.vertices.empty() ) {
|
||||
return false;
|
||||
}
|
||||
if ( mesh.indices.empty() ) {
|
||||
return false;
|
||||
}
|
||||
for ( const auto& uvs : mesh.uvs_channels ) {
|
||||
if ( uvs.size() != mesh.vertices.size() ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for ( const auto& colors : mesh.colors_channels ) {
|
||||
if ( colors.size() != mesh.vertices.size() ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ( !mesh.normals.empty() && mesh.normals.size() != mesh.vertices.size() ) {
|
||||
return false;
|
||||
}
|
||||
if ( !mesh.tangents.empty() && mesh.tangents.size() != mesh.vertices.size() ) {
|
||||
return false;
|
||||
}
|
||||
if ( !mesh.bitangents.empty() && mesh.bitangents.size() != mesh.vertices.size() ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool save_mesh(const mesh& mesh, const std::string& out_path, const opts& opts) {
|
||||
timer save_timer;
|
||||
|
||||
if ( !validate_mesh(mesh) ) {
|
||||
std::cerr << "Failed to validate out mesh: " << out_path << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::ofstream stream(out_path, std::ofstream::out | std::ofstream::binary);
|
||||
if ( !stream.is_open() ) {
|
||||
std::cerr << "Failed to open out file stream: " << out_path << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
write_str_to_ofstream(stream, mesh_file_signature);
|
||||
write_u32_to_ofstream(stream, mesh_file_version);
|
||||
|
||||
write_u32_to_ofstream(stream, static_cast<std::uint32_t>(mesh.vertices.size()));
|
||||
write_u32_to_ofstream(stream, static_cast<std::uint32_t>(mesh.indices.size()));
|
||||
|
||||
write_u32_to_ofstream(stream, static_cast<std::uint32_t>(mesh.uvs_channels.size()));
|
||||
write_u32_to_ofstream(stream, static_cast<std::uint32_t>(mesh.colors_channels.size()));
|
||||
|
||||
write_u32_to_ofstream(stream, static_cast<std::uint32_t>(mesh.normals.size()));
|
||||
write_u32_to_ofstream(stream, static_cast<std::uint32_t>(mesh.tangents.size()));
|
||||
write_u32_to_ofstream(stream, static_cast<std::uint32_t>(mesh.bitangents.size()));
|
||||
|
||||
std::size_t vertices_bytes = write_vector_to_ofstream(stream, mesh.vertices);
|
||||
std::size_t indices_bytes = write_vector_to_ofstream(stream, mesh.indices);
|
||||
|
||||
std::size_t uvs_bytes = 0;
|
||||
for ( const auto& uvs : mesh.uvs_channels ) {
|
||||
uvs_bytes += write_vector_to_ofstream(stream, uvs);
|
||||
}
|
||||
|
||||
std::size_t colors_bytes = 0;
|
||||
for ( const auto& colors : mesh.colors_channels ) {
|
||||
colors_bytes += write_vector_to_ofstream(stream, colors);
|
||||
}
|
||||
|
||||
std::size_t normals_bytes = write_vector_to_ofstream(stream, mesh.normals);
|
||||
std::size_t tangents_bytes = write_vector_to_ofstream(stream, mesh.tangents);
|
||||
std::size_t bitangents_bytes = write_vector_to_ofstream(stream, mesh.bitangents);
|
||||
|
||||
if ( opts.timers ) {
|
||||
std::cout << "> save mesh: ";
|
||||
save_timer.done();
|
||||
std::cout << " - " << out_path << std::endl;
|
||||
}
|
||||
|
||||
if ( opts.verbose ) {
|
||||
std::cout
|
||||
<< std::endl
|
||||
<< "> mesh info:" << std::endl
|
||||
<< "-> vertices: " << mesh.vertices.size() << ", " << vertices_bytes << " B" << std::endl
|
||||
<< "-> indices: " << mesh.indices.size() << ", " << indices_bytes << " B" << std::endl
|
||||
<< "-> uvs: " << mesh.uvs_channels.size() << ", " << uvs_bytes << " B" << std::endl
|
||||
<< "-> colors: " << mesh.colors_channels.size() << ", " << colors_bytes << " B" << std::endl
|
||||
<< "-> normals: " << mesh.normals.size() << ", " << normals_bytes << " B" << std::endl
|
||||
<< "-> tangents: " << mesh.tangents.size() << ", " << tangents_bytes << " B" << std::endl
|
||||
<< "-> bitangents: " << mesh.bitangents.size() << ", " << bitangents_bytes << " B" << std::endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool convert_mesh(const aiMesh* ai_mesh, const std::string& out_path, const opts& opts) {
|
||||
mesh out_mesh;
|
||||
timer convert_timer;
|
||||
|
||||
if ( ai_mesh->HasPositions() ) {
|
||||
out_mesh.vertices.reserve(ai_mesh->mNumVertices);
|
||||
std::transform(
|
||||
ai_mesh->mVertices,
|
||||
ai_mesh->mVertices + ai_mesh->mNumVertices,
|
||||
std::back_inserter(out_mesh.vertices),
|
||||
[](const aiVector3D& v) noexcept {
|
||||
return v3f{v.x, v.y, v.z};
|
||||
});
|
||||
}
|
||||
|
||||
if ( ai_mesh->HasFaces() ) {
|
||||
out_mesh.indices.reserve(ai_mesh->mNumFaces * 3u);
|
||||
std::for_each(
|
||||
ai_mesh->mFaces,
|
||||
ai_mesh->mFaces + ai_mesh->mNumFaces,
|
||||
[&out_mesh](const aiFace& f) {
|
||||
if ( f.mNumIndices != 3 ) {
|
||||
throw std::logic_error("invalide face index count");
|
||||
}
|
||||
out_mesh.indices.insert(
|
||||
out_mesh.indices.end(),
|
||||
f.mIndices,
|
||||
f.mIndices + f.mNumIndices);
|
||||
});
|
||||
}
|
||||
|
||||
for ( unsigned int channel = 0; channel < ai_mesh->GetNumUVChannels(); ++channel ) {
|
||||
std::vector<v2f> uvs;
|
||||
uvs.reserve(ai_mesh->mNumVertices);
|
||||
std::transform(
|
||||
ai_mesh->mTextureCoords[channel],
|
||||
ai_mesh->mTextureCoords[channel] + ai_mesh->mNumVertices,
|
||||
std::back_inserter(uvs),
|
||||
[](const aiVector3D& v) noexcept {
|
||||
return v2f{v.x, v.y};
|
||||
});
|
||||
out_mesh.uvs_channels.emplace_back(std::move(uvs));
|
||||
}
|
||||
|
||||
for ( unsigned int channel = 0; channel < ai_mesh->GetNumColorChannels(); ++channel ) {
|
||||
std::vector<std::uint32_t> colors;
|
||||
colors.reserve(ai_mesh->mNumVertices);
|
||||
std::transform(
|
||||
ai_mesh->mColors[channel],
|
||||
ai_mesh->mColors[channel] + ai_mesh->mNumVertices,
|
||||
std::back_inserter(colors),
|
||||
[](const aiColor4D& v) noexcept {
|
||||
return pack_color(v.r, v.g, v.b, v.a);
|
||||
});
|
||||
out_mesh.colors_channels.emplace_back(std::move(colors));
|
||||
}
|
||||
|
||||
if ( ai_mesh->HasNormals() ) {
|
||||
out_mesh.normals.reserve(ai_mesh->mNumVertices);
|
||||
std::transform(
|
||||
ai_mesh->mNormals,
|
||||
ai_mesh->mNormals + ai_mesh->mNumVertices,
|
||||
std::back_inserter(out_mesh.normals),
|
||||
[](const aiVector3D& v) noexcept {
|
||||
return v3f{v.x, v.y, v.z};
|
||||
});
|
||||
}
|
||||
|
||||
if ( ai_mesh->HasTangentsAndBitangents() ) {
|
||||
out_mesh.tangents.reserve(ai_mesh->mNumVertices);
|
||||
std::transform(
|
||||
ai_mesh->mTangents,
|
||||
ai_mesh->mTangents + ai_mesh->mNumVertices,
|
||||
std::back_inserter(out_mesh.tangents),
|
||||
[](const aiVector3D& v) noexcept {
|
||||
return v3f{v.x, v.y, v.z};
|
||||
});
|
||||
|
||||
out_mesh.bitangents.reserve(ai_mesh->mNumVertices);
|
||||
std::transform(
|
||||
ai_mesh->mBitangents,
|
||||
ai_mesh->mBitangents + ai_mesh->mNumVertices,
|
||||
std::back_inserter(out_mesh.bitangents),
|
||||
[](const aiVector3D& v) noexcept {
|
||||
return v3f{v.x, v.y, v.z};
|
||||
});
|
||||
}
|
||||
|
||||
if ( opts.timers ) {
|
||||
std::cout << std::endl << "> convert mesh: ";
|
||||
convert_timer.done();
|
||||
std::cout << " - " << out_path << std::endl;
|
||||
}
|
||||
|
||||
return save_mesh(out_mesh, out_path, opts);
|
||||
}
|
||||
|
||||
bool convert(const std::string& path, const opts& opts) {
|
||||
timer convert_timer;
|
||||
timer importer_timer;
|
||||
|
||||
Assimp::Importer importer;
|
||||
|
||||
if ( opts.timers ) {
|
||||
std::cout << "> prepare importer: ";
|
||||
importer_timer.done();
|
||||
}
|
||||
|
||||
const unsigned int importer_flags =
|
||||
aiProcess_Triangulate |
|
||||
aiProcess_MakeLeftHanded |
|
||||
aiProcess_OptimizeMeshes |
|
||||
aiProcess_JoinIdenticalVertices;
|
||||
|
||||
timer import_timer;
|
||||
|
||||
const aiScene* scene = importer.ReadFile(path, importer_flags);
|
||||
if ( !scene ) {
|
||||
std::cerr << "Failed to import model: " << path << std::endl;
|
||||
std::cerr << "Error: " << importer.GetErrorString() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( opts.timers ) {
|
||||
std::cout << "> import model: ";
|
||||
import_timer.done();
|
||||
}
|
||||
|
||||
for ( unsigned int mesh_index = 0; mesh_index < scene->mNumMeshes; ++mesh_index ) {
|
||||
const aiMesh* mesh = scene->mMeshes[mesh_index];
|
||||
|
||||
const std::string mesh_name = mesh->mName.length
|
||||
? mesh->mName.C_Str()
|
||||
: "mesh_" + std::to_string(mesh_index);
|
||||
|
||||
std::string mesh_out_path = std::string()
|
||||
.append(path)
|
||||
.append(".")
|
||||
.append(mesh_name)
|
||||
.append(".e2d_mesh");
|
||||
|
||||
if ( opts.verbose ) {
|
||||
std::cout
|
||||
<< std::endl
|
||||
<< ">> Mesh("
|
||||
<< mesh_name
|
||||
<< ") converting..."
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
if ( !convert_mesh(mesh, mesh_out_path, opts) ) {
|
||||
std::cerr << "Failed!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( opts.verbose ) {
|
||||
std::cout << "OK. " << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if ( opts.timers ) {
|
||||
std::cout << std::endl << "=====" << std::endl;
|
||||
convert_timer.done();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if ( argc < 2 ) {
|
||||
std::cout << "USAGE: model_converter mesh.obj" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
return convert(argv[1], opts(argc, argv)) ? 0 : 1;
|
||||
}
|
||||
10
scripts/build_all.bat
Normal file
10
scripts/build_all.bat
Normal file
@@ -0,0 +1,10 @@
|
||||
@echo off
|
||||
set SCRIPT_DIR=%~dp0%
|
||||
call %SCRIPT_DIR%\build_debug.bat || goto :error
|
||||
call %SCRIPT_DIR%\build_release.bat || goto :error
|
||||
|
||||
goto :EOF
|
||||
|
||||
:error
|
||||
echo Failed with error #%errorlevel%.
|
||||
exit /b %errorlevel%
|
||||
5
scripts/build_all.sh
Executable file
5
scripts/build_all.sh
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
SCRIPT_DIR=`dirname "$BASH_SOURCE"`
|
||||
$SCRIPT_DIR/build_debug.sh
|
||||
$SCRIPT_DIR/build_release.sh
|
||||
9
scripts/build_clear.bat
Normal file
9
scripts/build_clear.bat
Normal file
@@ -0,0 +1,9 @@
|
||||
@echo off
|
||||
set BUILD_DIR=%~dp0%\..\build
|
||||
rmdir /s /q %BUILD_DIR% || goto :error
|
||||
|
||||
goto :EOF
|
||||
|
||||
:error
|
||||
echo Failed with error #%errorlevel%.
|
||||
exit /b %errorlevel%
|
||||
4
scripts/build_clear.sh
Executable file
4
scripts/build_clear.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
BUILD_DIR=`dirname "$BASH_SOURCE"`/../build
|
||||
rm -rf $BUILD_DIR
|
||||
13
scripts/build_debug.bat
Normal file
13
scripts/build_debug.bat
Normal file
@@ -0,0 +1,13 @@
|
||||
@echo off
|
||||
set BUILD_DIR=%~dp0%\..\build
|
||||
mkdir %BUILD_DIR%\debug || goto :error
|
||||
cd %BUILD_DIR%\debug || goto :error
|
||||
cmake ../.. || goto :error
|
||||
cmake --build . --config Debug || goto :error
|
||||
cd ..\.. || goto :error
|
||||
|
||||
goto :EOF
|
||||
|
||||
:error
|
||||
echo Failed with error #%errorlevel%.
|
||||
exit /b %errorlevel%
|
||||
8
scripts/build_debug.sh
Executable file
8
scripts/build_debug.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
BUILD_DIR=`dirname "$BASH_SOURCE"`/../build
|
||||
mkdir -p $BUILD_DIR/debug
|
||||
cd $BUILD_DIR/debug
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug ../..
|
||||
cmake --build . -- -j8
|
||||
cd ../..
|
||||
13
scripts/build_release.bat
Normal file
13
scripts/build_release.bat
Normal file
@@ -0,0 +1,13 @@
|
||||
@echo off
|
||||
set BUILD_DIR=%~dp0%\..\build
|
||||
mkdir %BUILD_DIR%\release || goto :error
|
||||
cd %BUILD_DIR%\release || goto :error
|
||||
cmake ../.. || goto :error
|
||||
cmake --build . --config Release || goto :error
|
||||
cd ..\.. || goto :error
|
||||
|
||||
goto :EOF
|
||||
|
||||
:error
|
||||
echo Failed with error #%errorlevel%.
|
||||
exit /b %errorlevel%
|
||||
8
scripts/build_release.sh
Executable file
8
scripts/build_release.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
BUILD_DIR=`dirname "$BASH_SOURCE"`/../build
|
||||
mkdir -p $BUILD_DIR/release
|
||||
cd $BUILD_DIR/release
|
||||
cmake -DCMAKE_BUILD_TYPE=Release ../..
|
||||
cmake --build . -- -j8
|
||||
cd ../..
|
||||
5
scripts/update_modules.sh
Executable file
5
scripts/update_modules.sh
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
git submodule init
|
||||
git submodule update
|
||||
git pull --recurse-submodules
|
||||
git submodule update --init --remote --recursive
|
||||
Reference in New Issue
Block a user