finally nailed a memory leak because past me made assumptions RP3D cleared the triangle parts on body destruction per the documentation (although I still crash after a while on the DC build from fragmentation at 9MiB consumed......), crammed filetype preference to resolveURI since everything should be using that anyways, some other cruft I forget trying to nail down this memory leak

This commit is contained in:
ecker 2025-08-24 20:47:32 -05:00
parent 532c4054b6
commit 65cf3887b7
10 changed files with 119 additions and 44 deletions

View File

@ -341,7 +341,7 @@
} }
}, },
"memory pool": { "memory pool": {
"enabled": true, // needs to be kept on "enabled": true, // needs to be kept on for GC
"subPools": true, "subPools": true,
"alignment": 64, "alignment": 64,
"override": false, "override": false,
@ -355,11 +355,11 @@
"render modes": { "gui": true, "deferred": true }, "render modes": { "gui": true, "deferred": true },
"limiters": { "limiters": {
"deltaTime": 5, "deltaTime": 5,
"framerate": 0 // "auto" "framerate": 0 // "auto" // for some reason drops to 60
}, },
"threads": { "threads": {
"workers" : "auto", "workers" : "auto",
"frame limiter": 0 // "auto" "frame limiter": "auto"
}, },
"debug": { "debug": {
"framerate": { "framerate": {

View File

@ -83,7 +83,7 @@
} }
}, },
"audio": { "audio": {
"mute": false, "mute": true,
"async update": false, "async update": false,
"streams by default": true, "streams by default": true,
"buffers": { "buffers": {

View File

@ -1 +1 @@
gcc clang

View File

@ -13,6 +13,7 @@
#include <uf/utils/userdata/userdata.h> #include <uf/utils/userdata/userdata.h>
#include <uf/utils/mesh/mesh.h> #include <uf/utils/mesh/mesh.h>
#define UF_COMMAND_BUFFER_USERDATA 1
#define UF_COMMAND_BUFFER_POINTERED_USERDATA 1 #define UF_COMMAND_BUFFER_POINTERED_USERDATA 1
namespace ext { namespace ext {
@ -79,11 +80,15 @@ namespace ext {
} color; } color;
}; };
#if UF_COMMAND_BUFFER_USERDATA
#if UF_COMMAND_BUFFER_POINTERED_USERDATA #if UF_COMMAND_BUFFER_POINTERED_USERDATA
typedef uf::PointeredUserdata userdata_t; typedef uf::PointeredUserdata userdata_t;
#else #else
typedef uf::Userdata userdata_t; typedef uf::Userdata userdata_t;
#endif #endif
#else
typedef Info* userdata_t;
#endif
typedef std::function<void()> function_t; typedef std::function<void()> function_t;
static size_t preallocate; static size_t preallocate;

View File

@ -100,6 +100,7 @@ uf::asset::Payload uf::asset::resolveToPayload( const uf::stl::string& uri, cons
{ "jpg", uf::asset::Type::IMAGE }, { "jpg", uf::asset::Type::IMAGE },
{ "jpeg", uf::asset::Type::IMAGE }, { "jpeg", uf::asset::Type::IMAGE },
{ "png", uf::asset::Type::IMAGE }, { "png", uf::asset::Type::IMAGE },
{ "dtex", uf::asset::Type::IMAGE },
{ "ogg", uf::asset::Type::AUDIO }, { "ogg", uf::asset::Type::AUDIO },
{ "wav", uf::asset::Type::AUDIO }, { "wav", uf::asset::Type::AUDIO },

View File

@ -18,7 +18,7 @@
#define UF_GRAPH_EXTENDED 1 #define UF_GRAPH_EXTENDED 1
#if 0 && UF_ENV_DREAMCAST #if UF_ENV_DREAMCAST
#define UF_DEBUG_TIMER_MULTITRACE_START(...) UF_TIMER_MULTITRACE_START(__VA_ARGS__) #define UF_DEBUG_TIMER_MULTITRACE_START(...) UF_TIMER_MULTITRACE_START(__VA_ARGS__)
#define UF_DEBUG_TIMER_MULTITRACE(...) UF_TIMER_MULTITRACE(__VA_ARGS__) #define UF_DEBUG_TIMER_MULTITRACE(...) UF_TIMER_MULTITRACE(__VA_ARGS__)
#define UF_DEBUG_TIMER_MULTITRACE_END(...) UF_TIMER_MULTITRACE_END(__VA_ARGS__) #define UF_DEBUG_TIMER_MULTITRACE_END(...) UF_TIMER_MULTITRACE_END(__VA_ARGS__)
@ -248,7 +248,7 @@ namespace {
#if !UF_GRAPH_EXTENDED #if !UF_GRAPH_EXTENDED
mesh.buffers.emplace_back(uf::io::readAsBuffer( directory + "/" + filename )); mesh.buffers.emplace_back(uf::io::readAsBuffer( directory + "/" + filename ));
#else #else
if ( graph.metadata["stream"]["enabled"].as<bool>() ) { if ( graph.settings.stream.enabled ) {
mesh.buffers.emplace_back(); mesh.buffers.emplace_back();
mesh.buffer_paths.emplace_back(directory + "/" + filename); mesh.buffer_paths.emplace_back(directory + "/" + filename);
} else { } else {
@ -427,7 +427,7 @@ void uf::graph::load( pod::Graph& graph, const uf::stl::string& filename, const
ext::json::forEach( serializer["primitives"], [&]( ext::json::Value& value ){ ext::json::forEach( serializer["primitives"], [&]( ext::json::Value& value ){
auto name = key + value["name"].as<uf::stl::string>(); auto name = key + value["name"].as<uf::stl::string>();
// UF_MSG_DEBUG("{}", name); // UF_MSG_DEBUG("{}", name);
/*graph.storage*/storage.primitives[name] = decodePrimitives( value, graph ); storage.primitives[name] = decodePrimitives( value, graph );
graph.primitives.emplace_back(name); graph.primitives.emplace_back(name);
}); });
UF_DEBUG_TIMER_MULTITRACE("Read primitives."); UF_DEBUG_TIMER_MULTITRACE("Read primitives.");
@ -442,7 +442,7 @@ void uf::graph::load( pod::Graph& graph, const uf::stl::string& filename, const
ext::json::forEach( serializer["meshes"], [&]( ext::json::Value& value ){ ext::json::forEach( serializer["meshes"], [&]( ext::json::Value& value ){
auto name = key + value["name"].as<uf::stl::string>(); auto name = key + value["name"].as<uf::stl::string>();
// UF_MSG_DEBUG("{}", name); // UF_MSG_DEBUG("{}", name);
/*graph.storage*/storage.meshes[name] = decodeMesh( value, graph ); storage.meshes[name] = decodeMesh( value, graph );
graph.meshes.emplace_back(name); graph.meshes.emplace_back(name);
}); });
UF_DEBUG_TIMER_MULTITRACE("Read meshes"); UF_DEBUG_TIMER_MULTITRACE("Read meshes");
@ -457,7 +457,7 @@ void uf::graph::load( pod::Graph& graph, const uf::stl::string& filename, const
ext::json::forEach( serializer["images"], [&]( ext::json::Value& value ){ ext::json::forEach( serializer["images"], [&]( ext::json::Value& value ){
auto name = key + value["name"].as<uf::stl::string>(); auto name = key + value["name"].as<uf::stl::string>();
// UF_MSG_DEBUG("{}", name); // UF_MSG_DEBUG("{}", name);
/*graph.storage*/storage.images[name] = decodeImage( value, graph ); storage.images[name] = decodeImage( value, graph );
graph.images.emplace_back(name); graph.images.emplace_back(name);
}); });
UF_DEBUG_TIMER_MULTITRACE("Read images"); UF_DEBUG_TIMER_MULTITRACE("Read images");
@ -486,7 +486,7 @@ void uf::graph::load( pod::Graph& graph, const uf::stl::string& filename, const
ext::json::forEach( serializer["textures"], [&]( ext::json::Value& value ){ ext::json::forEach( serializer["textures"], [&]( ext::json::Value& value ){
auto name = key + value["name"].as<uf::stl::string>(); auto name = key + value["name"].as<uf::stl::string>();
// UF_MSG_DEBUG("{}", name); // UF_MSG_DEBUG("{}", name);
/*graph.storage*/storage.textures[name] = decodeTexture( value, graph ); storage.textures[name] = decodeTexture( value, graph );
graph.textures.emplace_back(name); graph.textures.emplace_back(name);
}); });
UF_DEBUG_TIMER_MULTITRACE("Read texture information"); UF_DEBUG_TIMER_MULTITRACE("Read texture information");
@ -501,7 +501,7 @@ void uf::graph::load( pod::Graph& graph, const uf::stl::string& filename, const
ext::json::forEach( serializer["samplers"], [&]( ext::json::Value& value ){ ext::json::forEach( serializer["samplers"], [&]( ext::json::Value& value ){
auto name = key + value["name"].as<uf::stl::string>(); auto name = key + value["name"].as<uf::stl::string>();
// UF_MSG_DEBUG("{}", name); // UF_MSG_DEBUG("{}", name);
/*graph.storage*/storage.samplers[name] = decodeSampler( value, graph ); storage.samplers[name] = decodeSampler( value, graph );
graph.samplers.emplace_back(name); graph.samplers.emplace_back(name);
}); });
UF_DEBUG_TIMER_MULTITRACE("Read sampler information"); UF_DEBUG_TIMER_MULTITRACE("Read sampler information");
@ -516,7 +516,7 @@ void uf::graph::load( pod::Graph& graph, const uf::stl::string& filename, const
ext::json::forEach( serializer["materials"], [&]( ext::json::Value& value ){ ext::json::forEach( serializer["materials"], [&]( ext::json::Value& value ){
auto name = key + value["name"].as<uf::stl::string>(); auto name = key + value["name"].as<uf::stl::string>();
// UF_MSG_DEBUG("{}", name); // UF_MSG_DEBUG("{}", name);
/*graph.storage*/storage.materials[name] = decodeMaterial( value, graph ); storage.materials[name] = decodeMaterial( value, graph );
graph.materials.emplace_back(name); graph.materials.emplace_back(name);
}); });
UF_DEBUG_TIMER_MULTITRACE("Read material information"); UF_DEBUG_TIMER_MULTITRACE("Read material information");
@ -542,7 +542,7 @@ void uf::graph::load( pod::Graph& graph, const uf::stl::string& filename, const
tasks.queue([&]{ tasks.queue([&]{
// load animation information // load animation information
UF_DEBUG_TIMER_MULTITRACE("Reading animation information..."); UF_DEBUG_TIMER_MULTITRACE("Reading animation information...");
/*graph.storage*/storage.animations.map.reserve( serializer["animations"].size() ); storage.animations.map.reserve( serializer["animations"].size() );
ext::json::forEach( serializer["animations"], [&]( ext::json::Value& value ){ ext::json::forEach( serializer["animations"], [&]( ext::json::Value& value ){
if ( value.is<uf::stl::string>() ) { if ( value.is<uf::stl::string>() ) {
auto path = directory + "/" + value.as<uf::stl::string>(); auto path = directory + "/" + value.as<uf::stl::string>();
@ -550,9 +550,9 @@ void uf::graph::load( pod::Graph& graph, const uf::stl::string& filename, const
json.readFromFile( path ); json.readFromFile( path );
auto name = key + json["name"].as<uf::stl::string>(); auto name = key + json["name"].as<uf::stl::string>();
if ( graph.settings.stream.animations ) { if ( graph.settings.stream.animations ) {
/*graph.storage*/storage.animations[name].path = path; storage.animations[name].path = path;
} else { } else {
/*graph.storage*/storage.animations[name] = decodeAnimation( json, graph ); storage.animations[name] = decodeAnimation( json, graph );
} }
graph.animations.emplace_back(name); graph.animations.emplace_back(name);
} else { } else {
@ -564,14 +564,14 @@ void uf::graph::load( pod::Graph& graph, const uf::stl::string& filename, const
auto name = key + json["name"].as<uf::stl::string>(); auto name = key + json["name"].as<uf::stl::string>();
if ( graph.settings.stream.animations ) { if ( graph.settings.stream.animations ) {
/*graph.storage*/storage.animations[name].path = path; storage.animations[name].path = path;
} else { } else {
/*graph.storage*/storage.animations[name] = decodeAnimation( json, graph ); storage.animations[name] = decodeAnimation( json, graph );
} }
graph.animations.emplace_back(name); graph.animations.emplace_back(name);
} else { } else {
auto name = key + value["name"].as<uf::stl::string>(); auto name = key + value["name"].as<uf::stl::string>();
/*graph.storage*/storage.animations[name] = decodeAnimation( value, graph ); storage.animations[name] = decodeAnimation( value, graph );
graph.animations.emplace_back(name); graph.animations.emplace_back(name);
} }
} }
@ -587,7 +587,7 @@ void uf::graph::load( pod::Graph& graph, const uf::stl::string& filename, const
ext::json::forEach( serializer["skins"], [&]( ext::json::Value& value ){ ext::json::forEach( serializer["skins"], [&]( ext::json::Value& value ){
auto name = key + value["name"].as<uf::stl::string>(); auto name = key + value["name"].as<uf::stl::string>();
// UF_MSG_DEBUG("{}", name); // UF_MSG_DEBUG("{}", name);
/*graph.storage*/storage.skins[name] = decodeSkin( value, graph ); storage.skins[name] = decodeSkin( value, graph );
graph.skins.emplace_back(name); graph.skins.emplace_back(name);
}); });
#if UF_ENV_DREAMCAST #if UF_ENV_DREAMCAST

View File

@ -26,7 +26,7 @@
#if UF_USE_OPENGL #if UF_USE_OPENGL
#define UF_GRAPH_SPARSE_READ_MESH 1 #define UF_GRAPH_SPARSE_READ_MESH 1
#else #else
#define UF_GRAPH_SPARSE_READ_MESH 0 #define UF_GRAPH_SPARSE_READ_MESH 1
#endif #endif
#define UF_GRAPH_EXTENDED 1 #define UF_GRAPH_EXTENDED 1
@ -1663,12 +1663,15 @@ void uf::graph::reload( pod::Graph& graph, pod::Node& node ) {
// bail if no update is detected // bail if no update is detected
auto drawCommandHash = ::fnv1aHash(queuedDrawIDs); auto drawCommandHash = ::fnv1aHash(queuedDrawIDs);
if ( drawCommandHash == graph.settings.stream.hash ) {
return;
}
graph.settings.stream.hash = drawCommandHash;
graph.settings.stream.lastUpdate = uf::physics::time::current; graph.settings.stream.lastUpdate = uf::physics::time::current;
if ( drawCommandHash == graph.settings.stream.hash ) {
// return;
}
graph.settings.stream.hash = drawCommandHash;
// read from disk
#if UF_GRAPH_SPARSE_READ_MESH
// needs to be dequantized first, naively copying the descriptor settings just doesn't work // needs to be dequantized first, naively copying the descriptor settings just doesn't work
{ {
#if UF_ENV_DREAMCAST && GL_QUANTIZED_SHORT #if UF_ENV_DREAMCAST && GL_QUANTIZED_SHORT
@ -1690,8 +1693,6 @@ void uf::graph::reload( pod::Graph& graph, pod::Node& node ) {
#endif #endif
} }
// read from disk
#if UF_GRAPH_SPARSE_READ_MESH
// reset counts // reset counts
mesh.vertex.count = 0; mesh.vertex.count = 0;
mesh.index.count = 0; mesh.index.count = 0;
@ -1867,6 +1868,7 @@ void uf::graph::reload( pod::Graph& graph, pod::Node& node ) {
LOAD_MESH_DATA( vertex ); LOAD_MESH_DATA( vertex );
} }
// in the event streamed in mesh data from any pathway isn't already converted
{ {
#if UF_ENV_DREAMCAST && GL_QUANTIZED_SHORT #if UF_ENV_DREAMCAST && GL_QUANTIZED_SHORT
mesh.convert<float, uint16_t>(); mesh.convert<float, uint16_t>();

View File

@ -10,9 +10,6 @@
#include <uf/utils/mesh/mesh.h> #include <uf/utils/mesh/mesh.h>
#include <uf/engine/graph/graph.h> #include <uf/engine/graph/graph.h>
#define VERBOSE false
#define VERBOSE_SUBMIT false
namespace { namespace {
size_t culled = 0; size_t culled = 0;
} }
@ -41,13 +38,17 @@ void ext::opengl::CommandBuffer::end() {
} }
void ext::opengl::CommandBuffer::record( const CommandBuffer::Info& header ) { void ext::opengl::CommandBuffer::record( const CommandBuffer::Info& header ) {
if ( state != 1 ) return; if ( state != 1 ) return;
switch ( header.type ) { switch ( header.type ) {
case ext::opengl::enums::Command::CLEAR: { case ext::opengl::enums::Command::CLEAR: {
InfoClear* info = (InfoClear*) &header; InfoClear* info = (InfoClear*) &header;
#if UF_COMMAND_BUFFER_USERDATA
auto& userdata = infos.emplace_back(); auto& userdata = infos.emplace_back();
userdata.create<InfoClear>( *info ); userdata.create<InfoClear>( *info );
info = &userdata.get<InfoClear>(); info = &userdata.get<InfoClear>();
#else
info = new InfoClear(*info);
infos.emplace_back(info);
#endif
info->type = enums::Command::CLEAR; info->type = enums::Command::CLEAR;
info->next = NULL; info->next = NULL;
} break; } break;
@ -55,25 +56,40 @@ void ext::opengl::CommandBuffer::record( const CommandBuffer::Info& header ) {
InfoViewport* info = (InfoViewport*) &header; InfoViewport* info = (InfoViewport*) &header;
if ( info->size.x == 0 ) info->size.x = ext::opengl::settings::width; if ( info->size.x == 0 ) info->size.x = ext::opengl::settings::width;
if ( info->size.y == 0 ) info->size.y = ext::opengl::settings::height; if ( info->size.y == 0 ) info->size.y = ext::opengl::settings::height;
#if UF_COMMAND_BUFFER_USERDATA
auto& userdata = infos.emplace_back(); auto& userdata = infos.emplace_back();
userdata.create<InfoViewport>( *info ); userdata.create<InfoViewport>( *info );
info->next = NULL;
info = &userdata.get<InfoViewport>(); info = &userdata.get<InfoViewport>();
#else
info = new InfoViewport(*info);
infos.emplace_back(info);
#endif
info->type = enums::Command::VIEWPORT; info->type = enums::Command::VIEWPORT;
info->next = NULL;
} break; } break;
case ext::opengl::enums::Command::VARIANT: { case ext::opengl::enums::Command::VARIANT: {
InfoVariant* info = (InfoVariant*) &header; InfoVariant* info = (InfoVariant*) &header;
#if UF_COMMAND_BUFFER_USERDATA
auto& userdata = infos.emplace_back(); auto& userdata = infos.emplace_back();
userdata.create<InfoVariant>( *info ); userdata.create<InfoVariant>( *info );
info = &userdata.get<InfoVariant>(); info = &userdata.get<InfoVariant>();
#else
info = new InfoVariant(*info);
infos.emplace_back(info);
#endif
info->type = enums::Command::VARIANT; info->type = enums::Command::VARIANT;
info->next = NULL; info->next = NULL;
} break; } break;
case ext::opengl::enums::Command::DRAW: { case ext::opengl::enums::Command::DRAW: {
InfoDraw* info = (InfoDraw*) &header; InfoDraw* info = (InfoDraw*) &header;
#if UF_COMMAND_BUFFER_USERDATA
auto& userdata = infos.emplace_back(); auto& userdata = infos.emplace_back();
userdata.create<InfoDraw>( *info ); userdata.create<InfoDraw>( *info );
info = &userdata.get<InfoDraw>(); info = &userdata.get<InfoDraw>();
#else
info = new InfoDraw(*info);
infos.emplace_back(info);
#endif
info->type = enums::Command::DRAW; info->type = enums::Command::DRAW;
info->next = NULL; info->next = NULL;
} break; } break;
@ -95,7 +111,11 @@ void ext::opengl::CommandBuffer::submit() {
mutex->lock(); mutex->lock();
//UF_TIMER_MULTITRACE_START("Starting command buffer submission: " << this); //UF_TIMER_MULTITRACE_START("Starting command buffer submission: " << this);
for ( auto& info : infos ) { for ( auto& info : infos ) {
#if UF_COMMAND_BUFFER_USERDATA
CommandBuffer::Info* header = (CommandBuffer::Info*) (void*) info; CommandBuffer::Info* header = (CommandBuffer::Info*) (void*) info;
#else
CommandBuffer::Info* header = (CommandBuffer::Info*) info;
#endif
switch ( header->type ) { switch ( header->type ) {
case ext::opengl::enums::Command::CLEAR: { case ext::opengl::enums::Command::CLEAR: {
InfoClear* info = (InfoClear*) header; InfoClear* info = (InfoClear*) header;
@ -128,6 +148,31 @@ void ext::opengl::CommandBuffer::submit() {
} }
void ext::opengl::CommandBuffer::flush() { void ext::opengl::CommandBuffer::flush() {
mutex->lock(); mutex->lock();
#if !UF_COMMAND_BUFFER_USERDATA
for ( auto& info : infos ) {
CommandBuffer::Info* header = (CommandBuffer::Info*) info;
switch ( header->type ) {
case ext::opengl::enums::Command::CLEAR: {
InfoClear* info = (InfoClear*) header;
delete info;
} break;
case ext::opengl::enums::Command::VIEWPORT: {
InfoViewport* info = (InfoViewport*) header;
delete info;
} break;
case ext::opengl::enums::Command::VARIANT: {
InfoVariant* info = (InfoVariant*) header;
delete info;
} break;
case ext::opengl::enums::Command::DRAW: {
InfoDraw* info = (InfoDraw*) header;
delete info;
} break;
default: {
} break;
}
}
#endif
infos.clear(); infos.clear();
state = 0; state = 0;
mutex->unlock(); mutex->unlock();
@ -451,7 +496,7 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::
if ( drawInfo.descriptor.inputs.index.count ) { if ( drawInfo.descriptor.inputs.index.count ) {
GL_ERROR_CHECK(glDrawElements(GL_TRIANGLES, drawInfo.descriptor.inputs.index.count, indicesType, (static_cast<uint8_t*>(drawInfo.attributes.index.pointer) + drawInfo.attributes.index.stride * drawInfo.descriptor.inputs.index.first))); GL_ERROR_CHECK(glDrawElements(GL_TRIANGLES, drawInfo.descriptor.inputs.index.count, indicesType, (static_cast<uint8_t*>(drawInfo.attributes.index.pointer) + drawInfo.attributes.index.stride * drawInfo.descriptor.inputs.index.first)));
} else { } else {
#if UF_ENV_DREAMCAST #if 0 && UF_ENV_DREAMCAST
// GLdc has a "regression" where glDrawArrays does not work // GLdc has a "regression" where glDrawArrays does not work
// everything should be using indices anyways so this path shouldn't really ever be taken // everything should be using indices anyways so this path shouldn't really ever be taken
uf::stl::vector<uint16_t> indices(drawInfo.descriptor.inputs.vertex.count); uf::stl::vector<uint16_t> indices(drawInfo.descriptor.inputs.vertex.count);

View File

@ -15,8 +15,12 @@ namespace {
rp3d::PhysicsCommon common; rp3d::PhysicsCommon common;
rp3d::PhysicsWorld* world; rp3d::PhysicsWorld* world;
reactphysics3d::TriangleMesh* createTriangleMesh( const uf::Mesh& mesh ) { // i was wrong to assume that RP3D handles deleting these per the documentation
uf::stl::unordered_map<size_t, uf::stl::vector<rp3d::TriangleVertexArray*>> triangleParts;
reactphysics3d::TriangleMesh* createTriangleMesh( const uf::Mesh& mesh, const uf::Object& object ) {
auto* rMesh = ::common.createTriangleMesh(); auto* rMesh = ::common.createTriangleMesh();
auto& parts = ::triangleParts[object.getUid()];
uf::Mesh::Input vertexInput = mesh.vertex; uf::Mesh::Input vertexInput = mesh.vertex;
uf::Mesh::Input indexInput = mesh.index; uf::Mesh::Input indexInput = mesh.index;
@ -73,7 +77,7 @@ namespace {
if ( vertexInput.count == 0 || indexInput.count == 0 ) continue; if ( vertexInput.count == 0 || indexInput.count == 0 ) continue;
if ( normalAttribute.descriptor.name == "normal" ) { if ( normalAttribute.descriptor.name == "normal" ) {
rMesh->addSubpart(new rp3d::TriangleVertexArray( auto* part = new rp3d::TriangleVertexArray(
vertexInput.count, vertexInput.count,
(const uint8_t*) (vertexAttribute.pointer) + vertexAttribute.stride * vertexInput.first, (const uint8_t*) (vertexAttribute.pointer) + vertexAttribute.stride * vertexInput.first,
vertexAttribute.stride, vertexAttribute.stride,
@ -88,9 +92,11 @@ namespace {
vertexType, vertexType,
normalType, normalType,
indexType indexType
)); );
parts.emplace_back(part);
rMesh->addSubpart(part);
} else { } else {
rMesh->addSubpart(new rp3d::TriangleVertexArray( auto* part = new rp3d::TriangleVertexArray(
vertexInput.count, vertexInput.count,
(const uint8_t*) (vertexAttribute.pointer) + vertexAttribute.stride * vertexInput.first, (const uint8_t*) (vertexAttribute.pointer) + vertexAttribute.stride * vertexInput.first,
vertexAttribute.stride, vertexAttribute.stride,
@ -101,12 +107,14 @@ namespace {
vertexType, vertexType,
indexType indexType
)); );
parts.emplace_back(part);
rMesh->addSubpart(part);
} }
} }
} else if ( vertexInput.count > 0 && indexInput.count > 0 ) { } else if ( vertexInput.count > 0 && indexInput.count > 0 ) {
if ( normalAttribute.descriptor.name == "normal" ) { if ( normalAttribute.descriptor.name == "normal" ) {
rMesh->addSubpart(new rp3d::TriangleVertexArray( auto* part = new rp3d::TriangleVertexArray(
vertexInput.count, vertexInput.count,
(const uint8_t*) (vertexAttribute.pointer) + vertexAttribute.stride * vertexInput.first, (const uint8_t*) (vertexAttribute.pointer) + vertexAttribute.stride * vertexInput.first,
vertexAttribute.stride, vertexAttribute.stride,
@ -121,9 +129,11 @@ namespace {
vertexType, vertexType,
normalType, normalType,
indexType indexType
)); );
parts.emplace_back(part);
rMesh->addSubpart(part);
} else { } else {
rMesh->addSubpart(new rp3d::TriangleVertexArray( auto* part = new rp3d::TriangleVertexArray(
vertexInput.count, vertexInput.count,
(const uint8_t*) (vertexAttribute.pointer) + vertexAttribute.stride * vertexInput.first, (const uint8_t*) (vertexAttribute.pointer) + vertexAttribute.stride * vertexInput.first,
vertexAttribute.stride, vertexAttribute.stride,
@ -134,7 +144,9 @@ namespace {
vertexType, vertexType,
indexType indexType
)); );
parts.emplace_back(part);
rMesh->addSubpart(part);
} }
} }
@ -420,6 +432,15 @@ pod::PhysicsState& ext::reactphysics::create( uf::Object& object ) {
void ext::reactphysics::destroy( uf::Object& object ) { void ext::reactphysics::destroy( uf::Object& object ) {
auto& state = object.getComponent<pod::PhysicsState>(); auto& state = object.getComponent<pod::PhysicsState>();
ext::reactphysics::destroy( state ); ext::reactphysics::destroy( state );
auto uid = object.getUid();
if ( ::triangleParts.count( uid ) > 0 ) {
auto& parts = ::triangleParts[uid];
for ( auto* part : parts ) {
delete part;
}
::triangleParts.erase( uid );
}
} }
void ext::reactphysics::destroy( pod::PhysicsState& state ) { void ext::reactphysics::destroy( pod::PhysicsState& state ) {
ext::reactphysics::detach( state ); ext::reactphysics::detach( state );
@ -468,6 +489,7 @@ void ext::reactphysics::detach( pod::PhysicsState& state ) {
if ( !state.body || !state.world ) return; if ( !state.body || !state.world ) return;
// auto& scene = uf::scene::getCurrentScene(); // auto& scene = uf::scene::getCurrentScene();
// auto& world = ext::reactphysics::globalStorage ? ::world : scene.getComponent<ext::reactphysics::WorldState>(); // auto& world = ext::reactphysics::globalStorage ? ::world : scene.getComponent<ext::reactphysics::WorldState>();
state.world->destroyRigidBody(state.body); state.world->destroyRigidBody(state.body);
state.body = NULL; state.body = NULL;
@ -478,7 +500,7 @@ void ext::reactphysics::detach( pod::PhysicsState& state ) {
pod::PhysicsState& ext::reactphysics::create( uf::Object& object, const uf::Mesh& mesh, bool dynamic ) { pod::PhysicsState& ext::reactphysics::create( uf::Object& object, const uf::Mesh& mesh, bool dynamic ) {
UF_ASSERT( mesh.index.count ); UF_ASSERT( mesh.index.count );
auto* rMesh = ::createTriangleMesh( mesh ); auto* rMesh = ::createTriangleMesh( mesh, object );
auto& state = ext::reactphysics::create( object ); auto& state = ext::reactphysics::create( object );
state.shape = ::common.createConcaveMeshShape( rMesh ); state.shape = ::common.createConcaveMeshShape( rMesh );

View File

@ -1 +1 @@
linux win64