Skip to content

Commit

Permalink
model importer refactor wip
Browse files Browse the repository at this point in the history
  • Loading branch information
nem0 committed Dec 4, 2024
1 parent ec36ba8 commit d44fce5
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 52 deletions.
38 changes: 27 additions & 11 deletions src/renderer/editor/fbx_importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "physics/physics_system.h"
#include "renderer/draw_stream.h"
#include "renderer/editor/model_importer.h"
#include "renderer/editor/model_meta.h"
#include "renderer/material.h"
#include "renderer/model.h"
#include "renderer/pipeline.h"
Expand Down Expand Up @@ -547,7 +548,8 @@ struct FBXImporter : ModelImporter {
const ofbx::Object* node = (const ofbx::Object*)bone.id;
const ImportMesh* mesh = getAnyMeshFromBone(node, i32(&bone - m_bones.begin()));
Matrix tr = toLumix(getBindPoseMatrix(mesh, node));
tr.normalizeScale();
tr.normalizeScale(); // TODO why?
tr.setTranslation(tr.getTranslation() * m_scene_scale);
bone.bind_pose_matrix = fixOrientation(tr);
bone.name = node->name;
}
Expand Down Expand Up @@ -696,7 +698,7 @@ struct FBXImporter : ModelImporter {
u32 tri_count = ofbx::triangulate(geom, polygon, tri_indices.begin());
for (u32 i = 0; i < tri_count; ++i) {
ofbx::Vec3 cp = positions.get(tri_indices[i]);
Vec3 pos = matrix.transformPoint(toLumixVec3(cp)) * meta.scene_scale * m_scene_scale;
Vec3 pos = matrix.transformPoint(toLumixVec3(cp)) * m_scene_scale;
pos = fixOrientation(pos);
write(pos);

Expand Down Expand Up @@ -955,14 +957,18 @@ struct FBXImporter : ModelImporter {

for (const Bone& bone : m_bones) {
const Bone* parent = getParent(bone);
if (!parent) continue;

// parent_scale - animated scale is not supported, but we can get rid of static scale if we ignore
// it in writeSkeleton() and use `parent_scale` in this function
const ofbx::Object* fbx_parent = (const ofbx::Object*)(parent->id);
const float parent_scale = (float)getScaleX(fbx_parent->getGlobalTransform());
float scale = m_scene_scale;
if (parent) {
// parent_scale - animated scale is not supported, but we can get rid of static scale if we ignore
// it in writeSkeleton() and use `parent_scale` in this function
const ofbx::Object* fbx_parent = (const ofbx::Object*)(parent->id);
const float parent_scale = (float)getScaleX(fbx_parent->getGlobalTransform());
scale *= parent_scale;
}
if (fabsf(scale - 1) < 1e-5f) continue;

Array<Key>& keys = tracks[u32(&bone - m_bones.begin())];
for (Key& k : keys) k.pos *= parent_scale;
for (Key& k : keys) k.pos *= scale;
}

if (m_orientation != Orientation::Y_UP) {
Expand Down Expand Up @@ -1243,7 +1249,15 @@ struct FBXImporter : ModelImporter {
});
}

bool parse(const Path& filename, const ModelMeta* meta) override {
bool parse(const Path& filename, const ModelMeta& meta) override {
return parseInternal(filename, &meta);
}

bool parseSimple(const Path& filename) override {
return parseInternal(filename, nullptr);
}

bool parseInternal(const Path& filename, const ModelMeta* meta) {
PROFILE_FUNCTION();
const bool ignore_geometry = meta == nullptr;

Expand All @@ -1267,6 +1281,7 @@ struct FBXImporter : ModelImporter {
return false;
}
m_scene_scale = m_scene->getGlobalSettings()->UnitScaleFactor * 0.01f;
if (meta) m_scene_scale *= meta->scene_scale;

const ofbx::GlobalSettings* settings = m_scene->getGlobalSettings();
switch (settings->UpAxis) {
Expand All @@ -1279,7 +1294,7 @@ struct FBXImporter : ModelImporter {
if (!ignore_geometry) extractEmbedded(*m_scene, src_dir, m_allocator);

gatherMeshes(filename, src_dir);
gatherAnimations(filename);
if(!meta || !meta->ignore_animations) gatherAnimations(filename);
if (meta) gatherLights(*meta);

if (!ignore_geometry) {
Expand All @@ -1303,6 +1318,7 @@ struct FBXImporter : ModelImporter {
Array<const ofbx::Mesh*> m_fbx_meshes;
ofbx::IScene* m_scene;
Orientation m_orientation = Orientation::Y_UP;
float m_scene_scale = 1.f;
};

ModelImporter* createFBXImporter(StudioApp& app, IAllocator& allocator) {
Expand Down
37 changes: 20 additions & 17 deletions src/renderer/editor/model_importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "physics/physics_module.h"
#include "physics/physics_resources.h"
#include "physics/physics_system.h"
#include "renderer/editor/model_meta.h"
#include "renderer/material.h"
#include "renderer/model.h"
#include "renderer/pipeline.h"
Expand Down Expand Up @@ -584,15 +585,15 @@ bool ModelImporter::write(const Path& src, const ModelMeta& meta) {
const Path filepath = Path(ResourcePath::getResource(src));
any_written = writeModel(src, meta) || any_written;
any_written = writeMaterials(filepath, meta, false) || any_written;
if (!meta.ignore_animations) any_written = writeAnimations(filepath, meta) || any_written;
any_written = writeAnimations(filepath, meta) || any_written;
if (meta.split) {
centerMeshes();
any_written = writeSubmodels(filepath, meta) || any_written;
}
any_written = writePhysics(filepath, meta, meta.split) || any_written;
any_written = writePhysics(filepath, meta) || any_written;
if (meta.split || meta.create_prefab_with_physics) {
jobs::moveJobToWorker(0);
any_written = writePrefab(filepath, meta, meta.split) || any_written;
any_written = writePrefab(filepath, meta) || any_written;
jobs::yield();
}
return any_written;
Expand Down Expand Up @@ -762,7 +763,7 @@ void ModelImporter::writeGeometry(int mesh_idx) {
write(import_mesh.aabb);
}

bool ModelImporter::writePrefab(const Path& src, const ModelMeta& meta, bool split_meshes) {
bool ModelImporter::writePrefab(const Path& src, const ModelMeta& meta) {
Engine& engine = m_app.getEngine();
World& world = engine.createWorld();

Expand All @@ -783,7 +784,7 @@ bool ModelImporter::writePrefab(const Path& src, const ModelMeta& meta, bool spl
PhysicsModule* pmodule = (PhysicsModule*)world.getModule(RIGID_ACTOR_TYPE);

const EntityRef root = world.createEntity({0, 0, 0}, Quat::IDENTITY);
if (!split_meshes) {
if (!meta.split) {
world.createComponent(MODEL_INSTANCE_TYPE, root);
rmodule->setModelInstancePath(root, src);

Expand Down Expand Up @@ -933,7 +934,7 @@ void ModelImporter::writeGeometry(const ModelMeta& meta) {
if (m_meshes.empty()) {
for (const Bone& bone : m_bones) {
// TODO check if this works with different values of m_orientation
const Vec3 p = bone.bind_pose_matrix.getTranslation() * meta.scene_scale * m_scene_scale;
const Vec3 p = bone.bind_pose_matrix.getTranslation();
origin_radius_squared = maximum(origin_radius_squared, squaredLength(p));
aabb.addPoint(p);
}
Expand Down Expand Up @@ -1030,23 +1031,25 @@ void ModelImporter::writeMeshes(const Path& src, int mesh_idx, const ModelMeta&
void ModelImporter::writeSkeleton(const ModelMeta& meta) {
write(m_bones.size());

u32 idx = 0;
for (const Bone& node : m_bones) {
for (i32 idx = 0, num = m_bones.size(); idx < num; ++idx) {
const Bone& node = m_bones[idx];
const char* name = node.name.c_str();
int len = (int)stringLength(name);
const i32 len = stringLength(name);
write(len);
writeString(name);

const i32 parent_index = getParentIndex(m_bones, node);
// m_bones must have parents before children
// i.e. importers must sort them that way
ASSERT(parent_index < idx);
write(parent_index);

const Matrix& tr = node.bind_pose_matrix;

const Quat q = tr.getRotation();
const Vec3 t = tr.getTranslation() * meta.scene_scale * m_scene_scale;
const Vec3 t = tr.getTranslation();
write(t);
write(q);
++idx;
}
}

Expand Down Expand Up @@ -1150,7 +1153,7 @@ void ModelImporter::writeModelHeader()
write(header);
}

bool ModelImporter::writePhysics(const Path& src, const ModelMeta& meta, bool split_meshes) {
bool ModelImporter::writePhysics(const Path& src, const ModelMeta& meta) {
if (m_meshes.empty()) return false;
if (meta.physics == ModelMeta::Physics::NONE) return false;

Expand All @@ -1167,7 +1170,7 @@ bool ModelImporter::writePhysics(const Path& src, const ModelMeta& meta, bool sp
const bool to_convex = meta.physics == ModelMeta::Physics::CONVEX;
header.m_convex = (u32)to_convex;

if (split_meshes) {
if (meta.split) {
for (const ImportMesh& mesh : m_meshes) {
m_out_file.clear();
m_out_file.write(&header, sizeof(header));
Expand Down Expand Up @@ -1328,7 +1331,7 @@ bool ModelImporter::writeAnimations(const Path& src, const ModelMeta& meta) {

Vec3 min(FLT_MAX), max(-FLT_MAX);
for (const Key& k : keys) {
const Vec3 p = k.pos * meta.scene_scale * m_scene_scale;
const Vec3 p = k.pos;
min = minimum(p, min);
max = maximum(p, max);
}
Expand All @@ -1342,7 +1345,7 @@ bool ModelImporter::writeAnimations(const Path& src, const ModelMeta& meta) {
if (bitsize == 0) {
translation_tracks[bone_idx].is_const = true;
write(Animation::TrackType::CONSTANT);
write(keys[0].pos * meta.scene_scale * m_scene_scale);
write(keys[0].pos);
}
else {
translation_tracks[bone_idx].is_const = false;
Expand All @@ -1355,7 +1358,7 @@ bool ModelImporter::writeAnimations(const Path& src, const ModelMeta& meta) {
write(bitsizes);
write(offset_bits);
offset_bits += bitsize;

memcpy(translation_tracks[bone_idx].bitsizes, bitsizes, sizeof(bitsizes));
translation_tracks[bone_idx].max = max;
translation_tracks[bone_idx].min = min;
Expand All @@ -1374,7 +1377,7 @@ bool ModelImporter::writeAnimations(const Path& src, const ModelMeta& meta) {

if (!keys.empty() && !track.is_const) {
const Key& k = keys[i];
Vec3 p = k.pos * meta.scene_scale * m_scene_scale;
Vec3 p = k.pos;
const u64 packed = pack(p, track);
const u32 bitsize = (track.bitsizes[0] + track.bitsizes[1] + track.bitsizes[2]);
ASSERT(bitsize <= 64);
Expand Down
46 changes: 26 additions & 20 deletions src/renderer/editor/model_importer.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,13 @@
#include "core/geometry.h"
#include "core/math.h"
#include "core/path.h"
#include "core/span.h"
#include "core/stream.h"
#include "engine/lumix.h"
#include "renderer/gpu/gpu.h"
#include "renderer/editor/model_meta.h"

namespace Lumix {

struct ImpostorTexturesContext {
virtual ~ImpostorTexturesContext() {}
virtual void readCallback0(Span<const u8> data) = 0;
virtual void readCallback1(Span<const u8> data) = 0;
virtual void readCallback2(Span<const u8> data) = 0;
virtual void readCallback3(Span<const u8> data) = 0;
virtual void start() = 0;

IVec2 tile_size;
Path path;
};
struct ImpostorTexturesContext;
struct ModelMeta;

enum class AttributeSemantic : u8;

Expand Down Expand Up @@ -79,9 +67,9 @@ struct ModelImporter {
u32 mesh_index = 0xFFffFFff;
u32 material_index = 0xffFFffFF;
bool is_skinned = false;
int bone_idx = -1;
i32 bone_idx = -1;
u32 lod = 0;
int submesh = -1;
i32 submesh = -1;
OutputMemoryStream vertex_buffer;
u32 vertex_size = 0xffFFffFF;
Array<AttributeDesc> attributes;
Expand All @@ -107,7 +95,14 @@ struct ModelImporter {

void init(); // TODO get rid of this?

virtual bool parse(const Path& filename, const ModelMeta* meta) = 0;
// simple parsing - you can get only the list of objects (mesh, materials, animations, etc.),
// but not their content (geometry, embedded textures, etc.)
// calling write(...) after this is invalid
// used for to get a list of subresources (addSubresources) and to reimport materials
virtual bool parseSimple(const Path& filename) = 0;

// full parsing - parse all data, including geometry
virtual bool parse(const Path& filename, const ModelMeta& meta) = 0;

// meta must be the same as in parse
// TODO fix this (remove meta from these functions?)
Expand Down Expand Up @@ -142,13 +137,13 @@ struct ModelImporter {
void writeGeometry(const ModelMeta& meta);
void writeGeometry(int mesh_idx);
void writeSkeleton(const ModelMeta& meta);
bool writePrefab(const Path& src, const ModelMeta& meta, bool split_meshes);
bool writePrefab(const Path& src, const ModelMeta& meta);
bool findTexture(StringView src_dir, StringView ext, ImportTexture& tex) const;
void bakeVertexAO(float min_ao);
bool writeSubmodels(const Path& src, const ModelMeta& meta);
bool writeModel(const Path& src, const ModelMeta& meta);
bool writeAnimations(const Path& src, const ModelMeta& meta);
bool writePhysics(const Path& src, const ModelMeta& meta, bool split_meshes);
bool writePhysics(const Path& src, const ModelMeta& meta);
void centerMeshes();

// compute AO, auto LODs, etc.
Expand All @@ -166,7 +161,18 @@ struct ModelImporter {
Array<ImportMesh> m_meshes;
Array<ImportAnimation> m_animations;
Array<DVec3> m_lights;
float m_scene_scale = 1.f;
};

struct ImpostorTexturesContext {
virtual ~ImpostorTexturesContext() {}
virtual void readCallback0(Span<const u8> data) = 0;
virtual void readCallback1(Span<const u8> data) = 0;
virtual void readCallback2(Span<const u8> data) = 0;
virtual void readCallback3(Span<const u8> data) = 0;
virtual void start() = 0;

IVec2 tile_size;
Path path;
};

} // namespace Lumix
1 change: 0 additions & 1 deletion src/renderer/editor/model_meta.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include "core/stream.h"
#include "core/string.h"
#include "core/tokenizer.h"
#include "fbx_importer.h"

namespace Lumix {

Expand Down
6 changes: 3 additions & 3 deletions src/renderer/editor/render_plugins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2190,7 +2190,7 @@ struct ModelPlugin final : AssetBrowser::IPlugin, AssetCompiler::IPlugin {

if (ImGui::Button("Reimport materials")) {
ModelImporter* fbx_importer = createFBXImporter(m_app, m_app.getAllocator());
if (fbx_importer->parse(m_resource->getPath(), nullptr)) {
if (fbx_importer->parseSimple(m_resource->getPath())) {
if (!fbx_importer->writeMaterials(m_resource->getPath(), m_meta, true)) {
logError("Failed to write materials for ", m_resource->getPath());
}
Expand Down Expand Up @@ -2574,7 +2574,7 @@ struct ModelPlugin final : AssetBrowser::IPlugin, AssetCompiler::IPlugin {

const char* path = _path.c_str();
if (path[0] == '/') ++path; // TODO why is this here?
if (!importer->parse(Path(path), nullptr)) {
if (!importer->parseSimple(Path(path))) {
logError("Failed to parse ", path);
destroyFBXImporter(*importer);
return;
Expand Down Expand Up @@ -2624,7 +2624,7 @@ struct ModelPlugin final : AssetBrowser::IPlugin, AssetCompiler::IPlugin {
meta.load(Path(filepath), m_app);

ModelImporter* importer = createFBXImporter(m_app, m_app.getAllocator());
bool result = importer->parse(filepath, &meta);
bool result = importer->parse(filepath, meta);
result = result && importer->write(src, meta);
destroyFBXImporter(*importer);

Expand Down

0 comments on commit d44fce5

Please sign in to comment.