Commit for 2022.01.09 01-24-17.7z

This commit is contained in:
mrq 2022-01-09 01:24:00 -06:00
parent f45db51561
commit 4a96f148ad
14 changed files with 523 additions and 387 deletions

View File

@ -3,7 +3,7 @@ CC = $(shell cat "./bin/exe/default.config")
TARGET_NAME = program
TARGET_EXTENSION = exe
TARGET_LIB_EXTENSION = dll
RENDERER = vulkan
RENDERER = opengl
include makefiles/$(ARCH).$(CC).make

View File

@ -2,7 +2,7 @@
"engine": {
"scenes": {
"start": "SS2",
"meshes": { "interleaved": false },
"meshes": { "interleaved": true },
"matrix": { "reverseInfinite": true },
"lights": {
"max": 24,
@ -146,7 +146,7 @@
"debug draw": {
"enabled": false,
// "layer": "Gui",
"rate": 0.0125
"rate": 0.06666666666
}
},
"bullet": {

View File

@ -1,9 +1,9 @@
{
"import": "/model.json",
"assets": [
{ "filename": "./models/tiny_msci.glb", "delay": 0, "single threaded": false, "category": "models" }
// { "filename": "./models/tiny_msci.glb", "delay": 0, "single threaded": false, "category": "models" }
// { "filename": "./models/tiny_msci/graph.json", "delay": 0, "single threaded": false, "category": "models" }
// { "filename": "./models/tiny_msci/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
{ "filename": "./models/tiny_msci/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
// { "filename": "./models/micro_sci.glb", "delay": 0, "single threaded": false, "category": "models" }
// { "filename": "./models/micro_sci/graph.json", "delay": 0, "single threaded": false, "category": "models" }

View File

@ -2,7 +2,7 @@
"engine": {
"scenes": {
"start": "SS2",
"meshes": { "interleaved": false },
"meshes": { "interleaved": true },
"matrix": { "reverseInfinite": false },
"lights": {
"max": 8,

View File

@ -64,7 +64,7 @@ namespace uf {
uf::stl::vector<Attribute> attributes;
size_t count = 0; // how many elements is the input using
size_t first = 0; // base index to start from
size_t stride = 0; // size of one element in the input's buffer
size_t size = 0; // size of one element in the input's buffer
size_t offset = 0; // bytes to offset from within the associated buffer
int32_t interleaved = -1; // index to interleaved buffer if in bounds
} vertex, index, instance, indirect;
@ -109,18 +109,39 @@ namespace uf {
void initialize();
void destroy();
uf::Mesh convert( bool ) const;
uf::Mesh convert() const;
uf::Mesh copy(bool) const;
uf::Mesh expand();
uf::Mesh expand(bool);
void updateDescriptor();
void bind( const uf::Mesh& );
void bind( const uf::Mesh&, bool );
void insert( const uf::Mesh& );
void generateIndices();
void generateIndirect();
bool isInterleaved() const;
bool isInterleaved( size_t ) const;
void print() const;
buffer_t& getBuffer( const uf::Mesh::Input&, size_t = 0 );
buffer_t& getBuffer( const uf::Mesh::Input&, const uf::Mesh::Attribute& );
const buffer_t& getBuffer( const uf::Mesh::Input&, size_t = 0 ) const;
const buffer_t& getBuffer( const uf::Mesh::Input&, const uf::Mesh::Attribute& ) const;
void print( bool = true ) const;
std::string printVertices( bool = true ) const;
std::string printIndices( bool = true ) const;
std::string printInstances( bool = true ) const;
std::string printIndirects( bool = true ) const;
uf::Mesh::Input remapInput( const uf::Mesh::Input&, size_t i = 0 ) const;
uf::Mesh::Input remapVertexInput( size_t i = 0 ) const;
uf::Mesh::Input remapIndexInput( size_t i = 0 ) const;
inline bool hasVertex( const uf::stl::vector<ext::RENDERER::AttributeDescriptor>& descriptors ) const { return _hasV( vertex, descriptors ); }
inline bool hasVertex( const uf::Mesh& mesh ) const { return _hasV( vertex, mesh.vertex ); }

View File

@ -188,33 +188,13 @@ namespace {
uf::Mesh decodeMesh( ext::json::Value& json, pod::Graph& graph ) {
uf::Mesh mesh;
/*
struct Attribute {
ext::RENDERER::AttributeDescriptor descriptor;
int32_t buffer = -1;
size_t offset = 0;
size_t stride = 0;
size_t length = 0;
void* pointer = NULL;
};
struct Input {
uf::stl::vector<Attribute> attributes;
size_t count = 0; // how many elements is the input using
size_t first = 0; // base index to start from
size_t stride = 0; // size of one element in the input's buffer
size_t offset = 0; // bytes to offset from within the associated buffer
int32_t interleaved = -1; // index to interleaved buffer if in bounds
} vertex, index, instance, indirect;
*/
#define DESERIALIZE_MESH(N) {\
auto& input = json["inputs"][#N];\
mesh.N.attributes.reserve( input["attributes"].size() );\
mesh.N.count = input["count"].as( mesh.N.count );\
mesh.N.first = input["first"].as( mesh.N.first );\
mesh.N.stride = input["stride"].as( mesh.N.stride );\
mesh.N.offset = input["stride"].as( mesh.N.offset );\
mesh.N.size = input["size"].as( mesh.N.size );\
mesh.N.offset = input["offset"].as( mesh.N.offset );\
mesh.N.interleaved = input["interleaved"].as( mesh.N.interleaved );\
ext::json::forEach( input["attributes"], [&]( ext::json::Value& value ){\
auto& attribute = mesh.N.attributes.emplace_back();\
@ -244,6 +224,8 @@ namespace {
});
mesh.updateDescriptor();
// return mesh.expand();
// if ( mesh.isInterleaved() != uf::Mesh::defaultInterleaved ) return mesh.copy(true);
return mesh;
}

View File

@ -160,7 +160,7 @@ namespace {
uf::stl::vector<Attribute> attributes;
size_t count = 0; // how many elements is the input using
size_t first = 0; // base index to start from
size_t stride = 0; // size of one element in the input's buffer
size_t size = 0; // size of one element in the input's buffer
size_t offset = 0; // bytes to offset from within the associated buffer
int32_t interleaved = -1; // index to interleaved buffer if in bounds
} vertex, index, instance, indirect;
@ -170,7 +170,7 @@ namespace {
auto& input = json["inputs"][#N];\
input["count"] = mesh.N.count;\
input["first"] = mesh.N.first;\
input["stride"] = mesh.N.stride;\
input["size"] = mesh.N.size;\
input["offset"] = mesh.N.offset;\
input["interleaved"] = mesh.N.interleaved;\
ext::json::reserve( input["attributes"], mesh.N.attributes.size() );\
@ -193,84 +193,7 @@ namespace {
SERIALIZE_MESH(index);
SERIALIZE_MESH(instance);
SERIALIZE_MESH(indirect);
/*
json["inputs"]["vertex"]["count"] = mesh.vertex.count;
json["inputs"]["vertex"]["first"] = mesh.vertex.first;
json["inputs"]["vertex"]["stride"] = mesh.vertex.stride;
json["inputs"]["vertex"]["offset"] = mesh.vertex.offset;
json["inputs"]["vertex"]["interleaved"] = mesh.vertex.interleaved;
ext::json::reserve( json["inputs"]["vertex"]["attributes"], mesh.vertex.attributes.size() );
for ( auto& attribute : mesh.vertex.attributes ) {
auto& a = json["inputs"]["vertex"]["attributes"].emplace_back();
a["descriptor"]["offset"] = attribute.descriptor.offset;
a["descriptor"]["size"] = attribute.descriptor.size;
a["descriptor"]["format"] = attribute.descriptor.format;
a["descriptor"]["name"] = attribute.descriptor.name;
a["descriptor"]["type"] = attribute.descriptor.type;
a["descriptor"]["components"] = attribute.descriptor.components;
a["buffer"] = attribute.buffer;
a["offset"] = attribute.offset;
a["stride"] = attribute.stride;
}
json["inputs"]["index"]["count"] = mesh.index.count;
json["inputs"]["index"]["first"] = mesh.index.first;
json["inputs"]["index"]["stride"] = mesh.index.stride;
json["inputs"]["index"]["offset"] = mesh.index.offset;
json["inputs"]["index"]["interleaved"] = mesh.index.interleaved;
ext::json::reserve( json["inputs"]["index"]["attributes"], mesh.index.attributes.size() );
for ( auto& attribute : mesh.index.attributes ) {
auto& a = json["inputs"]["index"]["attributes"].emplace_back();
a["descriptor"]["offset"] = attribute.descriptor.offset;
a["descriptor"]["size"] = attribute.descriptor.size;
a["descriptor"]["format"] = attribute.descriptor.format;
a["descriptor"]["name"] = attribute.descriptor.name;
a["descriptor"]["type"] = attribute.descriptor.type;
a["descriptor"]["components"] = attribute.descriptor.components;
a["buffer"] = attribute.buffer;
a["offset"] = attribute.offset;
a["stride"] = attribute.stride;
}
json["inputs"]["instance"]["count"] = mesh.instance.count;
json["inputs"]["instance"]["first"] = mesh.instance.first;
json["inputs"]["instance"]["stride"] = mesh.instance.stride;
json["inputs"]["instance"]["offset"] = mesh.instance.offset;
json["inputs"]["instance"]["interleaved"] = mesh.instance.interleaved;
ext::json::reserve( json["inputs"]["instance"]["attributes"], mesh.instance.attributes.size() );
for ( auto& attribute : mesh.instance.attributes ) {
auto& a = json["inputs"]["instance"]["attributes"].emplace_back();
a["descriptor"]["offset"] = attribute.descriptor.offset;
a["descriptor"]["size"] = attribute.descriptor.size;
a["descriptor"]["format"] = attribute.descriptor.format;
a["descriptor"]["name"] = attribute.descriptor.name;
a["descriptor"]["type"] = attribute.descriptor.type;
a["descriptor"]["components"] = attribute.descriptor.components;
a["buffer"] = attribute.buffer;
a["offset"] = attribute.offset;
a["stride"] = attribute.stride;
}
json["inputs"]["indirect"]["count"] = mesh.indirect.count;
json["inputs"]["indirect"]["first"] = mesh.indirect.first;
json["inputs"]["indirect"]["stride"] = mesh.indirect.stride;
json["inputs"]["indirect"]["offset"] = mesh.indirect.offset;
json["inputs"]["indirect"]["interleaved"] = mesh.indirect.interleaved;
ext::json::reserve( json["inputs"]["indirect"]["attributes"], mesh.indirect.attributes.size() );
for ( auto& attribute : mesh.indirect.attributes ) {
auto& a = json["inputs"]["indirect"]["attributes"].emplace_back();
a["descriptor"]["offset"] = attribute.descriptor.offset;
a["descriptor"]["size"] = attribute.descriptor.size;
a["descriptor"]["format"] = attribute.descriptor.format;
a["descriptor"]["name"] = attribute.descriptor.name;
a["descriptor"]["type"] = attribute.descriptor.type;
a["descriptor"]["components"] = attribute.descriptor.components;
a["buffer"] = attribute.buffer;
a["offset"] = attribute.offset;
a["stride"] = attribute.stride;
}
*/
ext::json::reserve( json["buffers"], mesh.buffers.size() );
for ( auto i = 0; i < mesh.buffers.size(); ++i ) {
const uf::stl::string filename = settings.filename + ".buffer." + std::to_string(i) + "." + ( settings.compress ? "gz" : "bin" );

View File

@ -475,18 +475,34 @@ void uf::graph::process( pod::Graph& graph ) {
graph.root.mesh = graph.meshes.size();
auto keyName = graph.name + "/" + graph.root.name;
auto& mesh = uf::graph::storage.meshes[graph.meshes.emplace_back(keyName)];
mesh.bindIndirect<pod::DrawCommand>();
mesh.bind<uf::graph::mesh::Skinned, uint32_t>();
uf::stl::vector<pod::DrawCommand> drawCommands;
size_t counts = 0;
for ( auto& name : graph.meshes ) {
if ( name == keyName ) continue;
auto& m = uf::graph::storage.meshes.map[name];
mesh.bindIndirect<pod::DrawCommand>();
mesh.bind<uf::graph::mesh::Skinned, uint32_t>();
mesh.insert( m );
m.updateDescriptor();
mesh.insertVertices( m );
mesh.insertIndices( m );
mesh.insertInstances( m );
// mesh.insertIndirects( m );
pod::DrawCommand* dc = (pod::DrawCommand*) m.getBuffer( m.indirect ).data();
for ( size_t i = 0; i < m.indirect.count; ++i ) drawCommands.emplace_back( dc[i] );
}
mesh.insertIndirects( drawCommands );
mesh = mesh.expand();
mesh = mesh.copy(true);
// fix up draw command for combined mesh
{
auto& attribute = mesh.indirect.attributes.front();
auto& buffer = mesh.buffers[mesh.isInterleaved(mesh.indirect.interleaved) ? mesh.indirect.interleaved : attribute.buffer];
auto& buffer = mesh.getBuffer(mesh.indirect); // mesh.buffers[mesh.isInterleaved(mesh.indirect.interleaved) ? mesh.indirect.interleaved : attribute.buffer];
pod::DrawCommand* drawCommands = (pod::DrawCommand*) buffer.data();
size_t totalIndices = 0;
@ -499,6 +515,17 @@ void uf::graph::process( pod::Graph& graph ) {
totalIndices += drawCommand.indices;
totalVertices += drawCommand.vertices;
}
/*
if ( totalIndices > mesh.index.count ) {
UF_MSG_ERROR("Calculated total indices exceed actual indices count: expecting " << mesh.index.count << ", got " << totalIndices);
UF_EXCEPTION("invalid drawCommand");
}
if ( totalVertices > mesh.vertex.count ) {
UF_MSG_ERROR("Calculated total vertices exceed actual vertices count: expecting " << mesh.vertex.count << ", got " << totalVertices);
UF_EXCEPTION("invalid drawCommand");
}
*/
}
{
auto& graphic = graph.root.entity->getComponent<uf::Graphic>();

View File

@ -242,8 +242,6 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::
if ( ext::opengl::settings::experimental::culling && drawInfo.attributes.instance.pointer && drawInfo.attributes.instance.length == sizeof(pod::Instance) ) {
pod::Instance& instance = *(pod::Instance*) drawInfo.attributes.instance.pointer;
pod::Matrix4f mat = (*drawInfo.matrices.projection) * (*drawInfo.matrices.view) * (*drawInfo.matrices.model);
// pod::Matrix4f mat = (*drawInfo.matrices.projection) * (*drawInfo.matrices.view) * (instance.model);
// pod::Matrix4f mat = uf::matrix::multiply( projection, modelView );
bool visible = inside( instance, mat );
drawCommand.instances = visible ? 1 : 0;
@ -298,7 +296,7 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::
GL_ERROR_CHECK(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
GL_ERROR_CHECK(glBindTexture(drawInfo.textures.primary.viewType, drawInfo.textures.primary.image));
GL_ERROR_CHECK(glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE));
GL_ERROR_CHECK(glTexCoordPointer(2, GL_FLOAT, drawInfo.attributes.uv.stride, drawInfo.attributes.uv.pointer));
GL_ERROR_CHECK(glTexCoordPointer(2, GL_FLOAT, drawInfo.attributes.uv.stride, (drawInfo.attributes.uv.pointer + drawInfo.attributes.uv.stride * drawInfo.descriptor.inputs.vertex.first)));
if ( drawInfo.textures.secondary.image && drawInfo.attributes.st.pointer ) {
// static GLuint previous = 0;
@ -313,15 +311,15 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::
#if UF_ENV_DREAMCAST
if ( blending ) GL_ERROR_CHECK(glDisable(GL_BLEND));
#endif
GL_ERROR_CHECK(glTexCoordPointer(2, GL_FLOAT, drawInfo.attributes.st.stride, drawInfo.attributes.st.pointer));
GL_ERROR_CHECK(glTexCoordPointer(2, GL_FLOAT, drawInfo.attributes.st.stride, (drawInfo.attributes.st.pointer + drawInfo.attributes.st.stride * drawInfo.descriptor.inputs.vertex.first)));
}
}
if ( drawInfo.attributes.normal.pointer ) GL_ERROR_CHECK(glNormalPointer(GL_FLOAT, drawInfo.attributes.normal.stride, drawInfo.attributes.normal.pointer));
if ( drawInfo.attributes.color.pointer ) GL_ERROR_CHECK(glColorPointer(4, GL_UNSIGNED_BYTE, drawInfo.attributes.color.stride, drawInfo.attributes.color.pointer));
GL_ERROR_CHECK(glVertexPointer(3, GL_FLOAT, drawInfo.attributes.position.stride, drawInfo.attributes.position.pointer));
GL_ERROR_CHECK(glDrawElements(GL_TRIANGLES, drawInfo.attributes.index.length / drawInfo.attributes.index.stride, indicesType, drawInfo.attributes.index.pointer));
if ( drawInfo.attributes.normal.pointer ) GL_ERROR_CHECK(glNormalPointer(GL_FLOAT, drawInfo.attributes.normal.stride, (drawInfo.attributes.normal.pointer + drawInfo.attributes.normal.stride * drawInfo.descriptor.inputs.vertex.first)));
if ( drawInfo.attributes.color.pointer ) GL_ERROR_CHECK(glColorPointer(4, GL_UNSIGNED_BYTE, drawInfo.attributes.color.stride, (drawInfo.attributes.color.pointer + drawInfo.attributes.color.stride * drawInfo.descriptor.inputs.vertex.first)));
GL_ERROR_CHECK(glVertexPointer(3, GL_FLOAT, drawInfo.attributes.position.stride, (drawInfo.attributes.position.pointer + drawInfo.attributes.position.stride * drawInfo.descriptor.inputs.vertex.first)));
GL_ERROR_CHECK(glDrawElements(GL_TRIANGLES, drawInfo.descriptor.inputs.index.count, indicesType, (drawInfo.attributes.index.pointer + drawInfo.attributes.index.stride * drawInfo.descriptor.inputs.index.first)));
if ( drawInfo.textures.secondary.image ) {
#if UF_ENV_DREAMCAST

View File

@ -43,7 +43,7 @@ void ext::opengl::Pipeline::initialize( const Graphic& graphic, const GraphicDes
auto& attribute = descriptor.inputs.vertex.attributes[i];
GL_ERROR_CHECK(glEnableVertexAttribArray(i));
GL_ERROR_CHECK(glVertexAttribPointer(0, attribute.descriptor.components, attribute.descriptor.type, false, descriptor.inputs.vertex.stride, attribute.descriptor.offset));
GL_ERROR_CHECK(glVertexAttribPointer(0, attribute.descriptor.components, attribute.descriptor.type, false, descriptor.inputs.vertex.size, attribute.descriptor.offset));
}
GL_ERROR_CHECK(glBindVertexArray(0));
}
@ -394,13 +394,16 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, const GraphicDe
drawCommandInfo.descriptor = descriptor;
drawCommandInfo.attributes.index = descriptor.inputs.index.attributes.front();
drawCommandInfo.attributes.index.pointer = (void*) ((uint8_t*) drawCommandInfo.attributes.index.pointer + drawCommand.indexID * drawCommandInfo.attributes.index.stride);
drawCommandInfo.attributes.index.length = drawCommand.indices * drawCommandInfo.attributes.index.stride;
drawCommandInfo.descriptor.inputs.index.first = drawCommand.indexID;
drawCommandInfo.descriptor.inputs.index.count = drawCommand.indices;
drawCommandInfo.descriptor.inputs.vertex.first = drawCommand.vertexID;
drawCommandInfo.descriptor.inputs.vertex.count = drawCommand.vertices;
// drawCommandInfo.attributes.index.pointer + drawCommandInfo.attributes.index.stride * drawCommandInfo.descriptor.inputs.index.first;
for ( uf::Mesh::Attribute attribute : descriptor.inputs.vertex.attributes ) {
attribute.pointer += drawCommand.vertexID * attribute.stride;
attribute.length = drawCommand.vertices * attribute.stride;
// UF_MSG_DEBUG( attribute.descriptor.name << ": " << attribute.descriptor.offset << " " << attribute.pointer << " " << attribute.pointer - attribute.descriptor.offset );
// attribute.pointer = attribute.pointer + attribute.stride * drawCommandInfo.descriptor.inputs.vertex.first;
if ( attribute.descriptor.name == "position" ) drawCommandInfo.attributes.position = attribute;
else if ( attribute.descriptor.name == "uv" ) drawCommandInfo.attributes.uv = attribute;
@ -408,14 +411,23 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, const GraphicDe
else if ( attribute.descriptor.name == "normal" ) drawCommandInfo.attributes.normal = attribute;
else if ( attribute.descriptor.name == "color" ) drawCommandInfo.attributes.color = attribute;
}
/*
{
float* p = (float*) (drawCommandInfo.attributes.position.pointer + drawCommandInfo.attributes.position.stride * drawCommandInfo.descriptor.inputs.vertex.first);
// float* p = (float*) drawCommandInfo.attributes.position.pointer;
UF_MSG_DEBUG( "[" << i << "] [" << drawCommandInfo.descriptor.inputs.vertex.first << "] (" << p[0] << ", " << p[1] << ", " << p[2] << ")" );
}
*/
/*
for ( size_t i = 0; i < drawCommand.vertices; ++i ) {
float* p = (float*) (drawCommandInfo.attributes.position.pointer + i * drawCommandInfo.attributes.position.stride);
float* uv = (float*) (drawCommandInfo.attributes.uv.pointer + i * drawCommandInfo.attributes.uv.stride);
float* p = (float*) (drawCommandInfo.attributes.position.pointer + drawCommandInfo.attributes.position.stride * (i + drawCommand.vertexID));
float* uv = (float*) (drawCommandInfo.attributes.uv.pointer + drawCommandInfo.attributes.uv.stride * (i + drawCommand.vertexID));
std::cout << "(" << p[0] << ", " << p[1] << ", " << p[2] << "|" << uv[0] << ", " << uv[1] << ") ";
}
std::cout << std::endl;
*/
drawCommandInfo.attributes.instance.pointer = &instance;
drawCommandInfo.attributes.instance.length = sizeof(instance);

View File

@ -174,8 +174,62 @@ void ext::reactphysics::detach( pod::PhysicsState& state ) {
// collider for mesh (static or dynamic)
pod::PhysicsState& ext::reactphysics::create( uf::Object& object, const uf::Mesh& mesh, bool dynamic ) {
UF_ASSERT( mesh.index.count );
auto* rMesh = ::common.createTriangleMesh();
mesh.print( false );
uf::Mesh::Input vertexInput = mesh.vertex;
uf::Mesh::Input indexInput = mesh.index;
uf::Mesh::Attribute vertexAttribute = mesh.vertex.attributes.front();
uf::Mesh::Attribute indexAttribute = mesh.index.attributes.front();
for ( auto& attribute : mesh.vertex.attributes ) if ( attribute.descriptor.name == "position" ) { vertexAttribute = attribute; break; }
UF_ASSERT( vertexAttribute.descriptor.name == "position" );
rp3d::TriangleVertexArray::IndexDataType indexType = rp3d::TriangleVertexArray::IndexDataType::INDEX_INTEGER_TYPE;
rp3d::TriangleVertexArray::VertexDataType vertexType = rp3d::TriangleVertexArray::VertexDataType::VERTEX_FLOAT_TYPE;
switch ( mesh.index.size ) {
case sizeof(uint16_t): indexType = rp3d::TriangleVertexArray::IndexDataType::INDEX_SHORT_TYPE; break;
case sizeof(uint32_t): indexType = rp3d::TriangleVertexArray::IndexDataType::INDEX_INTEGER_TYPE; break;
default: UF_EXCEPTION("unsupported index type"); break;
}
if ( mesh.indirect.count ) {
for ( auto i = 0; i < mesh.indirect.count; ++i ) {
vertexInput = mesh.remapVertexInput( i );
indexInput = mesh.remapIndexInput( i );
rMesh->addSubpart(new rp3d::TriangleVertexArray(
vertexInput.count,
(const uint8_t*) (vertexAttribute.pointer + vertexAttribute.stride * vertexInput.first),
vertexAttribute.stride,
indexInput.count / 3,
(const uint8_t*) (indexAttribute.pointer + indexAttribute.stride * indexInput.first),
indexAttribute.stride * 3,
vertexType,
indexType
));
}
} else {
rMesh->addSubpart(new rp3d::TriangleVertexArray(
vertexInput.count,
(const uint8_t*) (vertexAttribute.pointer + vertexAttribute.stride * vertexInput.first),
vertexAttribute.stride,
indexInput.count / 3,
(const uint8_t*) (indexAttribute.pointer + indexAttribute.stride * indexInput.first),
indexAttribute.stride * 3,
vertexType,
indexType
));
}
/*
if ( mesh.index.count ) {
uf::Mesh::Attribute vertexAttribute;
for ( auto& attribute : mesh.vertex.attributes ) if ( attribute.descriptor.name == "position" ) { vertexAttribute = attribute; break; }
@ -184,7 +238,7 @@ pod::PhysicsState& ext::reactphysics::create( uf::Object& object, const uf::Mesh
auto& indexAttribute = mesh.index.attributes.front();
rp3d::TriangleVertexArray::IndexDataType indexType = rp3d::TriangleVertexArray::IndexDataType::INDEX_INTEGER_TYPE;
rp3d::TriangleVertexArray::VertexDataType vertexType = rp3d::TriangleVertexArray::VertexDataType::VERTEX_FLOAT_TYPE;
switch ( mesh.index.stride ) {
switch ( mesh.index.size ) {
case sizeof(uint16_t): indexType = rp3d::TriangleVertexArray::IndexDataType::INDEX_SHORT_TYPE; break;
case sizeof(uint32_t): indexType = rp3d::TriangleVertexArray::IndexDataType::INDEX_INTEGER_TYPE; break;
default: UF_EXCEPTION("unsupported index type"); break;
@ -199,11 +253,11 @@ pod::PhysicsState& ext::reactphysics::create( uf::Object& object, const uf::Mesh
remappedIndexAttribute = mesh.remapIndexAttribute( indexAttribute, i );
vArray = new rp3d::TriangleVertexArray(
remappedVertexAttribute.length / remappedVertexAttribute.stride,
remappedVertexAttribute.length / mesh.vertex.size,
(const uint8_t*) remappedVertexAttribute.pointer,
remappedVertexAttribute.stride,
remappedIndexAttribute.length / remappedIndexAttribute.stride / 3,
remappedIndexAttribute.length / mesh.index.size / 3,
(const uint8_t*) remappedIndexAttribute.pointer,
remappedIndexAttribute.stride * 3,
@ -230,6 +284,7 @@ pod::PhysicsState& ext::reactphysics::create( uf::Object& object, const uf::Mesh
rMesh->addSubpart(vArray);
}
} else UF_EXCEPTION("to-do: not require indices for meshes");
*/
auto& state = ext::reactphysics::create( object );
state.shape = ::common.createConcaveMeshShape( rMesh );

View File

@ -219,7 +219,7 @@ void ext::vulkan::Pipeline::initialize( const Graphic& graphic, const GraphicDes
if ( 0 <= descriptor.inputs.vertex.interleaved ) {
inputBindingDescriptions.emplace_back(ext::vulkan::initializers::vertexInputBindingDescription(
vertexBindID, // descriptor.inputs.vertex.interleaved,
descriptor.inputs.vertex.stride,
descriptor.inputs.vertex.size,
VK_VERTEX_INPUT_RATE_VERTEX
));
for ( auto& attribute : descriptor.inputs.vertex.attributes ) {
@ -992,12 +992,12 @@ void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, const GraphicD
if ( index.buffer ) {
VkIndexType indicesType = VK_INDEX_TYPE_UINT32;
switch ( descriptor.inputs.index.stride ) {
switch ( descriptor.inputs.index.size ) {
case 1: indicesType = VK_INDEX_TYPE_UINT8_EXT; break;
case 2: indicesType = VK_INDEX_TYPE_UINT16; break;
case 4: indicesType = VK_INDEX_TYPE_UINT32; break;
default:
UF_EXCEPTION("invalid indices size of " << (int) descriptor.inputs.index.stride);
UF_EXCEPTION("invalid indices size of " << (int) descriptor.inputs.index.size);
break;
}
vkCmdBindIndexBuffer(commandBuffer, index.buffer, index.offset, indicesType);
@ -1021,14 +1021,14 @@ void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, const GraphicD
vkCmdDrawIndexedIndirect(commandBuffer, indirect.buffer,
descriptor.inputs.indirect.offset, // offset
descriptor.inputs.indirect.count, // drawCount
descriptor.inputs.indirect.stride // stride
descriptor.inputs.indirect.size // stride
);
} else {
for ( auto i = 0; i < descriptor.inputs.indirect.count; ++i ) {
vkCmdDrawIndexedIndirect(commandBuffer, indirect.buffer,
descriptor.inputs.indirect.offset + i * descriptor.inputs.indirect.stride, // offset
descriptor.inputs.indirect.offset + i * descriptor.inputs.indirect.size, // offset
1, // drawCount
descriptor.inputs.indirect.stride // stride
descriptor.inputs.indirect.size // stride
);
}
}
@ -1044,7 +1044,7 @@ void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, const GraphicD
vkCmdDrawIndexedIndirect(commandBuffer, indirect.buffer,
descriptor.inputs.indirect.offset, // offset
descriptor.inputs.indirect.count, // drawCount
descriptor.inputs.indirect.stride // stride
descriptor.inputs.indirect.size // stride
);
} else/* if ( !vertexInstance.buffer.empty() && !indirect.buffer ) */{
vkCmdDraw(commandBuffer,

View File

@ -2,47 +2,6 @@
#if UF_USE_XATLAS
#include <xatlas/xatlas.h>
#endif
#if 0
pod::Vector2ui UF_API ext::xatlas::unwrap( uf::stl::vector<uf::graph::mesh::Skinned>& vertices, uf::stl::vector<uint32_t>& indices ) {
#if UF_USE_XATLAS
uf::stl::vector<uf::graph::mesh::Skinned> source = std::move(vertices);
::xatlas::Atlas* atlas = ::xatlas::Create();
::xatlas::MeshDecl decl;
decl.vertexCount = source.size();
decl.vertexPositionData = source.data() + offsetof(uf::graph::mesh::Skinned, position);
decl.vertexPositionStride = sizeof(uf::graph::mesh::Skinned);
decl.vertexUvData = source.data() + offsetof(uf::graph::mesh::Skinned, uv);
decl.vertexUvStride = sizeof(uf::graph::mesh::Skinned);
decl.indexCount = indices.size();
decl.indexData = indices.data();
decl.indexFormat = ::xatlas::IndexFormat::UInt32;
::xatlas::AddMeshError error = ::xatlas::AddMesh(atlas, decl, 1);
if (error != ::xatlas::AddMeshError::Success) {
::xatlas::Destroy(atlas);
UF_EXCEPTION(::xatlas::StringForEnum(error));
}
auto& xmesh = atlas->meshes[0];
vertices.resize( xmesh.vertexCount );
for ( auto i = 0; i < xmesh.vertexCount; ++i ) {
auto& vertex = xmesh.vertexArray[i];
vertices[i] = source[vertex.xref];
vertices[i].st = { vertex.uv[0] / atlas->width, vertex.uv[1] / atlas->height };
}
for ( auto i = 0; i < xmesh.indexCount; ++i ) indices[i] = xmesh.indexArray[i];
pod::Vector2ui size = pod::Vector2ui{ atlas->width, atlas->height };
::xatlas::Destroy(atlas);
return size;
#endif
}
#endif
pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
#if UF_USE_XATLAS
struct Pair {
@ -58,52 +17,60 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
sources.reserve(graph.meshes.size());
::xatlas::Atlas* atlas = ::xatlas::Create();
for ( auto index = 0; index < graph.meshes.size(); ++index ) {
auto& name = graph.meshes[index];
auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name];
UF_ASSERT( !mesh.isInterleaved() );
sources.emplace_back(mesh).updateDescriptor();
if ( mesh.index.count ) {
uf::Mesh::Attribute positionAttribute;
uf::Mesh::Attribute uvAttribute;
uf::Mesh::Attribute stAttribute;
for ( auto& attribute : mesh.vertex.attributes ) {
if ( attribute.descriptor.name == "position" ) positionAttribute = attribute;
else if ( attribute.descriptor.name == "uv" ) uvAttribute = attribute;
else if ( attribute.descriptor.name == "st" ) stAttribute = attribute;
}
UF_ASSERT( positionAttribute.descriptor.name == "position" && uvAttribute.descriptor.name == "uv" && stAttribute.descriptor.name == "st" );
uf::Mesh::Input vertexInput = mesh.vertex;
uf::Mesh::Attribute positionAttribute;
uf::Mesh::Attribute uvAttribute;
uf::Mesh::Attribute stAttribute;
for ( auto& attribute : mesh.vertex.attributes ) {
if ( attribute.descriptor.name == "position" ) positionAttribute = attribute;
else if ( attribute.descriptor.name == "uv" ) uvAttribute = attribute;
else if ( attribute.descriptor.name == "st" ) stAttribute = attribute;
}
UF_ASSERT( positionAttribute.descriptor.name == "position" && uvAttribute.descriptor.name == "uv" && stAttribute.descriptor.name == "st" );
if ( mesh.index.count ) {
uf::Mesh::Input indexInput = mesh.index;
uf::Mesh::Attribute indexAttribute = mesh.index.attributes.front();
auto& indexAttribute = mesh.index.attributes.front();
::xatlas::IndexFormat indexType = ::xatlas::IndexFormat::UInt32;
switch ( mesh.index.stride ) {
switch ( mesh.index.size ) {
case sizeof(uint16_t): indexType = ::xatlas::IndexFormat::UInt16; break;
case sizeof(uint32_t): indexType = ::xatlas::IndexFormat::UInt32; break;
default: UF_EXCEPTION("unsupported index type"); break;
}
if ( mesh.indirect.count ) {
uf::Mesh::Attribute remappedPositionAttribute;
uf::Mesh::Attribute remappedUvAttribute;
uf::Mesh::Attribute remappedIndexAttribute;
for ( auto i = 0; i < mesh.indirect.count; ++i ) {
remappedPositionAttribute = mesh.remapVertexAttribute( positionAttribute, i );
remappedUvAttribute = mesh.remapVertexAttribute( uvAttribute, i );
remappedIndexAttribute = mesh.remapIndexAttribute( indexAttribute, i );
vertexInput = mesh.remapVertexInput( i );
indexInput = mesh.remapIndexInput( i );
auto& entry = entries.emplace_back();
entry.index = index;
entry.command = i;
auto& decl = entry.decl;
decl.vertexCount = remappedPositionAttribute.length / remappedPositionAttribute.stride;
decl.vertexPositionData = remappedPositionAttribute.pointer;
decl.vertexPositionStride = remappedPositionAttribute.stride;
decl.vertexUvData = remappedUvAttribute.pointer;
decl.vertexUvStride = remappedUvAttribute.stride;
decl.vertexPositionData = positionAttribute.pointer + positionAttribute.stride * vertexInput.first;
decl.vertexPositionStride = positionAttribute.stride;
decl.indexCount = remappedIndexAttribute.length / remappedIndexAttribute.stride;
decl.indexData = remappedIndexAttribute.pointer;
decl.vertexUvData = uvAttribute.pointer + uvAttribute.stride * vertexInput.first;
decl.vertexUvStride = uvAttribute.stride;
decl.vertexCount = vertexInput.count;
decl.indexCount = indexInput.count;
decl.indexData = indexAttribute.pointer + indexAttribute.stride * indexInput.first;
decl.indexFormat = indexType;
}
} else {
@ -111,20 +78,21 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
entry.index = index;
auto& decl = entry.decl;
decl.vertexCount = mesh.vertex.count;
decl.vertexPositionData = positionAttribute.pointer;
decl.vertexPositionData = positionAttribute.pointer + positionAttribute.stride * vertexInput.first;
decl.vertexPositionStride = positionAttribute.stride;
decl.vertexUvData = uvAttribute.pointer;
decl.vertexUvData = uvAttribute.pointer + uvAttribute.stride * vertexInput.first;
decl.vertexUvStride = uvAttribute.stride;
decl.indexCount = mesh.index.count;
decl.indexData = indexAttribute.pointer;
decl.indexFormat = indexType;
decl.indexFormat = indexType;
decl.vertexCount = vertexInput.count;
decl.indexCount = indexInput.count;
decl.indexData = indexAttribute.pointer + indexAttribute.stride * indexInput.first;
decl.indexFormat = indexType;
}
} else UF_EXCEPTION("to-do: not require indices for meshes");
}
for ( auto& mesh : entries ) {
::xatlas::AddMeshError error = ::xatlas::AddMesh(atlas, mesh.decl, entries.size());
if (error != ::xatlas::AddMeshError::Success) {
@ -160,7 +128,7 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
if ( mesh.indirect.count ) {
auto& primitive = /*graph.storage*/uf::graph::storage.primitives[name];
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.buffers[mesh.isInterleaved(mesh.indirect.interleaved) ? mesh.indirect.interleaved : mesh.indirect.attributes.front().buffer].data();
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data();
size_t vertexOffset = 0;
for ( auto j = 0; j < atlas->meshCount; ++j ) {
@ -201,7 +169,7 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
pod::Vector2f& st = *(pod::Vector2f*) ( ((uint8_t*) dstAttribute.pointer) + dstAttribute.stride * j);
st = pod::Vector2f{ vertex.uv[0] / atlas->width, vertex.uv[1] / atlas->height };
} else {
memcpy( ((uint8_t*) dstAttribute.pointer) + dstAttribute.stride * j, ((uint8_t*) srcAttribute.pointer) + srcAttribute.stride * ref, srcAttribute.stride );
memcpy( dstAttribute.pointer + dstAttribute.stride * j, srcAttribute.pointer + srcAttribute.stride * ref, srcAttribute.stride );
}
}
}
@ -210,7 +178,7 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
uf::Mesh::Attribute indexAttribute = mesh.remapIndexAttribute( mesh.index.attributes.front(), entry.command );
uint8_t* pointer = (uint8_t*) indexAttribute.pointer;
for ( auto index = 0; index < xmesh.indexCount; ++index ) {
switch ( mesh.index.stride ) {
switch ( mesh.index.size ) {
case 1: (( uint8_t*) pointer)[index] = xmesh.indexArray[index]; break;
case 2: ((uint16_t*) pointer)[index] = xmesh.indexArray[index]; break;
case 4: ((uint32_t*) pointer)[index] = xmesh.indexArray[index]; break;
@ -227,11 +195,23 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
auto& vertex = xmesh.vertexArray[j];
auto ref = vertex.xref;
if ( mesh.isInterleaved( mesh.vertex.interleaved ) ) {
uint8_t* srcAttribute = source.buffers[mesh.vertex.interleaved].data() + j * mesh.vertex.stride;
uint8_t* dstAttribute = mesh.buffers[mesh.vertex.interleaved].data() + j * mesh.vertex.stride;
for ( auto k = 0; k < mesh.vertex.attributes.size(); ++k ) {
auto srcAttribute = source.vertex.attributes[k];
auto dstAttribute = mesh.vertex.attributes[k];
memcpy( dstAttribute, srcAttribute, mesh.vertex.stride );
if ( dstAttribute.descriptor.name == "st" ) {
pod::Vector2f& st = *(pod::Vector2f*) ( ((uint8_t*) dstAttribute.pointer) + dstAttribute.stride * j);
st = pod::Vector2f{ vertex.uv[0] / atlas->width, vertex.uv[1] / atlas->height };
} else {
memcpy( dstAttribute.pointer + dstAttribute.stride * j, srcAttribute.pointer + srcAttribute.stride * ref, srcAttribute.stride );
}
}
/*
if ( mesh.isInterleaved( mesh.vertex.interleaved ) ) {
uint8_t* srcAttribute = source.buffers[mesh.vertex.interleaved].data() + j * mesh.vertex.size;
uint8_t* dstAttribute = mesh.buffers[mesh.vertex.interleaved].data() + j * mesh.vertex.size;
memcpy( dstAttribute, srcAttribute, mesh.vertex.size );
pod::Vector2f& st = *(pod::Vector2f*) (dstAttribute + stAttribute.descriptor.offset);
st = { vertex.uv[0] / atlas->width, vertex.uv[1] / atlas->height };
@ -246,12 +226,13 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
memcpy( dstAttribute, srcAttribute, attribute.descriptor.size );
}
}
*/
}
// indices
if ( mesh.index.count ) {
uint8_t* pointer = (uint8_t*) mesh.buffers[mesh.isInterleaved(mesh.index.interleaved) ? mesh.index.interleaved : mesh.index.attributes.front().buffer].data();
for ( auto index = 0; index < xmesh.indexCount; ++index ) {
switch ( mesh.index.stride ) {
switch ( mesh.index.size ) {
case 1: (( uint8_t*) pointer)[index] = xmesh.indexArray[index]; break;
case 2: ((uint16_t*) pointer)[index] = xmesh.indexArray[index]; break;
case 4: ((uint32_t*) pointer)[index] = xmesh.indexArray[index]; break;
@ -263,6 +244,93 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
mesh.updateDescriptor();
}
#if 0
for ( auto i = 0; i < atlas->meshCount; i++ ) {
auto& xmesh = atlas->meshes[i];
auto& entry = entries[i];
auto& name = graph.meshes[entry.index];
auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name];
auto& source = sources[entry.index];
uf::Mesh::Input vertexInput = mesh.vertex;
uf::Mesh::Attribute positionAttribute;
uf::Mesh::Attribute uvAttribute;
uf::Mesh::Attribute stAttribute;
for ( auto& attribute : mesh.vertex.attributes ) {
if ( attribute.descriptor.name == "position" ) positionAttribute = attribute;
else if ( attribute.descriptor.name == "uv" ) uvAttribute = attribute;
else if ( attribute.descriptor.name == "st" ) stAttribute = attribute;
}
UF_ASSERT( positionAttribute.descriptor.name == "position" && uvAttribute.descriptor.name == "uv" && stAttribute.descriptor.name == "st" );
if ( mesh.index.count ) {
uf::Mesh::Input indexInput = mesh.index;
uf::Mesh::Attribute indexAttribute = mesh.index.attributes.front();
::xatlas::IndexFormat indexType = ::xatlas::IndexFormat::UInt32;
switch ( mesh.index.size ) {
case sizeof(uint16_t): indexType = ::xatlas::IndexFormat::UInt16; break;
case sizeof(uint32_t): indexType = ::xatlas::IndexFormat::UInt32; break;
default: UF_EXCEPTION("unsupported index type"); break;
}
if ( mesh.indirect.count ) {
for ( auto v = 0; v < xmesh.vertexCount; ++v ) {
auto& vertex = xmesh.vertexArray[v];
auto ref = vertex.xref;
vertexInput = mesh.remapVertexInput( entry.command );
for ( size_t _ = 0; _ < vertexInput.attributes.size(); ++_ ) {
auto& srcAttribute = source.vertex.attributes[_];
auto& dstAttribute = mesh.vertex.attributes[_];
memcpy( dstAttribute.pointer + dstAttribute.stride * (vertexInput.first + v), srcAttribute.pointer + srcAttribute.stride * (vertexInput.first + ref), srcAttribute.stride );
}
pod::Vector2f& st = *(pod::Vector2f*) (stAttribute.pointer + stAttribute.stride * (vertexInput.first + v));
st = { vertex.uv[0] / atlas->width, vertex.uv[1] / atlas->height };
}
// indices
indexInput = mesh.remapIndexInput( entry.command );
for ( auto index = 0; index < xmesh.indexCount; ++index ) {
switch ( mesh.index.size ) {
case 1: (( uint8_t*) indexAttribute.pointer + indexAttribute.stride * indexInput.first)[index] = xmesh.indexArray[index]; break;
case 2: ((uint16_t*) indexAttribute.pointer + indexAttribute.stride * indexInput.first)[index] = xmesh.indexArray[index]; break;
case 4: ((uint32_t*) indexAttribute.pointer + indexAttribute.stride * indexInput.first)[index] = xmesh.indexArray[index]; break;
}
}
} else {
for ( auto v = 0; v < xmesh.vertexCount; ++v ) {
auto& vertex = xmesh.vertexArray[v];
auto ref = vertex.xref;
for ( size_t _ = 0; _ < vertexInput.attributes.size(); ++_ ) {
auto& srcAttribute = source.vertex.attributes[_];
auto& dstAttribute = mesh.vertex.attributes[_];
memcpy( dstAttribute.pointer + dstAttribute.stride * (vertexInput.first + v), srcAttribute.pointer + srcAttribute.stride * (vertexInput.first + ref), srcAttribute.stride );
}
pod::Vector2f& st = *(pod::Vector2f*) (stAttribute.pointer + stAttribute.stride * (vertexInput.first + v));
st = { vertex.uv[0] / atlas->width, vertex.uv[1] / atlas->height };
}
for ( auto index = 0; index < xmesh.indexCount; ++index ) {
switch ( mesh.index.size ) {
case 1: (( uint8_t*) indexAttribute.pointer + indexAttribute.stride * indexInput.first)[index] = xmesh.indexArray[index]; break;
case 2: ((uint16_t*) indexAttribute.pointer + indexAttribute.stride * indexInput.first)[index] = xmesh.indexArray[index]; break;
case 4: ((uint32_t*) indexAttribute.pointer + indexAttribute.stride * indexInput.first)[index] = xmesh.indexArray[index]; break;
}
}
}
} else UF_EXCEPTION("to-do: not require indices for meshes");
}
#endif
pod::Vector2ui size = pod::Vector2ui{ atlas->width, atlas->height };
::xatlas::Destroy(atlas);

View File

@ -48,8 +48,7 @@ UF_VERTEX_DESCRIPTOR(pod::Vertex_3F,
)
bool uf::Mesh::defaultInterleaved = false;
void uf::Mesh::initialize() {
}
void uf::Mesh::initialize() {}
void uf::Mesh::destroy() {
_destroy(vertex);
_destroy(index);
@ -58,39 +57,15 @@ void uf::Mesh::destroy() {
buffers.clear();
}
uf::Mesh uf::Mesh::convert( bool interleave ) const {
// implicitly convert to opposite interleaving
uf::Mesh uf::Mesh::convert() const {
return copy( !isInterleaved() );
}
uf::Mesh uf::Mesh::copy( bool interleaved ) const {
uf::Mesh res;
// overkill but I don't want to rewrite a bind<>();
res.vertex.attributes = vertex.attributes;
res.vertex.count = 0;
res.vertex.stride = vertex.stride;
res.vertex.offset = vertex.offset;
res.index.attributes = index.attributes;
res.index.count = 0;
res.index.interleaved = -1;
res.index.stride = index.stride;
res.index.offset = index.offset;
res.instance.attributes = instance.attributes;
res.instance.count = 0;
res.index.interleaved = -1;
res.instance.stride = instance.stride;
res.instance.offset = instance.offset;
res.indirect.attributes = indirect.attributes;
res.indirect.count = 0;
res.indirect.interleaved = -1;
res.indirect.stride = indirect.stride;
res.indirect.offset = indirect.offset;
res._bind( interleave );
res.insertVertices(*this);
res.insertIndices(*this);
res.insertInstances(*this);
res.insertIndirects(*this);
res.bind( *this, interleaved );
res.insert(*this);
res.updateDescriptor();
return res;
@ -101,17 +76,14 @@ void uf::Mesh::updateDescriptor() {
_updateDescriptor(instance);
_updateDescriptor(indirect);
}
void uf::Mesh::bind( const uf::Mesh& mesh ) {
void uf::Mesh::bind( const uf::Mesh& mesh ) { return bind( mesh, isInterleaved() ); }
void uf::Mesh::bind( const uf::Mesh& mesh, bool interleaved ) {
vertex.attributes = mesh.vertex.attributes;
vertex.interleaved = mesh.vertex.interleaved;
index.attributes = mesh.index.attributes;
index.interleaved = mesh.index.interleaved;
instance.attributes = mesh.instance.attributes;
instance.interleaved = mesh.instance.interleaved;
indirect.attributes = mesh.indirect.attributes;
indirect.interleaved = mesh.indirect.interleaved;
_bind();
_bind( interleaved );
}
void uf::Mesh::insert( const uf::Mesh& mesh ) {
if ( vertex.attributes.empty() && index.attributes.empty() && instance.attributes.empty() && indirect.attributes.empty() ) bind( mesh );
@ -120,6 +92,8 @@ void uf::Mesh::insert( const uf::Mesh& mesh ) {
insertIndices(mesh);
insertInstances(mesh);
insertIndirects(mesh);
updateDescriptor();
}
void uf::Mesh::generateIndices() {
// deduce type
@ -141,12 +115,92 @@ void uf::Mesh::generateIndices() {
case 4: { uf::stl::vector<uint32_t> indices( vertex.count ); std::iota( indices.begin(), indices.end(), 0 ); insertIndices( indices ); } break;
}
}
uf::Mesh uf::Mesh::expand() { return expand( isInterleaved() ); }
uf::Mesh uf::Mesh::expand( bool interleaved ) {
uf::Mesh res = copy( interleaved );
res.resizeVertices( index.count );
res.vertex.count = index.count;
auto& srcIndex = index.attributes.front();
auto& dstIndex = res.index.attributes.front();
#define GET_INDEX(T) {\
index = *(const T*) (srcIndex.pointer + idx * srcIndex.stride);\
*((T*) (dstIndex.pointer + idx * dstIndex.stride)) = idx;\
}
for ( size_t idx = 0; idx < index.count; ++idx ) {
size_t index = 0;
switch ( srcIndex.descriptor.size ) {
case 1: GET_INDEX(uint8_t); break;
case 2: GET_INDEX(uint16_t); break;
case 4: GET_INDEX(uint32_t); break;
}
for ( size_t _ = 0; _ < vertex.attributes.size(); ++_ ) {
auto& srcInput = vertex.attributes[_];
auto& dstInput = res.vertex.attributes[_];
memcpy( dstInput.pointer, srcInput.pointer + index * srcInput.stride, srcInput.descriptor.size );
dstInput.pointer += dstInput.stride;
}
}
#undef GET_INDEX
if ( res.indirect.count ) {
pod::DrawCommand* drawCommands = (pod::DrawCommand*) res.getBuffer(res.indirect).data();
for ( size_t i = 0, vertexID = 0; i < res.indirect.count; ++i ) {
auto& drawCommand = drawCommands[i];
drawCommand.vertexID = vertexID;
drawCommand.vertices = drawCommand.indices;
vertexID += drawCommand.indices;
}
}
res.updateDescriptor();
return res;
}
uf::Mesh::Input uf::Mesh::remapInput( const uf::Mesh::Input& input, size_t i ) const {
uf::Mesh::Input res = input;
UF_ASSERT( &input == &vertex || &input == &index );
UF_ASSERT( i < indirect.count );
const auto& drawCommand = ((const pod::DrawCommand*) getBuffer(indirect).data())[i];
res.first = &input == &vertex ? drawCommand.vertexID : drawCommand.indexID;
res.count = &input == &vertex ? drawCommand.vertices : drawCommand.indices;
return res;
}
uf::Mesh::Input uf::Mesh::remapVertexInput( size_t i ) const {
uf::Mesh::Input res = vertex;
UF_ASSERT( i < indirect.count );
const auto& drawCommand = ((const pod::DrawCommand*) getBuffer(indirect).data())[i];
res.first = drawCommand.vertexID;
res.count = drawCommand.vertices;
return res;
}
uf::Mesh::Input uf::Mesh::remapIndexInput( size_t i ) const {
uf::Mesh::Input res = index;
UF_ASSERT( i < indirect.count );
const auto& drawCommand = ((const pod::DrawCommand*) getBuffer(indirect).data())[i];
res.first = drawCommand.indexID;
res.count = drawCommand.indices;
return res;
}
void uf::Mesh::generateIndirect() {
if ( index.count == 0 ) generateIndices();
uf::stl::vector<pod::DrawCommand> commands;
for ( auto& attribute : index.attributes ) {
auto& buffer = buffers[isInterleaved(index.interleaved) ? index.interleaved : attribute.buffer];
auto& buffer = getBuffer(index, attribute);
commands.emplace_back(pod::DrawCommand{
.indices = buffer.size() / attribute.descriptor.size,
.instances = instance.count == 0 && instance.attributes.empty() ? 1 : instance.count,
@ -164,97 +218,93 @@ void uf::Mesh::generateIndirect() {
_bind();
insertIndirects( commands );
}
bool uf::Mesh::isInterleaved() const { return isInterleaved( vertex.interleaved ); }
bool uf::Mesh::isInterleaved( size_t i ) const { return 0 <= i && i < buffers.size(); }
void uf::Mesh::print() const {
std::stringstream str;
str << "Buffers: " << buffers.size() << "\n";
str << "Vertices: " << vertex.count << " | " << (isInterleaved(vertex.interleaved) ? "interleaved" : "deinterleaved") << "\n";
for ( auto i = 0; i < vertex.count; ++i ) {
if ( isInterleaved(vertex.interleaved) ) {
auto& buffer = buffers[vertex.interleaved];
uint8_t* e = (uint8_t*) &buffer[i * vertex.stride];
for ( auto& attribute : vertex.attributes ) {
str << "[" << i << "][" << attribute.descriptor.name << "]: ( ";
switch ( attribute.descriptor.type ) {
case uf::renderer::enums::Type::FLOAT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((float*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::UINT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((uint32_t*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::INT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((int32_t*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::USHORT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((uint16_t*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::SHORT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((int16_t*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::UBYTE: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((uint8_t*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::BYTE: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((int8_t*) (e + attribute.descriptor.offset))[j] << " "; break;
}
str << ")\n";
}
} else for ( auto& attribute : vertex.attributes ) {
auto& buffer = buffers[attribute.buffer];
str << "[" << i << "][" << attribute.descriptor.name << "]: ( ";
switch ( attribute.descriptor.type ) {
case uf::renderer::enums::Type::FLOAT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((float*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::UINT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((uint32_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::INT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((int32_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::USHORT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((uint16_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::SHORT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((int16_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::UBYTE: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((uint8_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::BYTE: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((int8_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
}
str << ")\n";
}
}
uf::Mesh::buffer_t& uf::Mesh::getBuffer( const uf::Mesh::Input& input, size_t i ) {
return getBuffer( input, input.attributes[i] );
}
uf::Mesh::buffer_t& uf::Mesh::getBuffer( const uf::Mesh::Input& input, const uf::Mesh::Attribute& attribute ) {
return buffers[isInterleaved(input.interleaved) ? input.interleaved : attribute.buffer];
}
const uf::Mesh::buffer_t& uf::Mesh::getBuffer( const uf::Mesh::Input& input, size_t i ) const {
return getBuffer( input, input.attributes[i] );
}
const uf::Mesh::buffer_t& uf::Mesh::getBuffer( const uf::Mesh::Input& input, const uf::Mesh::Attribute& attribute ) const {
return buffers[isInterleaved(input.interleaved) ? input.interleaved : attribute.buffer];
}
void uf::Mesh::print( bool full ) const {
std::cout << "Buffers: " << buffers.size() << "\n" << printVertices(full) << printIndices(full) << printInstances(full) << printIndirects() << std::endl;
}
str << "Indices: " << index.count << " | " << (isInterleaved(index.interleaved) ? "interleaved" : "deinterleaved") << "\n";
for ( auto i = 0; i < index.count; ++i ) {
if ( isInterleaved(index.interleaved) ) {
auto& buffer = buffers[index.interleaved];
switch ( index.stride ) {
case 1: str << "[" << i << "]: " << *(( uint8_t*) &buffer[i * index.stride]) << "\n"; break;
case 2: str << "[" << i << "]: " << *((uint16_t*) &buffer[i * index.stride]) << "\n"; break;
case 4: str << "[" << i << "]: " << *((uint32_t*) &buffer[i * index.stride]) << "\n"; break;
}
} else for ( auto& attribute : index.attributes ) {
auto& buffer = buffers[attribute.buffer];
switch ( attribute.descriptor.size ) {
case 1: str << "[" << i << "]: " << *(( uint8_t*) &buffer[i * attribute.descriptor.size]) << "\n"; break;
case 2: str << "[" << i << "]: " << *((uint16_t*) &buffer[i * attribute.descriptor.size]) << "\n"; break;
case 4: str << "[" << i << "]: " << *((uint32_t*) &buffer[i * attribute.descriptor.size]) << "\n"; break;
}
}
}
str << "Instances: " << instance.count << " | " << (isInterleaved(instance.interleaved) ? "interleaved" : "deinterleaved") << "\n";
for ( auto i = 0; i < instance.count; ++i ) {
if ( isInterleaved(instance.interleaved) ) {
auto& buffer = buffers[instance.interleaved];
uint8_t* e = (uint8_t*) &buffer[i * instance.stride];
for ( auto& attribute : instance.attributes ) {
str << "[" << i << "][" << attribute.descriptor.name << "]: ( ";
switch ( attribute.descriptor.type ) {
case uf::renderer::enums::Type::FLOAT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((float*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::UINT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((uint32_t*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::INT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((int32_t*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::USHORT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((uint16_t*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::SHORT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((int16_t*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::UBYTE: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((uint8_t*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::BYTE: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((int8_t*) (e + attribute.descriptor.offset))[j] << " "; break;
}
str << ")\n";
}
} else for ( auto& attribute : instance.attributes ) {
auto& buffer = buffers[attribute.buffer];
#define PRINT_HEADER(input) "Count: " << input.count << " | First: " << input.first << " | Size: " << input.size << " | Offset: " << input.offset << " | " << (isInterleaved(input.interleaved) ? "interleaved" : "deinterleaved") << "\n"
std::string uf::Mesh::printVertices( bool full ) const {
std::stringstream str;
str << "Vertices: " << PRINT_HEADER( vertex );
if ( full ) for ( auto i = 0; i < vertex.count; ++i ) {
for ( auto& attribute : vertex.attributes ) {
str << "[" << i << "][" << attribute.descriptor.name << "]: ( ";
uint8_t* e = (uint8_t*) attribute.pointer + i * attribute.stride;
switch ( attribute.descriptor.type ) {
case uf::renderer::enums::Type::FLOAT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((float*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::UINT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((uint32_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::INT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((int32_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::USHORT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((uint16_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::SHORT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((int16_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::UBYTE: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((uint8_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::BYTE: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((int8_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::UINT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((uint32_t*) e)[j] << " "; break;
case uf::renderer::enums::Type::INT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((int32_t*) e)[j] << " "; break;
case uf::renderer::enums::Type::USHORT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((uint16_t*) e)[j] << " "; break;
case uf::renderer::enums::Type::SHORT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((int16_t*) e)[j] << " "; break;
case uf::renderer::enums::Type::UBYTE: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((uint8_t*) e)[j] << " "; break;
case uf::renderer::enums::Type::BYTE: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((int8_t*) e)[j] << " "; break;
case uf::renderer::enums::Type::FLOAT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((float*) e)[j] << " "; break;
default: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((float*) e)[j] << " "; break;
}
str << ")\n";
}
}
str << "Indirect: " << indirect.count << " | " << (isInterleaved(indirect.interleaved) ? "interleaved" : "deinterleaved");
std::cout << str.str() << std::endl;
return str.str();
}
std::string uf::Mesh::printIndices( bool full ) const {
std::stringstream str;
str << "Indices: " << PRINT_HEADER( index );
if ( full ) for ( auto i = 0; i < index.count; ++i ) {
auto& buffer = getBuffer( index );
switch ( index.size ) {
case 1: str << "[" << i << "]: " << *(( uint8_t*) &buffer[i * index.size]) << "\n"; break;
case 2: str << "[" << i << "]: " << *((uint16_t*) &buffer[i * index.size]) << "\n"; break;
case 4: str << "[" << i << "]: " << *((uint32_t*) &buffer[i * index.size]) << "\n"; break;
}
}
return str.str();
}
std::string uf::Mesh::printInstances( bool full ) const {
std::stringstream str;
str << "Instances: " << PRINT_HEADER( instance );
if ( full ) for ( auto i = 0; i < instance.count; ++i ) {
for ( auto& attribute : vertex.attributes ) {
str << "[" << i << "][" << attribute.descriptor.name << "]: ( ";
uint8_t* e = (uint8_t*) attribute.pointer + i * attribute.stride;
switch ( attribute.descriptor.type ) {
case uf::renderer::enums::Type::UINT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((uint32_t*) e)[j] << " "; break;
case uf::renderer::enums::Type::INT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((int32_t*) e)[j] << " "; break;
case uf::renderer::enums::Type::USHORT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((uint16_t*) e)[j] << " "; break;
case uf::renderer::enums::Type::SHORT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((int16_t*) e)[j] << " "; break;
case uf::renderer::enums::Type::UBYTE: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((uint8_t*) e)[j] << " "; break;
case uf::renderer::enums::Type::BYTE: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << (int) ((int8_t*) e)[j] << " "; break;
case uf::renderer::enums::Type::FLOAT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((float*) e)[j] << " "; break;
default: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((float*) e)[j] << " "; break;
}
str << ")\n";
}
}
return str.str();
}
std::string uf::Mesh::printIndirects( bool full ) const {
std::stringstream str;
str << "Indirect: " << PRINT_HEADER( indirect ) << "{ indices, instances, indexID, vertexID, instanceID, padding1, padding2, vertices }\n";
if ( full ) for ( auto i = 0; i < indirect.count; ++i ) {
auto& buffer = getBuffer( indirect );
auto& drawCommand = *(const pod::DrawCommand*) (&buffer[i * indirect.size]);
str << "[" << i << "]: {" << drawCommand.indices << ", " << drawCommand.instances << ", " << drawCommand.indexID << ", " << drawCommand.vertexID << ", " << drawCommand.instanceID << ", " << drawCommand.padding1 << ", " << drawCommand.padding2 << ", " << drawCommand.vertices << "}\n";
}
return str.str();
}
//
void uf::Mesh::_destroy( uf::Mesh::Input& input ) {
@ -266,52 +316,52 @@ void uf::Mesh::_destroy( uf::Mesh::Input& input ) {
input.attributes.clear();
}
void uf::Mesh::_bind( bool interleave ) {
size_t buffer = 0;
int32_t buffer = 0;
#define PARSE_INPUT(INPUT, INTERLEAVED){\
if ( INTERLEAVED ) INPUT.interleaved = buffer;\
for ( auto i = 0; i < INPUT.attributes.size(); ++i ) INPUT.attributes[i].buffer = !INTERLEAVED ? buffer++ : buffer;\
INPUT.interleaved = (INTERLEAVED ? buffer : -1);\
for ( auto i = 0; i < INPUT.attributes.size(); ++i ) {\
INPUT.attributes[i].buffer = !INTERLEAVED ? buffer++ : buffer;\
INPUT.attributes[i].pointer = NULL;\
}\
if ( !INPUT.attributes.empty() && INTERLEAVED ) ++buffer;\
}
PARSE_INPUT(vertex, interleave)
PARSE_INPUT(index, false)
// PARSE_INPUT(instance, interleave)
PARSE_INPUT(instance, false)
PARSE_INPUT(instance, interleave)
PARSE_INPUT(indirect, false)
buffers.resize( buffer );
updateDescriptor();
// for ( auto& attribute : vertex.attributes ) UF_MSG_DEBUG( attribute.descriptor.name << "[" << attribute.descriptor.offset << "]: " << attribute.descriptor.size );
#undef PARSE_INPUT
}
void uf::Mesh::_updateDescriptor( uf::Mesh::Input& input ) {
input.stride = 0;
input.size = 0;
for ( auto& attribute : input.attributes ) {
const bool interleaved = isInterleaved(input.interleaved);
auto& buffer = buffers[interleaved ? input.interleaved : attribute.buffer];
attribute.length = buffer.size();
attribute.pointer = (void*) (buffer.data() + attribute.offset);
if ( !interleaved ) attribute.stride = attribute.descriptor.size;
else attribute.pointer += attribute.descriptor.offset;
input.stride += attribute.descriptor.size;
attribute.pointer = buffer.data() + attribute.offset;
input.size += attribute.descriptor.size;
if ( interleaved ) attribute.pointer += attribute.descriptor.offset;
}
for ( auto& attribute : input.attributes ) {
const bool interleaved = isInterleaved(input.interleaved);
if ( interleaved ) attribute.stride = input.stride;
attribute.stride = isInterleaved(input.interleaved) ? input.size : attribute.descriptor.size;
}
}
uf::Mesh::Attribute uf::Mesh::_remapAttribute( const uf::Mesh::Input& input, const uf::Mesh::Attribute& attribute, size_t i ) const {
uf::Mesh::Attribute res = attribute;
if ( i < indirect.count ) {
auto& drawCommand = ((const pod::DrawCommand*) buffers[isInterleaved(indirect.interleaved) ? indirect.interleaved : indirect.attributes.front().buffer].data())[i];
if ( &input == &vertex ) {
res.pointer += drawCommand.vertexID * res.stride;
res.length = drawCommand.vertices * res.stride;
} else if ( &input == &index ) {
res.pointer += drawCommand.indexID * res.stride;
res.length = drawCommand.indices * res.stride;
}
UF_ASSERT( i < indirect.count );
UF_ASSERT( &input == &vertex || &input == &index );
auto& drawCommand = ((const pod::DrawCommand*) getBuffer(indirect).data())[i];
if ( &input == &vertex ) {
res.pointer += drawCommand.vertexID * res.stride;
res.length = drawCommand.vertices * res.stride;
} else if ( &input == &index ) {
res.pointer += drawCommand.indexID * res.stride;
res.length = drawCommand.indices * res.stride;
}
return res;
}
@ -361,7 +411,7 @@ void uf::Mesh::_insertVs( uf::Mesh::Input& dstInput, const uf::Mesh& mesh, const
}
} else if ( !isInterleaved(dstInput.interleaved) && isInterleaved(srcInput.interleaved) ) {
// UF_EXCEPTION("to be implemented: interleaved -> deinterleaved");
uf::Mesh::Input _srcInput = _srcInput;
uf::Mesh::Input _srcInput = srcInput;
const uint8_t* src = (const uint8_t*) mesh.buffers.at(srcInput.interleaved).data();
size_t _ = 0;
while ( _++ < _srcInput.count ) {
@ -385,23 +435,23 @@ void uf::Mesh::_insertIs( uf::Mesh::Input& dstInput, const uf::Mesh& mesh, const
// both meshes are interleaved, just copy directly
if ( isInterleaved(dstInput.interleaved) && isInterleaved(srcInput.interleaved) ) {
auto& src = mesh.buffers[srcInput.interleaved];
auto& dst = buffers[dstInput.interleaved];
auto& src = mesh.getBuffer( srcInput );
auto& dst = getBuffer( dstInput );
dst.insert( dst.end(), src.begin(), src.end() );
// both meshes are de-interleaved, just copy directly
} else if ( !isInterleaved(dstInput.interleaved) && !isInterleaved(srcInput.interleaved) ) {
for ( auto i = 0; i < dstInput.attributes.size(); ++i ) {
auto& srcAttribute = srcInput.attributes[i];
auto& dstAttribute = dstInput.attributes[i];
auto& src = mesh.buffers[srcAttribute.buffer];
auto& dst = buffers[dstAttribute.buffer];
auto& src = mesh.getBuffer( srcInput );
auto& dst = getBuffer( dstInput );
dst.insert( dst.end(), src.begin(), src.end() );
}
// not easy to convert, will implement later
} else if ( isInterleaved(dstInput.interleaved) && !isInterleaved(srcInput.interleaved) ) {
// UF_EXCEPTION("to be implemented: deinterleaved -> interleaved");
uf::Mesh::Input _srcInput = srcInput;
auto& dst = buffers.at(dstInput.interleaved);
auto& dst = getBuffer( dstInput );
size_t _ = 0;
while ( _++ < _srcInput.count ) {
for ( auto& srcAttribute : _srcInput.attributes ) {
@ -411,13 +461,13 @@ void uf::Mesh::_insertIs( uf::Mesh::Input& dstInput, const uf::Mesh& mesh, const
}
} else if ( !isInterleaved(dstInput.interleaved) && isInterleaved(srcInput.interleaved) ) {
// UF_EXCEPTION("to be implemented: interleaved -> deinterleaved");
uf::Mesh::Input _srcInput = _srcInput;
const uint8_t* src = (const uint8_t*) mesh.buffers.at(srcInput.interleaved).data();
uf::Mesh::Input _srcInput = srcInput;
const uint8_t* src = (const uint8_t*) mesh.getBuffer( srcInput ).data();
size_t _ = 0;
while ( _++ < _srcInput.count ) {
for ( size_t i = 0; i < dstInput.attributes.size(); ++i ) {
auto& srcAttribute = _srcInput.attributes.at(i);
auto& dstAttribute = dstInput.attributes.at(i);
auto& srcAttribute = _srcInput.attributes[i];
auto& dstAttribute = dstInput.attributes[i];
auto& dst = buffers.at(dstAttribute.buffer);
dst.insert( dst.end(), src, src + srcAttribute.descriptor.size );
@ -436,7 +486,7 @@ bool uf::Mesh::_hasV( const uf::Mesh::Input& input, const uf::stl::vector<ext::R
return true;
}
bool uf::Mesh::_hasV( const uf::Mesh::Input& input, const uf::Mesh::Input& srcInput ) const {
if ( input.attributes.size() != srcInput.attributes.size() || input.stride != srcInput.stride ) return false;
if ( input.attributes.size() != srcInput.attributes.size() || input.size != srcInput.size ) return false;
for ( auto i = 0; i < input.attributes.size(); ++i ) if ( input.attributes[i].descriptor != srcInput.attributes[i].descriptor ) return false;
return true;
}
@ -445,12 +495,12 @@ void uf::Mesh::_bindV( uf::Mesh::Input& input, const uf::stl::vector<uf::rendere
for ( auto i = 0; i < descriptors.size(); ++i ) {
auto& attribute = input.attributes[i];
attribute.descriptor = descriptors[i];
input.stride += attribute.descriptor.size;
input.size += attribute.descriptor.size;
}
}
void uf::Mesh::_reserveVs( uf::Mesh::Input& input, size_t count ) {
if ( isInterleaved(input.interleaved) ) {
buffers[input.interleaved].reserve( count * input.stride );
buffers[input.interleaved].reserve( count * input.size );
for ( auto& attribute : input.attributes ) {
attribute.length = buffers[input.interleaved].size();
attribute.pointer = (void*) (buffers[input.interleaved].data());
@ -463,7 +513,7 @@ void uf::Mesh::_reserveVs( uf::Mesh::Input& input, size_t count ) {
}
void uf::Mesh::_resizeVs( uf::Mesh::Input& input, size_t count ) {
if ( isInterleaved(input.interleaved) ) {
buffers[input.interleaved].resize( count * input.stride );
buffers[input.interleaved].resize( count * input.size );
for ( auto& attribute : input.attributes ) {
attribute.length = buffers[input.interleaved].size();
attribute.pointer = (void*) (buffers[input.interleaved].data());
@ -478,7 +528,7 @@ void uf::Mesh::_insertV( uf::Mesh::Input& input, const void* data ) {
_reserveVs( input, ++input.count );
const uint8_t* pointer = (const uint8_t*) data;
if ( isInterleaved(input.interleaved) ) {
buffers[input.interleaved].insert( buffers[input.interleaved].end(), pointer, pointer + input.stride );
buffers[input.interleaved].insert( buffers[input.interleaved].end(), pointer, pointer + input.size );
} else for ( auto& attribute : input.attributes ) {
buffers[attribute.buffer].insert( buffers[attribute.buffer].end(), pointer + attribute.descriptor.offset, pointer + attribute.descriptor.offset + attribute.descriptor.size );
}
@ -486,13 +536,13 @@ void uf::Mesh::_insertV( uf::Mesh::Input& input, const void* data ) {
void uf::Mesh::_insertVs( uf::Mesh::Input& input, const void* data, size_t size ) {
#if 0
const uint8_t* pointer = (const uint8_t*) data;
for ( auto i = 0; i < size; ++i ) insertV( pointer + i * input.stride );
for ( auto i = 0; i < size; ++i ) insertV( pointer + i * input.size );
#else
_reserveVs( input, input.count += size );
const uint8_t* pointer = (const uint8_t*) data;
if ( isInterleaved(input.interleaved) ) {
buffers[input.interleaved].insert( buffers[input.interleaved].end(), pointer, pointer + size * input.stride );
} else for ( const uint8_t* p = pointer; p < pointer + size * input.stride; p += input.stride ) {
buffers[input.interleaved].insert( buffers[input.interleaved].end(), pointer, pointer + size * input.size );
} else for ( const uint8_t* p = pointer; p < pointer + size * input.size; p += input.size ) {
for ( auto& attribute : input.attributes )
buffers[attribute.buffer].insert( buffers[attribute.buffer].end(), p + attribute.descriptor.offset, p + attribute.descriptor.offset + attribute.descriptor.size );
}
@ -501,7 +551,7 @@ void uf::Mesh::_insertVs( uf::Mesh::Input& input, const void* data, size_t size
// Indices
void uf::Mesh::_bindI( uf::Mesh::Input& input, size_t size, ext::RENDERER::enums::Type::type_t type, size_t count ) {
input.attributes.resize( count );
input.stride = size;
input.size = size;
for ( auto i = 0; i < count; ++i ) {
auto& attribute = input.attributes[i];
attribute.descriptor.offset = 0;