Consolidate two filamesh readers into a lib.

This commit is contained in:
Philip Rideout
2018-10-16 13:31:16 -07:00
parent d9204052c8
commit 9e5f44bd34
16 changed files with 182 additions and 225 deletions
+1
View File
@@ -270,6 +270,7 @@ add_subdirectory(${EXTERNAL}/libgtest/tnt)
add_subdirectory(${LIBRARIES}/filabridge)
add_subdirectory(${LIBRARIES}/filaflat)
add_subdirectory(${LIBRARIES}/filamat)
add_subdirectory(${LIBRARIES}/filameshio)
add_subdirectory(${LIBRARIES}/image)
add_subdirectory(${LIBRARIES}/math)
add_subdirectory(${LIBRARIES}/utils)
+4 -3
View File
@@ -116,6 +116,7 @@ Many other features have been either prototyped or planned:
- `filaflat`: Serialization/deserialization library used for materials
- `filagui`: Helper library for [Dear ImGui](https://github.com/ocornut/imgui)
- `filamat`: Material generation library
- `filameshio`: Tiny mesh parsing library (see also `tools/filamesh`)
- `image`: Image filtering and simple transforms
- `imageio`: Image file reading / writing, only intended for internal use
- `math`: Math library
@@ -132,7 +133,7 @@ Many other features have been either prototyped or planned:
- `matinfo` Displays information about materials compiled with `matc`
- `mipgen` Generates a series of miplevels from a source image.
- `normal-blending`: Tool to blend normal maps
- `roughness-prefilter`: Pre-filters a roughness map from a normal map to reduce aliasing
- `roughness-prefilter`: Pre-filters a roughness map from a normal map to reduce aliasing
- `skygen`: Physically-based sky environment texture generator
- `specular-color`: Computes the specular color of conductors based on spectral data
@@ -730,7 +731,7 @@ in your build directory). These sample apps expect a path to a directory contain
for the IBL. To generate an IBL simply use this command:
```
cmgen -x ./ibls/ my_ibl.exr
cmgen -x ./ibls/ my_ibl.exr
```
The source environment map can be a PNG (8 or 16 bit), a PSD (16 or 32 bit), an HDR or an OpenEXR
@@ -870,7 +871,7 @@ Host tools (such as `matc` or `cmgen`) can use external dependencies freely.
## How to make contributions
Please read and follow the steps in [CONTRIBUTING.md](/CONTRIBUTING.md). Make sure you are
familiar with the [code style](/CODE_STYLE.md).
familiar with the [code style](/CODE_STYLE.md).
## License
+1 -1
View File
@@ -18,4 +18,4 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COPTS}")
add_executable(filamentjs jsenums.cpp jsbindings.cpp)
set_target_properties(filamentjs PROPERTIES OUTPUT_NAME filament)
target_link_libraries(filamentjs PRIVATE filament math utils image)
target_link_libraries(filamentjs PRIVATE filament math utils image filameshio)
+27
View File
@@ -0,0 +1,27 @@
cmake_minimum_required(VERSION 3.1)
project(filameshio)
set(TARGET filameshio)
set(PUBLIC_HDR_DIR include)
# ==================================================================================================
# Sources and headers
# ==================================================================================================
set(PUBLIC_HDRS ${PUBLIC_HDR_DIR}/${TARGET}/MeshIO.h)
set(DIST_HDRS ${PUBLIC_HDR_DIR}/${TARGET}/MeshIO.h)
set(SRCS src/MeshIO.cpp)
# ==================================================================================================
# Includes and target definition
# ==================================================================================================
include_directories(${PUBLIC_HDR_DIR})
add_library(${TARGET} STATIC ${PUBLIC_HDRS} ${SRCS})
target_include_directories(${TARGET} PUBLIC ${PUBLIC_HDR_DIR})
target_link_libraries(${TARGET} PUBLIC filament)
# ==================================================================================================
# Installation
# ==================================================================================================
set(INSTALL_TYPE ARCHIVE)
install(TARGETS ${TARGET} ${INSTALL_TYPE} DESTINATION lib/${DIST_DIR})
install(FILES ${DIST_HDRS} DESTINATION include/${TARGET})
@@ -14,34 +14,44 @@
* limitations under the License.
*/
#ifndef TNT_FILAMENT_SAMPLE_MESHIO_H
#define TNT_FILAMENT_SAMPLE_MESHIO_H
#ifndef TNT_FILAMENT_FILAMESHIO_MESHIO_H
#define TNT_FILAMENT_FILAMESHIO_MESHIO_H
#include <utils/Entity.h>
#include <utils/Path.h>
#include <map>
#include <utils/Entity.h>
#include <string>
namespace filament {
class Engine;
class Renderable;
class VertexBuffer;
class IndexBuffer;
class MaterialInstance;
}
namespace utils {
class Path;
}
class MeshIO {
public:
using Callback = void(*)(void* buffer, size_t size, void* user);
using MaterialRegistry = std::map<std::string, filament::MaterialInstance*>;
struct Mesh {
utils::Entity renderable;
filament::VertexBuffer* vertexBuffer = nullptr;
filament::IndexBuffer* indexBuffer = nullptr;
};
static Mesh loadMeshFromFile(filament::Engine* engine, const utils::Path& path,
const std::map<std::string, filament::MaterialInstance*>& materials);
static Mesh loadMeshFromFile(filament::Engine* engine,
const utils::Path& path,
const MaterialRegistry& materials);
static Mesh loadMeshFromBuffer(filament::Engine* engine,
void const* data, Callback destructor, void* user,
const MaterialRegistry& materials);
static Mesh loadMeshFromBuffer(filament::Engine* engine,
void const* data, Callback destructor, void* user,
filament::MaterialInstance* defaultMaterial);
};
#endif //TNT_FILAMENT_SAMPLE_MESHIO_H
#endif // TNT_FILAMENT_FILAMESHIO_MESHIO_H
@@ -14,7 +14,7 @@
* limitations under the License.
*/
#include "MeshIO.h"
#include <filameshio/MeshIO.h>
#include <iostream>
#include <string>
@@ -44,6 +44,8 @@
using namespace filament;
using namespace math;
#define DEFAULT_MATERIAL "DefaultMaterial"
static size_t fileSize(int fd) {
size_t filesize;
filesize = (size_t) lseek(fd, 0, SEEK_END);
@@ -90,7 +92,7 @@ struct Part {
};
MeshIO::Mesh MeshIO::loadMeshFromFile(filament::Engine* engine, const utils::Path& path,
const std::map<std::string, filament::MaterialInstance*>& materials) {
const MaterialRegistry& materials) {
Mesh mesh;
@@ -181,7 +183,7 @@ MeshIO::Mesh MeshIO::loadMeshFromFile(filament::Engine* engine, const utils::Pat
if (m != materials.end()) {
builder.material(i, m->second);
} else {
builder.material(i, materials.at("DefaultMaterial"));
builder.material(i, materials.at(DEFAULT_MATERIAL));
}
}
@@ -196,3 +198,89 @@ MeshIO::Mesh MeshIO::loadMeshFromFile(filament::Engine* engine, const utils::Pat
return mesh;
}
MeshIO::Mesh MeshIO::loadMeshFromBuffer(filament::Engine* engine,
void const* data, Callback destructor, void* user,
MaterialInstance* defaultMaterial) {
MaterialRegistry reg;
reg[DEFAULT_MATERIAL] = defaultMaterial;
return loadMeshFromBuffer(engine, data, destructor, user, reg);
}
MeshIO::Mesh MeshIO::loadMeshFromBuffer(filament::Engine* engine,
void const* data, Callback destructor, void* user,
const MaterialRegistry& materials) {
const char* p = (const char *) data;
if (strncmp("FILAMESH", p, 8)) {
puts("Magic string not found.");
abort();
}
p += 8;
Header* header = (Header*) p;
p += sizeof(Header);
char const* vertexData = p;
p += header->vertexSize;
char const* indices = p;
p += header->indexSize;
Part* parts = (Part*) p;
p += header->parts * sizeof(Part);
uint32_t materialCount = (uint32_t) *p;
p += sizeof(uint32_t);
std::vector<std::string> partsMaterial(materialCount);
for (size_t i = 0; i < materialCount; i++) {
uint32_t nameLength = (uint32_t) *p;
p += sizeof(uint32_t);
partsMaterial[i] = p;
p += nameLength + 1; // null terminated
}
Mesh mesh;
mesh.indexBuffer = IndexBuffer::Builder()
.indexCount(header->indexCount)
.bufferType(header->indexType ? IndexBuffer::IndexType::USHORT
: IndexBuffer::IndexType::UINT)
.build(*engine);
mesh.indexBuffer->setBuffer(*engine,
IndexBuffer::BufferDescriptor(indices, header->indexSize, destructor, user));
VertexBuffer::Builder vbb;
vbb.vertexCount(header->vertexCount)
.bufferCount(1)
.normalized(VertexAttribute::TANGENTS);
mesh.vertexBuffer = vbb
.attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::HALF4,
header->offsetPosition, uint8_t(header->stridePosition))
.attribute(VertexAttribute::TANGENTS, 0, VertexBuffer::AttributeType::SHORT4,
header->offsetTangents, uint8_t(header->strideTangents))
.attribute(VertexAttribute::UV0, 0, VertexBuffer::AttributeType::HALF2,
header->offsetUV0, uint8_t(header->strideUV0))
.build(*engine);
mesh.vertexBuffer->setBufferAt(*engine, 0,
VertexBuffer::BufferDescriptor(vertexData, header->vertexSize, destructor, user));
mesh.renderable = utils::EntityManager::get().create();
RenderableManager::Builder builder(header->parts);
builder.boundingBox(header->aabb);
const auto defaultmi = materials.at(DEFAULT_MATERIAL);
for (size_t i = 0; i < header->parts; i++) {
builder.geometry(i, RenderableManager::PrimitiveType::TRIANGLES,
mesh.vertexBuffer, mesh.indexBuffer, parts[i].offset,
parts[i].minIndex, parts[i].maxIndex, parts[i].indexCount);
const auto miter = materials.find(partsMaterial[i]);
builder.material(i, miter == materials.end() ? defaultmi : miter->second);
}
builder.build(*engine, mesh.renderable);
return mesh;
}
+2 -3
View File
@@ -127,10 +127,9 @@ function(add_filamesh_demo NAME)
include_directories(${GENERATION_ROOT})
add_executable(
${NAME}
${NAME}.cpp
app/MeshIO.cpp)
${NAME}.cpp)
add_dependencies(${NAME} sample_materials)
target_link_libraries(${NAME} PRIVATE ${APP_LIBS})
target_link_libraries(${NAME} PRIVATE ${APP_LIBS} filameshio)
target_compile_options(${NAME} PRIVATE ${COMPILER_FLAGS})
endfunction()
+1 -1
View File
@@ -37,13 +37,13 @@
#include "app/Config.h"
#include "app/FilamentApp.h"
#include "app/MeshIO.h"
#include <stb_image.h>
#include <utils/EntityManager.h>
#include <filamat/MaterialBuilder.h>
#include <filameshio/MeshIO.h>
using namespace math;
using namespace filament;
+1 -2
View File
@@ -37,13 +37,12 @@
#include "app/Config.h"
#include "app/FilamentApp.h"
#include "app/MeshIO.h"
#include <stb_image.h>
#include <utils/EntityManager.h>
#include <filamat/MaterialBuilder.h>
#include <filameshio/MeshIO.h>
using namespace math;
using namespace filament;
+2 -2
View File
@@ -23,6 +23,7 @@
#include <utils/Path.h>
#include <filament/Engine.h>
#include <filament/LightManager.h>
#include <filament/Material.h>
#include <filament/MaterialInstance.h>
#include <filament/RenderableManager.h>
@@ -36,13 +37,12 @@
#include "app/Config.h"
#include "app/FilamentApp.h"
#include "app/MeshIO.h"
#include <stb_image.h>
#include <utils/EntityManager.h>
#include <filamat/MaterialBuilder.h>
#include <filament/LightManager.h>
#include <filameshio/MeshIO.h>
using namespace math;
using namespace filament;
+1 -1
View File
@@ -37,13 +37,13 @@
#include "app/Config.h"
#include "app/FilamentApp.h"
#include "app/MeshIO.h"
#include <stb_image.h>
#include <utils/EntityManager.h>
#include <filamat/MaterialBuilder.h>
#include <filameshio/MeshIO.h>
using namespace math;
using namespace filament;
+1 -3
View File
@@ -183,12 +183,10 @@ function(add_demo NAME)
include_directories(${GENERATION_ROOT})
add_executable(${NAME} ${NAME}.cpp
../app/CameraManipulator.cpp
filamesh.h
filamesh.cpp
filaweb.h
filaweb.cpp)
add_dependencies(${NAME} sample_materials sample_assets)
target_link_libraries(${NAME} PRIVATE filament filagui image math utils)
target_link_libraries(${NAME} PRIVATE filament filagui filameshio image math utils)
# Copy the generated js and wasm files into the public folder, as well as the app-specific
# manually-written HTML file.
-142
View File
@@ -1,142 +0,0 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "filamesh.h"
#include <filament/Box.h>
#include <filament/RenderableManager.h>
#include <utils/EntityManager.h>
#include <math/mat4.h>
#include <math/vec3.h>
#include <vector>
#include <string>
using namespace filament;
using namespace math;
using namespace utils;
using namespace std;
struct Header {
uint32_t version;
uint32_t parts;
Box aabb;
uint32_t interleaved;
uint32_t offsetPosition;
uint32_t stridePosition;
uint32_t offsetTangents;
uint32_t strideTangents;
uint32_t offsetColor;
uint32_t strideColor;
uint32_t offsetUV0;
uint32_t strideUV0;
uint32_t offsetUV1;
uint32_t strideUV1;
uint32_t vertexCount;
uint32_t vertexSize;
uint32_t indexType;
uint32_t indexCount;
uint32_t indexSize;
};
struct Part {
uint32_t offset;
uint32_t indexCount;
uint32_t minIndex;
uint32_t maxIndex;
uint32_t materialID;
Box aabb;
};
Filamesh decodeMesh(Engine& engine, void const* data, off_t offset, MaterialInstance* mi,
driver::BufferDescriptor::Callback destructor, void* user) {
const char* p = (const char *) data + offset;
if (strncmp("FILAMESH", p, 8)) {
puts("Magic string not found.");
abort();
}
p += 8;
Header* header = (Header*) p;
p += sizeof(Header);
char const* vertexData = p;
p += header->vertexSize;
char const* indices = p;
p += header->indexSize;
Part* parts = (Part*) p;
p += header->parts * sizeof(Part);
uint32_t materialCount = (uint32_t) *p;
p += sizeof(uint32_t);
vector<string> partsMaterial;
partsMaterial.resize(materialCount);
for (size_t i = 0; i < materialCount; i++) {
uint32_t nameLength = (uint32_t) *p;
p += sizeof(uint32_t);
partsMaterial[i] = p;
p += nameLength + 1; // null terminated
}
Mesh* mesh = new Mesh();
mesh->indexBuffer = IndexBuffer::Builder()
.indexCount(header->indexCount)
.bufferType(header->indexType ? IndexBuffer::IndexType::USHORT
: IndexBuffer::IndexType::UINT)
.build(engine);
mesh->indexBuffer->setBuffer(
engine, IndexBuffer::BufferDescriptor(indices, header->indexSize));
VertexBuffer::Builder vbb;
vbb.vertexCount(header->vertexCount)
.bufferCount(1)
.normalized(VertexAttribute::TANGENTS);
mesh->vertexBuffer = vbb
.attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::HALF4,
header->offsetPosition, uint8_t(header->stridePosition))
.attribute(VertexAttribute::TANGENTS, 0, VertexBuffer::AttributeType::SHORT4,
header->offsetTangents, uint8_t(header->strideTangents))
.attribute(VertexAttribute::UV0, 0, VertexBuffer::AttributeType::HALF2,
header->offsetUV0, uint8_t(header->strideUV0))
.build(engine);
VertexBuffer::BufferDescriptor buffer(vertexData, header->vertexSize,
destructor, user);
mesh->vertexBuffer->setBufferAt(engine, 0, move(buffer));
mesh->renderable = EntityManager::get().create();
RenderableManager::Builder builder(header->parts);
builder.boundingBox(header->aabb);
for (size_t i = 0; i < header->parts; i++) {
builder.geometry(i, RenderableManager::PrimitiveType::TRIANGLES,
mesh->vertexBuffer, mesh->indexBuffer, parts[i].offset,
parts[i].minIndex, parts[i].maxIndex, parts[i].indexCount);
builder.material(i, mi);
}
builder.build(engine, mesh->renderable);
return Filamesh(mesh);
}
-39
View File
@@ -1,39 +0,0 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <filament/Engine.h>
#include <filament/IndexBuffer.h>
#include <filament/MaterialInstance.h>
#include <filament/Texture.h>
#include <filament/VertexBuffer.h>
#include <filament/driver/BufferDescriptor.h>
#include <utils/Entity.h>
#include <memory>
struct Mesh {
utils::Entity renderable;
filament::VertexBuffer* vertexBuffer = {};
filament::IndexBuffer* indexBuffer = {};
};
using Filamesh = std::unique_ptr<Mesh>;
Filamesh decodeMesh(filament::Engine& engine, void const* data, off_t offset,
filament::MaterialInstance* mi, filament::driver::BufferDescriptor::Callback destructor,
void* user);
+14 -7
View File
@@ -16,7 +16,6 @@
#include "../material_sandbox.h"
#include "filamesh.h"
#include "filaweb.h"
#include <filament/Engine.h>
@@ -26,6 +25,8 @@
#include <filament/Scene.h>
#include <filament/View.h>
#include <filameshio/MeshIO.h>
#include <math/vec3.h>
#include <utils/Entity.h>
@@ -44,7 +45,7 @@ using WrapMode = TextureSampler::WrapMode;
using Format = Texture::InternalFormat;
struct SandboxApp {
Filamesh filamesh;
MeshIO::Mesh filamesh;
Camera* cam;
SandboxParameters params;
filaweb::SkyLight skylight;
@@ -81,12 +82,18 @@ void setup(Engine* engine, View* view, Scene* scene) {
// Create mesh.
const uint8_t* mdata = mesh.rawData.get();
const auto destructor = [](void* buffer, size_t size, void* user) {
auto asset = (filaweb::Asset*) user;
asset->rawData.reset();
// This destruction lambda is called for the vertex buffer AND index buffer, so release CPU
// memory only after both have been uploaded to the GPU. The static count trick here works
// only because we create a single mesh in this demo.
static int count = 0;
if (++count == 2) {
auto asset = (filaweb::Asset*) user;
asset->rawData.reset();
}
};
MaterialInstance* materialInstance = app.params.materialInstance[MATERIAL_LIT];
app.filamesh = decodeMesh(*engine, mdata, 0, materialInstance, destructor, &mesh);
scene->addEntity(app.filamesh->renderable);
app.filamesh = MeshIO::loadMeshFromBuffer(engine, mdata, destructor, &mesh, materialInstance);
scene->addEntity(app.filamesh.renderable);
// Create the sun.
scene->addEntity(app.params.light);
@@ -155,7 +162,7 @@ void ui(Engine* engine, View* view) {
MaterialInstance* materialInstance = updateInstances(params, *engine);
auto& rcm = engine->getRenderableManager();
auto instance = rcm.getInstance(app.filamesh->renderable);
auto instance = rcm.getInstance(app.filamesh.renderable);
for (size_t i = 0; i < rcm.getPrimitiveCount(instance); i++) {
rcm.setMaterialInstanceAt(instance, i, materialInstance);
}
+15 -7
View File
@@ -14,7 +14,6 @@
* limitations under the License.
*/
#include "filamesh.h"
#include "filaweb.h"
#include <filament/Engine.h>
@@ -28,6 +27,8 @@
#include <filament/VertexBuffer.h>
#include <filament/View.h>
#include <filameshio/MeshIO.h>
#include <utils/Entity.h>
#include <utils/EntityManager.h>
@@ -43,7 +44,7 @@ using WrapMode = TextureSampler::WrapMode;
using Format = Texture::InternalFormat;
struct SuzanneApp {
Filamesh filamesh;
MeshIO::Mesh filamesh;
Material* mat;
MaterialInstance* mi;
Camera* cam;
@@ -162,11 +163,18 @@ void setup(Engine* engine, View* view, Scene* scene) {
printf("%s: %d bytes\n", "mesh", mesh.rawSize);
const uint8_t* mdata = mesh.rawData.get();
const auto destructor = [](void* buffer, size_t size, void* user) {
auto asset = (filaweb::Asset*) user;
asset->rawData.reset();
// This destruction lambda is called for the vertex buffer AND index buffer, so release CPU
// memory only after both have been uploaded to the GPU. The static count trick here works
// only because we create a single mesh in this demo.
static int count = 0;
if (++count == 2) {
auto asset = (filaweb::Asset*) user;
asset->rawData.reset();
}
};
app.filamesh = decodeMesh(*engine, mdata, 0, app.mi, destructor, &mesh);
scene->addEntity(app.filamesh->renderable);
app.filamesh = MeshIO::loadMeshFromBuffer(engine, mdata, destructor, &mesh, app.mi);
scene->addEntity(app.filamesh.renderable);
// Create textures.
TextureSampler sampler(TextureSampler::MinFilter::LINEAR_MIPMAP_LINEAR, MagFilter::LINEAR,
@@ -243,7 +251,7 @@ void animate(Engine* engine, View* view, double now) {
double ratio = double(width) / height;
app.cam->setProjection(45.0, ratio, 0.1, 50.0, ratio < 1 ? Fov::HORIZONTAL : Fov::VERTICAL);
auto& tcm = engine->getTransformManager();
tcm.setTransform(tcm.getInstance(app.filamesh->renderable),
tcm.setTransform(tcm.getInstance(app.filamesh.renderable),
mat4f{mat3f{1.0}, float3{0.0f, 0.0f, -4.0f}} *
mat4f::rotate(now, math::float3{0, 1, 0}));
};