Skip to content

Commit

Permalink
Use UFBX instead of the Autodesk FBX SDK (#209)
Browse files Browse the repository at this point in the history
* Initial commit for ufbx integration

* All FBX SDK code is replaced but extensive testing is needed to verify the implementation.

* Fix FindFBX

* Continue UFBX import

* Add leveleditor materials to base repo.

Delete materials from work.

* Minor resource loader fixes

* Fix material templates from projects

* Add necessary texture lock

* Correctly imports meshes from FBX

Have to test animations to confirm the implementation works

* Implement streaming for models

This finally allows models to be fully async

* Avoid running visibility and creating a wait event if models haven't loaded yet

* Fix skinned meshes if a character isn't enabled - use a default palette of joints

* Allow for entities to load animations and skeletons

* Start bugfixing animation loading with ufbx

* Continue work on animations

* Scaling fixes

* Fix immediately loaded meshes

* Always enable debug rendering

* Debug rendering of characters

* More fbx stuff

* Fix using wrong vertex layout with debug rendering

* Fix animations.

Missing - not reading prerotation when getting animation samples.

* Fix rotation order incorrectly being applied to pre rotation

* Handle scaling correctly.

* Revert joint debug scaling

* Make sure material loaders properly do an immediate load if the material itself is supposed to be immediately loaded.

* Change asserts to use message and not format
  • Loading branch information
Duttenheim authored Mar 13, 2024
1 parent 0e85820 commit 7a6c54c
Show file tree
Hide file tree
Showing 57 changed files with 729 additions and 2,102 deletions.
1 change: 1 addition & 0 deletions code/addons/dynui/imguicontext.cc
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ ImguiContext::ImguiDrawFunction(const CoreGraphics::CmdBufferId cmdBuf)

// set texture in shader, we shouldn't have to put it into ImGui
CoreGraphics::TextureId texture = tex.nebulaHandle;
CoreGraphics::TextureIdLock _0(texture);
CoreGraphics::TextureDimensions dims = CoreGraphics::TextureGetDimensions(texture);
auto usage = CoreGraphics::TextureGetUsage(texture);
if (usage & CoreGraphics::TextureUsage::RenderTexture || usage & CoreGraphics::TextureUsage::ReadWriteTexture)
Expand Down
10 changes: 9 additions & 1 deletion code/addons/graphicsfeature/components/graphicsfeature.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,15 @@
"type": "uint",
"default": -1
},
"raytracing": "bool"
"raytracing": "bool",
"anim": {
"type": "resource",
"default": ""
},
"skeleton": {
"type": "resource",
"default": ""
}
},
"Camera": {
"viewHandle": {
Expand Down
2 changes: 1 addition & 1 deletion code/addons/graphicsfeature/graphicsfeatureunit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -364,10 +364,10 @@ GraphicsFeatureUnit::OnBeginFrame()
uiFunc();
}

this->gfxServer->RenderDebug(0);
switch (Core::CVarReadInt(this->r_debug))
{
case 2:
this->gfxServer->RenderDebug(0);
case 1:
Game::GameServer::Instance()->RenderDebug();
default:
Expand Down
23 changes: 20 additions & 3 deletions code/addons/graphicsfeature/managers/graphicsmanager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "models/modelcontext.h"
#include "visibility/visibilitycontext.h"
#include "raytracing/raytracingcontext.h"
#include "characters/charactercontext.h"
#include "game/gameserver.h"
#include "graphicsfeature/components/graphicsfeature.h"
#include "basegamefeature/components/basegamefeature.h"
Expand Down Expand Up @@ -45,18 +46,29 @@ GraphicsManager::~GraphicsManager()
/**
*/
void
RegisterModelEntity(Graphics::GraphicsEntityId const gid, Resources::ResourceName const res, bool const raytracing, Math::mat4 const& t)
RegisterModelEntity(
Graphics::GraphicsEntityId const gid
, Resources::ResourceName const res
, Resources::ResourceName const anim
, Resources::ResourceName const skeleton
, bool const raytracing
, Math::mat4 const& t
)
{
Models::ModelContext::RegisterEntity(gid);
if (raytracing && CoreGraphics::RayTracingSupported)
{
Raytracing::RaytracingContext::RegisterEntity(gid);
}
if (anim.IsValid() && skeleton.IsValid())
{
Characters::CharacterContext::RegisterEntity(gid);
}
Models::ModelContext::Setup(
gid,
res,
"NONE",
[gid, raytracing, t]()
[gid, anim, skeleton, raytracing, t]()
{
if (!Graphics::GraphicsServer::Instance()->IsValidGraphicsEntity(gid))
return;
Expand All @@ -66,6 +78,11 @@ RegisterModelEntity(Graphics::GraphicsEntityId const gid, Resources::ResourceNam
{
Raytracing::RaytracingContext::SetupModel(gid, CoreGraphics::BlasInstanceFlags::NoFlags, 0xFF);
}
if (anim.IsValid() && skeleton.IsValid())
{
Characters::CharacterContext::Setup(gid, skeleton, 0, anim, 0, "NONE");
Characters::CharacterContext::PlayClip(gid, nullptr, 0, 0, Characters::EnqueueMode::Replace);
}
Visibility::ObservableContext::Setup(gid, Visibility::VisibilityEntityType::Model);
}
);
Expand Down Expand Up @@ -187,7 +204,7 @@ GraphicsManager::InitModel(Game::World* world, Game::Entity entity, Model* model
Game::Orientation orient = world->GetComponent<Game::Orientation>(entity);
Game::Scale scale = world->GetComponent<Game::Scale>(entity);
Math::mat4 worldTransform = Math::trs(pos, orient, scale);
RegisterModelEntity(model->graphicsEntityId, model->resource, model->raytracing, worldTransform);
RegisterModelEntity(model->graphicsEntityId, model->resource, model->anim, model->skeleton, model->raytracing, worldTransform);
}

//------------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion code/render/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ ENDIF()
fips_dir(materials)
# Add engine templates and generate glue file which is needed by the material system
nebula_material_template_compile(base.json gltf.json)
nebula_material_template_glue()
nebula_project_material_template_compile()

fips_files(
material.cc
Expand Down
6 changes: 6 additions & 0 deletions code/render/characters/charactercontext.cc
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ EvalCharacter(SizeT totalJobs, SizeT groupSize, IndexT groupIndex, SizeT invocat
if (skeleton == InvalidSkeletonId)
continue;
const Util::FixedArray<Math::mat4>& bindPose = Characters::SkeletonGetBindPose(skeleton);
const Util::FixedArray<Characters::CharacterJoint>& joints = Characters::SkeletonGetJoints(skeleton);
const Util::FixedArray<Math::mat4>& jointPalette = context->jointPalettes->Get(index);
const Util::FixedArray<Math::mat4>& scaledJointPalette = context->scaledJointPalettes->Get(index);
const Util::FixedArray<Math::vec4>& idleSamples = Characters::SkeletonGetIdleSamples(skeleton);
Expand Down Expand Up @@ -622,6 +623,8 @@ EvalCharacter(SizeT totalJobs, SizeT groupSize, IndexT groupIndex, SizeT invocat
Math::mat4& unscaledMatrix = unscaledMatrixBase[jointIndex];
Math::mat4& scaledMatrix = scaledMatrixBase[jointIndex];

Math::vec3 baseScale = xyz(idleSamples[jointIndex * 3 + 2]);

// update unscaled matrix
// animation rotation
scaledMatrix = Math::affine(scale, rotate, translate);
Expand Down Expand Up @@ -810,6 +813,9 @@ CharacterContext::OnRenderDebug(uint32 flags)
IndexT i;
for (i = 0; i < jointPalettes.Size(); i++)
{
if (modelContexts[i] == Graphics::InvalidGraphicsEntityId)
continue;

const Util::FixedArray<Math::mat4>& jointsPalette = jointPalettes[i];
const Math::mat4& transform = Models::ModelContext::GetTransform(modelContexts[i]);
IndexT j;
Expand Down
3 changes: 3 additions & 0 deletions code/render/coregraphics/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ void BufferSparseCommitChanges(const BufferId id);
/// Get buffer device address
CoreGraphics::DeviceAddress BufferGetDeviceAddress(const BufferId id);

/// Shortcut for creating a staging buffer and copy
void BufferCopyWithStaging(const CoreGraphics::BufferId dest, const uint offset, const void* data, const uint size);

//------------------------------------------------------------------------------
/**
*/
Expand Down
24 changes: 17 additions & 7 deletions code/render/coregraphics/meshloader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ MeshLoader::InitializeResource(Ids::Id32 entry, const Util::StringAtom& tag, con

if (resIdExt == "nvx")
{
this->SetupMeshFromNvx(stream, entry, ret);
this->SetupMeshFromNvx(stream, entry, ret, immediate);
return ret;
}
else
Expand Down Expand Up @@ -130,10 +130,10 @@ MeshLoader::StreamResource(const Resources::ResourceId entry, IndexT frameIndex,
CoreGraphics::BufferId vbo = CoreGraphics::GetVertexBuffer();
CoreGraphics::BufferId ibo = CoreGraphics::GetIndexBuffer();

int loadBits = requestedBits;
int loadBits = 0x0;

// Upload vertices
if (loadBits & ~0x1)
if (requestedBits & ~0x1)
{
auto [offset, buffer] = CoreGraphics::UploadArray(vertexData, header->vertexDataSize);
if (buffer != CoreGraphics::InvalidBufferId)
Expand All @@ -155,7 +155,7 @@ MeshLoader::StreamResource(const Resources::ResourceId entry, IndexT frameIndex,
}

// Upload indices
if (loadBits & ~0x2)
if (requestedBits & ~0x2)
{
auto [offset, buffer] = CoreGraphics::UploadArray(indexData, header->indexDataSize);
if (buffer != CoreGraphics::InvalidBufferId)
Expand Down Expand Up @@ -203,7 +203,7 @@ MeshLoader::LodMask(const Ids::Id32 entry, float lod, bool stream) const
native binary mesh file format).
*/
void
MeshLoader::SetupMeshFromNvx(const Ptr<IO::Stream>& stream, const Ids::Id32 entry, const MeshResourceId meshResource)
MeshLoader::SetupMeshFromNvx(const Ptr<IO::Stream>& stream, const Ids::Id32 entry, const MeshResourceId meshResource, bool immediate)
{
n_assert(stream.isvalid());

Expand Down Expand Up @@ -234,8 +234,8 @@ MeshLoader::SetupMeshFromNvx(const Ptr<IO::Stream>& stream, const Ids::Id32 entr
n_assert(header->numMeshes > 0);
auto vertexRanges = (Nvx3VertexRange*)(header + 1);
auto groups = (Nvx3Group*)(vertexRanges + header->numMeshes);
//auto vertexData = (ubyte*)(groups + header->numGroups);
//auto indexData = (ubyte*)(vertexData + header->vertexDataSize);
auto vertexData = (ubyte*)(groups + header->numGroups);
auto indexData = (ubyte*)(vertexData + header->vertexDataSize);
//auto meshletData = (Nvx3Meshlet*)(indexData + header->indexDataSize);

meshes.Resize(header->numMeshes);
Expand All @@ -255,13 +255,23 @@ MeshLoader::SetupMeshFromNvx(const Ptr<IO::Stream>& stream, const Ids::Id32 entr
// Allocate vertices from global repository
vertexAllocation = CoreGraphics::AllocateVertices(header->vertexDataSize);
streamData->vertexAllocationOffset = vertexAllocation;

if (immediate)
{
BufferCopyWithStaging(CoreGraphics::GetVertexBuffer(), streamData->vertexAllocationOffset.offset, vertexData, header->vertexDataSize);
}
}

// Upload index data
{
// Allocate vertices from global repository
indexAllocation = CoreGraphics::AllocateIndices(header->indexDataSize);
streamData->indexAllocationOffset = indexAllocation;

if (immediate)
{
BufferCopyWithStaging(CoreGraphics::GetIndexBuffer(), streamData->indexAllocationOffset.offset, indexData, header->indexDataSize);
}
}

for (uint i = 0; i < header->numGroups; i++)
Expand Down
2 changes: 1 addition & 1 deletion code/render/coregraphics/meshloader.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class MeshLoader : public Resources::ResourceLoader
uint LodMask(const Ids::Id32 entry, float lod, bool stream) const override;

/// setup mesh from nvx3 file in memory
void SetupMeshFromNvx(const Ptr<IO::Stream>& stream, const Ids::Id32 entry, const MeshResourceId meshResource);
void SetupMeshFromNvx(const Ptr<IO::Stream>& stream, const Ids::Id32 entry, const MeshResourceId meshResource, bool immediate);
};

} // namespace CoreGraphics
28 changes: 28 additions & 0 deletions code/render/coregraphics/vk/vkbuffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -564,4 +564,32 @@ BufferGetDeviceAddress(const BufferId id)
return vkGetBufferDeviceAddress(dev, &deviceAddress);
}

//------------------------------------------------------------------------------
/**
*/
void
BufferCopyWithStaging(const CoreGraphics::BufferId dest, const uint offset, const void* data, const uint size)
{
// Create buffer to copy from
CoreGraphics::BufferCreateInfo bufInfo;
bufInfo.byteSize = size;
bufInfo.usageFlags = CoreGraphics::BufferUsageFlag::TransferBufferSource;
bufInfo.mode = CoreGraphics::BufferAccessMode::HostLocal;
bufInfo.queueSupport = CoreGraphics::GraphicsQueueSupport;
bufInfo.data = data;
bufInfo.dataSize = size;
CoreGraphics::BufferId buf = CoreGraphics::CreateBuffer(bufInfo);

// Perform copy on the setup queue
CoreGraphics::BufferCopy from, to;
from.offset = 0;
to.offset = offset;
CoreGraphics::CmdBufferId cmdBuf = CoreGraphics::LockGraphicsSetupCommandBuffer();
CoreGraphics::CmdCopy(cmdBuf, buf, { from }, dest, { to }, size);
CoreGraphics::UnlockGraphicsSetupCommandBuffer();

// Destroy the buffer
CoreGraphics::DestroyBuffer(buf);
}

} // namespace CoreGraphics
9 changes: 6 additions & 3 deletions code/render/coregraphics/vk/vkshaperenderer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,6 @@ VkShapeRenderer::DrawShapes(const CoreGraphics::CmdBufferId cmdBuf)
if (this->shapes[shaderType].Size() > 0)
{
CoreGraphics::CmdSetShaderProgram(cmdBuf, this->programs[shaderType]);
CoreGraphics::CmdSetVertexLayout(cmdBuf, this->vertexLayout);
CoreGraphics::CmdSetGraphicsPipeline(cmdBuf);

IndexT i;
Expand Down Expand Up @@ -269,8 +268,9 @@ VkShapeRenderer::DrawSimpleShape(const CoreGraphics::CmdBufferId cmdBuf, const M
CoreGraphics::CmdPushConstants(cmdBuf, CoreGraphics::GraphicsPipeline, this->lineWidth, sizeof(float), &lineThickness);

const MeshId mesh = this->meshes[shapeType];
CoreGraphics::CmdSetIndexBuffer(cmdBuf, MeshGetIndexType(mesh), MeshGetIndexBuffer(mesh), MeshGetIndexOffset(mesh));
CoreGraphics::CmdSetVertexBuffer(cmdBuf, 0, MeshGetVertexBuffer(mesh, 0), MeshGetVertexOffset(mesh, 0));
CoreGraphics::CmdSetVertexLayout(cmdBuf, CoreGraphics::MeshGetVertexLayout(mesh));
CoreGraphics::CmdSetIndexBuffer(cmdBuf, MeshGetIndexType(mesh), CoreGraphics::GetIndexBuffer(), MeshGetIndexOffset(mesh));
CoreGraphics::CmdSetVertexBuffer(cmdBuf, 0, CoreGraphics::GetVertexBuffer(), MeshGetVertexOffset(mesh, 0));
const Util::Array<CoreGraphics::PrimitiveGroup>& groups = MeshGetPrimitiveGroups(mesh);

IndexT i;
Expand Down Expand Up @@ -300,6 +300,7 @@ VkShapeRenderer::DrawMesh(const CoreGraphics::CmdBufferId cmdBuf, const Math::ma
const Util::Array<CoreGraphics::PrimitiveGroup>& groups = MeshGetPrimitiveGroups(mesh);

// set resources
CoreGraphics::CmdSetVertexLayout(cmdBuf, MeshGetVertexLayout(mesh));
CoreGraphics::CmdSetIndexBuffer(cmdBuf, MeshGetIndexType(mesh), MeshGetIndexBuffer(mesh), MeshGetIndexOffset(mesh));
CoreGraphics::CmdSetVertexBuffer(cmdBuf, 0, MeshGetVertexBuffer(mesh, 0), MeshGetVertexOffset(mesh, 0));

Expand Down Expand Up @@ -397,6 +398,7 @@ VkShapeRenderer::DrawBufferedPrimitives(const CoreGraphics::CmdBufferId cmdBuf)
for (j = 1; j < CoreGraphics::PrimitiveTopology::NumTopologies; j++)
{
CoreGraphics::CmdSetPrimitiveTopology(cmdBuf, CoreGraphics::PrimitiveTopology::Code(j));
CoreGraphics::CmdSetVertexLayout(cmdBuf, this->vertexLayout);
CoreGraphics::CmdSetGraphicsPipeline(cmdBuf);

IndexT i;
Expand Down Expand Up @@ -431,6 +433,7 @@ VkShapeRenderer::DrawBufferedIndexedPrimitives(const CoreGraphics::CmdBufferId c
{
auto topology = CoreGraphics::PrimitiveTopology::Code(j);
CoreGraphics::CmdSetPrimitiveTopology(cmdBuf, topology);
CoreGraphics::CmdSetVertexLayout(cmdBuf, this->vertexLayout);
CoreGraphics::CmdSetGraphicsPipeline(cmdBuf);

IndexT i;
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions code/render/materials/materialloader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ MaterialLoader::InitializeResource(const Ids::Id32 entry, const Util::StringAtom
CoreGraphics::TextureIdLock _0(rid);
var.Set(CoreGraphics::TextureGetBindlessHandle(rid), mem);
MaterialSetConstant(id, constant, var);
});
}, immediate);
CoreGraphics::TextureIdLock _0(tex);
var.Set(CoreGraphics::TextureGetBindlessHandle(tex), mem);

Expand Down Expand Up @@ -516,7 +516,7 @@ MaterialLoader::InitializeResource(const Ids::Id32 entry, const Util::StringAtom
{
CoreGraphics::TextureIdLock _0(rid);
MaterialSetTexture(id, texture, rid);
});
}, immediate);

CoreGraphics::TextureIdLock _0(tex);
MaterialSetTexture(id, texture, tex);
Expand Down
15 changes: 15 additions & 0 deletions code/render/models/model.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,21 @@ enum NodeBits
};
__ImplementEnumBitOperators(NodeBits);

enum class LoadBits
{
NoBits = N_BIT(0),
MeshBit = N_BIT(1),
AnimBit = N_BIT(2),
MaterialBit = N_BIT(3)
};
__ImplementEnumBitOperators(LoadBits);

struct ModelStreamingData
{
LoadBits requiredBits;
LoadBits loadedBits;
};

struct NodeInstanceRange
{
Memory::RangeAllocation allocation;
Expand Down
19 changes: 17 additions & 2 deletions code/render/models/modelcontext.cc
Original file line number Diff line number Diff line change
Expand Up @@ -737,11 +737,18 @@ ModelContext::UpdateTransforms(const Graphics::FrameContext& ctx)
n_assert(ConstantsUpdateCounter == 0);
ConstantsUpdateCounter = 1;

// Create a set of default joints
static Util::FixedArray<Math::mat4> defaultJoints(256);
ObjectsShared::JointBlock joints;
memcpy(joints.JointPalette, defaultJoints.Begin(), sizeof(ObjectsShared::JointBlock::JointPalette));
uint defaultJointsOffset = CoreGraphics::SetConstants(joints);

Jobs2::JobDispatch(
[
nodeInstanceTransformRanges = nodeInstanceTransformRanges.ConstBegin()
, nodeInstanceStateRanges = nodeInstanceStateRanges.ConstBegin()
, cameraTransform
, defaultJointsOffset
]
(SizeT totalJobs, SizeT groupSize, IndexT groupIndex, SizeT invocationOffset)
{
Expand All @@ -757,17 +764,25 @@ ModelContext::UpdateTransforms(const Graphics::FrameContext& ctx)
SizeT j;
for (j = stateRange.begin; j < stateRange.end; j++)
{
Math::mat4 transform = NodeInstances.transformable.nodeTransforms[transformRange.begin + NodeInstances.renderable.nodeTransformIndex[j]];
Math::mat4 transform = NodeInstances.transformable
.nodeTransforms[transformRange.begin + NodeInstances.renderable.nodeTransformIndex[j]];

// Allocate object constants
alignas(16) ObjectsShared::ObjectBlock block;
ObjectsShared::ObjectBlock block;
transform.store(block.Model);
inverse(transform).store(block.InvModel);
block.DitherFactor = NodeInstances.renderable.nodeLods[j];
block.ObjectId = j;

uint offset = CoreGraphics::SetConstants(block);
NodeInstances.renderable.nodeStates[j].resourceTableOffsets[NodeInstances.renderable.nodeStates[j].objectConstantsIndex] = offset;

/*
if (NodeInstances.renderable.nodeStates[j].skinningConstantsIndex != InvalidIndex)
{
NodeInstances.renderable.nodeStates[j].resourceTableOffsets[NodeInstances.renderable.nodeStates[j].skinningConstantsIndex] = defaultJointsOffset;
}
*/
}
}
}, nodeInstanceStateRanges.Size(), 256, { &lodUpdateCounter }, &ConstantsUpdateCounter, &ModelContext::completionEvent);
Expand Down
Loading

0 comments on commit 7a6c54c

Please sign in to comment.