Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ void FilamentApp::setupMaterial() {

void FilamentApp::setupMesh() {
MeshReader::Mesh mesh = MeshReader::loadMeshFromBuffer(engine, RESOURCES_CUBE_DATA,
nullptr, nullptr, app.materialInstance);
RESOURCES_CUBE_SIZE, nullptr, nullptr, app.materialInstance);
app.materialInstance->setParameter("baseColor", RgbType::sRGB, {0.71f, 0.0f, 0.0f});

app.renderable = mesh.renderable;
Expand Down
2 changes: 1 addition & 1 deletion ios/samples/hello-pbr/hello-pbr/FilamentApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ void FilamentApp::initialize() {

app.materialInstance = app.mat->createInstance();
MeshReader::Mesh mesh = MeshReader::loadMeshFromBuffer(engine, RESOURCES_MATERIAL_SPHERE_DATA,
nullptr, nullptr, app.materialInstance);
RESOURCES_MATERIAL_SPHERE_SIZE, nullptr, nullptr, app.materialInstance);
app.materialInstance->setParameter("baseColor", RgbType::sRGB, {0.71f, 0.0f, 0.0f});

app.renderable = mesh.renderable;
Expand Down
4 changes: 2 additions & 2 deletions libs/filameshio/include/filameshio/MeshReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class UTILS_PUBLIC MeshReader {
* named "DefaultMaterial" to the registry.
*/
static Mesh loadMeshFromBuffer(filament::Engine* engine,
void const* data, Callback destructor, void* user,
void const* data, size_t dataSize, Callback destructor, void* user,
MaterialRegistry& materials);

/**
Expand All @@ -111,7 +111,7 @@ class UTILS_PUBLIC MeshReader {
* renderable are assigned the specified default material.
*/
static Mesh loadMeshFromBuffer(filament::Engine* engine,
void const* data, Callback destructor, void* user,
void const* data, size_t dataSize, Callback destructor, void* user,
filament::MaterialInstance* defaultMaterial);
};

Expand Down
58 changes: 52 additions & 6 deletions libs/filameshio/src/MeshReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,9 @@ MeshReader::Mesh MeshReader::loadMeshFromFile(filament::Engine* engine, const ut
Mesh mesh;

int fd = open(path.c_str(), O_RDONLY);
if (fd < 0) {
return mesh;
}

size_t size = fileSize(fd);
char* data = (char*) malloc(size);
Expand All @@ -176,7 +179,7 @@ MeshReader::Mesh MeshReader::loadMeshFromFile(filament::Engine* engine, const ut
p += sizeof(MAGICID);

if (!strncmp(MAGICID, magic, 8)) {
mesh = loadMeshFromBuffer(engine, data, nullptr, nullptr, materials);
mesh = loadMeshFromBuffer(engine, data, size, nullptr, nullptr, materials);
}

Fence::waitAndDestroy(engine->createFence());
Expand All @@ -188,42 +191,77 @@ MeshReader::Mesh MeshReader::loadMeshFromFile(filament::Engine* engine, const ut
}

MeshReader::Mesh MeshReader::loadMeshFromBuffer(filament::Engine* engine,
void const* data, Callback destructor, void* user,
void const* data, size_t dataSize, Callback destructor, void* user,
MaterialInstance* defaultMaterial) {
MaterialRegistry reg;
reg.registerMaterialInstance(utils::CString(DEFAULT_MATERIAL), defaultMaterial);
return loadMeshFromBuffer(engine, data, destructor, user, reg);
return loadMeshFromBuffer(engine, data, dataSize, destructor, user, reg);
}

MeshReader::Mesh MeshReader::loadMeshFromBuffer(filament::Engine* engine,
void const* data, Callback destructor, void* user,
void const* data, size_t dataSize, Callback destructor, void* user,
MaterialRegistry& materials) {
const uint8_t* p = (const uint8_t*) data;
if (strncmp(MAGICID, (const char *) p, 8)) {
const uint8_t* const end = p + dataSize;

if (dataSize < 8 || strncmp(MAGICID, (const char *) p, 8)) {
utils::slog.e << "Magic string not found." << utils::io::endl;
return {};
}
p += 8;

if (size_t(end - p) < sizeof(Header)) {
utils::slog.e << "Buffer too small for header." << utils::io::endl;
return {};
}
Header* header = (Header*) p;
p += sizeof(Header);

if (header->vertexSize > size_t(end - p)) {
utils::slog.e << "Invalid vertexSize." << utils::io::endl;
return {};
}
uint8_t const* vertexData = p;
p += header->vertexSize;

if (header->indexSize > size_t(end - p)) {
utils::slog.e << "Invalid indexSize." << utils::io::endl;
return {};
}
uint8_t const* indices = p;
p += header->indexSize;

size_t partsBytes = size_t(header->parts) * sizeof(Part);
if (header->parts != 0 && partsBytes / sizeof(Part) != header->parts) {
utils::slog.e << "Invalid parts count." << utils::io::endl;
return {};
}
if (partsBytes > size_t(end - p)) {
utils::slog.e << "Invalid parts count." << utils::io::endl;
return {};
}
Part* parts = (Part*) p;
p += header->parts * sizeof(Part);
p += partsBytes;

if (size_t(end - p) < sizeof(uint32_t)) {
utils::slog.e << "Buffer too small for material count." << utils::io::endl;
return {};
}
uint32_t materialCount = (uint32_t) *p;
p += sizeof(uint32_t);

std::vector<std::string> partsMaterial(materialCount);
for (size_t i = 0; i < materialCount; i++) {
if (size_t(end - p) < sizeof(uint32_t)) {
utils::slog.e << "Buffer too small for material name." << utils::io::endl;
return {};
}
uint32_t nameLength = (uint32_t) *p;
p += sizeof(uint32_t);
if (size_t(end - p) < nameLength + 1u) {
utils::slog.e << "Invalid material name length." << utils::io::endl;
return {};
}
partsMaterial[i] = (const char*) p;
p += nameLength + 1; // null terminated
}
Expand All @@ -244,6 +282,10 @@ MeshReader::Mesh MeshReader::loadMeshFromBuffer(filament::Engine* engine,
size_t indexSize = header->indexType == UI16 ? sizeof(uint16_t) : sizeof(uint32_t);
size_t indexCount = header->indexCount;
size_t uncompressedSize = indexSize * indexCount;
if (indexCount != 0 && uncompressedSize / indexCount != indexSize) {
utils::slog.e << "Index buffer size overflow." << utils::io::endl;
return {};
}
void* uncompressed = malloc(uncompressedSize);
int err = meshopt_decodeIndexBuffer(uncompressed, indexCount, indexSize, indices,
indicesSize);
Expand Down Expand Up @@ -303,6 +345,10 @@ MeshReader::Mesh MeshReader::loadMeshFromBuffer(filament::Engine* engine,
(hasUV1 ? sizeof(ushort2) : 0);
size_t vertexCount = header->vertexCount;
size_t uncompressedSize = vertexSize * vertexCount;
if (vertexCount != 0 && uncompressedSize / vertexCount != vertexSize) {
utils::slog.e << "Vertex buffer size overflow." << utils::io::endl;
return {};
}
void* uncompressed = malloc(uncompressedSize);
const uint8_t* srcdata = vertexData + sizeof(CompressionHeader);
int err = 0;
Expand Down
4 changes: 2 additions & 2 deletions libs/filameshio/tests/test_filamesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ TEST_F(FilameshTest, NonInterleaved) {

// Deserialize the mesh as a smoke test.
MaterialInstance* mi = engine->getDefaultMaterial()->createInstance();
auto mesh = MeshReader::loadMeshFromBuffer(engine, stream.str().data(), nullptr, nullptr, mi);
auto mesh = MeshReader::loadMeshFromBuffer(engine, stream.str().data(), stream.str().size(), nullptr, nullptr, mi);
auto& rm = engine->getRenderableManager();
auto inst = rm.getInstance(mesh.renderable);
EXPECT_EQ(rm.getPrimitiveCount(inst), 1);
Expand Down Expand Up @@ -206,7 +206,7 @@ TEST_F(FilameshTest, Interleaved) {

// Deserialize the mesh as a smoke test.
MaterialInstance* mi = engine->getDefaultMaterial()->createInstance();
auto mesh = MeshReader::loadMeshFromBuffer(engine, stream.str().data(), nullptr, nullptr, mi);
auto mesh = MeshReader::loadMeshFromBuffer(engine, stream.str().data(), stream.str().size(), nullptr, nullptr, mi);
auto& rm = engine->getRenderableManager();
auto inst = rm.getInstance(mesh.renderable);
EXPECT_EQ(rm.getPrimitiveCount(inst), 1);
Expand Down
2 changes: 1 addition & 1 deletion samples/hellopbr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ int main(int argc, char** argv) {
mi->setParameter("reflectance", 0.5f);

// Add geometry into the scene.
app.mesh = MeshReader::loadMeshFromBuffer(engine, MONKEY_SUZANNE_DATA, nullptr, nullptr, mi);
app.mesh = MeshReader::loadMeshFromBuffer(engine, MONKEY_SUZANNE_DATA, MONKEY_SUZANNE_SIZE, nullptr, nullptr, mi);
auto ti = tcm.getInstance(app.mesh.renderable);
app.transform = mat4f{ mat3f(1), float3(0, 0, -4) } * tcm.getWorldTransform(ti);
rcm.setCastShadows(rcm.getInstance(app.mesh.renderable), false);
Expand Down
2 changes: 1 addition & 1 deletion samples/hellostereo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ int main(int argc, char** argv) {

// Add a monkey and a light source into the main scene.
app.monkeyMesh = MeshReader::loadMeshFromBuffer(
engine, MONKEY_SUZANNE_DATA, nullptr, nullptr, mi);
engine, MONKEY_SUZANNE_DATA, MONKEY_SUZANNE_SIZE, nullptr, nullptr, mi);
auto ti = tcm.getInstance(app.monkeyMesh.renderable);
app.monkeyTransform = mat4f{mat3f(1), monkeyPosition } * tcm.getWorldTransform(ti);
rcm.setCastShadows(rcm.getInstance(app.monkeyMesh.renderable), false);
Expand Down
2 changes: 1 addition & 1 deletion samples/materialinstancestress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ int main(int argc, char** argv) {
auto setup = [&app](Engine* engine, View* view, Scene* scene) {
app.desiredObjectCount = app.ui.objectCountSlider;
app.suzanneTemplate = MeshReader::loadMeshFromBuffer(engine,
MONKEY_SUZANNE_DATA, nullptr, nullptr, nullptr);
MONKEY_SUZANNE_DATA, MONKEY_SUZANNE_SIZE, nullptr, nullptr, nullptr);

app.litMaterial = Material::Builder()
.package(RESOURCES_AIDEFAULTMAT_DATA, RESOURCES_AIDEFAULTMAT_SIZE)
Expand Down
4 changes: 2 additions & 2 deletions samples/multiple_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ void setup_static_scene(Window& w, Engine* engine) {
w.materialInstance->setParameter("sheenColor", 0.00f);
w.materialInstance->setParameter("clearCoat", 1.00f);
w.materialInstance->setParameter("clearCoatRoughness", 0.00f);
w.mesh = filamesh::MeshReader::loadMeshFromBuffer(engine, MONKEY_SUZANNE_DATA, nullptr, nullptr, w.materialInstance);
w.mesh = filamesh::MeshReader::loadMeshFromBuffer(engine, MONKEY_SUZANNE_DATA, MONKEY_SUZANNE_SIZE, nullptr, nullptr, w.materialInstance);
w.scene->addEntity(w.mesh.renderable);

int width, height;
Expand Down Expand Up @@ -330,7 +330,7 @@ void setup_animating_scene(Window& w, Engine* engine) {
w.materialInstance->setParameter("sheenColor", 0.00f);
w.materialInstance->setParameter("clearCoat", 0.00f);
w.materialInstance->setParameter("clearCoatRoughness", 0.00f);
w.mesh = filamesh::MeshReader::loadMeshFromBuffer(engine, MONKEY_SUZANNE_DATA, nullptr, nullptr, w.materialInstance);
w.mesh = filamesh::MeshReader::loadMeshFromBuffer(engine, MONKEY_SUZANNE_DATA, MONKEY_SUZANNE_SIZE, nullptr, nullptr, w.materialInstance);
w.scene->addEntity(w.mesh.renderable);

int width, height;
Expand Down
2 changes: 1 addition & 1 deletion samples/rendertarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ int main(int argc, char** argv) {
mi->setParameter("reflectance", 0.5f);

// Add monkey into the scene.
app.monkeyMesh = MeshReader::loadMeshFromBuffer(engine, MONKEY_SUZANNE_DATA, nullptr, nullptr, mi);
app.monkeyMesh = MeshReader::loadMeshFromBuffer(engine, MONKEY_SUZANNE_DATA, MONKEY_SUZANNE_SIZE, nullptr, nullptr, mi);
auto ti = tcm.getInstance(app.monkeyMesh.renderable);
app.transform = mat4f{ mat3f(1), float3(0, 0, -4) } * tcm.getWorldTransform(ti);
rcm.setCastShadows(rcm.getInstance(app.monkeyMesh.renderable), false);
Expand Down
4 changes: 2 additions & 2 deletions samples/suzanne.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,8 @@ int main(int argc, char** argv) {
ibl->setRotation(mat3f::rotation(0.5f, float3{ 0, 1, 0 }));

// Add geometry into the scene.
app.mesh = filamesh::MeshReader::loadMeshFromBuffer(engine, MONKEY_SUZANNE_DATA, nullptr,
nullptr, app.materialInstance);
app.mesh = filamesh::MeshReader::loadMeshFromBuffer(engine, MONKEY_SUZANNE_DATA,
MONKEY_SUZANNE_SIZE, nullptr, nullptr, app.materialInstance);
auto ti = tcm.getInstance(app.mesh.renderable);
app.transform = mat4f{ mat3f(1), float3(0, 0, -4) } * tcm.getWorldTransform(ti);
rcm.setCastShadows(rcm.getInstance(app.mesh.renderable), false);
Expand Down
2 changes: 1 addition & 1 deletion web/filament-js/jsbindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1907,7 +1907,7 @@ class_<MeshReader>("MeshReader")
};
// Parse the filamesh buffer. This creates the VB, IB, and renderable.
return MeshReader::loadMeshFromBuffer(
engine, buffer.bd->buffer,
engine, buffer.bd->buffer, buffer.bd->size,
destructor, bundle, matreg);
}), allow_raw_pointers());

Expand Down