Commit for 2022.06.05 22-42-59.7z
This commit is contained in:
parent
82390c927b
commit
a9f5a56366
8
Makefile
8
Makefile
@ -186,7 +186,7 @@ ifneq (,$(findstring simd,$(REQ_DEPS)))
|
||||
endif
|
||||
endif
|
||||
ifneq (,$(findstring meshoptimizer,$(REQ_DEPS)))
|
||||
FLAGS += -DUF_USE_MESHOPTIMIZER
|
||||
FLAGS += -DUF_USE_MESHOPT
|
||||
DEPS += -lmeshoptimizer
|
||||
endif
|
||||
ifneq (,$(findstring draco,$(REQ_DEPS)))
|
||||
@ -315,7 +315,9 @@ clean:
|
||||
@-rm ./bin/dreamcast/build/*
|
||||
@-rm ./bin/dreamcast/romdisk.*
|
||||
@-rm ./bin/dreamcast/$(TARGET_NAME).*
|
||||
# @-find ./bin/data/ -name "*.gz" -type f -delete
|
||||
|
||||
clean-zips:
|
||||
@-find ./bin/data/ -name "*.gz" -type f -delete
|
||||
|
||||
run:
|
||||
$(KOS_EMU) ./bin/dreamcast/$(TARGET_NAME).cdi
|
||||
@ -328,6 +330,8 @@ clean:
|
||||
@-rm -f $(OBJS_DLL)
|
||||
@-rm -f $(OBJS_EXT_DLL)
|
||||
@-rm -f $(OBJS)
|
||||
|
||||
clean-zips:
|
||||
@-find ./bin/data/ -name "*.gz" -type f -delete
|
||||
|
||||
run:
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
"matrix": { "reverseInfinite": true },
|
||||
"lights": { "enabled": true,
|
||||
"useLightmaps": false,
|
||||
"max": 16
|
||||
"max": 32
|
||||
},
|
||||
"shadows": {
|
||||
"enabled": true,
|
||||
@ -24,17 +24,17 @@
|
||||
},
|
||||
"vxgi": {
|
||||
"limiter": 1,
|
||||
"size": 86,
|
||||
"size": 128,
|
||||
"dispatch": 8,
|
||||
"cascades": 4,
|
||||
"cascadePower": 4,
|
||||
"cascadePower": 3,
|
||||
"granularity": 8,
|
||||
"voxelizeScale": 1,
|
||||
"occlusionFalloff": 2,
|
||||
"shadows": 0,
|
||||
"extents": {
|
||||
"min": [ -4, -4, -4 ],
|
||||
"max": [ 4, 4, 4 ]
|
||||
"min": [ -8, -1, -8 ],
|
||||
"max": [ 8, 4, 8 ]
|
||||
}
|
||||
},
|
||||
"bloom": {
|
||||
|
||||
@ -24,14 +24,15 @@
|
||||
"precision": 4,
|
||||
"combined": false,
|
||||
"encode buffers": true,
|
||||
"unwrap": true,
|
||||
"unwrap": false,
|
||||
"optimize": "tagged",
|
||||
"quit": true,
|
||||
"mesh": {
|
||||
// "print": true
|
||||
}
|
||||
},
|
||||
"baking": {
|
||||
"enabled": false,
|
||||
"enabled": true,
|
||||
"resolution": 8192,
|
||||
"shadows": 1024,
|
||||
"layers": 1,
|
||||
|
||||
@ -22,7 +22,8 @@
|
||||
"tags": {
|
||||
"/^worldspawn/": {
|
||||
"physics": { "type": "mesh", "static": true },
|
||||
"grid": { "size": [4,1,4], "epsilon": 1.0, "cleanup": true, "print": true }
|
||||
"grid": { "size": [4,1,4], "epsilon": 1.0, "cleanup": true, "print": true },
|
||||
"optimize mesh": { "simplify": 0 }
|
||||
},
|
||||
"info_player_spawn": { "action": "attach", "filename": "./player.json", "preserve orientation": true },
|
||||
|
||||
|
||||
@ -2,15 +2,16 @@
|
||||
"import": "/model.json",
|
||||
"assets": [
|
||||
// { "filename": "./craeture.json", "delay": 1 },
|
||||
{ "filename": "./test.json", "delay": 1 },
|
||||
|
||||
// { "filename": "./models/tiny_msci.glb" }
|
||||
// { "filename": "./models/tiny_msci/graph.json" }
|
||||
{ "filename": "./models/tiny_msci/graph.json" }
|
||||
|
||||
// { "filename": "./models/micro_sci.glb" }
|
||||
// { "filename": "./models/micro_sci/graph.json" }
|
||||
|
||||
// { "filename": "./models/msci.glb" }
|
||||
{ "filename": "./models/msci/graph.json" }
|
||||
// { "filename": "./models/msci/graph.json" }
|
||||
|
||||
// { "filename": "./models/medsci.glb" }
|
||||
// { "filename": "./models/medsci/graph.json" }
|
||||
@ -25,7 +26,8 @@
|
||||
"tags": {
|
||||
"/^worldspawn/": {
|
||||
"physics": { "type": "mesh", "static": true },
|
||||
"grid": { "size": [5,1,5], "epsilon": 1.0, "cleanup": true, "print": true }
|
||||
"grid": { "size": [5,1,5], "epsilon": 1.0, "cleanup": true, "print": true },
|
||||
"optimize mesh": { "simplify": 0 }
|
||||
},
|
||||
"info_player_spawn": {
|
||||
"action": "attach",
|
||||
|
||||
25
bin/data/scenes/ss2/test.json
Normal file
25
bin/data/scenes/ss2/test.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "Gui: Text Test",
|
||||
"type": "Gui",
|
||||
"ignore": false,
|
||||
"transform": {
|
||||
"position": [18.3785, 2.41477, 0.859857],
|
||||
"rotation": {
|
||||
"axis": [ 0, 0, 1 ],
|
||||
"angle": 3.141
|
||||
},
|
||||
"scale": [ 1, 1, 1 ]
|
||||
},
|
||||
"metadata": {
|
||||
"uv": [ 0, 0, 1, 1 ],
|
||||
"location": "",
|
||||
"scaling": "relative",
|
||||
"world": true,
|
||||
"cull mode": "none",
|
||||
"text settings": {
|
||||
"scale": 8,
|
||||
"font": "Coolvetica.ttf",
|
||||
"string": "Grimgram"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"engine": {
|
||||
"scenes": {
|
||||
"start": "SS2",
|
||||
"start": "McDonalds",
|
||||
"meshes": { "interleaved": false },
|
||||
"matrix": { "reverseInfinite": false },
|
||||
"lights": { "enabled": false,
|
||||
|
||||
@ -7,6 +7,7 @@ namespace uf {
|
||||
pod::ColorRgba color{ (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0 };
|
||||
pod::Vector2f st{};
|
||||
pod::Vector3f normal{};
|
||||
pod::Vector<uint16_t, 2> id{};
|
||||
|
||||
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
|
||||
};
|
||||
@ -19,6 +20,7 @@ namespace uf {
|
||||
pod::Vector3f tangent{};
|
||||
pod::Vector<uint16_t, 4> joints{};
|
||||
pod::Vector4f weights{};
|
||||
pod::Vector<uint16_t, 2> id{};
|
||||
|
||||
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
|
||||
};
|
||||
|
||||
@ -6,6 +6,6 @@
|
||||
|
||||
namespace ext {
|
||||
namespace meshopt {
|
||||
void UF_API optimize( uf::Mesh&, size_t = SIZE_MAX );
|
||||
bool UF_API optimize( uf::Mesh&, float simplify = 1.0f, size_t = SIZE_MAX );
|
||||
}
|
||||
}
|
||||
@ -87,16 +87,22 @@ namespace uf {
|
||||
if ( mlet.indices.empty() ) continue;
|
||||
|
||||
auto& meshlet = meshlets[mlet.primitive.instance.primitiveID];
|
||||
size_t primitiveID = partitioned.size();
|
||||
auto& slice = partitioned.emplace_back();
|
||||
slice.vertices.reserve( mlet.indices.size() );
|
||||
slice.indices.reserve( mlet.indices.size() );
|
||||
for ( auto idx : mlet.indices ) {
|
||||
slice.vertices.emplace_back( meshlet.vertices[idx] );
|
||||
slice.indices.emplace_back( slice.indices.size() );
|
||||
auto& vertex = slice.vertices.emplace_back( meshlet.vertices[idx] );
|
||||
auto& index = slice.indices.emplace_back( slice.indices.size() );
|
||||
|
||||
vertex.id.x = primitiveID;
|
||||
vertex.id.y = meshlet.primitive.instance.meshID;
|
||||
}
|
||||
|
||||
slice.primitive.instance = meshlet.primitive.instance;
|
||||
slice.primitive.instance.materialID = meshlet.primitive.instance.materialID;
|
||||
slice.primitive.instance.primitiveID = partitioned.size() - 1;
|
||||
slice.primitive.instance.primitiveID = primitiveID;
|
||||
slice.primitive.instance.meshID = meshlet.primitive.instance.meshID;
|
||||
slice.primitive.instance.objectID = 0;
|
||||
slice.primitive.instance.auxID = atlasID;
|
||||
slice.primitive.instance.bounds.min = node.effectiveExtents.min;
|
||||
|
||||
@ -359,8 +359,10 @@ uf::stl::string uf::Asset::load(const uf::Asset::Payload& payload ) {
|
||||
#endif
|
||||
asset = uf::graph::load( filename, metadata[payload.filename] );
|
||||
uf::graph::process( asset );
|
||||
#if !UF_ENV_DREAMCAST
|
||||
if ( asset.metadata["debug"]["print stats"].as<bool>() ) UF_MSG_INFO(uf::graph::stats( asset ).dump(1,'\t'));
|
||||
if ( asset.metadata["debug"]["print tree"].as<bool>() ) UF_MSG_INFO(uf::graph::print( asset ));
|
||||
#endif
|
||||
if ( !asset.metadata["debug"]["no cleanup"].as<bool>() ) uf::graph::cleanup( asset );
|
||||
} break;
|
||||
default: {
|
||||
|
||||
@ -121,47 +121,111 @@ pod::Graph& UF_API uf::graph::convert( uf::Object& object, bool process ) {
|
||||
for ( auto index : graph.root.children ) uf::graph::process( graph, index, *graph.root.entity );
|
||||
}
|
||||
|
||||
// remap textures->images IDs
|
||||
for ( auto& name : graph.textures ) {
|
||||
auto& texture = uf::graph::storage.textures[name];
|
||||
auto& keys = uf::graph::storage.images.keys;
|
||||
auto& indices = uf::graph::storage.images.indices;
|
||||
|
||||
if ( !(0 <= texture.index && texture.index < graph.images.size()) ) continue;
|
||||
|
||||
auto& needle = graph.images[texture.index];
|
||||
#if 1
|
||||
texture.index = indices[needle];
|
||||
#elif 1
|
||||
for ( size_t i = 0; i < keys.size(); ++i ) {
|
||||
if ( keys[i] != needle ) continue;
|
||||
texture.index = i;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
auto it = std::find( keys.begin(), keys.end(), needle );
|
||||
UF_ASSERT( it != keys.end() );
|
||||
texture.index = it - keys.begin();
|
||||
#endif
|
||||
}
|
||||
// remap materials->texture IDs
|
||||
for ( auto& name : graph.materials ) {
|
||||
auto& material = uf::graph::storage.materials[name];
|
||||
auto& keys = uf::graph::storage.textures.keys;
|
||||
auto& indices = uf::graph::storage.textures.indices;
|
||||
int32_t* IDs[] = { &material.indexAlbedo, &material.indexNormal, &material.indexEmissive, &material.indexOcclusion, &material.indexMetallicRoughness };
|
||||
for ( auto* pointer : IDs ) {
|
||||
auto& ID = *pointer;
|
||||
if ( !(0 <= ID && ID < graph.materials.size()) ) continue;
|
||||
auto it = std::find( keys.begin(), keys.end(), graph.textures[ID] );
|
||||
if ( !(0 <= ID && ID < graph.textures.size()) ) continue;
|
||||
auto& needle = graph.textures[ID];
|
||||
#if 1
|
||||
ID = indices[needle];
|
||||
#elif 1
|
||||
for ( size_t i = 0; i < keys.size(); ++i ) {
|
||||
if ( keys[i] != needle ) continue;
|
||||
ID = i;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
if ( !(0 <= ID && ID < graph.textures.size()) ) continue;
|
||||
auto it = std::find( keys.begin(), keys.end(), needle );
|
||||
UF_ASSERT( it != keys.end() );
|
||||
ID = it - keys.begin();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
// remap textures->images IDs
|
||||
/*
|
||||
for ( auto& name : graph.textures ) {
|
||||
auto& texture = uf::graph::storage.textures[name];
|
||||
auto& keys = uf::graph::storage.images.keys;
|
||||
|
||||
if ( !(0 <= texture.index && texture.index < graph.textures.size()) ) continue;
|
||||
auto it = std::find( keys.begin(), keys.end(), graph.images[texture.index] );
|
||||
UF_ASSERT( it != keys.end() );
|
||||
texture.index = it - keys.begin();
|
||||
}
|
||||
*/
|
||||
// remap instance variables
|
||||
for ( auto& name : graph.instances ) {
|
||||
auto& instance = uf::graph::storage.instances[name];
|
||||
|
||||
if ( 0 <= instance.materialID && instance.materialID < graph.materials.size() ) {
|
||||
auto& keys = /*graph.storage*/uf::graph::storage.materials.keys;
|
||||
auto it = std::find( keys.begin(), keys.end(), graph.materials[instance.materialID] );
|
||||
auto& indices = /*graph.storage*/uf::graph::storage.materials.indices;
|
||||
|
||||
if ( !(0 <= instance.materialID && instance.materialID < graph.materials.size()) ) continue;
|
||||
|
||||
auto& needle = graph.materials[instance.materialID];
|
||||
#if 1
|
||||
instance.materialID = indices[needle];
|
||||
#elif 1
|
||||
for ( size_t i = 0; i < keys.size(); ++i ) {
|
||||
if ( keys[i] != needle ) continue;
|
||||
instance.materialID = i;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
auto it = std::find( keys.begin(), keys.end(), needle );
|
||||
UF_ASSERT( it != keys.end() );
|
||||
instance.materialID = it - keys.begin();
|
||||
#endif
|
||||
}
|
||||
if ( 0 <= instance.lightmapID && instance.lightmapID < graph.textures.size() ) {
|
||||
auto& keys = /*graph.storage*/uf::graph::storage.textures.keys;
|
||||
auto& indices = /*graph.storage*/uf::graph::storage.textures.indices;
|
||||
|
||||
if ( !(0 <= instance.lightmapID && instance.lightmapID < graph.textures.size()) ) continue;
|
||||
|
||||
auto& needle = graph.textures[instance.lightmapID];
|
||||
#if 1
|
||||
instance.lightmapID = indices[needle];
|
||||
#elif 1
|
||||
for ( size_t i = 0; i < keys.size(); ++i ) {
|
||||
if ( keys[i] != needle ) continue;
|
||||
instance.lightmapID = i;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
auto it = std::find( keys.begin(), keys.end(), needle );
|
||||
UF_ASSERT( it != keys.end() );
|
||||
instance.lightmapID = it - keys.begin();
|
||||
#endif
|
||||
}
|
||||
#if 0
|
||||
// i genuinely dont remember what this is used for
|
||||
|
||||
if ( 0 <= instance.imageID && instance.imageID < graph.images.size() ) {
|
||||
auto& keys = /*graph.storage*/uf::graph::storage.images.keys;
|
||||
auto it = std::find( keys.begin(), keys.end(), graph.images[instance.imageID] );
|
||||
UF_ASSERT( it != keys.end() );
|
||||
instance.imageID = it - keys.begin();
|
||||
}
|
||||
#endif
|
||||
// remap a skinID as an actual jointID
|
||||
if ( 0 <= instance.jointID && instance.jointID < graph.skins.size() ) {
|
||||
auto& name = graph.skins[instance.jointID];
|
||||
@ -172,12 +236,6 @@ pod::Graph& UF_API uf::graph::convert( uf::Object& object, bool process ) {
|
||||
instance.jointID += joints.size();
|
||||
}
|
||||
}
|
||||
if ( 0 <= instance.lightmapID && instance.lightmapID < graph.textures.size() ) {
|
||||
auto& keys = /*graph.storage*/uf::graph::storage.textures.keys;
|
||||
auto it = std::find( keys.begin(), keys.end(), graph.textures[instance.lightmapID] );
|
||||
UF_ASSERT( it != keys.end() );
|
||||
instance.lightmapID = it - keys.begin();
|
||||
}
|
||||
}
|
||||
|
||||
uf::graph::reload();
|
||||
|
||||
@ -225,16 +225,36 @@ namespace {
|
||||
});
|
||||
|
||||
// remove extraneous buffers
|
||||
#if UF_USE_OPENGL
|
||||
/*
|
||||
for ( auto& attribute : mesh.vertex.attributes ) {
|
||||
if ( attribute.descriptor.name == "position" ) continue;
|
||||
if ( attribute.descriptor.name == "color" ) continue;
|
||||
if ( attribute.descriptor.name == "uv" ) continue;
|
||||
if ( attribute.descriptor.name == "st" ) continue;
|
||||
if ( !mesh.isInterleaved() ) {
|
||||
uf::stl::vector<size_t> remove; remove.reserve(mesh.vertex.attributes.size());
|
||||
|
||||
for ( size_t i = 0; i < mesh.vertex.attributes.size(); ++i ) {
|
||||
auto& attribute = mesh.vertex.attributes[i];
|
||||
if ( attribute.descriptor.name == "position" ) continue;
|
||||
if ( attribute.descriptor.name == "color" ) continue;
|
||||
if ( attribute.descriptor.name == "uv" ) continue;
|
||||
if ( attribute.descriptor.name == "st" ) continue;
|
||||
|
||||
if ( graph.metadata["flags"]["SKINNED"].as<bool>() ) {
|
||||
if ( attribute.descriptor.name == "tangent" ) continue;
|
||||
if ( attribute.descriptor.name == "joints" ) continue;
|
||||
if ( attribute.descriptor.name == "weights" ) continue;
|
||||
}
|
||||
#if !UF_USE_OPENGL
|
||||
if ( attribute.descriptor.name == "normal" ) continue;
|
||||
#endif
|
||||
|
||||
remove.insert(remove.begin(), i);
|
||||
}
|
||||
for ( auto& i : remove ) {
|
||||
// UF_MSG_DEBUG("Removing " << mesh.vertex.attributes[i].descriptor.name);
|
||||
mesh.buffers[mesh.vertex.attributes[i].buffer].clear();
|
||||
mesh.buffers[mesh.vertex.attributes[i].buffer].shrink_to_fit();
|
||||
mesh.vertex.attributes.erase(mesh.vertex.attributes.begin() + i);
|
||||
}
|
||||
} else {
|
||||
UF_MSG_DEBUG("Attribute removal requested yet mesh is not interleaved, ignoring...");
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
|
||||
mesh.updateDescriptor();
|
||||
|
||||
|
||||
@ -9,12 +9,7 @@
|
||||
#include <uf/utils/math/physics.h>
|
||||
#include <uf/ext/xatlas/xatlas.h>
|
||||
|
||||
#if UF_ENV_DREAMCAST
|
||||
#define UF_GRAPH_LOAD_MULTITHREAD 0
|
||||
#else
|
||||
#define UF_GRAPH_LOAD_MULTITHREAD 1 // causes Vulkan OOM
|
||||
#endif
|
||||
|
||||
#if !UF_ENV_DREAMCAST
|
||||
namespace {
|
||||
struct EncodingSettings : public ext::json::EncodingSettings {
|
||||
bool combined = false;
|
||||
@ -23,7 +18,7 @@ namespace {
|
||||
uf::stl::string filename = "";
|
||||
};
|
||||
|
||||
uf::Serializer encode( const uf::Image& image, const EncodingSettings& settings ) {
|
||||
uf::Serializer encode( const uf::Image& image, const EncodingSettings& settings, const pod::Graph& graph ) {
|
||||
uf::Serializer json;
|
||||
json["size"] = uf::vector::encode( image.getDimensions() );
|
||||
json["bpp"] = image.getBpp() / image.getChannels();
|
||||
@ -31,7 +26,7 @@ namespace {
|
||||
json["data"] = uf::base64::encode( image.getPixels() );
|
||||
return json;
|
||||
}
|
||||
uf::Serializer encode( const pod::Texture& texture, const EncodingSettings& settings ) {
|
||||
uf::Serializer encode( const pod::Texture& texture, const EncodingSettings& settings, const pod::Graph& graph ) {
|
||||
uf::Serializer json;
|
||||
json["index"] = texture.index;
|
||||
json["sampler"] = texture.sampler;
|
||||
@ -40,7 +35,7 @@ namespace {
|
||||
json["lerp"] = uf::vector::encode( texture.lerp, settings );
|
||||
return json;
|
||||
}
|
||||
uf::Serializer encode( const uf::renderer::Sampler& sampler, const EncodingSettings& settings ) {
|
||||
uf::Serializer encode( const uf::renderer::Sampler& sampler, const EncodingSettings& settings, const pod::Graph& graph ) {
|
||||
uf::Serializer json;
|
||||
json["min"] = sampler.descriptor.filter.min;
|
||||
json["mag"] = sampler.descriptor.filter.mag;
|
||||
@ -48,7 +43,7 @@ namespace {
|
||||
json["v"] = sampler.descriptor.addressMode.v;
|
||||
return json;
|
||||
}
|
||||
uf::Serializer encode( const pod::Material& material, const EncodingSettings& settings ) {
|
||||
uf::Serializer encode( const pod::Material& material, const EncodingSettings& settings, const pod::Graph& graph ) {
|
||||
uf::Serializer json;
|
||||
json["base"] = uf::vector::encode( material.colorBase, settings );
|
||||
json["emissive"] = uf::vector::encode( material.colorEmissive, settings );
|
||||
@ -64,14 +59,14 @@ namespace {
|
||||
json["modeAlpha"] = material.modeAlpha;
|
||||
return json;
|
||||
}
|
||||
uf::Serializer encode( const pod::Light& light, const EncodingSettings& settings ) {
|
||||
uf::Serializer encode( const pod::Light& light, const EncodingSettings& settings, const pod::Graph& graph ) {
|
||||
uf::Serializer json;
|
||||
json["color"] = uf::vector::encode( light.color, settings );
|
||||
json["intensity"] = light.intensity;
|
||||
json["range"] = light.range;
|
||||
return json;
|
||||
}
|
||||
uf::Serializer encode( const pod::Animation& animation, const EncodingSettings& settings ) {
|
||||
uf::Serializer encode( const pod::Animation& animation, const EncodingSettings& settings, const pod::Graph& graph ) {
|
||||
uf::Serializer json;
|
||||
json["name"] = animation.name;
|
||||
json["start"] = animation.start;
|
||||
@ -99,7 +94,7 @@ namespace {
|
||||
}
|
||||
return json;
|
||||
}
|
||||
uf::Serializer encode( const pod::Skin& skin, const EncodingSettings& settings ) {
|
||||
uf::Serializer encode( const pod::Skin& skin, const EncodingSettings& settings, const pod::Graph& graph ) {
|
||||
uf::Serializer json;
|
||||
json["name"] = skin.name;
|
||||
|
||||
@ -111,7 +106,7 @@ namespace {
|
||||
json["inverseBindMatrices"].emplace_back( uf::matrix::encode(inverseBindMatrix, settings) );
|
||||
return json;
|
||||
}
|
||||
uf::Serializer encode( const pod::Instance& instance, const EncodingSettings& settings ) {
|
||||
uf::Serializer encode( const pod::Instance& instance, const EncodingSettings& settings, const pod::Graph& graph ) {
|
||||
uf::Serializer json;
|
||||
json["model"] = uf::matrix::encode( instance.model, settings );
|
||||
json["color"] = uf::vector::encode( instance.color, settings );
|
||||
@ -126,7 +121,7 @@ namespace {
|
||||
|
||||
return json;
|
||||
}
|
||||
uf::Serializer encode( const pod::DrawCommand& drawCommand, const EncodingSettings& settings ) {
|
||||
uf::Serializer encode( const pod::DrawCommand& drawCommand, const EncodingSettings& settings, const pod::Graph& graph ) {
|
||||
uf::Serializer json;
|
||||
json["indices"] = drawCommand.indices;
|
||||
json["instances"] = drawCommand.instances;
|
||||
@ -138,34 +133,48 @@ namespace {
|
||||
json["vertices"] = drawCommand.vertices;
|
||||
return json;
|
||||
}
|
||||
uf::Serializer encode( const pod::Primitive& primitive, const EncodingSettings& settings ) {
|
||||
uf::Serializer encode( const pod::Primitive& primitive, const EncodingSettings& settings, const pod::Graph& graph ) {
|
||||
uf::Serializer json;
|
||||
json["drawCommand"] = encode( primitive.drawCommand, settings );
|
||||
json["instance"] = encode( primitive.instance, settings );
|
||||
json["drawCommand"] = encode( primitive.drawCommand, settings, graph );
|
||||
json["instance"] = encode( primitive.instance, settings, graph );
|
||||
return json;
|
||||
}
|
||||
uf::Serializer encode( const uf::Mesh& mesh, const EncodingSettings& settings ) {
|
||||
uf::Serializer encode( const uf::Mesh& mesh, const EncodingSettings& settings, const pod::Graph& graph ) {
|
||||
uf::Serializer json;
|
||||
#if 0
|
||||
uf::Mesh mesh = mesh;
|
||||
// remove extraneous buffers
|
||||
if ( !mesh.isInterleaved() ) {
|
||||
uf::stl::vector<size_t> remove; remove.reserve(mesh.vertex.attributes.size());
|
||||
|
||||
/*
|
||||
struct Attribute {
|
||||
ext::RENDERER::AttributeDescriptor descriptor;
|
||||
int32_t buffer = -1;
|
||||
size_t offset = 0;
|
||||
for ( size_t i = 0; i < mesh.vertex.attributes.size(); ++i ) {
|
||||
auto& attribute = mesh.vertex.attributes[i];
|
||||
if ( attribute.descriptor.name == "position" ) continue;
|
||||
if ( attribute.descriptor.name == "color" ) continue;
|
||||
if ( attribute.descriptor.name == "uv" ) continue;
|
||||
if ( attribute.descriptor.name == "st" ) continue;
|
||||
|
||||
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 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;
|
||||
*/
|
||||
if ( graph.metadata["flags"]["SKINNED"].as<bool>() ) {
|
||||
if ( attribute.descriptor.name == "tangent" ) continue;
|
||||
if ( attribute.descriptor.name == "joints" ) continue;
|
||||
if ( attribute.descriptor.name == "weights" ) continue;
|
||||
}
|
||||
#if !UF_USE_OPENGL
|
||||
if ( attribute.descriptor.name == "normal" ) continue;
|
||||
#endif
|
||||
|
||||
remove.insert(remove.begin(), i);
|
||||
}
|
||||
for ( auto& i : remove ) {
|
||||
// UF_MSG_DEBUG("Removing " << mesh.vertex.attributes[i].descriptor.name);
|
||||
mesh.buffers[mesh.vertex.attributes[i].buffer].clear();
|
||||
mesh.buffers[mesh.vertex.attributes[i].buffer].shrink_to_fit();
|
||||
mesh.vertex.attributes.erase(mesh.vertex.attributes.begin() + i);
|
||||
}
|
||||
} else {
|
||||
// UF_MSG_DEBUG("Attribute removal requested yet mesh is not interleaved, ignoring...");
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SERIALIZE_MESH(N) {\
|
||||
auto& input = json["inputs"][#N];\
|
||||
@ -203,7 +212,7 @@ namespace {
|
||||
}
|
||||
return json;
|
||||
}
|
||||
uf::Serializer encode( const pod::Node& node, const EncodingSettings& settings ) {
|
||||
uf::Serializer encode( const pod::Node& node, const EncodingSettings& settings, const pod::Graph& graph ) {
|
||||
uf::Serializer json;
|
||||
json["name"] = node.name;
|
||||
json["index"] = node.index;
|
||||
@ -239,7 +248,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
|
||||
};
|
||||
|
||||
if ( settings.encoding == "auto" ) settings.encoding = ext::json::PREFERRED_ENCODING;
|
||||
if ( settings.compression == "auto" ) settings.compression = ext::json::PREFERRED_COMPRESSION;
|
||||
if ( settings.compression == "auto" ) settings.compression = ext::json::PREFERRED_COMPRESSION;
|
||||
|
||||
if ( !settings.combined ) uf::io::mkdir(directory);
|
||||
#if UF_USE_XATLAS
|
||||
@ -258,7 +267,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
|
||||
for ( size_t i = 0; i < graph.instances.size(); ++i ) {
|
||||
auto& name = graph.instances[i];
|
||||
auto& instance = /*graph.storage*/uf::graph::storage.instances.map.at(name);
|
||||
uf::Serializer json = encode( instance, settings );
|
||||
uf::Serializer json = encode( instance, settings, graph );
|
||||
json["name"] = name;
|
||||
serializer["instances"].emplace_back( json );
|
||||
}
|
||||
@ -272,7 +281,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
|
||||
json["name"] = name;
|
||||
// ext::json::reserve( json["primitives"], primitives.size() );
|
||||
for ( auto& primitive : primitives ) {
|
||||
json["primitives"].emplace_back( encode( primitive, settings ) );
|
||||
json["primitives"].emplace_back( encode( primitive, settings, graph ) );
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -285,7 +294,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
|
||||
json["name"] = name;
|
||||
// ext::json::reserve( json["drawCommands"], drawCommands.size() );
|
||||
for ( auto& drawCommand : drawCommands ) {
|
||||
json["drawCommands"].emplace_back( encode( drawCommand, settings ) );
|
||||
json["drawCommands"].emplace_back( encode( drawCommand, settings, graph ) );
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -299,14 +308,14 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
|
||||
auto& mesh = /*graph.storage*/uf::graph::storage.meshes.map.at(name);
|
||||
if ( !s.encodeBuffers ) {
|
||||
s.filename = directory+"/mesh."+std::to_string(i)+".json";
|
||||
encode(mesh, s).writeToFile(s.filename);
|
||||
encode(mesh, s, graph).writeToFile(s.filename);
|
||||
uf::Serializer json;
|
||||
json["name"] = name;
|
||||
json["filename"] = uf::io::filename(s.filename);
|
||||
serializer["meshes"].emplace_back( json );
|
||||
} else {
|
||||
s.filename = directory+"/mesh."+std::to_string(i);
|
||||
auto json = encode(mesh, s);
|
||||
auto json = encode(mesh, s, graph);
|
||||
json["name"] = name;
|
||||
serializer["meshes"].emplace_back(json);
|
||||
}
|
||||
@ -314,7 +323,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
|
||||
} else {
|
||||
for ( auto& name : graph.meshes ) {
|
||||
auto& mesh = /*graph.storage*/uf::graph::storage.meshes.map.at(name);
|
||||
auto json = encode(mesh, settings);
|
||||
auto json = encode(mesh, settings, graph);
|
||||
json["name"] = name;
|
||||
serializer["meshes"].emplace_back(json);
|
||||
}
|
||||
@ -330,7 +339,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
|
||||
image.save(directory + "/atlas.png");
|
||||
serializer["atlas"] = "atlas.png";
|
||||
} else {
|
||||
serializer["atlas"] = encode(image, settings);
|
||||
serializer["atlas"] = encode(image, settings, graph);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -352,7 +361,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
|
||||
} else {
|
||||
for ( auto& name : graph.images ) {
|
||||
auto& image = /*graph.storage*/uf::graph::storage.images.map.at(name);
|
||||
auto json = encode(image, settings);
|
||||
auto json = encode(image, settings, graph);
|
||||
json["name"] = name;
|
||||
serializer["images"].emplace_back( json );
|
||||
}
|
||||
@ -363,7 +372,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
|
||||
ext::json::reserve( serializer["textures"], graph.textures.size() );
|
||||
for ( auto& name : graph.textures ) {
|
||||
auto& texture = /*graph.storage*/uf::graph::storage.textures.map.at(name);
|
||||
auto json = encode(texture, settings);
|
||||
auto json = encode(texture, settings, graph);
|
||||
json["name"] = name;
|
||||
serializer["textures"].emplace_back(json);
|
||||
}
|
||||
@ -373,7 +382,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
|
||||
ext::json::reserve( serializer["samplers"], graph.samplers.size() );
|
||||
for ( auto& name : graph.samplers ) {
|
||||
auto& sampler = /*graph.storage*/uf::graph::storage.samplers.map.at(name);
|
||||
auto json = encode(sampler, settings);
|
||||
auto json = encode(sampler, settings, graph);
|
||||
json["name"] = name;
|
||||
serializer["samplers"].emplace_back(json);
|
||||
}
|
||||
@ -383,7 +392,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
|
||||
ext::json::reserve( serializer["materials"], graph.materials.size() );
|
||||
for ( auto& name : graph.materials ) {
|
||||
auto& material = /*graph.storage*/uf::graph::storage.materials.map.at(name);
|
||||
auto json = encode(material, settings);
|
||||
auto json = encode(material, settings, graph);
|
||||
json["name"] = name;
|
||||
serializer["materials"].emplace_back(json);
|
||||
}
|
||||
@ -394,7 +403,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
|
||||
for ( auto pair : graph.lights ) {
|
||||
auto& name = pair.first;
|
||||
auto& light = pair.second;
|
||||
auto json = encode(light, settings);
|
||||
auto json = encode(light, settings, graph);
|
||||
json["name"] = name;
|
||||
serializer["lights"].emplace_back(json);
|
||||
}
|
||||
@ -407,13 +416,13 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
|
||||
auto& name = graph.animations[i];
|
||||
uf::stl::string f = "animation."+std::to_string(i)+".json";
|
||||
auto& animation = /*graph.storage*/uf::graph::storage.animations.map.at(name);
|
||||
encode(animation, settings).writeToFile(directory+"/"+f);
|
||||
encode(animation, settings, graph).writeToFile(directory+"/"+f);
|
||||
serializer["animations"].emplace_back(f);
|
||||
}
|
||||
} else {
|
||||
for ( auto& name : graph.animations ) {
|
||||
auto& animation = /*graph.storage*/uf::graph::storage.animations.map.at(name);
|
||||
serializer["animations"][name] = encode(animation, settings);
|
||||
serializer["animations"][name] = encode(animation, settings, graph);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -422,14 +431,14 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
|
||||
ext::json::reserve( serializer["skins"], graph.skins.size() );
|
||||
for ( auto& name : graph.skins ) {
|
||||
auto& skin = /*graph.storage*/uf::graph::storage.skins.map.at(name);
|
||||
serializer["skins"].emplace_back( encode(skin, settings) );
|
||||
serializer["skins"].emplace_back( encode(skin, settings, graph) );
|
||||
}
|
||||
});
|
||||
jobs.emplace_back([&]{
|
||||
// store node information
|
||||
ext::json::reserve( serializer["nodes"], graph.nodes.size() );
|
||||
for ( auto& node : graph.nodes ) serializer["nodes"].emplace_back( encode(node, settings) );
|
||||
serializer["root"] = encode(graph.root, settings);
|
||||
for ( auto& node : graph.nodes ) serializer["nodes"].emplace_back( encode(node, settings, graph) );
|
||||
serializer["root"] = encode(graph.root, settings, graph);
|
||||
});
|
||||
#if UF_GRAPH_LOAD_MULTITHREAD
|
||||
if ( !jobs.empty() ) uf::thread::batchWorkers_Async( jobs );
|
||||
@ -551,4 +560,5 @@ uf::Serializer uf::graph::stats( const pod::Graph& graph ) {
|
||||
*/
|
||||
#endif
|
||||
return json;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -22,6 +22,7 @@ UF_VERTEX_DESCRIPTOR(uf::graph::mesh::Base,
|
||||
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Base, R8G8B8A8_UNORM, color)
|
||||
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Base, R32G32_SFLOAT, st)
|
||||
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Base, R32G32B32_SFLOAT, normal)
|
||||
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Base, R16G16_UINT, id)
|
||||
);
|
||||
UF_VERTEX_DESCRIPTOR(uf::graph::mesh::Skinned,
|
||||
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R32G32B32_SFLOAT, position)
|
||||
@ -32,6 +33,7 @@ UF_VERTEX_DESCRIPTOR(uf::graph::mesh::Skinned,
|
||||
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R32G32B32_SFLOAT, tangent)
|
||||
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R16G16B16A16_UINT, joints)
|
||||
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R32G32B32A32_SFLOAT, weights)
|
||||
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R16G16_UINT, id)
|
||||
);
|
||||
|
||||
pod::Matrix4f uf::graph::local( pod::Graph& graph, int32_t index ) {
|
||||
|
||||
@ -19,6 +19,10 @@
|
||||
|
||||
#include <gltf/tiny_gltf.h>
|
||||
#include <uf/ext/gltf/gltf.h>
|
||||
|
||||
#if UF_USE_MESHOPT
|
||||
#include <uf/ext/meshopt/meshopt.h>
|
||||
#endif
|
||||
#if UF_USE_XATLAS
|
||||
#include <uf/ext/xatlas/xatlas.h>
|
||||
#endif
|
||||
@ -282,7 +286,6 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
|
||||
meshgrid.print = meshgrid.metadata["print"].as(meshgrid.print);
|
||||
meshgrid.cleanup = meshgrid.metadata["cleanup"].as(meshgrid.cleanup);
|
||||
}
|
||||
|
||||
|
||||
if ( graph.metadata["flags"]["SKINNED"].as<bool>() ) {
|
||||
#define UF_GRAPH_MESH_FORMAT uf::graph::mesh::Skinned, uint32_t
|
||||
@ -298,75 +301,6 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
|
||||
#undef UF_GRAPH_PROCESS_PRIMITIVES_FULL
|
||||
#undef UF_GRAPH_MESH_FORMAT
|
||||
}
|
||||
|
||||
#if 0
|
||||
if ( m.name == "worldspawn_20" ) {
|
||||
uf::stl::vector<::Primitive<>> objs;
|
||||
|
||||
#include "processPrimitives2.inl"
|
||||
|
||||
graph.primitives.emplace_back(keyName);
|
||||
graph.drawCommands.emplace_back(keyName);
|
||||
|
||||
auto& drawCommands = /*graph.storage*/uf::graph::storage.drawCommands[keyName];
|
||||
auto& primitives = /*graph.storage*/uf::graph::storage.primitives[keyName];
|
||||
auto& mesh = /*graph.storage*/uf::graph::storage.meshes[keyName];
|
||||
|
||||
mesh.bindIndirect<pod::DrawCommand>();
|
||||
mesh.bind<uf::graph::mesh::Skinned, uint32_t>();
|
||||
|
||||
size_t indexID = 0;
|
||||
size_t vertexID = 0;
|
||||
for ( auto& obj : objs ) {
|
||||
drawCommands.emplace_back(pod::DrawCommand{
|
||||
.indices = obj.indices.size(),
|
||||
.instances = 1,
|
||||
.indexID = indexID,
|
||||
.vertexID = vertexID,
|
||||
.instanceID = 0,
|
||||
|
||||
|
||||
.vertices = obj.vertices.size(),
|
||||
});
|
||||
|
||||
primitives.emplace_back( obj.primitive );
|
||||
|
||||
indexID += obj.indices.size();
|
||||
vertexID += obj.vertices.size();
|
||||
|
||||
mesh.insertVertices(obj.vertices);
|
||||
mesh.insertIndices(obj.indices);
|
||||
}
|
||||
|
||||
mesh.insertIndirects(drawCommands);
|
||||
mesh.updateDescriptor();
|
||||
} else {
|
||||
graph.primitives.emplace_back(keyName);
|
||||
graph.drawCommands.emplace_back(keyName);
|
||||
|
||||
auto& drawCommands = /*graph.storage*/uf::graph::storage.drawCommands[keyName];
|
||||
auto& primitives = /*graph.storage*/uf::graph::storage.primitives[keyName];
|
||||
auto& mesh = /*graph.storage*/uf::graph::storage.meshes[keyName];
|
||||
|
||||
mesh.bindIndirect<pod::DrawCommand>();
|
||||
|
||||
if ( graph.metadata["flags"]["SKINNED"].as<bool>() ) {
|
||||
mesh.bind<uf::graph::mesh::Skinned, uint32_t>();
|
||||
uf::stl::vector<uf::graph::mesh::Skinned> vertices;
|
||||
uf::stl::vector<uint32_t> indices;
|
||||
#define UF_GRAPH_PROCESS_PRIMITIVES_FULL 1
|
||||
#include "processPrimitives.inl"
|
||||
#undef UF_GRAPH_PROCESS_PRIMITIVES_FULL
|
||||
} else {
|
||||
mesh.bind<uf::graph::mesh::Base, uint32_t>();
|
||||
uf::stl::vector<uf::graph::mesh::Base> vertices;
|
||||
uf::stl::vector<uint32_t> indices;
|
||||
#include "processPrimitives.inl"
|
||||
}
|
||||
mesh.insertIndirects(drawCommands);
|
||||
mesh.updateDescriptor();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
// load skins
|
||||
@ -530,14 +464,50 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
|
||||
texture.index = atlasImageIndex;
|
||||
}
|
||||
}
|
||||
// generate STs
|
||||
#if UF_USE_XATLAS
|
||||
if ( graph.metadata["exporter"]["unwrap"].as<bool>() ) {
|
||||
// generate STs
|
||||
if ( graph.metadata["exporter"]["unwrap"].as<bool>(true) ) {
|
||||
UF_MSG_DEBUG( "Generating ST's..." );
|
||||
size_t atlases = ext::xatlas::unwrap( graph );
|
||||
UF_MSG_DEBUG( "Generated ST's for " << atlases << " lightmaps" );
|
||||
}
|
||||
#endif
|
||||
#if UF_USE_MESHOPT
|
||||
// cleanup if blender's exporter is poopy
|
||||
if ( graph.metadata["exporter"]["optimize"].as<bool>(true) || graph.metadata["exporter"]["optimize"].as<uf::stl::string>("") == "tagged" ) {
|
||||
UF_MSG_DEBUG( "Optimizing meshes..." );
|
||||
for ( auto& keyName : graph.meshes ) {
|
||||
size_t level = SIZE_MAX;
|
||||
float simplify = 1.0f;
|
||||
|
||||
if ( graph.metadata["exporter"]["optimize"].as<uf::stl::string>("") == "tagged" ) {
|
||||
bool should = false;
|
||||
|
||||
ext::json::forEach( graph.metadata["tags"], [&]( const uf::stl::string& key, ext::json::Value& value ) {
|
||||
if ( ext::json::isNull( value["optimize mesh"] ) ) return;
|
||||
if ( uf::string::isRegex( key ) ) {
|
||||
if ( !uf::string::matched( keyName, key ) ) return;
|
||||
} else if ( keyName != key ) return;
|
||||
should = true;
|
||||
if ( ext::json::isObject( value["optimize mesh"] ) ) {
|
||||
level = value["optimize mesh"]["level"].as(level);
|
||||
simplify = value["optimize mesh"]["simplify"].as(simplify);
|
||||
}
|
||||
});
|
||||
|
||||
if ( !should ) continue;
|
||||
}
|
||||
|
||||
auto& mesh = /*graph.storage*/uf::graph::storage.meshes[keyName];
|
||||
UF_MSG_DEBUG("Optimizing mesh at level " << level << ": " << keyName);
|
||||
if ( !ext::meshopt::optimize( mesh, simplify, level ) ) {
|
||||
UF_MSG_ERROR("Mesh optimization failed: " << keyName );
|
||||
}
|
||||
}
|
||||
|
||||
UF_MSG_DEBUG( "Optimized mesh" );
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( graph.metadata["exporter"]["enabled"].as<bool>() ) {
|
||||
graph.name = uf::graph::save( graph, filename );
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
uf::stl::vector<uf::Meshlet_T<UF_GRAPH_MESH_FORMAT>> meshlets;
|
||||
|
||||
for ( auto& p : m.primitives ) {
|
||||
size_t primitiveID = meshlets.size();
|
||||
auto& meshlet = meshlets.emplace_back();
|
||||
|
||||
struct Attribute {
|
||||
@ -123,6 +124,9 @@ for ( auto& p : m.primitives ) {
|
||||
vertex.tangent.x = -vertex.tangent.x;
|
||||
#endif
|
||||
}
|
||||
|
||||
vertex.id.x = primitiveID;
|
||||
vertex.id.y = meshID;
|
||||
}
|
||||
|
||||
if ( p.indices > -1 ) {
|
||||
@ -155,10 +159,8 @@ for ( auto& p : m.primitives ) {
|
||||
#undef COPY_INDICES
|
||||
}
|
||||
|
||||
|
||||
|
||||
meshlet.primitive.instance.materialID = p.material;
|
||||
meshlet.primitive.instance.primitiveID = meshlets.size() - 1;
|
||||
meshlet.primitive.instance.primitiveID = primitiveID;
|
||||
meshlet.primitive.instance.meshID = meshID;
|
||||
meshlet.primitive.instance.objectID = 0;
|
||||
|
||||
|
||||
@ -1,126 +1,164 @@
|
||||
#include <uf/ext/meshopt/meshopt.h>
|
||||
#if UF_USE_MESHOPTIMIZER
|
||||
#include <meshoptimizer.h>
|
||||
#endif
|
||||
#if UF_USE_MESHOPT
|
||||
#include <meshoptimizer.h>
|
||||
|
||||
void ext::meshopt::optimize( uf::Mesh& mesh, size_t o ) {
|
||||
#if 0
|
||||
bool ext::meshopt::optimize( uf::Mesh& mesh, float simplify, size_t o ) {
|
||||
if ( mesh.isInterleaved() ) {
|
||||
UF_MSG_ERROR("optimization of interleaved meshes is currently not supported");
|
||||
return false;
|
||||
}
|
||||
mesh.updateDescriptor();
|
||||
|
||||
void* vertices = NULL;
|
||||
void* indices = NULL;
|
||||
size_t verticesCount = mesh.attributes.vertex.length;
|
||||
size_t indicesCount = mesh.attributes.index.length;
|
||||
struct Remap {
|
||||
uf::Mesh::Attribute attribute;
|
||||
uf::stl::vector<uint8_t> buffer;
|
||||
};
|
||||
|
||||
if ( !indicesCount ) mesh.generateIndices();
|
||||
if ( o == 0 ) {
|
||||
if ( !indicesCount ) {
|
||||
mesh.resizeIndices(verticesCount);
|
||||
switch ( mesh.attributes.index.size ) {
|
||||
case sizeof(uint32_t):
|
||||
for ( size_t i = 0; i < verticesCount; ++i ) ((uint32_t*) mesh.attributes.index.pointer)[i] = i;
|
||||
break;
|
||||
case sizeof(uint16_t):
|
||||
for ( size_t i = 0; i < verticesCount; ++i ) ((uint16_t*) mesh.attributes.index.pointer)[i] = i;
|
||||
break;
|
||||
case sizeof(uint8_t):
|
||||
for ( size_t i = 0; i < verticesCount; ++i ) ((uint8_t*) mesh.attributes.index.pointer)[i] = i;
|
||||
break;
|
||||
uf::stl::vector<Remap> attributes;
|
||||
uf::stl::vector<meshopt_Stream> streams;
|
||||
for ( auto& attribute : mesh.vertex.attributes ) {
|
||||
auto& p = attributes.emplace_back();
|
||||
p.attribute = attribute;
|
||||
|
||||
auto& stream = streams.emplace_back();
|
||||
stream.data = p.attribute.pointer;
|
||||
stream.size = p.attribute.descriptor.size;
|
||||
stream.stride = p.attribute.stride;
|
||||
}
|
||||
|
||||
size_t indicesCount = mesh.vertex.count;
|
||||
uf::stl::vector<uint32_t> remap(indicesCount);
|
||||
|
||||
size_t verticesCount = meshopt_generateVertexRemapMulti( &remap[0], NULL, indicesCount, indicesCount, &streams[0], streams.size() );
|
||||
|
||||
// generate new indices, as they're going to be specific to a region of vertices due to drawcommand shittery
|
||||
uf::stl::vector<uint32_t> indices(indicesCount);
|
||||
meshopt_remapIndexBuffer(&indices[0], NULL, indicesCount, &remap[0]);
|
||||
|
||||
//
|
||||
for ( auto& p : attributes ) {
|
||||
auto& buffer = p.buffer;
|
||||
buffer.resize(verticesCount * p.attribute.descriptor.size);
|
||||
|
||||
meshopt_remapVertexBuffer(&buffer[0], p.attribute.pointer, indicesCount, p.attribute.descriptor.size, &remap[0]);
|
||||
}
|
||||
//
|
||||
meshopt_optimizeVertexCache(&indices[0], &indices[0], indicesCount, verticesCount);
|
||||
//
|
||||
meshopt_optimizeVertexFetchRemap(&remap[0], &indices[0], indicesCount, verticesCount);
|
||||
//
|
||||
for ( auto& p : attributes ) {
|
||||
auto& buffer = p.buffer;
|
||||
p.attribute.pointer = &buffer[0];
|
||||
|
||||
meshopt_remapVertexBuffer(p.attribute.pointer, p.attribute.pointer, verticesCount, p.attribute.descriptor.size, &remap[0]);
|
||||
}
|
||||
// almost always causes ID discontinuities
|
||||
if ( 0.0f < simplify && simplify < 1.0f ) {
|
||||
uf::stl::vector<uint32_t> indicesSimplified(indicesCount);
|
||||
|
||||
uf::Mesh::Attribute positionAttribute;
|
||||
for ( auto& p : attributes ) if ( p.attribute.descriptor.name == "position" ) positionAttribute = p.attribute;
|
||||
|
||||
size_t targetIndices = indicesCount * simplify;
|
||||
float targetError = 1e-2f / simplify;
|
||||
|
||||
float realError = 0.0f;
|
||||
// size_t realIndices = meshopt_simplify(&indicesSimplified[0], &indices[0], indicesCount, (float*) positionAttribute.pointer, verticesCount, positionAttribute.stride, targetError, realError);
|
||||
size_t realIndices = meshopt_simplifySloppy(&indicesSimplified[0], &indices[0], indicesCount, (float*) positionAttribute.pointer, verticesCount, positionAttribute.stride, targetIndices);
|
||||
|
||||
UF_MSG_DEBUG("[Simplified] indices: " << indicesCount << " -> " << realIndices << " | error: " << targetError << " -> " << realError);
|
||||
|
||||
indicesCount = realIndices;
|
||||
indices.swap( indicesSimplified );
|
||||
}
|
||||
// done
|
||||
if ( mesh.indirect.count ) {
|
||||
bool discontinuityDetected = false;
|
||||
size_t lastID = 0;
|
||||
struct Remap {
|
||||
pod::DrawCommand* drawCommand;
|
||||
struct {
|
||||
size_t start = SIZE_MAX;
|
||||
size_t end = 0;
|
||||
} index, vertex;
|
||||
};
|
||||
|
||||
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data();
|
||||
uf::stl::vector<Remap> remappedDrawCommands( mesh.indirect.count );
|
||||
|
||||
uf::Mesh::Attribute idAttribute;
|
||||
for ( auto& p : attributes ) if ( p.attribute.descriptor.name == "id" ) idAttribute = p.attribute;
|
||||
for ( size_t index = 0; index < indicesCount; ++index ) {
|
||||
size_t vertex = indices[index];
|
||||
pod::Vector<uint16_t,2>& id = *(pod::Vector<uint16_t,2>*) ( static_cast<uint8_t*>(idAttribute.pointer) + idAttribute.stride * vertex );
|
||||
|
||||
auto& d = remappedDrawCommands[id.x];
|
||||
d.drawCommand = &drawCommands[id.x];
|
||||
d.vertex.start = std::min( d.vertex.start, vertex );
|
||||
d.vertex.end = std::max( d.vertex.end, vertex );
|
||||
|
||||
d.index.start = std::min( d.index.start, index );
|
||||
d.index.end = std::max( d.index.end, index );
|
||||
|
||||
if ( lastID == id.x ) {
|
||||
|
||||
} else if ( lastID + 1 == id.x ) {
|
||||
lastID = id.x;
|
||||
} else {
|
||||
UF_MSG_DEBUG("Discontinuity detected: " << index << " | " << vertex << " | " << lastID << " | " << id.x);
|
||||
discontinuityDetected = true;
|
||||
lastID = id.x;
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
if ( discontinuityDetected ) {
|
||||
UF_MSG_ERROR("Discontinuity detected, bailing...");
|
||||
return false;
|
||||
}
|
||||
|
||||
for ( auto& d : remappedDrawCommands ) {
|
||||
d.drawCommand->indices = d.index.end - d.index.start + 1;
|
||||
d.drawCommand->indexID = d.index.start;
|
||||
d.drawCommand->vertexID = d.vertex.start;
|
||||
d.drawCommand->vertices = d.vertex.end - d.vertex.start + 1;
|
||||
}
|
||||
|
||||
for ( size_t index = 0; index < indicesCount; ++index ) {
|
||||
auto& vertex = indices[index];
|
||||
pod::Vector<uint16_t,2>& id = *(pod::Vector<uint16_t,2>*) ( static_cast<uint8_t*>(idAttribute.pointer) + idAttribute.stride * vertex );
|
||||
|
||||
auto& d = remappedDrawCommands[id.x];
|
||||
vertex -= d.vertex.start;
|
||||
}
|
||||
}
|
||||
|
||||
mesh.index.count = indicesCount;
|
||||
mesh.vertex.count = verticesCount;
|
||||
|
||||
// vertices
|
||||
for ( size_t i = 0; i < attributes.size(); ++i ) {
|
||||
auto& attribute = mesh.vertex.attributes[i];
|
||||
auto& remapped = attributes[i];
|
||||
|
||||
mesh.buffers[attribute.buffer].swap( remapped.buffer );
|
||||
attribute.pointer = mesh.buffers[attribute.buffer].data();
|
||||
}
|
||||
|
||||
// indices
|
||||
{
|
||||
vertices = malloc(verticesCount * mesh.attributes.vertex.size);
|
||||
memcpy( vertices, mesh.attributes.vertex.pointer, verticesCount );
|
||||
}
|
||||
if ( indicesCount > 0 ) {
|
||||
indices = malloc(indicesCount);
|
||||
memcpy( indices, mesh.attributes.index.pointer, indicesCount );
|
||||
mesh.resizeIndices( mesh.index.count );
|
||||
uint8_t* pointer = (uint8_t*) mesh.getBuffer(mesh.index).data();
|
||||
for ( auto index = 0; index < indicesCount; ++index ) {
|
||||
switch ( mesh.index.size ) {
|
||||
case 1: (( uint8_t*) pointer)[index] = indices[index]; break;
|
||||
case 2: ((uint16_t*) pointer)[index] = indices[index]; break;
|
||||
case 4: ((uint32_t*) pointer)[index] = indices[index]; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uf::stl::vector<uint32_t> remap(verticesCount);
|
||||
verticesCount = meshopt_generateVertexRemap(&remap[0], (uint32_t*) indices, indicesCount ? indicesCount : verticesCount, (float*) vertices, verticesCount, mesh.attributes.vertex.size);
|
||||
|
||||
mesh.resizeIndices(indicesCount);
|
||||
mesh.resizeVertices(verticesCount);
|
||||
|
||||
meshopt_remapIndexBuffer((uint32_t*) mesh.attributes.index.pointer, (uint32_t*) indices, indicesCount, &remap[0]);
|
||||
meshopt_remapVertexBuffer(mesh.attributes.vertex.pointer, (float*) vertices, verticesCount, mesh.attributes.vertex.size, &remap[0]);
|
||||
|
||||
if ( vertices ) free(vertices);
|
||||
if ( indices ) free(indices);
|
||||
#endif
|
||||
#if 0
|
||||
auto vertices = std::move( this->vertices );
|
||||
size_t valueCount = vertices.size();
|
||||
|
||||
uf::stl::vector<uint32_t> remap(valueCount);
|
||||
size_t verticesCount = meshopt_generateVertexRemap(&remap[0], NULL, valueCount, &vertices[0], valueCount, sizeof(T));
|
||||
|
||||
this->indices.resize(valueCount);
|
||||
meshopt_remapIndexBuffer(&this->indices[0], NULL, valueCount, &remap[0]);
|
||||
//meshopt_remapIndexBuffer(&this->indices[0], (const U*) NULL, indices, &remap[0]);
|
||||
this->vertices.resize(verticesCount);
|
||||
meshopt_remapVertexBuffer(&this->vertices[0], &vertices[0], valueCount, sizeof(T), &remap[0]);
|
||||
|
||||
size_t verticesCount = this->vertices.size();
|
||||
size_t indicesCount = this->indices.size();
|
||||
if ( indicesCount == 0 ) indicesCount = verticesCount;
|
||||
|
||||
auto vertices = std::move( this->vertices );
|
||||
auto indices = std::move( this->indices );
|
||||
|
||||
uf::stl::vector<uint32_t> remap(indicesCount);
|
||||
verticesCount = meshopt_generateVertexRemap(&remap[0], &indices[0], indicesCount, &vertices[0], verticesCount, sizeof(T));
|
||||
|
||||
this->indices.resize(indicesCount);
|
||||
this->vertices.resize(verticesCount);
|
||||
|
||||
meshopt_remapIndexBuffer(&this->indices[0], &indices[0], indicesCount, &remap[0]);
|
||||
meshopt_remapVertexBuffer(&this->vertices[0], &vertices[0], verticesCount, sizeof(T), &remap[0]);
|
||||
#endif
|
||||
#if 0
|
||||
// optimize for cache
|
||||
if ( o >= 2 ) {
|
||||
meshopt_optimizeVertexCache(mesh.attributes.index.pointer, mesh.attributes.index.pointer, mesh.attributes.index.length, mesh.attributes.vertex.length);
|
||||
}
|
||||
// optimize for overdraw
|
||||
if ( o >= 3 ) {
|
||||
const float kOverdrawThreshold = 3.f;
|
||||
meshopt_optimizeOverdraw(mesh.attributes.index.pointer, mesh.attributes.index.pointer, mesh.attributes.index.length, (float*) mesh.attributes.vertex.pointer.position, mesh.attributes.vertex.length, sizeof(T), kOverdrawThreshold);
|
||||
}
|
||||
// optimize for fetch
|
||||
if ( o >= 4 ) {
|
||||
meshopt_optimizeVertexFetch(mesh.attributes.vertex.pointer, mesh.attributes.index.pointer, mesh.attributes.index.length, mesh.attributes.vertex.pointer, mesh.attributes.vertex.length, mesh.attributes.vertex.size);
|
||||
}
|
||||
#endif
|
||||
mesh.updateDescriptor();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
auto vertices = std::move( this->vertices );
|
||||
U indices = vertices.size();
|
||||
|
||||
uf::stl::vector<uint32_t> remap(indices);
|
||||
size_t verticesCount = meshopt_generateVertexRemap(&remap[0], NULL, indices, &vertices[0], indices, sizeof(T));
|
||||
|
||||
this->indices.resize(indices);
|
||||
//meshopt_remapIndexBuffer(&this->indices[0], NULL, indices, &remap[0]);
|
||||
meshopt_remapIndexBuffer(&this->indices[0], (const U*) NULL, indices, &remap[0]);
|
||||
this->vertices.resize(verticesCount);
|
||||
meshopt_remapVertexBuffer(&this->vertices[0], &vertices[0], indices, sizeof(T), &remap[0]);
|
||||
// optimize for cache
|
||||
if ( o >= 1 ) {
|
||||
meshopt_optimizeVertexCache(&this->indices[0], &this->indices[0], this->indices.size(), this->vertices.size());
|
||||
}
|
||||
// optimize for overdraw
|
||||
if ( o >= 2 ) {
|
||||
const float kOverdrawThreshold = 3.f;
|
||||
meshopt_optimizeOverdraw(&this->indices[0], &this->indices[0], this->indices.size(), (float*) &this->vertices[0].position, this->vertices.size(), sizeof(T), kOverdrawThreshold);
|
||||
}
|
||||
// optimize for fetch
|
||||
if ( o >= 3 ) {
|
||||
meshopt_optimizeVertexFetch(&this->vertices[0], &this->indices[0], this->indices.size(), &this->vertices[0], this->vertices.size(), sizeof(T));
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
@ -232,11 +232,21 @@ namespace {
|
||||
|
||||
void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::InfoDraw& drawInfo ) {
|
||||
pod::Matrix4f modelView = uf::matrix::identity(), projection = uf::matrix::identity();
|
||||
|
||||
if ( drawInfo.matrices.model && drawInfo.matrices.view ) modelView = uf::matrix::multiply( *drawInfo.matrices.view, *drawInfo.matrices.model );
|
||||
else if ( drawInfo.matrices.model ) modelView = *drawInfo.matrices.model;
|
||||
else if ( drawInfo.matrices.view ) modelView = *drawInfo.matrices.view;
|
||||
|
||||
if ( drawInfo.matrices.projection ) projection = *drawInfo.matrices.projection;
|
||||
|
||||
#if 0
|
||||
{
|
||||
if ( drawInfo.matrices.model ) UF_MSG_DEBUG( "model: " << drawInfo.matrices.model << " " << uf::matrix::toString( *drawInfo.matrices.model ) );
|
||||
if ( drawInfo.matrices.view ) UF_MSG_DEBUG( "view: " << drawInfo.matrices.view << " " << uf::matrix::toString( *drawInfo.matrices.view ) );
|
||||
if ( drawInfo.matrices.projection ) UF_MSG_DEBUG( "projection: " << drawInfo.matrices.projection << " " << uf::matrix::toString( *drawInfo.matrices.projection ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( drawInfo.attributes.indirect.pointer && drawInfo.attributes.indirect.length == sizeof(pod::DrawCommand) ) {
|
||||
pod::DrawCommand& drawCommand = *(pod::DrawCommand*) drawInfo.attributes.indirect.pointer;
|
||||
if ( ext::opengl::settings::experimental::culling && drawInfo.attributes.instance.pointer && drawInfo.attributes.instance.length == sizeof(pod::Instance) ) {
|
||||
|
||||
@ -357,8 +357,10 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, const GraphicDe
|
||||
}
|
||||
|
||||
auto uniformBufferIt = uniformBuffers.begin();
|
||||
auto uniformBuffer = (*uniformBufferIt++).buffer;
|
||||
auto uniformBuffer = (*uniformBufferIt).buffer;
|
||||
auto uniformBufferSize = (*uniformBufferIt).range;
|
||||
pod::Camera::Viewports* viewports = (pod::Camera::Viewports*) device->getBuffer( uniformBuffer );
|
||||
pod::Uniform* viewports2 = (pod::Uniform*) device->getBuffer( uniformBuffer );
|
||||
|
||||
CommandBuffer::InfoDraw drawCommandInfoBase = {};
|
||||
drawCommandInfoBase.type = ext::opengl::enums::Command::DRAW;
|
||||
@ -373,10 +375,14 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, const GraphicDe
|
||||
}
|
||||
|
||||
drawCommandInfoBase.attributes.index = descriptor.inputs.index.attributes.front();
|
||||
drawCommandInfoBase.matrices.view = &viewports->matrices[0].view;
|
||||
drawCommandInfoBase.matrices.projection = &viewports->matrices[0].projection;
|
||||
if ( uniformBufferSize == sizeof(pod::Camera::Viewports) ) {
|
||||
drawCommandInfoBase.matrices.view = &viewports->matrices[0].view;
|
||||
drawCommandInfoBase.matrices.projection = &viewports->matrices[0].projection;
|
||||
} else if ( uniformBufferSize == sizeof(pod::Uniform) ) {
|
||||
drawCommandInfoBase.matrices.model = &viewports2->modelView;
|
||||
drawCommandInfoBase.matrices.projection = &viewports2->projection;
|
||||
}
|
||||
|
||||
#if 1
|
||||
if ( descriptor.inputs.indirect.count ) {
|
||||
auto& indirectAttribute = descriptor.inputs.indirect.attributes.front();
|
||||
|
||||
@ -406,22 +412,6 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, const GraphicDe
|
||||
auto& infos = pool[textureID];
|
||||
|
||||
CommandBuffer::InfoDraw& drawCommandInfo = infos.emplace_back( drawCommandInfoBase );
|
||||
/*
|
||||
drawCommandInfo.type = ext::opengl::enums::Command::DRAW;
|
||||
drawCommandInfo.descriptor = descriptor;
|
||||
drawCommandInfo.attributes.index = descriptor.inputs.index.attributes.front();
|
||||
for ( uf::Mesh::Attribute attribute : descriptor.inputs.vertex.attributes ) {
|
||||
if ( attribute.descriptor.name == "position" ) drawCommandInfo.attributes.position = attribute;
|
||||
else if ( attribute.descriptor.name == "uv" ) drawCommandInfo.attributes.uv = attribute;
|
||||
else if ( attribute.descriptor.name == "st" ) drawCommandInfo.attributes.st = attribute;
|
||||
else if ( attribute.descriptor.name == "normal" ) drawCommandInfo.attributes.normal = attribute;
|
||||
else if ( attribute.descriptor.name == "color" ) drawCommandInfo.attributes.color = attribute;
|
||||
}
|
||||
|
||||
drawCommandInfo.attributes.index = descriptor.inputs.index.attributes.front();
|
||||
drawCommandInfo.matrices.view = &viewports->matrices[0].view;
|
||||
drawCommandInfo.matrices.projection = &viewports->matrices[0].projection;
|
||||
*/
|
||||
|
||||
drawCommandInfo.descriptor.inputs.index.first = drawCommand.indexID;
|
||||
drawCommandInfo.descriptor.inputs.index.count = drawCommand.indices;
|
||||
@ -447,41 +437,18 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, const GraphicDe
|
||||
auto texture2DID = textures[instance.lightmapID].index;
|
||||
drawCommandInfo.textures.secondary = this->material.textures.at(texture2DID).descriptor;
|
||||
}
|
||||
// if ( !optimize )
|
||||
commandBuffer.record(drawCommandInfo);
|
||||
}
|
||||
// if ( optimize ) for ( auto pair : pool ) for ( auto& info : pair.second ) commandBuffer.record(info);
|
||||
} else {
|
||||
} else {
|
||||
/*
|
||||
auto uniformBufferIt = uniformBuffers.begin();
|
||||
auto uniformBuffer = (*uniformBufferIt++).buffer;
|
||||
auto uniformOffset = (size_t) 0;
|
||||
|
||||
|
||||
CommandBuffer::InfoDraw drawCommandInfo = {};
|
||||
drawCommandInfo.type = ext::opengl::enums::Command::DRAW;
|
||||
drawCommandInfo.descriptor = descriptor;
|
||||
drawCommandInfo.attributes.index = descriptor.inputs.index.attributes.front();
|
||||
for ( auto& attribute : descriptor.inputs.vertex.attributes ) {
|
||||
if ( attribute.descriptor.name == "position" ) drawCommandInfo.attributes.position = attribute;
|
||||
else if ( attribute.descriptor.name == "uv" ) drawCommandInfo.attributes.uv = attribute;
|
||||
else if ( attribute.descriptor.name == "st" ) drawCommandInfo.attributes.st = attribute;
|
||||
else if ( attribute.descriptor.name == "normal" ) drawCommandInfo.attributes.normal = attribute;
|
||||
else if ( attribute.descriptor.name == "color" ) drawCommandInfo.attributes.color = attribute;
|
||||
}
|
||||
|
||||
drawCommandInfo.textures.primary = this->material.textures.front().descriptor;
|
||||
|
||||
if ( !uniformBuffers.empty() ) {
|
||||
pod::Uniform* uniforms = (pod::Uniform*) device->getBuffer( uniformBuffer );
|
||||
drawCommandInfo.matrices.model = NULL;
|
||||
drawCommandInfo.matrices.view = &uniforms->modelView;
|
||||
drawCommandInfo.matrices.projection = &uniforms->projection;
|
||||
}
|
||||
UF_MSG_DEBUG( viewports << " " << uniformBuffers.size() );
|
||||
if ( drawCommandInfoBase.matrices.model ) UF_MSG_DEBUG( "model: " << drawCommandInfoBase.matrices.model << " " << uf::matrix::toString( *drawCommandInfoBase.matrices.model ) );
|
||||
if ( drawCommandInfoBase.matrices.view ) UF_MSG_DEBUG( "view: " << drawCommandInfoBase.matrices.view << " " << uf::matrix::toString( *drawCommandInfoBase.matrices.view ) );
|
||||
if ( drawCommandInfoBase.matrices.projection ) UF_MSG_DEBUG( "projection: " << drawCommandInfoBase.matrices.projection << " " << uf::matrix::toString( *drawCommandInfoBase.matrices.projection ) );
|
||||
*/
|
||||
|
||||
commandBuffer.record(drawCommandInfoBase);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void ext::opengl::Graphic::destroy() {
|
||||
for ( auto& pair : pipelines ) pair.second.destroy();
|
||||
|
||||
@ -322,7 +322,8 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) {
|
||||
}
|
||||
// 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();
|
||||
// uint8_t* pointer = (uint8_t*) mesh.buffers[mesh.isInterleaved(mesh.index.interleaved) ? mesh.index.interleaved : mesh.index.attributes.front().buffer].data();
|
||||
uint8_t* pointer = (uint8_t*) mesh.getBuffer(mesh.index).data();
|
||||
for ( auto index = 0; index < xmesh.indexCount; ++index ) {
|
||||
switch ( mesh.index.size ) {
|
||||
case 1: (( uint8_t*) pointer)[index] = xmesh.indexArray[index]; break;
|
||||
|
||||
@ -40,6 +40,7 @@ namespace {
|
||||
uf::stl::unordered_map<uf::stl::string, uf::stl::unordered_map<uf::stl::string, uf::Glyph>> cache;
|
||||
} glyphs;
|
||||
#endif
|
||||
|
||||
uf::stl::string defaultRenderMode = "Gui";
|
||||
uf::Serializer defaultSettings;
|
||||
|
||||
@ -342,18 +343,16 @@ void ext::Gui::load( const uf::Image& image ) {
|
||||
if ( ext::json::isNull(metadataJson["projection"]) ) metadataJson["projection"] = false;
|
||||
if ( ext::json::isNull(metadataJson["flip uv"]) ) metadataJson["flip uv"] = true;
|
||||
if ( ext::json::isNull(metadataJson["front face"]) ) metadataJson["front face"] = "ccw";
|
||||
#if UF_USE_OPENGL
|
||||
metadataJson["cull mode"] = "back";
|
||||
// metadataJson["depth test"]["test"] = false;
|
||||
// metadataJson["depth test"]["write"] = true;
|
||||
// if ( metadataJson["flip uv"].is<bool>() ) metadataJson["flip uv"] = !metadataJson["flip uv"].as<bool>();
|
||||
#endif
|
||||
} else {
|
||||
if ( ext::json::isNull(metadataJson["projection"]) ) metadataJson["projection"] = true;
|
||||
if ( ext::json::isNull(metadataJson["flip uv"]) ) metadataJson["flip uv"] = false;
|
||||
if ( ext::json::isNull(metadataJson["front face"]) ) metadataJson["front face"] = "cw";
|
||||
}
|
||||
metadataJson["cull mode"] = "none";
|
||||
|
||||
if ( metadataJson["world"].as<bool>() ) {
|
||||
|
||||
}
|
||||
|
||||
graphic.descriptor.parse( metadataJson );
|
||||
if ( uf::matrix::reverseInfiniteProjection ) {
|
||||
} else {
|
||||
@ -752,9 +751,10 @@ void ext::GuiBehavior::tick( uf::Object& self ) {
|
||||
|
||||
bool isGlyph = this->hasComponent<ext::GuiBehavior::GlyphMetadata>();
|
||||
#if UF_USE_OPENGL
|
||||
auto model = uf::matrix::identity();
|
||||
auto model = transform.model;
|
||||
auto& shader = graphic.material.getShader("vertex");
|
||||
pod::Uniform uniform;
|
||||
|
||||
if ( metadata.mode == 1 ) {
|
||||
uniform.modelView = transform.model;
|
||||
uniform.projection = uf::matrix::identity();
|
||||
@ -764,7 +764,6 @@ void ext::GuiBehavior::tick( uf::Object& self ) {
|
||||
auto& camera = controller.getComponent<uf::Camera>();
|
||||
uniform.modelView = camera.getView() * uf::transform::model( transform );
|
||||
uniform.projection = camera.getProjection();
|
||||
model = uniform.modelView;
|
||||
} else if ( metadata.mode == 3 ) {
|
||||
pod::Transform<> flatten = uf::transform::flatten( transform );
|
||||
uniform.modelView =
|
||||
@ -773,19 +772,8 @@ void ext::GuiBehavior::tick( uf::Object& self ) {
|
||||
uf::quaternion::matrix( flatten.orientation ) *
|
||||
flatten.model;
|
||||
uniform.projection = camera.getProjection();
|
||||
model = uniform.modelView;
|
||||
} else {
|
||||
pod::Transform<> flatten = uf::transform::flatten( transform );
|
||||
model =
|
||||
uf::matrix::translate( uf::matrix::identity(), flatten.position ) *
|
||||
uf::matrix::scale( uf::matrix::identity(), flatten.scale ) *
|
||||
uf::quaternion::matrix( flatten.orientation ) *
|
||||
flatten.model;
|
||||
|
||||
flatten.position.y = -flatten.position.y;
|
||||
if ( isGlyph ) flatten.scale.y = -flatten.scale.y;
|
||||
|
||||
flatten.position.z = 1;
|
||||
uniform.modelView =
|
||||
uf::matrix::translate( uf::matrix::identity(), flatten.position ) *
|
||||
uf::matrix::scale( uf::matrix::identity(), flatten.scale ) *
|
||||
@ -793,7 +781,15 @@ void ext::GuiBehavior::tick( uf::Object& self ) {
|
||||
flatten.model;
|
||||
uniform.projection = uf::matrix::identity();
|
||||
}
|
||||
|
||||
shader.updateUniform( "UBO", (const void*) &uniform, sizeof(uniform) );
|
||||
pod::Uniform* uniformBuffer = (pod::Uniform*) shader.device->getBuffer(shader.getUniformBuffer("UBO").descriptor.buffer);
|
||||
#if 0
|
||||
UF_MSG_DEBUG( "buffer: " << uniformBuffer );
|
||||
UF_MSG_DEBUG( "modelView: " << &uniformBuffer->modelView << " " << uf::matrix::toString( uniformBuffer->modelView ) );
|
||||
UF_MSG_DEBUG( "projection: " << &uniformBuffer->projection << " " << uf::matrix::toString( uniformBuffer->projection ) );
|
||||
#endif
|
||||
|
||||
/*
|
||||
auto model = uf::matrix::identity();
|
||||
auto uniformBuffer = graphic.getUniform();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user