diff --git a/asset/json/scene_simple.json b/asset/json/scene_simple.json index d75d59ec..189e4924 100644 --- a/asset/json/scene_simple.json +++ b/asset/json/scene_simple.json @@ -2,16 +2,6 @@ "name": "SceneSimple", "default_texture_name": "albedo", "materials": [ - { - "name": "SceneSimpleMaterial", - "program_name": "SceneSimpleProgram", - "texture_names": [ - "apple_texture" - ], - "inner_names": [ - "Color" - ] - }, { "name": "CubeMapMaterial", "program_name": "CubeMapProgram", @@ -99,17 +89,6 @@ "negative_z": "asset/cubemap/positive_z.png" } }, - { - "name": "apple_texture", - "cubemap": "false", - "pixel_element_size": { - "value": "BYTE" - }, - "pixel_structure": { - "value": "RGB" - }, - "file_name": "asset/apple/color.jpg" - }, { "name": "albedo", "cubemap": "false", @@ -203,8 +182,7 @@ { "name": "AppleMesh", "parent": "mesh_holder", - "file_name": "apple.obj", - "material_name": "SceneSimpleMaterial", + "obj_file": "asset/model/apple.obj", "render_time_enum": "SCENE_RENDER_TIME" } ], diff --git a/include/frame/file/file_system.h b/include/frame/file/file_system.h index 56909da4..2f8496ca 100644 --- a/include/frame/file/file_system.h +++ b/include/frame/file/file_system.h @@ -1,10 +1,19 @@ #pragma once #include +#include namespace frame::file { +/** + * @brief Find the path to a file, this will avoid build directory. + * @param file: Basic search pattern for your file "asset/json/test.json". + * @return Full path to the file. + */ +std::filesystem::path FindFile( + std::filesystem::path file, + const std::vector& paths); /** * @brief Find the path to a file, this will avoid build directory. * @param file: Basic search pattern for your file "asset/json/test.json". diff --git a/include/frame/file/mtl.h b/include/frame/file/mtl.h new file mode 100644 index 00000000..7e6cf7ed --- /dev/null +++ b/include/frame/file/mtl.h @@ -0,0 +1,53 @@ +#pragma once + +#include +#include +#include +#include + +#include + +#include "frame/logger.h" + +namespace frame::file +{ + +// Structure to hold the material properties from the MTL file. +struct MtlMaterial +{ + std::string name; + std::string ambient_str; + glm::vec4 ambient_vec4; + std::string diffuse_str; + glm::vec4 diffuse_vec4; + std::string displacement_str; + std::string emmissive_str; + std::string metallic_str; + float metallic_val; + std::string normal_str; + std::string roughness_str; + float roughness_val; + std::string sheen_str; + float sheen_val; +}; + +// Mtl class to parse and store material information from a .mtl file. +class Mtl +{ + public: + // Constructor that takes the path to the .mtl file and a list of search + // paths for textures. + Mtl(const std::filesystem::path& path, + const std::vector& search_paths = {}); + // Get a material by name. + const MtlMaterial& GetMaterial(const std::string& name) const; + // Get all materials. + const std::vector& GetMaterials() const; + + private: + std::vector materials_; + std::map material_name_map_; + Logger& logger_ = Logger::GetInstance(); +}; + +} // End namespace frame::file. diff --git a/src/frame/file/CMakeLists.txt b/src/frame/file/CMakeLists.txt index 41fc1216..9f7287ea 100644 --- a/src/frame/file/CMakeLists.txt +++ b/src/frame/file/CMakeLists.txt @@ -4,9 +4,11 @@ add_library(FrameFile STATIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../include/frame/file/file_system.h ${CMAKE_CURRENT_SOURCE_DIR}/../../../include/frame/file/image_stb.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../../include/frame/file/mtl.h file_system.cpp image.cpp image.h + mtl.cpp obj.cpp obj.h ply.cpp diff --git a/src/frame/file/file_system.cpp b/src/frame/file/file_system.cpp index b6f06e9b..edd77a1f 100644 --- a/src/frame/file/file_system.cpp +++ b/src/frame/file/file_system.cpp @@ -93,6 +93,21 @@ std::filesystem::path FindDirectory(std::filesystem::path file) }); } +std::filesystem::path FindFile( + std::filesystem::path file, + const std::vector& paths) +{ + for (const auto& path : paths) + { + auto full_path = path / file; + if (std::filesystem::is_regular_file(full_path)) + { + return full_path; + } + } + return FindFile(file); +} + std::filesystem::path FindFile(std::filesystem::path file) { return FindElement(file, [](const std::filesystem::path& p) { diff --git a/src/frame/file/mtl.cpp b/src/frame/file/mtl.cpp new file mode 100644 index 00000000..e8cedb82 --- /dev/null +++ b/src/frame/file/mtl.cpp @@ -0,0 +1,140 @@ +#include "frame/file/mtl.h" + +#include +#include + +#include + +#include "frame/file/file_system.h" + +namespace frame::file +{ + +Mtl::Mtl(const std::filesystem::path& path, + const std::vector& search_paths) +{ + std::ifstream file(path); + if (!file.is_open()) + { + throw std::runtime_error( + std::format("Could not open file: {}", path.string())); + } + + std::string line; + MtlMaterial* current_material = nullptr; + + while (std::getline(file, line)) + { + std::istringstream iss(line); + std::string keyword; + iss >> keyword; + + if (keyword == "newmtl") + { + std::string name; + iss >> name; + materials_.emplace_back(); + current_material = &materials_.back(); + current_material->name = name; + material_name_map_[name] = materials_.size() - 1; + } + else if (current_material) + { + if (keyword == "map_Ka") + { + std::string texture_path; + iss >> texture_path; + current_material->ambient_str = + FindFile(texture_path, search_paths).string(); + } + else if (keyword == "Ka") + { + iss >> current_material->ambient_vec4.r >> + current_material->ambient_vec4.g >> + current_material->ambient_vec4.b; + } + else if (keyword == "map_Kd") + { + std::string texture_path; + iss >> texture_path; + current_material->diffuse_str = + FindFile(texture_path, search_paths).string(); + } + else if (keyword == "Kd") + { + iss >> current_material->diffuse_vec4.r >> + current_material->diffuse_vec4.g >> + current_material->diffuse_vec4.b; + } + else if (keyword == "map_disp" || keyword == "disp") + { + std::string texture_path; + iss >> texture_path; + current_material->displacement_str = + FindFile(texture_path, search_paths).string(); + } + else if (keyword == "map_Ke" || keyword == "Ke") + { + std::string texture_path; + iss >> texture_path; + current_material->emmissive_str = + FindFile(texture_path, search_paths).string(); + } + else if (keyword == "map_Pm" || keyword == "Pm") + { + std::string texture_path; + iss >> texture_path; + current_material->metallic_str = + FindFile(texture_path, search_paths).string(); + } + else if (keyword == "refl") + { + // Not supported yet. + } + else if (keyword == "norm") + { + std::string texture_path; + iss >> texture_path; + current_material->normal_str = + FindFile(texture_path, search_paths).string(); + } + else if (keyword == "map_Pr" || keyword == "Pr") + { + std::string texture_path; + iss >> texture_path; + current_material->roughness_str = + FindFile(texture_path, search_paths).string(); + } + else if (keyword == "map_Ps" || keyword == "Ps") + { + std::string texture_path; + iss >> texture_path; + current_material->sheen_str = + FindFile(texture_path, search_paths).string(); + } + else if (keyword == "d") + { + // alpha + iss >> current_material->diffuse_vec4.a; + current_material->ambient_vec4.a = + current_material->diffuse_vec4.a; + } + } + } +} + +const MtlMaterial& Mtl::GetMaterial(const std::string& name) const +{ + if (material_name_map_.count(name)) + { + return materials_[material_name_map_.at(name)]; + } + throw std::runtime_error(std::format("Material not found: {}", name)); +} + +const std::vector& Mtl::GetMaterials() const +{ + return materials_; +} + +} // End namespace frame::file. diff --git a/src/frame/file/obj.cpp b/src/frame/file/obj.cpp index 792df38a..093ce8b8 100644 --- a/src/frame/file/obj.cpp +++ b/src/frame/file/obj.cpp @@ -4,6 +4,7 @@ #include #define TINYOBJLOADER_IMPLEMENTATION // define this in only *one* .cc #include +#include #include #include "frame/file/file_system.h" @@ -11,8 +12,38 @@ namespace frame::file { -Obj::Obj(std::filesystem::path file_name) +Obj::Obj( + const std::filesystem::path& file_name, + const std::vector& search_paths) { + // First thing first, find the material file. + std::ifstream obj_file(file_name); + if (!obj_file.is_open()) + { + throw std::runtime_error( + std::format("Could not open file: {}", file_name.string())); + } + std::string line; + std::string mtl_file_name; + while (std::getline(obj_file, line)) + { + std::istringstream iss(line); + std::string keyword; + iss >> keyword; + if (keyword == "mtllib") + { + iss >> mtl_file_name; + break; + } + } + + if (!mtl_file_name.empty()) + { + auto mtl_path = FindFile(mtl_file_name, search_paths); + Mtl mtl(mtl_path, search_paths); + materials_ = mtl.GetMaterials(); + } + #ifdef TINY_OBJ_LOADER_V2 tinyobj::ObjReaderConfig reader_config; const auto pair = SplitFileDirectory(file_name); @@ -38,7 +69,6 @@ Obj::Obj(std::filesystem::path file_name) auto& attrib = reader.GetAttrib(); auto& shapes = reader.GetShapes(); - auto& materials = reader.GetMaterials(); #else tinyobj::attrib_t attrib; std::vector shapes; @@ -153,34 +183,6 @@ Obj::Obj(std::filesystem::path file_name) meshes_.push_back(mesh); } } - - for (const auto& material : materials) - { - ObjMaterial obj_material{}; - obj_material.name = material.name; - obj_material.ambient_str = material.ambient_texname; - obj_material.ambient_vec4 = glm::vec4( - material.ambient[0], - material.ambient[1], - material.ambient[2], - material.dissolve); - obj_material.diffuse_str = material.diffuse_texname; - obj_material.diffuse_vec4 = glm::vec4( - material.diffuse[0], - material.diffuse[1], - material.diffuse[2], - material.dissolve); - obj_material.displacement_str = material.displacement_texname; - obj_material.emmissive_str = material.emissive_texname; - obj_material.metallic_str = material.metallic_texname; - obj_material.metallic_val = material.metallic; - obj_material.normal_str = material.normal_texname; - obj_material.roughness_str = material.roughness_texname; - obj_material.roughness_val = material.roughness; - obj_material.sheen_str = material.sheen_texname; - obj_material.sheen_val = material.sheen; - materials_.emplace_back(obj_material); - } } Obj::~Obj() = default; diff --git a/src/frame/file/obj.h b/src/frame/file/obj.h index 8632f664..f8cb98de 100644 --- a/src/frame/file/obj.h +++ b/src/frame/file/obj.h @@ -5,6 +5,7 @@ #include #include +#include "frame/file/mtl.h" #include "frame/logger.h" namespace frame::file @@ -89,28 +90,6 @@ class ObjMesh bool has_texture_coordinates_ = false; }; -/** - * @class ObjMaterial - * @brief Material file that old information for material in an obj style. - */ -struct ObjMaterial -{ - std::string name; - glm::vec4 ambient_vec4 = glm::vec4(0.5f, 0.5f, 0.5f, 1.0f); - std::string ambient_str; - glm::vec4 diffuse_vec4 = glm::vec4(0.5f, 0.5f, 0.5f, 1.0f); - std::string diffuse_str; - std::string displacement_str; - float roughness_val = 0.0f; - std::string roughness_str; - float metallic_val = 0.0f; - std::string metallic_str; - float sheen_val = 0.0f; - std::string sheen_str; - std::string emmissive_str; - std::string normal_str; -}; - /** * @class Obj * @brief The class that will open an obj file and store data from it on the @@ -122,8 +101,10 @@ class Obj /** * @brief Constructor parse from an OBJ file. * @param file_name: File to be open. + * @param search_paths: Paths to search for MTL files in. */ - Obj(std::filesystem::path file_name); + Obj(const std::filesystem::path& file_name, + const std::vector& search_paths = {}); ~Obj(); public: @@ -140,7 +121,7 @@ class Obj * (*.mtl). * @return The materials that are in the file. */ - const std::vector& GetMaterials() const + const std::vector& GetMaterials() const { return materials_; } @@ -155,7 +136,7 @@ class Obj protected: std::vector meshes_ = {}; - std::vector materials_ = {}; + std::vector materials_ = {}; bool has_texture_coordinates_ = false; Logger& logger_ = Logger::GetInstance(); }; diff --git a/src/frame/json/parse_scene_tree.cpp b/src/frame/json/parse_scene_tree.cpp index 9f1e1166..dc3021f5 100644 --- a/src/frame/json/parse_scene_tree.cpp +++ b/src/frame/json/parse_scene_tree.cpp @@ -1,195 +1,195 @@ -#include "frame/json/parse_scene_tree.h" - -#include - -#include "frame/file/file_system.h" -#include "frame/file/obj.h" -#include "frame/json/parse_uniform.h" -#include "frame/node_camera.h" -#include "frame/node_light.h" -#include "frame/node_matrix.h" -#include "frame/node_static_mesh.h" -#include "frame/opengl/buffer.h" -#include "frame/opengl/file/load_static_mesh.h" -#include "frame/opengl/static_mesh.h" - -namespace frame::json -{ - -namespace -{ - -std::function GetFunctor( - LevelInterface& level) -{ - return [&level](const std::string& name) -> NodeInterface* { - auto maybe_id = level.GetIdFromName(name); - if (!maybe_id) - { - throw std::runtime_error(std::format("No id from name: {}", name)); - } - EntityId id = maybe_id; - return &level.GetSceneNodeFromId(id); - }; -} - -[[nodiscard]] bool ParseNodeMatrix( - LevelInterface& level, const proto::NodeMatrix& proto_scene_matrix) -{ - std::unique_ptr scene_matrix = nullptr; - // Determine if the node should behave as a rotation matrix. Older scene - // files didn't specify the matrix_type_enum but provided a quaternion when - // rotation was expected, so infer the rotation flag from either the proto - // field or the presence of a quaternion. - bool rotation = proto_scene_matrix.matrix_type_enum() == - proto::NodeMatrix::ROTATION_MATRIX || - proto_scene_matrix.has_quaternion(); - - if (proto_scene_matrix.has_matrix()) - { - scene_matrix = std::make_unique( - GetFunctor(level), - ParseUniform(proto_scene_matrix.matrix()), - rotation); - } - else if (proto_scene_matrix.has_quaternion()) - { - scene_matrix = std::make_unique( - GetFunctor(level), - ParseUniform(proto_scene_matrix.quaternion()), - rotation); - } - else - { - scene_matrix = std::make_unique( - GetFunctor(level), glm::mat4(1.0f), rotation); - } - - // In case the proto explicitly requested a rotation matrix but we passed - // "rotation" as false to the constructor (shouldn't happen, but for - // clarity), force the type here. - if (rotation) - { - scene_matrix->GetData().set_matrix_type_enum( - proto::NodeMatrix::ROTATION_MATRIX); - } - - scene_matrix->GetData().set_name(proto_scene_matrix.name()); - scene_matrix->SetParentName(proto_scene_matrix.parent()); - auto maybe_scene_id = level.AddSceneNode(std::move(scene_matrix)); - return static_cast(maybe_scene_id); -} - -[[nodiscard]] bool ParseNodeStaticMeshClearBuffer( - LevelInterface& level, const proto::NodeStaticMesh& proto_scene_static_mesh) -{ - auto node_interface = std::make_unique( - GetFunctor(level), proto_scene_static_mesh.clean_buffer()); - node_interface->GetData().set_name(proto_scene_static_mesh.name()); - auto maybe_scene_id = level.AddSceneNode(std::move(node_interface)); - if (!maybe_scene_id) - { - throw std::runtime_error("No scene Id."); - } - auto scene_id = maybe_scene_id; - auto& node = - dynamic_cast(level.GetSceneNodeFromId(scene_id)); - node.GetData().set_render_time_enum( - proto_scene_static_mesh.render_time_enum()); - level.AddMeshMaterialId( - scene_id, 0, proto_scene_static_mesh.render_time_enum()); - return true; -} - -[[nodiscard]] bool ParseNodeStaticMeshMeshEnum( - LevelInterface& level, const proto::NodeStaticMesh& proto_scene_static_mesh) -{ - if (proto_scene_static_mesh.mesh_enum() == proto::NodeStaticMesh::INVALID) - { - throw std::runtime_error("Didn't find any mesh file name or any enum."); - } - // In this case there is only one material per mesh. - EntityId mesh_id = 0; - switch (proto_scene_static_mesh.mesh_enum()) - { - case proto::NodeStaticMesh::CUBE: { - mesh_id = level.GetDefaultStaticMeshCubeId(); - break; - } - case proto::NodeStaticMesh::QUAD: { - mesh_id = level.GetDefaultStaticMeshQuadId(); - break; - } - default: { - throw std::runtime_error( - std::format( - "unknown mesh enum value: {}", - static_cast(proto_scene_static_mesh.mesh_enum()))); - } - } - const EntityId material_id = - level.GetIdFromName(proto_scene_static_mesh.material_name()); - auto& mesh = level.GetStaticMeshFromId(mesh_id); - mesh.GetData().set_render_primitive_enum( - proto_scene_static_mesh.render_primitive_enum()); - std::unique_ptr node_interface = - std::make_unique(GetFunctor(level), mesh_id); - node_interface->GetData().set_name(proto_scene_static_mesh.name()); - node_interface->SetParentName(proto_scene_static_mesh.parent()); - node_interface->GetData().set_material_name( - proto_scene_static_mesh.material_name()); - auto scene_id = level.AddSceneNode(std::move(node_interface)); - auto& node = - dynamic_cast(level.GetSceneNodeFromId(scene_id)); - node.GetData().set_render_time_enum( - proto_scene_static_mesh.render_time_enum()); - level.AddMeshMaterialId( - scene_id, material_id, proto_scene_static_mesh.render_time_enum()); - return true; -} - -[[nodiscard]] bool ParseNodeStaticMeshFileName( - LevelInterface& level, const proto::NodeStaticMesh& proto_scene_static_mesh) -{ - auto vec_node_mesh_id = opengl::file::LoadStaticMeshesFromFile( - level, - frame::file::FindFile( - "asset/model/" + proto_scene_static_mesh.file_name()), - proto_scene_static_mesh.name(), - proto_scene_static_mesh.material_name()); - if (vec_node_mesh_id.empty()) - { - return false; - } - int i = 0; +#include "frame/json/parse_scene_tree.h" + +#include + +#include "frame/file/file_system.h" +#include "frame/file/obj.h" +#include "frame/json/parse_uniform.h" +#include "frame/node_camera.h" +#include "frame/node_light.h" +#include "frame/node_matrix.h" +#include "frame/node_static_mesh.h" +#include "frame/opengl/buffer.h" +#include "frame/opengl/file/load_static_mesh.h" +#include "frame/opengl/static_mesh.h" + +namespace frame::json +{ + +namespace +{ + +std::function GetFunctor( + LevelInterface& level) +{ + return [&level](const std::string& name) -> NodeInterface* { + auto maybe_id = level.GetIdFromName(name); + if (!maybe_id) + { + throw std::runtime_error(std::format("No id from name: {}", name)); + } + EntityId id = maybe_id; + return &level.GetSceneNodeFromId(id); + }; +} + +[[nodiscard]] bool ParseNodeMatrix( + LevelInterface& level, const proto::NodeMatrix& proto_scene_matrix) +{ + std::unique_ptr scene_matrix = nullptr; + // Determine if the node should behave as a rotation matrix. Older scene + // files didn't specify the matrix_type_enum but provided a quaternion when + // rotation was expected, so infer the rotation flag from either the proto + // field or the presence of a quaternion. + bool rotation = proto_scene_matrix.matrix_type_enum() == + proto::NodeMatrix::ROTATION_MATRIX || + proto_scene_matrix.has_quaternion(); + + if (proto_scene_matrix.has_matrix()) + { + scene_matrix = std::make_unique( + GetFunctor(level), + ParseUniform(proto_scene_matrix.matrix()), + rotation); + } + else if (proto_scene_matrix.has_quaternion()) + { + scene_matrix = std::make_unique( + GetFunctor(level), + ParseUniform(proto_scene_matrix.quaternion()), + rotation); + } + else + { + scene_matrix = std::make_unique( + GetFunctor(level), glm::mat4(1.0f), rotation); + } + + // In case the proto explicitly requested a rotation matrix but we passed + // "rotation" as false to the constructor (shouldn't happen, but for + // clarity), force the type here. + if (rotation) + { + scene_matrix->GetData().set_matrix_type_enum( + proto::NodeMatrix::ROTATION_MATRIX); + } + + scene_matrix->GetData().set_name(proto_scene_matrix.name()); + scene_matrix->SetParentName(proto_scene_matrix.parent()); + auto maybe_scene_id = level.AddSceneNode(std::move(scene_matrix)); + return static_cast(maybe_scene_id); +} + +[[nodiscard]] bool ParseNodeStaticMeshClearBuffer( + LevelInterface& level, const proto::NodeStaticMesh& proto_scene_static_mesh) +{ + auto node_interface = std::make_unique( + GetFunctor(level), proto_scene_static_mesh.clean_buffer()); + node_interface->GetData().set_name(proto_scene_static_mesh.name()); + auto maybe_scene_id = level.AddSceneNode(std::move(node_interface)); + if (!maybe_scene_id) + { + throw std::runtime_error("No scene Id."); + } + auto scene_id = maybe_scene_id; + auto& node = + dynamic_cast(level.GetSceneNodeFromId(scene_id)); + node.GetData().set_render_time_enum( + proto_scene_static_mesh.render_time_enum()); + level.AddMeshMaterialId( + scene_id, 0, proto_scene_static_mesh.render_time_enum()); + return true; +} + +[[nodiscard]] bool ParseNodeStaticMeshMeshEnum( + LevelInterface& level, const proto::NodeStaticMesh& proto_scene_static_mesh) +{ + if (proto_scene_static_mesh.mesh_enum() == proto::NodeStaticMesh::INVALID) + { + throw std::runtime_error("Didn't find any mesh file name or any enum."); + } + // In this case there is only one material per mesh. + EntityId mesh_id = 0; + switch (proto_scene_static_mesh.mesh_enum()) + { + case proto::NodeStaticMesh::CUBE: { + mesh_id = level.GetDefaultStaticMeshCubeId(); + break; + } + case proto::NodeStaticMesh::QUAD: { + mesh_id = level.GetDefaultStaticMeshQuadId(); + break; + } + default: { + throw std::runtime_error( + std::format( + "unknown mesh enum value: {}", + static_cast(proto_scene_static_mesh.mesh_enum()))); + } + } + const EntityId material_id = + level.GetIdFromName(proto_scene_static_mesh.material_name()); + auto& mesh = level.GetStaticMeshFromId(mesh_id); + mesh.GetData().set_render_primitive_enum( + proto_scene_static_mesh.render_primitive_enum()); + std::unique_ptr node_interface = + std::make_unique(GetFunctor(level), mesh_id); + node_interface->GetData().set_name(proto_scene_static_mesh.name()); + node_interface->SetParentName(proto_scene_static_mesh.parent()); + node_interface->GetData().set_material_name( + proto_scene_static_mesh.material_name()); + auto scene_id = level.AddSceneNode(std::move(node_interface)); + auto& node = + dynamic_cast(level.GetSceneNodeFromId(scene_id)); + node.GetData().set_render_time_enum( + proto_scene_static_mesh.render_time_enum()); + level.AddMeshMaterialId( + scene_id, material_id, proto_scene_static_mesh.render_time_enum()); + return true; +} + +[[nodiscard]] bool ParseNodeStaticMeshFileName( + LevelInterface& level, const proto::NodeStaticMesh& proto_scene_static_mesh) +{ + auto vec_node_mesh_id = opengl::file::LoadStaticMeshesFromFile( + level, + frame::file::FindFile( + "asset/model/" + proto_scene_static_mesh.file_name()), + proto_scene_static_mesh.name(), + proto_scene_static_mesh.material_name()); + if (vec_node_mesh_id.empty()) + { + return false; + } + int i = 0; for (const auto& [node_id, material_id] : vec_node_mesh_id) - { + { auto& node = level.GetSceneNodeFromId(node_id); - auto& mesh = level.GetStaticMeshFromId(node.GetLocalMesh()); - mesh.GetData().set_file_name(proto_scene_static_mesh.file_name()); - mesh.GetData().set_render_primitive_enum( - proto_scene_static_mesh.render_primitive_enum()); - auto str = std::format("{}.{}", proto_scene_static_mesh.name(), i); - mesh.SetName(str); - auto& static_mesh_node = dynamic_cast(node); - static_mesh_node.GetData().set_file_name( - proto_scene_static_mesh.file_name()); - // Rename the node to match the reference name (without the 'Node.' - // prefix) so serialization will use the same identifier as the input - // file. - if (vec_node_mesh_id.size() == 1) - { - static_mesh_node.SetName(proto_scene_static_mesh.name()); - } - else - { - static_mesh_node.SetName(str); - } - node.SetParentName(proto_scene_static_mesh.parent()); - static_mesh_node.GetData().set_material_name( - proto_scene_static_mesh.material_name()); - static_mesh_node.GetData().set_render_time_enum( - proto_scene_static_mesh.render_time_enum()); + auto& mesh = level.GetStaticMeshFromId(node.GetLocalMesh()); + mesh.GetData().set_file_name(proto_scene_static_mesh.file_name()); + mesh.GetData().set_render_primitive_enum( + proto_scene_static_mesh.render_primitive_enum()); + auto str = std::format("{}.{}", proto_scene_static_mesh.name(), i); + mesh.SetName(str); + auto& static_mesh_node = dynamic_cast(node); + static_mesh_node.GetData().set_file_name( + proto_scene_static_mesh.file_name()); + // Rename the node to match the reference name (without the 'Node.' + // prefix) so serialization will use the same identifier as the input + // file. + if (vec_node_mesh_id.size() == 1) + { + static_mesh_node.SetName(proto_scene_static_mesh.name()); + } + else + { + static_mesh_node.SetName(str); + } + node.SetParentName(proto_scene_static_mesh.parent()); + static_mesh_node.GetData().set_material_name( + proto_scene_static_mesh.material_name()); + static_mesh_node.GetData().set_render_time_enum( + proto_scene_static_mesh.render_time_enum()); if (!material_id) { throw std::runtime_error(std::format( @@ -197,129 +197,179 @@ std::function GetFunctor( proto_scene_static_mesh.name(), proto_scene_static_mesh.file_name())); } - level.AddMeshMaterialId( + level.AddMeshMaterialId( node_id, - material_id, - proto_scene_static_mesh.render_time_enum()); - ++i; - } - return true; -} - -[[nodiscard]] bool ParseNodeStaticMeshStreamInput( - LevelInterface& level, const proto::NodeStaticMesh& proto_scene_static_mesh) -{ - assert(proto_scene_static_mesh.has_multi_plugin()); - auto point_buffer = std::make_unique( - opengl::BufferTypeEnum::ARRAY_BUFFER, - opengl::BufferUsageEnum::STREAM_DRAW); - point_buffer->SetName("point." + proto_scene_static_mesh.name()); - auto point_buffer_id = level.AddBuffer(std::move(point_buffer)); - auto normal_buffer = std::make_unique( - opengl::BufferTypeEnum::ARRAY_BUFFER, - opengl::BufferUsageEnum::STREAM_DRAW); - normal_buffer->SetName("normal." + proto_scene_static_mesh.name()); - auto normal_buffer_id = level.AddBuffer(std::move(normal_buffer)); - auto index_buffer = std::make_unique( - opengl::BufferTypeEnum::ELEMENT_ARRAY_BUFFER, - opengl::BufferUsageEnum::STREAM_DRAW); - index_buffer->SetName("index." + proto_scene_static_mesh.name()); - auto index_buffer_id = level.AddBuffer(std::move(index_buffer)); - auto color_buffer = std::make_unique( - opengl::BufferTypeEnum::ARRAY_BUFFER, - opengl::BufferUsageEnum::STREAM_DRAW); - color_buffer->SetName("color." + proto_scene_static_mesh.name()); - auto color_buffer_id = level.AddBuffer(std::move(color_buffer)); - - // Create a new static mesh. - StaticMeshParameter parameter = {}; - parameter.point_buffer_id = point_buffer_id; - parameter.normal_buffer_id = normal_buffer_id; - parameter.color_buffer_id = color_buffer_id; - parameter.index_buffer_id = index_buffer_id; - parameter.render_primitive_enum = proto::NodeStaticMesh::POINT_PRIMITIVE; - auto mesh = std::make_unique(level, parameter); - mesh->SetName("mesh." + proto_scene_static_mesh.name()); - auto mesh_id = level.AddStaticMesh(std::move(mesh)); - const EntityId material_id = - level.GetIdFromName(proto_scene_static_mesh.material_name()); - // Create the node corresponding to the mesh. - auto& mesh_ref = level.GetStaticMeshFromId(mesh_id); - mesh_ref.GetData().set_render_primitive_enum( - proto_scene_static_mesh.render_primitive_enum()); - std::unique_ptr node_interface = - std::make_unique(GetFunctor(level), mesh_id); - node_interface->GetData().set_name(proto_scene_static_mesh.name()); - node_interface->SetParentName(proto_scene_static_mesh.parent()); - node_interface->GetData().set_material_name( - proto_scene_static_mesh.material_name()); - auto scene_id = level.AddSceneNode(std::move(node_interface)); - auto& node = - dynamic_cast(level.GetSceneNodeFromId(scene_id)); - node.GetData().set_render_time_enum( - proto_scene_static_mesh.render_time_enum()); - level.AddMeshMaterialId( - scene_id, material_id, proto_scene_static_mesh.render_time_enum()); - if (!scene_id) - { - throw std::runtime_error("No scene Id."); - } - return true; -} - -[[nodiscard]] bool ParseNodeStaticMesh( - LevelInterface& level, const proto::NodeStaticMesh& proto_scene_static_mesh) -{ - // 1st case this is a clean static mesh node. - if (proto_scene_static_mesh.has_clean_buffer()) - { - return ParseNodeStaticMeshClearBuffer(level, proto_scene_static_mesh); - } - // 2nd case this is a enum static mesh node (CUBE or QUAD). - if (proto_scene_static_mesh.has_mesh_enum()) - { - return ParseNodeStaticMeshMeshEnum(level, proto_scene_static_mesh); - } - // 3rd case this is a mesh file. - if (proto_scene_static_mesh.has_file_name()) - { - return ParseNodeStaticMeshFileName(level, proto_scene_static_mesh); - } - // 4th case stream input. - if (proto_scene_static_mesh.has_multi_plugin()) - { - return ParseNodeStaticMeshStreamInput(level, proto_scene_static_mesh); - } - return false; -} - -[[nodiscard]] bool ParseNodeCamera( - LevelInterface& level, const frame::proto::NodeCamera& proto_scene_camera) -{ - if (proto_scene_camera.fov_degrees() == 0.0) - { - throw std::runtime_error("Need field of view degrees in camera."); - } - auto scene_camera = std::make_unique( - GetFunctor(level), - ParseUniform(proto_scene_camera.position()), - ParseUniform(proto_scene_camera.target()), - ParseUniform(proto_scene_camera.up()), - proto_scene_camera.fov_degrees(), - proto_scene_camera.aspect_ratio(), - proto_scene_camera.near_clip(), - proto_scene_camera.far_clip()); - scene_camera->GetData().set_name(proto_scene_camera.name()); - scene_camera->SetParentName(proto_scene_camera.parent()); - auto maybe_scene_id = level.AddSceneNode(std::move(scene_camera)); - return static_cast(maybe_scene_id); -} - -[[nodiscard]] bool ParseNodeLight( - LevelInterface& level, const proto::NodeLight& proto_scene_light) -{ - switch (proto_scene_light.light_type()) - { + material_id, + proto_scene_static_mesh.render_time_enum()); + ++i; + } + return true; +} + +[[nodiscard]] bool ParseNodeStaticMeshStreamInput( + LevelInterface& level, const proto::NodeStaticMesh& proto_scene_static_mesh) +{ + assert(proto_scene_static_mesh.has_multi_plugin()); + auto point_buffer = std::make_unique( + opengl::BufferTypeEnum::ARRAY_BUFFER, + opengl::BufferUsageEnum::STREAM_DRAW); + point_buffer->SetName("point." + proto_scene_static_mesh.name()); + auto point_buffer_id = level.AddBuffer(std::move(point_buffer)); + auto normal_buffer = std::make_unique( + opengl::BufferTypeEnum::ARRAY_BUFFER, + opengl::BufferUsageEnum::STREAM_DRAW); + normal_buffer->SetName("normal." + proto_scene_static_mesh.name()); + auto normal_buffer_id = level.AddBuffer(std::move(normal_buffer)); + auto index_buffer = std::make_unique( + opengl::BufferTypeEnum::ELEMENT_ARRAY_BUFFER, + opengl::BufferUsageEnum::STREAM_DRAW); + index_buffer->SetName("index." + proto_scene_static_mesh.name()); + auto index_buffer_id = level.AddBuffer(std::move(index_buffer)); + auto color_buffer = std::make_unique( + opengl::BufferTypeEnum::ARRAY_BUFFER, + opengl::BufferUsageEnum::STREAM_DRAW); + color_buffer->SetName("color." + proto_scene_static_mesh.name()); + auto color_buffer_id = level.AddBuffer(std::move(color_buffer)); + + // Create a new static mesh. + StaticMeshParameter parameter = {}; + parameter.point_buffer_id = point_buffer_id; + parameter.normal_buffer_id = normal_buffer_id; + parameter.color_buffer_id = color_buffer_id; + parameter.index_buffer_id = index_buffer_id; + parameter.render_primitive_enum = proto::NodeStaticMesh::POINT_PRIMITIVE; + auto mesh = std::make_unique(level, parameter); + mesh->SetName("mesh." + proto_scene_static_mesh.name()); + auto mesh_id = level.AddStaticMesh(std::move(mesh)); + const EntityId material_id = + level.GetIdFromName(proto_scene_static_mesh.material_name()); + // Create the node corresponding to the mesh. + auto& mesh_ref = level.GetStaticMeshFromId(mesh_id); + mesh_ref.GetData().set_render_primitive_enum( + proto_scene_static_mesh.render_primitive_enum()); + std::unique_ptr node_interface = + std::make_unique(GetFunctor(level), mesh_id); + node_interface->GetData().set_name(proto_scene_static_mesh.name()); + node_interface->SetParentName(proto_scene_static_mesh.parent()); + node_interface->GetData().set_material_name( + proto_scene_static_mesh.material_name()); + auto scene_id = level.AddSceneNode(std::move(node_interface)); + auto& node = + dynamic_cast(level.GetSceneNodeFromId(scene_id)); + node.GetData().set_render_time_enum( + proto_scene_static_mesh.render_time_enum()); + level.AddMeshMaterialId( + scene_id, material_id, proto_scene_static_mesh.render_time_enum()); + if (!scene_id) + { + throw std::runtime_error("No scene Id."); + } + return true; +} + +[[nodiscard]] bool ParseNodeStaticMesh( + LevelInterface& level, const proto::NodeStaticMesh& proto_scene_static_mesh) +{ + // 1st case this is a clean static mesh node. + if (proto_scene_static_mesh.has_clean_buffer()) + { + return ParseNodeStaticMeshClearBuffer(level, proto_scene_static_mesh); + } + // 2nd case this is a enum static mesh node (CUBE or QUAD). + if (proto_scene_static_mesh.has_mesh_enum()) + { + return ParseNodeStaticMeshMeshEnum(level, proto_scene_static_mesh); + } + // 3rd case this is a mesh file. + if (proto_scene_static_mesh.has_file_name()) + { + return ParseNodeStaticMeshFileName(level, proto_scene_static_mesh); + } + // 4th case this is a mesh obj file. + if (proto_scene_static_mesh.has_obj_file()) + { + auto vec_node_mesh_id = opengl::file::LoadStaticMeshesFromFile( + level, + frame::file::FindFile(proto_scene_static_mesh.obj_file()), + proto_scene_static_mesh.name()); + if (vec_node_mesh_id.empty()) + { + return false; + } + int i = 0; + for (const auto& [node_id, material_id] : vec_node_mesh_id) + { + auto& node = level.GetSceneNodeFromId(node_id); + auto& mesh = level.GetStaticMeshFromId(node.GetLocalMesh()); + mesh.GetData().set_file_name(proto_scene_static_mesh.obj_file()); + mesh.GetData().set_render_primitive_enum( + proto_scene_static_mesh.render_primitive_enum()); + auto str = std::format("{}.{}", proto_scene_static_mesh.name(), i); + mesh.SetName(str); + auto& static_mesh_node = dynamic_cast(node); + static_mesh_node.GetData().set_file_name( + proto_scene_static_mesh.obj_file()); + if (vec_node_mesh_id.size() == 1) + { + static_mesh_node.SetName(proto_scene_static_mesh.name()); + } + else + { + static_mesh_node.SetName(str); + } + node.SetParentName(proto_scene_static_mesh.parent()); + static_mesh_node.GetData().set_render_time_enum( + proto_scene_static_mesh.render_time_enum()); + if (!material_id) + { + throw std::runtime_error(std::format( + "No material found for mesh {} in file {}", + proto_scene_static_mesh.name(), + proto_scene_static_mesh.obj_file())); + } + level.AddMeshMaterialId( + node_id, + material_id, + proto_scene_static_mesh.render_time_enum()); + ++i; + } + return true; + } + // 5th case stream input. + if (proto_scene_static_mesh.has_multi_plugin()) + { + return ParseNodeStaticMeshStreamInput(level, proto_scene_static_mesh); + } + return false; +} + +[[nodiscard]] bool ParseNodeCamera( + LevelInterface& level, const frame::proto::NodeCamera& proto_scene_camera) +{ + if (proto_scene_camera.fov_degrees() == 0.0) + { + throw std::runtime_error("Need field of view degrees in camera."); + } + auto scene_camera = std::make_unique( + GetFunctor(level), + ParseUniform(proto_scene_camera.position()), + ParseUniform(proto_scene_camera.target()), + ParseUniform(proto_scene_camera.up()), + proto_scene_camera.fov_degrees(), + proto_scene_camera.aspect_ratio(), + proto_scene_camera.near_clip(), + proto_scene_camera.far_clip()); + scene_camera->GetData().set_name(proto_scene_camera.name()); + scene_camera->SetParentName(proto_scene_camera.parent()); + auto maybe_scene_id = level.AddSceneNode(std::move(scene_camera)); + return static_cast(maybe_scene_id); +} + +[[nodiscard]] bool ParseNodeLight( + LevelInterface& level, const proto::NodeLight& proto_scene_light) +{ + switch (proto_scene_light.light_type()) + { case proto::NodeLight::POINT_LIGHT: { EntityId node_id = NullId; auto node_light = std::make_unique( @@ -346,57 +396,57 @@ std::function GetFunctor( node_id = level.AddSceneNode(std::move(node_light)); return static_cast(node_id); } - case proto::NodeLight::AMBIENT_LIGHT: - [[fallthrough]]; - case proto::NodeLight::SPOT_LIGHT: - [[fallthrough]]; - case proto::NodeLight::INVALID_LIGHT: - [[fallthrough]]; - default: - throw std::runtime_error( - std::format( - "Unknown scene light type {}", - static_cast(proto_scene_light.light_type()))); - } - return false; -} - -} // End namespace. - -[[nodiscard]] bool ParseSceneTreeFile( - const proto::SceneTree& proto_scene_tree, LevelInterface& level) -{ - level.SetDefaultCameraName(proto_scene_tree.default_camera_name()); - level.SetDefaultRootSceneNodeName(proto_scene_tree.default_root_name()); - for (const auto& proto_matrix : proto_scene_tree.node_matrices()) - { - if (!ParseNodeMatrix(level, proto_matrix)) - { - return false; - } - } - for (const auto& proto_static_mesh : proto_scene_tree.node_static_meshes()) - { - if (!ParseNodeStaticMesh(level, proto_static_mesh)) - { - return false; - } - } - for (const auto& proto_camera : proto_scene_tree.node_cameras()) - { - if (!ParseNodeCamera(level, proto_camera)) - { - return false; - } - } - for (const auto& proto_light : proto_scene_tree.node_lights()) - { - if (!ParseNodeLight(level, proto_light)) - { - return false; - } - } - return true; -} - -} // End namespace frame::json. + case proto::NodeLight::AMBIENT_LIGHT: + [[fallthrough]]; + case proto::NodeLight::SPOT_LIGHT: + [[fallthrough]]; + case proto::NodeLight::INVALID_LIGHT: + [[fallthrough]]; + default: + throw std::runtime_error( + std::format( + "Unknown scene light type {}", + static_cast(proto_scene_light.light_type()))); + } + return false; +} + +} // End namespace. + +[[nodiscard]] bool ParseSceneTreeFile( + const proto::SceneTree& proto_scene_tree, LevelInterface& level) +{ + level.SetDefaultCameraName(proto_scene_tree.default_camera_name()); + level.SetDefaultRootSceneNodeName(proto_scene_tree.default_root_name()); + for (const auto& proto_matrix : proto_scene_tree.node_matrices()) + { + if (!ParseNodeMatrix(level, proto_matrix)) + { + return false; + } + } + for (const auto& proto_static_mesh : proto_scene_tree.node_static_meshes()) + { + if (!ParseNodeStaticMesh(level, proto_static_mesh)) + { + return false; + } + } + for (const auto& proto_camera : proto_scene_tree.node_cameras()) + { + if (!ParseNodeCamera(level, proto_camera)) + { + return false; + } + } + for (const auto& proto_light : proto_scene_tree.node_lights()) + { + if (!ParseNodeLight(level, proto_light)) + { + return false; + } + } + return true; +} + +} // End namespace frame::json. diff --git a/src/frame/opengl/file/load_static_mesh.cpp b/src/frame/opengl/file/load_static_mesh.cpp index 41a329a9..612f4c16 100644 --- a/src/frame/opengl/file/load_static_mesh.cpp +++ b/src/frame/opengl/file/load_static_mesh.cpp @@ -39,18 +39,18 @@ std::optional CreateBufferInLevel( } std::unique_ptr LoadTextureFromString( - const std::string& str, + const std::filesystem::path& path, const proto::PixelElementSize pixel_element_size, const proto::PixelStructure pixel_structure) { return std::make_unique( - frame::file::FindFile("asset/" + str), + path, pixel_element_size, pixel_structure); } std::optional LoadMaterialFromObj( - LevelInterface& level, const frame::file::ObjMaterial& material_obj) + LevelInterface& level, const frame::file::MtlMaterial& material_obj) { // Load textures. auto color = (material_obj.ambient_str.empty()) @@ -117,6 +117,11 @@ std::optional LoadMaterialFromObj( material->AddTextureId(metallic_id, metallic_name); // Finally add the material to the level. material->SetName(material_obj.name); + auto maybe_program_id = level.GetIdFromName("SceneSimpleProgram"); + if (maybe_program_id) + { + material->SetProgramId(*maybe_program_id); + } return level.AddMaterial(std::move(material)); } @@ -416,7 +421,7 @@ std::vector> LoadStaticMeshesFromObjFile( const std::string& material_name /* = ""*/) { std::vector> entity_id_vec; - frame::file::Obj obj(file); + frame::file::Obj obj(file, {file.parent_path(), "asset/model", "asset"}); const auto& meshes = obj.GetMeshes(); Logger& logger = Logger::GetInstance(); std::vector material_ids; diff --git a/src/frame/proto/scene.proto b/src/frame/proto/scene.proto index 7db2d8b8..fd1b2a86 100644 --- a/src/frame/proto/scene.proto +++ b/src/frame/proto/scene.proto @@ -1,187 +1,189 @@ -syntax = "proto3"; - -import "pixel.proto"; -import "math.proto"; -import "plugin.proto"; - -package frame.proto; - -// Scene is a way to load meshes. -// For now it only load them from obj, mtl files but ths will be able to load -// from fbx files as soon as we switch to this assimp library. This will add -// skeleton animation so a new type of mesh. - -// Matrix -// Next 6 -message NodeMatrix { - // This is the name of the scene matrix. - string name = 1; - // Give the name of the parent (if present). - string parent = 2; - - // Is it a rotation or a static move? - enum MatrixTypeEnum { - STATIC_MATRIX = 0; - ROTATION_MATRIX = 1; - } - MatrixTypeEnum matrix_type_enum = 5; - - // Could be a matrix or a quaternion. - oneof matrix_oneof { - UniformMatrix4 matrix = 3; - UniformVector4 quaternion = 4; - } -} - -// Static Mesh. -// Next 13 -message NodeStaticMesh { - // This is the name of the mesh. - string name = 1; - // Give the name of the parent (if present). - string parent = 2; - - // Different kind of rendering possible. - enum RenderPrimitiveEnum { - TRIANGLE_PRIMITIVE = 0; //< default! - POINT_PRIMITIVE = 1; - LINE_PRIMITIVE = 2; - } - // What kind of rendering is required (default = triangle). - RenderPrimitiveEnum render_primitive_enum = 8; - - // Some mesh are included? - enum MeshEnum { - INVALID = 0; - CUBE = 1; - QUAD = 2; - } - // Can only have one of the 3 cases mesh_enum, file_name or stream_input. - oneof mesh_oneof { - // If any of the clean buffer is activated, then only this is used! - CleanBuffer clean_buffer = 7; - // This can be a static mesh enum. - MeshEnum mesh_enum = 6; - // Where the file is loaded from. - string file_name = 3; - // Plugin input. - MultiPlugin multi_plugin = 10; - } - - // Material name. - string material_name = 5; - - // Render time enum. - enum RenderTimeEnum { - // This will be rendered at all frames (this is default). - SCENE_RENDER_TIME = 0; - // This will be pre-rendered only once at the beginning. - PRE_RENDER_TIME = 1; - // This will be post-rendered at the end of every frame. - POST_PROCESS_TIME = 2; - // This is the time we render the skybox. - SKYBOX_RENDER_TIME = 3; - // Shadow render time (this is used internally and should not be used - // as a descriptor in the scene). - SHADOW_RENDER_TIME = 4; - } - - // When should it be rendered (default = PER_FRAME). - RenderTimeEnum render_time_enum = 11; - - // Shadow effect enum. - enum ShadowEffectEnum { - // Opaque effect normal object behaviour (default). - OPAQUE_SHADOW_EFFECT = 0; - // No effect light go through. - TRANSPARENT_SHADOW_EFFECT = 1; - } - - // Shadow effect (default = OPAQUE_EFFECT_SHADOW). - ShadowEffectEnum shadow_effect_enum = 12; -} - -// Camera -// Next 10 -message NodeCamera { - // This is the name of the camera. - string name = 1; - // Give the name of the parent (if present). - string parent = 2; - // Position of the camera in space. - UniformVector3 position = 3; - // Target where the camera is looking. - UniformVector3 target = 4; - // Up vector of the camera. - UniformVector3 up = 5; - // Fov in degrees. - float fov_degrees = 6; - // Width / Height proportions. - float aspect_ratio = 7; - // Near clipping plane. - float near_clip = 8; - // Far clipping plane. - float far_clip = 9; -} - -// Light -// Next 11 -message NodeLight { - // This is the name of the light. - string name = 1; - // Give the name of the parent (if present). - string parent = 2; - - // Light type this is what the light can be. - enum LightTypeEnum { - INVALID_LIGHT = 0; - AMBIENT_LIGHT = 1; - POINT_LIGHT = 2; - DIRECTIONAL_LIGHT = 3; - SPOT_LIGHT = 4; - } - // The light type of this light. - LightTypeEnum light_type = 3; - - // Position of the light. - // not considered in case this is AMBIENT, DIRECTIONAL. - UniformVector3 position = 4; - // Direction of the light - // not considered in case this is AMBIENT, POINT. - UniformVector3 direction = 5; - // Dot inner limit for spot light. - // not considered in cast this is AMBIENT, POINT, DIRECTIONAL. - float dot_inner_limit = 6; - // Dot outer limit for spot light. - // not considered in cast this is AMBIENT, POINT, DIRECTIONAL. - float dot_outer_limit = 7; - - // Color of the light. - UniformVector3 color = 8; - - enum ShadowTypeEnum { - NO_SHADOW = 0; - HARD_SHADOW = 1; - SOFT_SHADOW = 2; - } - - // Shadow type for the light. - ShadowTypeEnum shadow_type = 9; -} - -// Scene definition. -// Next 9 -message SceneTree { - // This defined witch is the root of the scene tree (not really needed). - string default_root_name = 1; - // This is the default camera node name. - string default_camera_name = 2; - // This is a list of scene matrices. - repeated NodeMatrix node_matrices = 3; - // This is a list of scene meshes. - repeated NodeStaticMesh node_static_meshes = 4; - // This is the camera scene node. - repeated NodeCamera node_cameras = 5; - // This is the node for the lights. - repeated NodeLight node_lights = 6; -} +syntax = "proto3"; + +import "pixel.proto"; +import "math.proto"; +import "plugin.proto"; + +package frame.proto; + +// Scene is a way to load meshes. +// For now it only load them from obj, mtl files but ths will be able to load +// from fbx files as soon as we switch to this assimp library. This will add +// skeleton animation so a new type of mesh. + +// Matrix +// Next 6 +message NodeMatrix { + // This is the name of the scene matrix. + string name = 1; + // Give the name of the parent (if present). + string parent = 2; + + // Is it a rotation or a static move? + enum MatrixTypeEnum { + STATIC_MATRIX = 0; + ROTATION_MATRIX = 1; + } + MatrixTypeEnum matrix_type_enum = 5; + + // Could be a matrix or a quaternion. + oneof matrix_oneof { + UniformMatrix4 matrix = 3; + UniformVector4 quaternion = 4; + } +} + +// Static Mesh. +// Next 13 +message NodeStaticMesh { + // This is the name of the mesh. + string name = 1; + // Give the name of the parent (if present). + string parent = 2; + + // Different kind of rendering possible. + enum RenderPrimitiveEnum { + TRIANGLE_PRIMITIVE = 0; //< default! + POINT_PRIMITIVE = 1; + LINE_PRIMITIVE = 2; + } + // What kind of rendering is required (default = triangle). + RenderPrimitiveEnum render_primitive_enum = 8; + + // Some mesh are included? + enum MeshEnum { + INVALID = 0; + CUBE = 1; + QUAD = 2; + } + // Can only have one of the 3 cases mesh_enum, file_name or stream_input. + oneof mesh_oneof { + // If any of the clean buffer is activated, then only this is used! + CleanBuffer clean_buffer = 7; + // This can be a static mesh enum. + MeshEnum mesh_enum = 6; + // Where the file is loaded from. + string file_name = 3; + // Where the obj file is loaded from (will also load the mtl file). + string obj_file = 13; + // Plugin input. + MultiPlugin multi_plugin = 10; + } + + // Material name. + string material_name = 5; + + // Render time enum. + enum RenderTimeEnum { + // This will be rendered at all frames (this is default). + SCENE_RENDER_TIME = 0; + // This will be pre-rendered only once at the beginning. + PRE_RENDER_TIME = 1; + // This will be post-rendered at the end of every frame. + POST_PROCESS_TIME = 2; + // This is the time we render the skybox. + SKYBOX_RENDER_TIME = 3; + // Shadow render time (this is used internally and should not be used + // as a descriptor in the scene). + SHADOW_RENDER_TIME = 4; + } + + // When should it be rendered (default = PER_FRAME). + RenderTimeEnum render_time_enum = 11; + + // Shadow effect enum. + enum ShadowEffectEnum { + // Opaque effect normal object behaviour (default). + OPAQUE_SHADOW_EFFECT = 0; + // No effect light go through. + TRANSPARENT_SHADOW_EFFECT = 1; + } + + // Shadow effect (default = OPAQUE_EFFECT_SHADOW). + ShadowEffectEnum shadow_effect_enum = 12; +} + +// Camera +// Next 10 +message NodeCamera { + // This is the name of the camera. + string name = 1; + // Give the name of the parent (if present). + string parent = 2; + // Position of the camera in space. + UniformVector3 position = 3; + // Target where the camera is looking. + UniformVector3 target = 4; + // Up vector of the camera. + UniformVector3 up = 5; + // Fov in degrees. + float fov_degrees = 6; + // Width / Height proportions. + float aspect_ratio = 7; + // Near clipping plane. + float near_clip = 8; + // Far clipping plane. + float far_clip = 9; +} + +// Light +// Next 11 +message NodeLight { + // This is the name of the light. + string name = 1; + // Give the name of the parent (if present). + string parent = 2; + + // Light type this is what the light can be. + enum LightTypeEnum { + INVALID_LIGHT = 0; + AMBIENT_LIGHT = 1; + POINT_LIGHT = 2; + DIRECTIONAL_LIGHT = 3; + SPOT_LIGHT = 4; + } + // The light type of this light. + LightTypeEnum light_type = 3; + + // Position of the light. + // not considered in case this is AMBIENT, DIRECTIONAL. + UniformVector3 position = 4; + // Direction of the light + // not considered in case this is AMBIENT, POINT. + UniformVector3 direction = 5; + // Dot inner limit for spot light. + // not considered in cast this is AMBIENT, POINT, DIRECTIONAL. + float dot_inner_limit = 6; + // Dot outer limit for spot light. + // not considered in cast this is AMBIENT, POINT, DIRECTIONAL. + float dot_outer_limit = 7; + + // Color of the light. + UniformVector3 color = 8; + + enum ShadowTypeEnum { + NO_SHADOW = 0; + HARD_SHADOW = 1; + SOFT_SHADOW = 2; + } + + // Shadow type for the light. + ShadowTypeEnum shadow_type = 9; +} + +// Scene definition. +// Next 9 +message SceneTree { + // This defined witch is the root of the scene tree (not really needed). + string default_root_name = 1; + // This is the default camera node name. + string default_camera_name = 2; + // This is a list of scene matrices. + repeated NodeMatrix node_matrices = 3; + // This is a list of scene meshes. + repeated NodeStaticMesh node_static_meshes = 4; + // This is the camera scene node. + repeated NodeCamera node_cameras = 5; + // This is the node for the lights. + repeated NodeLight node_lights = 6; +}