engine/engine/inc/uf/utils/mesh/grid.h

124 lines
4.9 KiB
C++

#pragma once
#include <uf/config.h>
#include <uf/utils/mesh/mesh.h>
#include <uf/engine/graph/graph.h>
#include <limits>
namespace uf {
namespace meshgrid {
struct Node {
struct {
pod::Vector3f min = {};
pod::Vector3f max = {};
} extents;
struct {
pod::Vector3f min = { std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max() };
pod::Vector3f max = { -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max() };
} effectiveExtents;
pod::Vector3ui id = {};
uf::stl::unordered_map<size_t, uf::Meshlet_T<>> meshlets;
};
struct Grid {
pod::Vector3ui divisions = {1,1,1};
int indices = 0;
struct {
pod::Vector3f min = { std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max() };
pod::Vector3f max = { -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max() };
pod::Vector3f center = {};
pod::Vector3f corner = {};
pod::Vector3f size = {};
pod::Vector3f piece = {};
} extents;
// uf::stl::vector<Node> nodes;
uf::stl::unordered_map<pod::Vector3ui, Node> nodes;
};
void UF_API print( const Grid& );
void UF_API cleanup( Grid& );
void UF_API calculate( uf::meshgrid::Grid&, float = std::numeric_limits<float>::epsilon() );
void UF_API calculate( uf::meshgrid::Grid&, int, float = std::numeric_limits<float>::epsilon() );
void UF_API calculate( uf::meshgrid::Grid&, const pod::Vector3ui&, float = std::numeric_limits<float>::epsilon() );
void UF_API partition( uf::meshgrid::Grid&, const void*, size_t, const void*, size_t, const pod::Primitive& );
void UF_API partition( uf::meshgrid::Grid&, uf::Mesh&, const pod::Primitive& );
template<typename T, typename U = uint32_t>
void UF_API partition( uf::meshgrid::Grid& grid, const uf::stl::vector<T>& vertices, const uf::stl::vector<U>& indices, const pod::Primitive& primitive ) {
auto vertexDescriptor = T::descriptor.front();
for ( auto& descriptor : T::descriptor ) if ( descriptor.name == "position" ) { vertexDescriptor = descriptor; break; }
UF_ASSERT( vertexDescriptor.name == "position" );
return partition( grid,
vertices.data(), sizeof(T),
indices.data(), sizeof(U),
primitive
);
}
template<typename T, typename U = uint32_t>
uf::stl::vector<uf::Meshlet_T<T,U>> UF_API partition( uf::meshgrid::Grid& grid, const uf::stl::vector<uf::Meshlet_T<T,U>>& meshlets, float eps = std::numeric_limits<float>::epsilon() ) {
uf::stl::vector<uf::Meshlet_T<T,U>> partitioned;
for ( auto& meshlet : meshlets ) {
grid.extents.min = uf::vector::min( grid.extents.min, meshlet.primitive.instance.bounds.min );
grid.extents.max = uf::vector::max( grid.extents.max, meshlet.primitive.instance.bounds.max );
}
uf::meshgrid::calculate( grid, eps );
for ( auto& meshlet : meshlets ) {
uf::meshgrid::partition<T,U>( grid, meshlet.vertices, meshlet.indices, meshlet.primitive );
}
uf::meshgrid::cleanup( grid );
size_t atlasID = 0;
for ( auto& pair : grid.nodes ) { auto& node = pair.second;
++atlasID;
for ( auto& pair2 : node.meshlets ) { auto& mlet = pair2.second;
if ( mlet.indices.empty() ) continue;
auto& meshlet = meshlets[mlet.primitive.instance.primitiveID];
size_t primitiveID = partitioned.size();
auto& slice = partitioned.emplace_back();
slice.vertices.reserve( mlet.indices.size() );
slice.indices.reserve( mlet.indices.size() );
for ( auto idx : mlet.indices ) {
auto& vertex = slice.vertices.emplace_back( meshlet.vertices[idx] );
auto& index = slice.indices.emplace_back( slice.indices.size() );
vertex.id.x = primitiveID;
vertex.id.y = meshlet.primitive.instance.meshID;
}
slice.primitive.instance = meshlet.primitive.instance;
slice.primitive.instance.materialID = meshlet.primitive.instance.materialID;
slice.primitive.instance.primitiveID = primitiveID;
slice.primitive.instance.meshID = meshlet.primitive.instance.meshID;
slice.primitive.instance.objectID = 0;
slice.primitive.instance.auxID = atlasID;
slice.primitive.instance.bounds.min = node.effectiveExtents.min;
slice.primitive.instance.bounds.max = node.effectiveExtents.max;
slice.primitive.drawCommand.indices = slice.indices.size();
slice.primitive.drawCommand.instances = 1;
slice.primitive.drawCommand.indexID = 0;
slice.primitive.drawCommand.vertexID = 0;
slice.primitive.drawCommand.instanceID = 0;
slice.primitive.drawCommand.auxID = atlasID; // meshlet.primitive.instance.meshID;
slice.primitive.drawCommand.vertices = slice.vertices.size();
}
}
return partitioned;
}
}
}