diff --git a/.clang-format b/.clang-format deleted file mode 100644 index f0b9d64..0000000 --- a/.clang-format +++ /dev/null @@ -1,14 +0,0 @@ -# We'll use defaults from the LLVM style, but with 4 columns indentation. -BasedOnStyle: LLVM -IndentWidth: 4 - - -Language: Cpp - -# Force pointers to the type for C++. -DerivePointerAlignment: false -PointerAlignment: Left - -LambdaBodyIndentation: OuterScope - -AlignConsecutiveAssignments: true diff --git a/.gitignore b/.gitignore index 118019c..8f971c7 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,3 @@ compile_commands.json *.autosave build -.cache diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..5c7247b --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,7 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..36bf36d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,22 @@ +{ + "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools", + "cmake.configureOnOpen": true, + "files.associations": { + "array": "cpp", + "cwchar": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "functional": "cpp", + "initializer_list": "cpp", + "iosfwd": "cpp", + "istream": "cpp", + "new": "cpp", + "ostream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "type_traits": "cpp", + "tuple": "cpp" + }, + "mesonbuild.configureOnOpen": false +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..05054c5 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,28 @@ +{ + "tasks": [ + { + "type": "cppbuild", + "label": "C/C++: g++ build active file", + "command": "/usr/bin/g++", + "args": [ + "-fdiagnostics-color=always", + "-g", + "${file}", + "-o", + "${fileDirname}/${fileBasenameNoExtension}" + ], + "options": { + "cwd": "${fileDirname}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "Task generated by Debugger." + } + ], + "version": "2.0.0" +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 898f21e..52ddf60 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,19 +1,17 @@ # # CMake build system for pixwerx # -cmake_minimum_required(VERSION 3.28) +cmake_minimum_required(VERSION 3.8) project(pixwerx) # -# pixwerx is C++23 +# pixwerx ist C++20 # -set (CMAKE_CXX_STANDARD 23) +set (CMAKE_CXX_STANDARD 20) -# # internal cmake modules -# set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/etc/cmake ${CMAKE_MODULE_PATH}) # boilerplate locations for build @@ -30,4 +28,3 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON) # add_subdirectory(src) add_subdirectory(share) -add_subdirectory(tests) diff --git a/LICENSE b/LICENSE index 11faed7..21124e8 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 1999-2024 Hartmut Seichter +Copyright (c) 1999-2021 Hartmut Seichter Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 28dca57..d9547ed 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,34 @@ -# pixwerx +# pixwerx -pixwerx is a general purpose 3D engine written in C++23 and scriptable with Lua. +pixwerx is an opinionated, academic approach to a 3D engine. It tries to mix +modern andproven methods to build a fast and portable engine beyond pure 3D. -## Principles +## Design Principles + +Dogdooding: pixwerx is built on the principle of dogfooding. The engine is a +full-stack system that tries to implement all necessary functions. The engine +editor is just a UI build with the engine. + +Reasonable dependencies: like many engines pixwerx tries to include as much 3rd- +party code as possible and implements some of the core systems itself. + +No premature optimization: pixwerx implements only very few systems with machine +code. It tries to utilize the power of the compiler as much as possible. + +Computer graphics 101: pixwerx does implement graphics components and systems in +a way that makes code portable and not over-parameterized. Usability is +achieved through layers on top of the core components. -- datadriven design -- multiple platform capable through heavy usage of STL -- minimal set of dependencies -- efficiency through meta-meta programming techniques -- no CPU intrinsics ## License -pixwerx is licenced under the terms of the MIT License. Please consult the LICENSE file. +pixwerx is licenced under the terms of the MIT License. Please consult the +LICENSE file. ## Authors -© 1999-2024 Hartmut Seichter +© 1999-2020 Hartmut Seichter + + + + diff --git a/share/CMakeLists.txt b/share/CMakeLists.txt index 3cf5d0d..0ad654b 100644 --- a/share/CMakeLists.txt +++ b/share/CMakeLists.txt @@ -1,4 +1,4 @@ -# find_package(mkdocs 1.0) +find_package(mkdocs 1.0) # if(MKDOCS_FOUND) # configure_file(mkdocs.yml "${CMAKE_CURRENT_BINARY_DIR}/mkdocs.yml" COPYONLY) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4dab9d5..92925fa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,13 +3,13 @@ add_subdirectory(deps) # build internal core add_subdirectory(core) -# add_subdirectory(scene) -# add_subdirectory(system) +add_subdirectory(scene) +add_subdirectory(system) add_subdirectory(io) #add_subdirectory(ui) -# add_subdirectory(binding) -# add_subdirectory(visual) -# add_subdirectory(geometry) +add_subdirectory(binding) +add_subdirectory(visual) +add_subdirectory(geometry) -# add_subdirectory(runtime) +add_subdirectory(runtime) diff --git a/src/binding/include/pw/scripting/script.hpp b/src/binding/include/pw/scripting/script.hpp index e007644..ac1c504 100644 --- a/src/binding/include/pw/scripting/script.hpp +++ b/src/binding/include/pw/scripting/script.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/binding/src/script_core.cpp b/src/binding/src/script_core.cpp index 3fa9997..9cd9343 100644 --- a/src/binding/src/script_core.cpp +++ b/src/binding/src/script_core.cpp @@ -1,34 +1,39 @@ +#include "pw/core/vector.hpp" +#include "pw/core/quaternion.hpp" #include "pw/core/axisangle.hpp" -#include "pw/core/color.hpp" #include "pw/core/debug.hpp" +#include "pw/core/size.hpp" +#include "pw/core/point.hpp" +#include "pw/core/time.hpp" +#include "pw/core/geometry.hpp" #include "pw/core/image.hpp" #include "pw/core/matrix_transform.hpp" -#include "pw/core/point.hpp" -#include "pw/core/primitives.hpp" -#include "pw/core/quaternion.hpp" #include "pw/core/rectangle.hpp" -#include "pw/core/size.hpp" -#include "pw/core/time.hpp" -#include "pw/core/vector.hpp" +#include "pw/core/color.hpp" #include "runtime_lua.hpp" + // seems CRTP magic doesnt work with SOL namespace sol { -// template <> struct is_automagical : std::false_type {}; -// template <> struct is_automagical : std::false_type {}; -// template <> struct is_automagical : std::false_type {}; -// template <> struct is_automagical : std::false_type {}; -// template <> struct is_automagical : std::false_type {}; -// template <> struct is_automagical : std::false_type {}; +template <> struct is_automagical : std::false_type {}; +template <> struct is_automagical : std::false_type {}; +template <> struct is_automagical : std::false_type {}; +template <> struct is_automagical : std::false_type {}; +template <> struct is_automagical : std::false_type {}; +template <> struct is_automagical : std::false_type {}; } namespace pw { -// vector3 table_to_vector3(sol::table t) { return vector3(t[0], t[1], t[2]); } +vector3 table_to_vector3(sol::table t) +{ + return vector3(t[0],t[1],t[2]); +} template -std::vector convert_sequence(sol::state& lua, sol::table t) { +std::vector convert_sequence(sol::state& lua,sol::table t) +{ const std::size_t sz = t.size(); std::vector res(sz); for (std::size_t i = 1; i <= sz; i++) { @@ -37,57 +42,45 @@ std::vector convert_sequence(sol::state& lua, sol::table t) { return res; } -void register_core_function(sol::state& lua, sol::table& ns) { - ns.set("pi", pw::pi()); - ns.new_usertype( - "color", sol::call_constructor, sol::constructors(), // - "rgba", &color::rgba, // - "data", sol::property([](color& c) { return c.rgba.data(); }), // - "table", - sol::property([](const color& c) { // - return sol::as_table(std::array{ - c.rgba.x(), c.rgba.y(), c.rgba.z(), c.rgba.w()}); - }, [](color& c, const sol::table& t) { - c = color{ - .rgba = vector4f{t[0], t[1], t[2], t[3]} - }; - })); +void register_core_function(sol::state& lua,sol::table& ns) +{ -#if 0 + ns.set("pi",pw::pi()); - ns.new_usertype( - "matrix4x4", sol::call_constructor, sol::constructors(), - "row", &matrix4x4::row, "column", &matrix4x4::column, "inverse", - sol::readonly_property(&matrix4x4::inverse), "identity", - sol::readonly_property(&matrix4x4::identity), - sol::meta_function::multiplication, - [](const matrix4x4& a, const vector4& b) { return vector4(a * b); }); - ns.new_usertype( - "vector2", sol::call_constructor, - sol::constructors(), - "x", - sol::property( - sol::resolve(&vector2::x), - [](vector2& v, vector2::value_type val) { v.x() = val; }), - "y", - sol::property( - sol::resolve(&vector2::y), - [](vector2& v, vector2::value_type val) { v.y() = val; }), - "dot", &vector2::dot, sol::meta_function::addition, - [](const vector2& a, const vector2& b) { return vector2(a + b); }, - sol::meta_function::subtraction, - [](const vector2& a, const vector2& b) { return vector2(a - b); }, - "data", sol::property([](vector2& s) { return std::ref(s.data); }), - "table", sol::property([](const vector2& s) { - return sol::as_table(std::array{s.x(), s.y()}); - }, [](vector2& s, const sol::table& t) { - s.data[0] = t[1]; - s.data[1] = t[2]; - })); + ns.new_usertype("color", + sol::call_constructor,sol::constructors(), + "rgba",&color::rgba, + "data",sol::property([](color& c) { return std::ref(c.rgba.data);} ), + "table",sol::property([](const color& c){ return sol::as_table(std::array{c.rgba.x(),c.rgba.y(),c.rgba.z(),c.rgba.w()}); }, + [](color& c,const sol::table& t) { c = color((real_t)t[0],t[1],t[2],t[3]);}) + + ); + + + ns.new_usertype("matrix4x4", + sol::call_constructor,sol::constructors(), + "row",&matrix4x4::row, + "column",&matrix4x4::column, + "inverse", sol::readonly_property(&matrix4x4::inverse), + "identity",sol::readonly_property(&matrix4x4::identity), + sol::meta_function::multiplication,[](const matrix4x4& a,const vector4& b) { return vector4(a * b); } + ); + + ns.new_usertype("vector2", + sol::call_constructor,sol::constructors(), + "x", sol::property(sol::resolve(&vector2::x), [](vector2& v,vector2::value_type val){ v.x() = val;}), + "y", sol::property(sol::resolve(&vector2::y), [](vector2& v,vector2::value_type val){ v.y() = val;}), + "dot",&vector2::dot, + sol::meta_function::addition,[](const vector2& a,const vector2& b){ return vector2(a + b); }, + sol::meta_function::subtraction,[](const vector2& a,const vector2& b){ return vector2(a - b); }, + "data",sol::property([](vector2& s) { return std::ref(s.data);} ), + "table",sol::property([](const vector2& s){ return sol::as_table(std::array{s.x(),s.y()}); }, + [](vector2& s,const sol::table& t) { s.data[0] = t[1]; s.data[1] = t[2];} ) + ); ns.new_usertype("vector3" ,sol::call_constructor,sol::constructors() @@ -265,9 +258,9 @@ void register_core_function(sol::state& lua, sol::table& ns) { ns.create_named("mathf") .set_function("ping_pong",ping_pong); -#endif } + PW_REGISTER_LUA(core) -} // namespace pw +} diff --git a/src/binding/src/script_system.cpp b/src/binding/src/script_system.cpp index c76c2df..19a43af 100644 --- a/src/binding/src/script_system.cpp +++ b/src/binding/src/script_system.cpp @@ -1,9 +1,9 @@ -// #include "script_system.hpp" +//#include "script_system.hpp" -#include "pw/system/display.hpp" -#include "pw/system/input.hpp" -#include "pw/system/path.hpp" #include "pw/system/window.hpp" +#include "pw/system/input.hpp" +#include "pw/system/display.hpp" +#include "pw/system/path.hpp" #include "runtime_lua.hpp" @@ -13,37 +13,49 @@ namespace pw { -void register_system_function(sol::state&, sol::table& ns) { - ns.new_usertype( - "window", "update", &window::update, "on_update", - sol::writeonly_property(&window::set_on_update), "on_resize", - sol::writeonly_property(&window::set_on_resize), "title", - sol::writeonly_property(&window::set_title), "size", - sol::property(&window::size, &window::set_size), "client_size", - sol::readonly_property(&window::client_size), "position", - sol::property(&window::position, &window::set_position), "fullscreen", - sol::property(&window::fullscreen, &window::set_fullscreen), "visible", - sol::property(&window::visible, &window::set_visible)); +void register_system_function(sol::state&, sol::table &ns) +{ + ns.new_usertype("window", + "update",&window::update, + "on_update",sol::writeonly_property(&window::set_on_update), + "on_resize",sol::writeonly_property(&window::set_on_resize), + "title",sol::writeonly_property(&window::set_title), + "size",sol::property(&window::size,&window::set_size), + "client_size",sol::readonly_property(&window::client_size), + "position",sol::property(&window::position,&window::set_position), + "fullscreen",sol::property(&window::fullscreen,&window::set_fullscreen), + "visible",sol::property(&window::visible,&window::set_visible) + ); - ns.new_usertype( - "input", "new", sol::no_constructor, "get", &input::get, - "mouse_position", sol::readonly_property(&input::mouse_position), - "mouse_button", sol::readonly_property(&input::mouse_button), - "mouse_pressed", sol::readonly_property(&input::mouse_pressed), - "has_input", sol::readonly_property(&input::has_input), "input_string", - sol::readonly_property(&input::input_string)); - ns.new_usertype("display", "all", &display::all, "name", - sol::readonly_property(&display::name)); + ns.new_usertype("input", + "new", sol::no_constructor, + "get",&input::get, + "mouse_position",sol::readonly_property(&input::mouse_position), + "mouse_button",sol::readonly_property(&input::mouse_button), + "mouse_pressed",sol::readonly_property(&input::mouse_pressed), + "has_input",sol::readonly_property(&input::has_input), + "input_string",sol::readonly_property(&input::input_string) + ); - ns.new_usertype( - "path", "new", sol::no_constructor, "get", &path::get, "separator", - sol::readonly_property(&path::separator), "executable_path", - sol::readonly_property(&path::executable_path), "resource_paths", - sol::readonly_property( - [](const path& p) { return sol::as_table(p.resource_paths()); })); + ns.new_usertype("display", + "all",&display::all, + "name",sol::readonly_property(&display::name) + ); + + ns.new_usertype("path" + ,"new",sol::no_constructor + ,"get",&path::get + ,"separator",sol::readonly_property(&path::separator) + ,"executable_path",sol::readonly_property(&path::executable_path) + ,"resource_paths",sol::readonly_property([](const path& p){return sol::as_table(p.resource_paths());}) + ); } + + + PW_REGISTER_LUA(system) -} // namespace pw + +} diff --git a/src/binding/src/script_visual.cpp b/src/binding/src/script_visual.cpp index a4a0e92..2ee87a1 100644 --- a/src/binding/src/script_visual.cpp +++ b/src/binding/src/script_visual.cpp @@ -1,76 +1,92 @@ #include "pw/core/debug.hpp" -#include "pw/visual/context.hpp" -#include "pw/visual/framebuffer.hpp" #include "pw/visual/pipeline.hpp" #include "pw/visual/shader.hpp" +#include "pw/visual/framebuffer.hpp" #include "pw/visual/texture.hpp" +#include "pw/visual/context.hpp" #include "pw/core/size.hpp" + #include "runtime_lua.hpp" namespace pw { -void register_visual_function(sol::state& lua, sol::table& ns) { +void register_visual_function(sol::state& lua,sol::table &ns) +{ - // ns.new_usertype("pipeline" - // ,"create",&pipeline::create - // ,"draw",&pipeline::draw - // ); +// ns.new_usertype("pipeline" +// ,"create",&pipeline::create +// ,"draw",&pipeline::draw +// ); - ns.new_usertype( - "shader", sol::call_constructor, sol::constructors(), "ready", - sol::readonly_property(&shader::ready), "use", &shader::use, "build", - &shader::build, "source", &shader::source, "set_source", - &shader::set_source, "set_uniforms", &shader::set_uniforms, - "set_uniform_float", &shader::set_uniform, "set_uniform_uint", - &shader::set_uniform, "set_uniform_int", - &shader::set_uniform, "set_uniform_mat4", - &shader::set_uniform, "set_uniform_vec4", - &shader::set_uniform, "set_uniform_texture", - &shader::set_uniform + ns.new_usertype("shader" + ,sol::call_constructor,sol::constructors() + ,"ready",sol::readonly_property(&shader::ready) + ,"use",&shader::use + ,"build",&shader::build + ,"source",&shader::source + ,"set_source",&shader::set_source + ,"set_uniforms",&shader::set_uniforms + ,"set_uniform_float",&shader::set_uniform + ,"set_uniform_uint",&shader::set_uniform + ,"set_uniform_int",&shader::set_uniform + ,"set_uniform_mat4",&shader::set_uniform + ,"set_uniform_vec4",&shader::set_uniform + ,"set_uniform_texture",&shader::set_uniform - ); + ); - ns["shader_type"] = ns.create_named( - "shader_type", "fragment", shader::code_type::fragment, "vertex", - shader::code_type::vertex, "geometry", shader::code_type::geometry, - "compute", shader::code_type::compute); - // new_enum( + ns["shader_type"] = ns.create_named("shader_type" + ,"fragment",shader::code_type::fragment + ,"vertex",shader::code_type::vertex + ,"geometry",shader::code_type::geometry + ,"compute",shader::code_type::compute); - // ns.new_usertype("render_pass" - // ,"submit",&render_pass::submit - // ); +// new_enum( - ns.new_usertype( - "renderer", sol::call_constructor, - sol::constructors(), "update", - &renderer::update, "ready", sol::readonly_property(&renderer::ready), - "change_count", sol::readonly_property(&renderer::change_count), - "release", &renderer::release, "draw", &renderer::draw); - ns.new_usertype( - "framebuffer", sol::call_constructor, - sol::constructors(), "create", &framebuffer::create, - "bind", &framebuffer::bind, "unbind", &framebuffer::unbind, "blit", - &framebuffer::blit); +// ns.new_usertype("render_pass" +// ,"submit",&render_pass::submit +// ); - ns.new_usertype("texture", sol::call_constructor, - sol::constructors(), "create", - &texture::create, "update", &texture::update, - "bind", &texture::bind, "unbind", &texture::unbind, - "native_handle", &texture::native_handle); - ns.new_usertype( - "context", sol::call_constructor, sol::constructors(), - "clear", &context::clear, "clearcolor", - sol::property(&context::clearcolor, &context::set_clearcolor), - "set_viewport", &context::set_viewport, "get_error", - &context::get_error); + ns.new_usertype("renderer" + ,sol::call_constructor,sol::constructors() + ,"update",&renderer::update + ,"ready",sol::readonly_property(&renderer::ready) + ,"change_count",sol::readonly_property(&renderer::change_count) + ,"release",&renderer::release + ,"draw",&renderer::draw + ); + + ns.new_usertype("framebuffer" + ,sol::call_constructor,sol::constructors() + ,"create",&framebuffer::create + ,"bind",&framebuffer::bind + ,"unbind",&framebuffer::unbind + ,"blit",&framebuffer::blit); + + ns.new_usertype("texture" + ,sol::call_constructor,sol::constructors() + ,"create",&texture::create + ,"update",&texture::update + ,"bind",&texture::bind + ,"unbind",&texture::unbind + ,"native_handle",&texture::native_handle + ); + + ns.new_usertype("context" + ,sol::call_constructor,sol::constructors() + ,"clear",&context::clear + ,"clearcolor",sol::property(&context::clearcolor,&context::set_clearcolor) + ,"set_viewport",&context::set_viewport + ,"get_error",&context::get_error + ); } PW_REGISTER_LUA(visual) -} // namespace pw +} diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 7c77e34..f592f11 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -8,6 +8,7 @@ set(hdrs include/pw/core/globals.hpp include/pw/core/material.hpp include/pw/core/math.hpp + include/pw/core/matrixbase.hpp include/pw/core/matrix.hpp include/pw/core/quaternion.hpp include/pw/core/image.hpp @@ -17,7 +18,7 @@ set(hdrs include/pw/core/serialize.hpp include/pw/core/size.hpp include/pw/core/time.hpp - include/pw/core/primitives.hpp + include/pw/core/geometry.hpp include/pw/core/image.hpp include/pw/core/vector.hpp include/pw/core/matrix_transform.hpp @@ -34,12 +35,12 @@ set(srcs src/core.cpp src/image.cpp src/debug.cpp - # src/geometry.cpp - # src/material.cpp - # src/resource.cpp - # src/serialize.cpp - # src/time.cpp - # src/image.cpp + src/geometry.cpp + src/material.cpp + src/resource.cpp + src/serialize.cpp + src/time.cpp + src/image.cpp ) add_library(pwcore @@ -58,3 +59,4 @@ target_include_directories( target_link_libraries(pwcore) add_subdirectory(tests) + diff --git a/src/core/include/pw/core/aabb.hpp b/src/core/include/pw/core/aabb.hpp index a651acb..ada4cd1 100644 --- a/src/core/include/pw/core/aabb.hpp +++ b/src/core/include/pw/core/aabb.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -8,8 +8,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -23,47 +23,30 @@ #ifndef PW_CORE_AABB_HPP #define PW_CORE_AABB_HPP -#include "primitives.hpp" #include -#include -#include - namespace pw { -template struct aabb final { +struct aabb { - using value_type = vector; + vector3 min; + vector3 max; - value_type min{}; - value_type max{}; + aabb(const vector3 min_vec,const vector3 max_vec) + : min(min_vec) + , max(max_vec) + {} - constexpr auto dimension() const noexcept { return max - min; } + aabb() { + min.zero(); max.zero(); + } - static constexpr auto - make(const std::vector>& vertices) - -> aabb { - return std::accumulate( - std::begin(vertices), std::end(vertices), - aabb{.min{vertices.front()}, .max{vertices.front()}}, - [](const auto& prev, const auto& e) { - return aabb{.min{e.min(prev.min)}, .max{e.max(prev.max)}}; - }); - } + vector3 dimension() const { + return max - min; + } - static constexpr auto make_from_indexed_vertices( - const std::vector>& vertices, - std::vector& indices) -> aabb { - return std::accumulate(std::begin(indices), std::end(indices), - aabb{.min{vertices[indices.front()]}, - .max{vertices[indices.front()]}}, - [&vertices](const auto& prev, const auto& e) { - return aabb{.min{vertices[e].min(prev.min)}, - .max{vertices[e].max(prev.max)}}; - }); - } }; -} // namespace pw +} #endif diff --git a/src/core/include/pw/core/axisangle.hpp b/src/core/include/pw/core/axisangle.hpp index 183557c..0ad6575 100644 --- a/src/core/include/pw/core/axisangle.hpp +++ b/src/core/include/pw/core/axisangle.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -8,8 +8,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -23,64 +23,95 @@ #ifndef PW_CORE_AXISANGLE_HPP #define PW_CORE_AXISANGLE_HPP -#include #include namespace pw { -template struct axisangle final { +template +struct axisangle_ { - using value_type = Scalar; - using axis_type = vector3; + using value_type = T; + using axis_type = vector3_; - axis_type axis = axis_type::basis(2); - Scalar angle{}; + axis_type axis; + T angle; - constexpr static auto - from_matrix(const matrix& m) noexcept -> axisangle { + axisangle_() + : axis(vector3_::up()), + angle(0) + {} - return {.axis = axis_type{m[2][1] - m[1][2], // x - m[0][2] - m[2][0], // y - m[1][0] - m[0][1]} // z - .normalized(), - .angle = - std::acos((m[0][0] + m[1][1] + m[2][2] - 1) / Scalar{2})}; + axisangle_(vector3_ axis,T angle) + : axis(std::move(axis)) + , angle(std::move(angle)) + { } - constexpr auto to_matrix() const noexcept -> matrix { + static const axisangle_ from_matrix(const matrix_<4,4,T>& m) + { + using std::acos; + using std::sqrt; - const auto axis_n = axis.normalized(); // always normalize + axisangle_ aa_res; + aa_res.angle = acos((m(0,0) + m(1,1) + m(2,2) - 1) / T(2)); + const T m2112 = m(2,1) - m(1,2); + const T m0220 = m(0,2) - m(2,0); + const T m1001 = m(1,0) - m(0,1); + // no singularity check here ... + const T mrot_denom = sqrt( m2112 * m2112 + m0220 * m0220 + m1001 * m1001 ); - const auto cos_a = std::cos(angle); - const auto sin_a = std::sin(angle); - const auto cos_1_a = 1 - cos_a; + aa_res.axis.x() = m2112 / mrot_denom; + aa_res.axis.y() = m0220 / mrot_denom; + aa_res.axis.z() = m1001 / mrot_denom; - const auto v1_a = axis_n.x() * axis_n.y() * cos_1_a; - const auto v2_a = axis_n.z() * sin_a; + return aa_res; + } - const auto v1_b = axis_n.x() * axis_n.z() * cos_1_a; - const auto v2_b = axis_n.y() * sin_a; + matrix_<4,4,T> to_matrix() const + { + using std::cos; + using std::sin; - const auto v1_c = axis_n.y() * axis_n.z() * cos_1_a; - const auto v2_c = axis_n.x() * sin_a; + // result + matrix_<4,4,T> rot_mat; rot_mat.set_identity(); + axis_type axis_n = axis.normalized(); // always normalize - return { - pw::vector{cos_a + axis_n.x() * axis_n.x() * cos_1_a, // [0,0] - v1_a - v2_a, // [0,1] - v1_b + v2_b}, // [0,2] - pw::vector{v1_a + v2_a, // [1,0] - cos_a + axis_n.y() * axis_n.y() * cos_1_a, // [1,1] - v1_c - v2_c}, // [1,2] - pw::vector{v1_b - v2_b, // [2,0] - v1_c + v2_c, // [2,1] - cos_a + axis_n.z() * axis_n.z() * cos_1_a} // [2,2] - }; + const T cos_a = cos(angle); + const T sin_a = sin(angle); + const T cos_1_a = T(1) - cos_a; + + rot_mat(0,0) = cos_a + axis_n.x() * axis_n.x() * cos_1_a; + rot_mat(1,1) = cos_a + axis_n.y() * axis_n.y() * cos_1_a; + rot_mat(2,2) = cos_a + axis_n.z() * axis_n.z() * cos_1_a; + + T v1 = axis_n.x() * axis_n.y() * cos_1_a; + T v2 = axis_n.z() * sin_a; + rot_mat(1,0) = v1 + v2; + rot_mat(0,1) = v1 - v2; + + v1 = axis_n.x() * axis_n.z() * cos_1_a; + v2 = axis_n.y() * sin_a; + rot_mat(2,0) = v1 - v2; + rot_mat(0,2) = v1 + v2; + + v1 = axis_n.y() * axis_n.z() * cos_1_a; + v2 = axis_n.x() * sin_a; + rot_mat(2,1) = v1 + v2; + rot_mat(1,2) = v1 - v2; + + return rot_mat; } }; -using axisanglef = axisangle; -using axisangled = axisangle; -} // namespace pw +using axisangle = axisangle_ ; +using axisanglef = axisangle_ ; +using axisangled = axisangle_ ; + +} + + + + #endif diff --git a/src/core/include/pw/core/buffer.hpp b/src/core/include/pw/core/buffer.hpp new file mode 100644 index 0000000..5f894c3 --- /dev/null +++ b/src/core/include/pw/core/buffer.hpp @@ -0,0 +1,11 @@ +#ifndef PW_CORE_BUFFER_HPP +#define PW_CORE_BUFFER_HPP + +#include +#include + + + + + +#endif // PW_CORE_BUFFER_HPP diff --git a/src/core/include/pw/core/color.hpp b/src/core/include/pw/core/color.hpp index 766f2c5..fd2837b 100644 --- a/src/core/include/pw/core/color.hpp +++ b/src/core/include/pw/core/color.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -8,8 +8,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -23,34 +23,40 @@ #ifndef PW_CORE_COLOR_HPP #define PW_CORE_COLOR_HPP -#include #include - +#include namespace pw { -struct color final { +struct color { - vector4f rgba{vector4f::all(1)}; + vector4 rgba {0, 0, 0, 1}; - static constexpr auto from_rgb8888(uint8_t r8, uint8_t g8, uint8_t b8, - uint8_t a8) -> color { - return {static_cast(r8) / std::numeric_limits::max(), - static_cast(g8) / std::numeric_limits::max(), - static_cast(b8) / std::numeric_limits::max(), - static_cast(a8) / std::numeric_limits::max()}; - } + color() = default; - static constexpr auto from_rgb8888(uint32_t v) -> color { - return from_rgb8888((v & 0xff000000) >> 24, (v & 0x00ff0000) >> 16, - (v & 0x0000ff00) >> 8, (v & 0x000000ff)); - } + color(uint8_t r8,uint8_t g8,uint8_t b8,uint8_t a8) + : color(static_cast(r8 / std::numeric_limits::max()), + static_cast(g8 / std::numeric_limits::max()), + static_cast(b8 / std::numeric_limits::max()), + static_cast(a8 / std::numeric_limits::max())) + { + } - uint32_t to_rgb8888() const { - return 0; - } + color(real_t r,real_t g,real_t b,real_t a) + : rgba({r,g,b,a}) + { + } + + color(const vector4& v) : rgba(v) { } + + operator vector4() const { return rgba; } + + uint32_t to_rgb8888() const { + return 0; + } }; -} // namespace pw +} + #endif diff --git a/src/core/include/pw/core/context.hpp b/src/core/include/pw/core/context.hpp new file mode 100644 index 0000000..e69de29 diff --git a/src/core/include/pw/core/core.hpp b/src/core/include/pw/core/core.hpp index ed32cf9..60c4361 100644 --- a/src/core/include/pw/core/core.hpp +++ b/src/core/include/pw/core/core.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/core/include/pw/core/debug.hpp b/src/core/include/pw/core/debug.hpp index c1ce297..3350453 100644 --- a/src/core/include/pw/core/debug.hpp +++ b/src/core/include/pw/core/debug.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -8,8 +8,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -26,67 +26,72 @@ #include -#include #include +#include namespace pw { /** - * @brief multipurpose logger used internally - */ + * @brief multipurpose logger used internally + */ class debug { - public: +public: + enum level { - none, //!< nothing will be logged, even no errors - error, //!< only errors will be logged - warning, //!< log warnings (non-critical errors) - message, //!< log messages (something to note but not an error) - notification, //!< log some more information - info, //!< log verbose information - all = 0xFF //!< log absolutely everything + none, //!< nothing will be logged, even no errors + error, //!< only errors will be logged + warning, //!< log warnings (non-critical errors) + message, //!< log messages (something to note but not an error) + notification, //!< log some more information + info, //!< log verbose information + all = 0xFF //!< log absolutely everything }; /** * @brief the streaming interface for the logger */ class stream { - public: + public: + + stream(debug* log = nullptr); ~stream(); stream(const stream& other); - stream& operator<<(const bool& value); - stream& operator<<(const char* value); - stream& operator<<(const std::string& value); ///! log a string - stream& - operator<<(const std::string_view& value); ///! log a string_view - stream& operator<<(const float& value); ///! log a float value - stream& operator<<(const double& value); ///! log a double value + stream& operator << (const bool &value); + stream& operator << (const char *value); + stream& operator << (const std::string& value); ///! log a string + stream& operator << (const std::string_view& value); ///! log a string_view - stream& operator<<(const int& value); ///! log a int value - stream& operator<<(const unsigned int& value); ///! log a int value + stream& operator << (const float &value); ///! log a float value + stream& operator << (const double &value); ///! log a double value - stream& operator<<(const long& value); ///! log a long value - stream& operator<<(const unsigned long& value); ///! log a int value + stream& operator << (const int &value); ///! log a int value + stream& operator << (const unsigned int &value); ///! log a int value - stream& operator<<(const void* value); ///! pointer + stream& operator << (const long &value); ///! log a long value + stream& operator << (const unsigned long &value); ///! log a int value + + stream& operator << (const void *value); ///! pointer + + + protected: - protected: debug* _log; std::string _line; }; /** sets the logging level */ - void set_level(level level) { _level = level; } + void set_level(level level) {_level = level;} /** gets the logging level */ level level() const { return _level; } /** - * @brief get the stream interface of the logger - * @return return a temporary object that will write and flush the logger - */ + * @brief get the stream interface of the logger + * @return return a temporary object that will write and flush the logger + */ static stream s(enum level level = info); inline static stream d() { return s(debug::info); } @@ -103,14 +108,15 @@ class debug { * @brief write a message to the log * @param message string */ - void write(const std::string& message); + void write(const std::string &message); typedef std::function Callback; typedef std::vector CallbackList; ~debug(); - protected: +protected: + debug(); CallbackList _callbacks; @@ -120,7 +126,7 @@ class debug { ///** // * @brief helper for changing the log level in a scope // */ -// struct ScopeLogLevel +//struct ScopeLogLevel //{ // debug::level levelOutside; // explicit ScopeLogLevel(debug::level level) @@ -134,12 +140,12 @@ class debug { // } //}; -// template -// struct tpScopeLog { -// const char* info; -// explicit tpScopeLog(const char* i) : info(i) { -// debug::s(level) << info; -// } +//template +//struct tpScopeLog { +// const char* info; +// explicit tpScopeLog(const char* i) : info(i) { +// debug::s(level) << info; +// } // ~tpScopeLog() { // debug::s(level) << info; @@ -148,8 +154,9 @@ class debug { // some macros -// #define LOG_INFO() Log::s() -// #define LOG_FUNC() LOG_INFO() << __FUNCTION__ << " " << __LINE__ << " " -} // namespace pw +//#define LOG_INFO() Log::s() +//#define LOG_FUNC() LOG_INFO() << __FUNCTION__ << " " << __LINE__ << " " +} + #endif diff --git a/src/core/include/pw/core/formatter.hpp b/src/core/include/pw/core/formatter.hpp deleted file mode 100644 index 94030d1..0000000 --- a/src/core/include/pw/core/formatter.hpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 1999-2024 Hartmut Seichter - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#ifndef PW_CORE_FORMATTER_HPP -#define PW_CORE_FORMATTER_HPP - -#include -#include -#include - -#include -#include -#include - -template -struct std::formatter> { - - constexpr auto parse(std::format_parse_context& ctx) { return ctx.begin(); } - - constexpr auto format(const pw::vector& v, - std::format_context& ctx) const noexcept { - return std::format_to( - ctx.out(), "{}", - std::accumulate(std::next(std::begin(v)), std::end(v), - std::to_string(v[0]), - [](const auto& prev, const auto& e) { - return prev + " " + std::to_string(e); - })); - } -}; - -template -struct std::formatter> { - - constexpr auto parse(std::format_parse_context& ctx) { return ctx.begin(); } - - constexpr auto format(const pw::matrix& m, - std::format_context& ctx) const noexcept { - return std::format_to( - ctx.out(), "{}", - std::accumulate(std::next(std::begin(m)), std::end(m), - std::format("{}", m[0]), - [](const auto& prev, const auto& e) { - return prev + "\n" + std::format("{}", e); - })); - } -}; - -#endif diff --git a/src/core/include/pw/core/frustum.hpp b/src/core/include/pw/core/frustum.hpp deleted file mode 100644 index 5f69d16..0000000 --- a/src/core/include/pw/core/frustum.hpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 1999-2024 Hartmut Seichter - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#ifndef PW_CORE_FRUSTUM_HPP -#define PW_CORE_FRUSTUM_HPP - -#include -#include - -namespace pw { - -template struct frustum final { - Scalar left{-1}, right{1}, bottom{-1}, top{1}, z_near{-1}, z_far{1}; - - static constexpr auto make_perspective_symmetric(Scalar fov_h_deg, - Scalar aspect_ratio, - Scalar z_near, - Scalar z_far) -> frustum { - const auto tangent_half{ - std::tan(pw::deg_to_rad(fov_h_deg / Scalar{2}))}; - const auto top{tangent_half * z_near}; - const auto right{top * aspect_ratio}; - - return {.left = -right, - .right = right, - .bottom = -top, - .top = top, - .z_near = z_near, - .z_far = z_far}; - } - - static constexpr auto make_orthographic_symmetric(Scalar scale, - Scalar aspect_ratio, - Scalar z_near, - Scalar z_far) -> frustum { - return {.left = -scale, - .right = scale, - .bottom = -scale * aspect_ratio, - .top = scale * aspect_ratio, - .z_near = z_near, - .z_far = z_far}; - } -}; - -} // namespace pw - -#endif diff --git a/src/core/include/pw/core/primitives.hpp b/src/core/include/pw/core/geometry.hpp similarity index 64% rename from src/core/include/pw/core/primitives.hpp rename to src/core/include/pw/core/geometry.hpp index ed2dc17..e3edf50 100644 --- a/src/core/include/pw/core/primitives.hpp +++ b/src/core/include/pw/core/geometry.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -8,8 +8,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -20,53 +20,26 @@ * SOFTWARE. * */ -#ifndef PW_CORE_PRIMITIVES_HPP -#define PW_CORE_PRIMITIVES_HPP +#ifndef PW_CORE_GEOMETRY_HPP +#define PW_CORE_GEOMETRY_HPP -#include #include -#include #include -#include +#include +#include namespace pw { -struct primitives final { - - enum struct topology_type { - point_list, - line_list, - line_strip, - triangle_list, - triangle_strip, - triangle_fan, - line_list_with_adjacency, - line_strip_with_adjacency, - triangle_list_with_adjacency, - triangle_strip_with_adjacency, - patch_list - }; - - using vertex_type = vector3; - using index_type = std::size_t; - - std::vector vertices{}; - std::vector indices{}; - topology_type topology{}; -}; - -} // namespace pw - -#if 0 /* - * NOTE this needs to be rewritten to take into account for *any* kind of - * geometry Some ideas are drafted down there to separate out the attribute - * buffers. Things to consider: multiple UVs, triangle soup, per-vertex-color, - * texture transforms, weights, etc. pp. + * NOTE this needs to be rewritten to take into account for *any* kind of geometry + * Some ideas are drafted down there to separate out the attribute buffers. Things to + * consider: multiple UVs, triangle soup, per-vertex-color, texture transforms, weights, + * etc. pp. */ class geometry { - public: +public: + /** * @brief describes the topology for the primitives based on Vulkan */ @@ -79,16 +52,14 @@ class geometry { triangle_fan }; - using index_t = uint32_t; //< needs to be compatible with GL_UNSIGNED_INT + using index_t = uint32_t; //< needs to be compatible with GL_UNSIGNED_INT using indices_t = std::vector; geometry() = default; geometry(primitive_topology_type t, vector3_array v, indices_t i); ~geometry() = default; - void set_primitive_topology(primitive_topology_type t) { - _primitive_topology = t; - } + void set_primitive_topology(primitive_topology_type t) { _primitive_topology = t; } primitive_topology_type primitive_topology() { return _primitive_topology; } void set_vertices(vector3_array v); @@ -101,9 +72,7 @@ class geometry { const vector3_array& normals() const; void set_texture_coordinates(std::vector v); - const std::vector& texture_coordinates() const { - return _texture_coords; - } + const std::vector& texture_coordinates() const { return _texture_coords;} void transform(const matrix4x4& m); @@ -116,12 +85,13 @@ class geometry { uint64_t change_count() const { return _change_count; } void set_change_count(uint64_t n) { _change_count = n; } - protected: - primitive_topology_type _primitive_topology = - primitive_topology_type::point_list; - vector3_array _vertices; //!< vertex data - indices_t _indices; //!< indices +protected: + + primitive_topology_type _primitive_topology = primitive_topology_type::point_list; + + vector3_array _vertices; //!< vertex data + indices_t _indices; //!< indices vector3_array _normals; //!< normal data vector3_array _tangents; //!< tangent data @@ -129,13 +99,10 @@ class geometry { std::vector _texture_coords; //! texture coordinates - uint64_t _change_count{0}; + uint64_t _change_count { 0 }; }; -struct attribute final { - -}; +} #endif -#endif diff --git a/src/core/include/pw/core/globals.hpp b/src/core/include/pw/core/globals.hpp index aeeefbc..e66d0f6 100644 --- a/src/core/include/pw/core/globals.hpp +++ b/src/core/include/pw/core/globals.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -8,8 +8,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -24,9 +24,6 @@ #define PW_CORE_GLOBALS_HPP #include -#include -#include - #include #include #include @@ -37,9 +34,11 @@ using std::shared_ptr; using std::unique_ptr; using std::weak_ptr; -using std::make_shared; using std::make_unique; +using std::make_shared; -} // namespace pw +using real_t = float; + +} #endif diff --git a/src/core/include/pw/core/image.hpp b/src/core/include/pw/core/image.hpp index f5258f6..6fd14d7 100644 --- a/src/core/include/pw/core/image.hpp +++ b/src/core/include/pw/core/image.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -8,8 +8,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -29,53 +29,58 @@ namespace pw { class image { - public: - using size_type = pw::size; +public: image() = default; - using data_t = std::byte; + using data_t = std::byte; - enum pixel_layout { RGB8, RGBA8, LUM, DEPTH, HDR }; + enum pixel_layout { + RGB8, + RGBA8, + LUM, + DEPTH, + HDR + }; - image(const size_type& s, pixel_layout t, const data_t* ptr = nullptr); - bool create(const size_type& s, pixel_layout t, - const data_t* ptr = nullptr); + image(const size& s, pixel_layout t, const data_t *ptr = nullptr); - void release(bool release_memory = false); + bool create(const size& s, pixel_layout t, const data_t *ptr = nullptr); - const data_t* data() const { return _data.data(); } - data_t* data() { return _data.data(); } + void release(bool release_memory = false); - const float* data_float() const { - return reinterpret_cast(_data.data()); - } - float* data_float() { return reinterpret_cast(_data.data()); } + const data_t *data() const { return _data.data(); } + data_t *data() { return _data.data(); } + + const float *data_float() const { return reinterpret_cast(_data.data()); } + float *data_float() { return reinterpret_cast(_data.data());} pixel_layout layout() const; - void set_layout(const pixel_layout& layout); + void set_layout(const pixel_layout &layout); uint64_t change_count() const; - void set_change_count(const uint64_t& change_count); + void set_change_count(const uint64_t &change_count); static uint32_t bytes_per_pixel(pixel_layout t); static uint32_t components(pixel_layout t); - size_type size() const { return _size; } + ::pw::size size() const; void generate_noise(); bool is_valid() const; - protected: - size_type _size{.width = 0, .height = 0}; - pixel_layout _layout{pixel_layout::RGB8}; - uint64_t _change_count{0}; +protected: + + ::pw::size _size { 0, 0 }; + pixel_layout _layout { pixel_layout::RGB8 }; + uint64_t _change_count { 0 }; + + std::vector _data; - std::vector _data; }; -} // namespace pw +} #endif diff --git a/src/core/include/pw/core/material.hpp b/src/core/include/pw/core/material.hpp index dd29339..7e1dd98 100644 --- a/src/core/include/pw/core/material.hpp +++ b/src/core/include/pw/core/material.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -58,10 +58,13 @@ public: using texture_t = std::tuple; -protected: - vector4 _color = {{}, {1.0, 0.0, 1.0, 1.0}}; - std::vector _textures; + +protected: + + vector4 _color = vector4 { 1.0, 0.0, 1.0, 1.0 }; + + std::vector _textures; }; diff --git a/src/core/include/pw/core/math.hpp b/src/core/include/pw/core/math.hpp index 2ba1347..61cd9e3 100644 --- a/src/core/include/pw/core/math.hpp +++ b/src/core/include/pw/core/math.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -8,8 +8,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -23,60 +23,55 @@ #ifndef PW_CORE_MATH_HPP #define PW_CORE_MATH_HPP -#include #include -#include -#include +#include +//#include +//#include namespace pw { -static constexpr double __PW_PI{ - 3.1415926535897932384626433832795028841971693993751058209}; -static constexpr double __PW_PI_DOUBLE{2 * __PW_PI}; +constexpr double __PW_PI = 3.1415926535897932384626433832795028841971693993751058209; +constexpr double __PW_PI_DOUBLE = 2.0 * __PW_PI; -template inline static constexpr T pi() { - return static_cast(__PW_PI); +template +inline const T pi() { return static_cast(__PW_PI); } + +template +inline const T one_over_pi() { return static_cast(1 / __PW_PI); } + +template +inline T rad_to_deg(const T& angle_in_radian) { + return angle_in_radian * static_cast(180) * one_over_pi(); } -template inline const T one_over_pi() { - return static_cast(1 / __PW_PI); +template +inline T deg_to_rad(const T& angle_in_degree) { + return angle_in_degree * pi() / static_cast(180); } -template inline T rad_to_deg(const T& angle_in_radian) { - return angle_in_radian * static_cast(180) * one_over_pi(); +template +inline T repeat(const T& t, const T& length) { + return std::clamp(t - std::floor(t / length) * length, T(0), length); } -template inline T deg_to_rad(const T& angle_in_degree) { - return angle_in_degree * pi() / static_cast(180); +template +inline T ping_pong(const T& t,const T& length) { + auto tn = repeat(t, length * T(2)); + return length - std::abs(tn - length); } -template inline T repeat(const T& t, const T& length) { - return std::clamp(t - std::floor(t / length) * length, T{}, length); +template +inline T wrap_angle(const T& angle_in_radian) { + using std::floor; + return angle_in_radian - __PW_PI_DOUBLE * floor( angle_in_radian / __PW_PI_DOUBLE ); } -template inline T ping_pong(const T& t, const T& length) { - auto tn = repeat(t, length * T{2}); - return length - std::abs(tn - length); -} - -template inline T wrap_angle(const T& angle_in_radian) { - using std::floor; - return angle_in_radian - - __PW_PI_DOUBLE * floor(angle_in_radian / __PW_PI_DOUBLE); -} - -// void extractRotation(const matrix &A, Quaterniond &q,const unsigned int -// maxIter) +//void extractRotation(const matrix &A, Quaterniond &q,const unsigned int maxIter) //{ // for (auto iter = 0; iter < maxIter; iter++){ // auto R = q.matrix(); -// Vector3d omega = (R.col(0).cross(A.col(0)) + -// R.col(1).cross(A.col(1)) + R.col(2).cross(A.col(2)))*(1.0 / -// fabs(R.col(0).dot(A.col(0)) + R.col(1).dot(A.col(1)) + -// R.col(2).dot(A.col(2))) +1.0e-9);double w = omega.norm();if (w -//< 1.0e-9)break;q = Quaterniond(AngleAxisd(w, (1.0 / -// w)*omega))*q;q.normalize();}} +// Vector3d omega = (R.col(0).cross(A.col(0)) + R.col(1).cross(A.col(1)) + R.col(2).cross(A.col(2)))*(1.0 / fabs(R.col(0).dot(A.col(0)) + R.col(1).dot(A.col(1)) + R.col(2).dot(A.col(2))) +1.0e-9);double w = omega.norm();if (w < 1.0e-9)break;q = Quaterniond(AngleAxisd(w, (1.0 / w)*omega))*q;q.normalize();}} -} // namespace pw +} #endif diff --git a/src/core/include/pw/core/matrix.hpp b/src/core/include/pw/core/matrix.hpp index 1111708..afacaea 100644 --- a/src/core/include/pw/core/matrix.hpp +++ b/src/core/include/pw/core/matrix.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -8,8 +8,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -25,279 +25,255 @@ #include #include -#include +#include -#include -#include +#include +#include -namespace pw { +namespace pw +{ -template -struct matrix final { + template + struct matrix_ : matrixbase_> + { + T data[R * C]; - static_assert(Rows > 0 && Cols > 0, "Undefined matrix type."); + using matrixbase_>::matrixbase_; - static constexpr unsigned int diag_size{std::min(Rows, Cols)}; - static constexpr unsigned int rows{Rows}; - static constexpr unsigned int cols{Cols}; - static constexpr bool is_square{Rows == Cols}; + static constexpr std::size_t rows{R}; + static constexpr std::size_t cols{C}; - using size_type = std::common_type_t; - using row_type = vector; - using column_type = vector; - using diag_type = vector; - using transpose_type = matrix; - using minor_type = matrix; + static constexpr std::size_t coefficients{R * C}; - using reference = row_type&; - using const_reference = const row_type&; - using pointer = row_type*; - using const_pointer = const row_type*; + using col_type = matrix_; + using row_type = matrix_<1, C, T>; + using transpose_type = matrix_; - vector m_{}; + matrix_ &operator=(const matrix_ &other) + { + for (size_t i = 0; i < other.size(); i++) + (*this)[i] = other[i]; + return *this; + } - auto&& data(this auto&& self) { - return std::forward(self).m_[0].data(); - } + matrix_(std::initializer_list args) + { + typename std::initializer_list::iterator it = args.begin(); + for (; it != args.end(); it++) + data[it - args.begin()] = *it; + } - auto&& operator[](this auto&& self, int r) { - return std::forward(self).m_[r]; - } + template + matrix_ &set(Arguments... values) + { + static_assert(sizeof...(Arguments) == R * C, "Incorrect number of arguments"); + data = {values...}; + return *this; + } - // - // part of tuple-protocol - // - template auto get(this auto&& self) -> decltype(auto) { - static_assert(idx < Rows, "Out of bounds access to a member."); - // TODO: use forward_like when clang is catching up - return std::forward_like(self.m_[idx]); - // return std::forward(self).m_[idx]; - } + inline size_t offset(size_t r, size_t c) const + { + return (RowMajor) ? r * C + c : c * R + r; + } - constexpr auto diagonal() const noexcept -> diag_type { - return [this](std::index_sequence) { - return diag_type{(*this)[Is][Is]...}; - }(std::make_index_sequence{}); - } + inline T &operator()(std::size_t r, std::size_t c) + { + return data[offset(r, c)]; + } - constexpr auto trace() const noexcept -> Scalar { - static_assert(Rows == Cols, - "trace is only defined for square matrices"); - return [this, sum = Scalar{0}]( - std::index_sequence) mutable { - return ((*this)[Is][Is] + ... + sum); - }(std::make_index_sequence{}); - } + inline const T &operator()(std::size_t r, std::size_t c) const + { + return data[offset(r, c)]; + } - constexpr auto column(const unsigned int& c) const noexcept -> column_type { - return [this, &c](std::index_sequence) { - return column_type{(*this)[Rs][c]...}; - }(std::make_index_sequence{}); - } + inline const T *ptr() const { return &data[0]; } - constexpr auto transposed() const noexcept -> transpose_type { - return [this](std::index_sequence) { - return transpose_type{(*this).column(Cs)...}; - }(std::make_index_sequence{}); - } + //! set identity + inline matrix_ &set_identity() + { + for (std::size_t r = 0; r < rows; r++) + for (std::size_t c = 0; c < cols; c++) + (*this)(r, c) = (c == r) ? T(1) : T(0); + return *this; + } - static constexpr auto all(const Scalar& value) { - return [&value](std::index_sequence) { - return matrix{vector::all((value) + Rs - Rs)...}; - }(std::make_index_sequence{}); - } + inline matrix_ &set_uniform(const T& v) + { + std::fill(std::begin(data),std::end(data),v); + return *this; + } - static constexpr auto identity() noexcept -> matrix { - static_assert(Rows == Cols, - "identity only defined for square matrices"); - return [](std::index_sequence) { - return matrix{vector::basis(Rs)...}; - }(std::make_index_sequence{}); - } + template + auto slice(std::size_t r, std::size_t c) const + { + matrix_ s; + for (std::size_t ri = 0; ri < Rs; ri++) + for (std::size_t ci = 0; ci < Cs; ci++) + s(ri, ci) = (*this)(ri + r, ci + c); + return s; + } - static constexpr auto from_diagonal(const diag_type& d) noexcept -> matrix { - static_assert( - Rows == Cols, - "creating from diagonal vector only defined for square matrices"); - return [&d](std::index_sequence) { - return matrix{vector::basis(Rs) * d[Rs]...}; - }(std::make_index_sequence{}); - } + template + matrix_ &set_slice(const matrix_ &s, + std::size_t r, std::size_t c) + { + for (std::size_t ri = 0; ri < Rs; ri++) + for (std::size_t ci = 0; ci < Cs; ci++) + (*this)(ri + r, ci + c) = s(ri, ci); + return *this; + } - constexpr auto minor(std::unsigned_integral auto r0, - std::unsigned_integral auto c0) const noexcept { - static_assert(Rows > 1 && Cols > 1, "cannot create minor matrix"); - return [this, &r0, &c0](std::index_sequence) { - return matrix{ - (*this)[(Rs < r0) ? Rs : Rs + 1].minor(c0)...}; - }(std::make_index_sequence{}); - } + template + auto minor(std::size_t r0, std::size_t c0) const + { + matrix_ m; + size_t r = 0; + for (size_t ri = 0; ri < R; ri++) + { + size_t c = 0; + if (ri == r0) + continue; + for (size_t ci = 0; ci < C; ci++) + { + if (ci == c0) + continue; + m(r, c) = (*this)(ri, ci); + c++; + } + r++; + } + return m; + } - constexpr auto determinant() const noexcept -> Scalar { - static_assert(Rows == Cols, - "determinant only defined for square matrices"); - return [this](std::index_sequence) { - return ((((Cs % 2 == 0) ? (*this)[0][Cs] : -(*this)[0][Cs]) * - (*this).minor(0u, Cs).determinant()) + - ...); - }(std::make_index_sequence{}); - } + T determinant() const + { + T det(0); + for (size_t c = 0; c < C; c++) + det += ((c % 2 == 0) ? (*this)(0, c) : -(*this)(0, c)) * this->minor(0, c).determinant(); + return det; + } - constexpr auto inverse() const noexcept -> matrix { - const auto inv_det{Scalar(1) / this->determinant()}; - matrix inv; // no initialization needed! - for (auto c = 0u; c < Cols; c++) { - for (auto r = 0u; r < Rows; r++) { - const auto min_det = this->minor(r, c).determinant(); - const auto co_fact{((r + c) % 2 == 1) ? -min_det : min_det}; - inv[r][c] = inv_det * co_fact; - } - } - return inv; - } + auto transposed() const + { + transpose_type res; + for (size_t r = rows; r-- > 0;) + for (size_t c = cols; c-- > 0;) + res(c, r) = (*this)(r, c); + return res; + } - constexpr matrix operator*(const Scalar& v) const noexcept { - return [this, &v](std::index_sequence) { - return matrix{((*this)[Rs] * v)...}; - }(std::make_index_sequence{}); - } - constexpr matrix operator/(const Scalar& v) const noexcept { - return operator*(Scalar{1} / v); - } + auto inverse() const + { + T invDet = T(1) / this->determinant(); + matrix_ inv; + for (int j = 0; j < C; j++) + for (int i = 0; i < R; i++) + { + const T minorDet = this->minor(j, i).determinant(); + const T coFactor = ((i + j) % 2 == 1) ? -minorDet : minorDet; + inv(i, j) = invDet * coFactor; + } + return inv; + } - constexpr matrix operator+(const Scalar& v) const noexcept { - return [this, &v](std::index_sequence) { - return matrix{((*this)[Rs] + v)...}; - }(std::make_index_sequence{}); - } - constexpr matrix operator-(const Scalar& v) const noexcept { - return operator+(-v); - } + inline bool row_major() const + { + return RowMajor; + } - constexpr auto operator*=(const Scalar& v) noexcept { - [this, &v](std::index_sequence) { - (((*this)[Rs] *= v), ...); - }(std::make_index_sequence{}); - return *this; - } + inline bool square() const { return R == C; } - constexpr auto operator/=(const Scalar& v) noexcept { - return operator*=(Scalar{1} / v); - } + inline const matrix_ operator+(const matrix_ &other) const + { + matrix_ res(*this); + for (size_t r = 0; r < R; r++) + for (size_t c = 0; c < C; c++) + res(r, c) += other(r, c); + return res; + } - constexpr auto operator+=(const Scalar& v) noexcept { - [this, &v](std::index_sequence) { - (((*this)[Rs] += v), ...); - }(std::make_index_sequence{}); - return *this; - } + inline const matrix_ operator-(const matrix_ &other) const + { + matrix_ res(*this); + for (size_t r = 0; r < R; r++) + for (size_t c = 0; c < C; c++) + res(r, c) -= other(r, c); + return res; + } - constexpr auto operator-=(const Scalar& v) noexcept { - return operator+=(-v); - } + auto row(size_t row_) const + { + row_type r; + for (size_t i = 0; i < cols; i++) + r[i] = (*this)(row_, i); + return r; + } - template - constexpr auto slice(std::size_t r = 0, std::size_t c = 0) const noexcept - -> matrix { - return [&r, &c, this](std::index_sequence) { - return matrix{(*this)[r + Rs].slice( - std::make_index_sequence{}, c)...}; - }(std::make_index_sequence{}); // rowwise expansion - } + auto column(size_t col_) const + { + col_type c; + for (size_t i = 0; i < rows; i++) + c[i] = (*this)(i, col_); + return c; + } - constexpr auto unproject(const Scalar& w) const noexcept - -> matrix { - return [&w, this](std::index_sequence) { - return matrix{ - (Rs < Rows) ? (*this)[Rs].unproject(0) - : vector::basis(Cols) * w...}; - }(std::make_index_sequence{}); // rowwise expansion - } + static constexpr auto identity() + { + matrix_ res; + for (std::size_t r = 0; r < rows; r++) + for (std::size_t c = 0; c < cols; c++) + res(r, c) = (c == r) ? T(1) : T(0); + return res; + } + }; - // - // Iterators - // - constexpr const_pointer begin() const { return &m_[0]; } + template <> + inline float matrix_<1, 1, float>::determinant() const + { + return (*this)(0, 0); + } - constexpr const_pointer end() const { return &m_[Rows]; } -}; + template <> + inline double matrix_<1, 1, double>::determinant() const + { + return (*this)(0, 0); + } -template <> constexpr float matrix::determinant() const noexcept { - return (*this)[0][0]; + template + auto operator*(const matrix_ &A, + const matrix_ &B) + { + matrix_ result; + result.zero(); // zero the output + for (size_t r = 0; r < R; r++) + for (size_t c = 0; c < Cb; c++) + for (size_t iI = 0; iI < R; iI++) + result(r, c) += A(r, iI) * B(iI, c); // inner product + return result; + } + + // + // common matrix types + // + + template + using matrix2x2_ = matrix_<2, 2, T>; + template + using matrix3x3_ = matrix_<3, 3, T>; + template + using matrix4x4_ = matrix_<4, 4, T>; + + using matrix2x2f = matrix2x2_; + using matrix2x2d = matrix2x2_; + using matrix2x2 = matrix2x2_; + + using matrix3x3f = matrix3x3_; + using matrix3x3d = matrix3x3_; + using matrix3x3 = matrix3x3_; + + using matrix4x4f = matrix4x4_; + using matrix4x4d = matrix4x4_; + using matrix4x4 = matrix4x4_; } -template <> -constexpr double matrix::determinant() const noexcept { - return (*this)[0][0]; -} - -template -constexpr auto operator*(const matrix& A, - const matrix& B) noexcept { - matrix result{}; - [&result, &A, &B](std::index_sequence) { - ( - [&](auto&& Ai, std::index_sequence) { - ( - [&](auto&& Ai, auto&& Bi, - std::index_sequence) { - ((result[Ai][Bi] += A[Ai][iI] * B[iI][Bi]), - ...); // do the actual multiplication - }(Ai, Ib, std::make_index_sequence{}), - ...); // forward row of A, colum of B and unpack inner loop - }(Ia, std::make_index_sequence{}), - ...); // forward current row, unpack A - }(std::make_index_sequence{}); // rows of A as input - return result; -} - -template -constexpr auto operator*(const matrix& A, - const vector& B) noexcept { - // first step - should move to concepts to allow for std::array and - // std::span to be allowed - vector, Ca> result{}; - [&result, &A, &B](std::index_sequence) { - ( - [&](auto&& Ai, std::index_sequence) { - ((result[Ib] += A[Ai][Ib] * B[Ib]), ...); - }(Ia, std::make_index_sequence{}), - ...); // forward current row, unpack A - }(std::make_index_sequence{}); // rows of A as input - return result; -} - -// -// deduction guides -// - -// -// type aliases -// -template using matrix2x2 = matrix; -template using matrix3x3 = matrix; -template using matrix4x4 = matrix; - -using matrix2x2f = matrix2x2; -using matrix3x3f = matrix3x3; -using matrix4x4f = matrix4x4; - -using matrix2x2d = matrix2x2; -using matrix3x3d = matrix3x3; -using matrix4x4d = matrix4x4; - -} // namespace pw - -// -// tuple protocol -// -template -struct std::tuple_size> - : std::integral_constant {}; - -template -struct std::tuple_element> { - using type = pw::matrix::row_type; -}; - #endif diff --git a/src/core/include/pw/core/matrix_transform.hpp b/src/core/include/pw/core/matrix_transform.hpp index f3ec0b9..7131fe3 100644 --- a/src/core/include/pw/core/matrix_transform.hpp +++ b/src/core/include/pw/core/matrix_transform.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -8,8 +8,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -23,159 +23,149 @@ #ifndef PW_CORE_MATRIX_TRANSFORM_HPP #define PW_CORE_MATRIX_TRANSFORM_HPP -#include -#include -#include #include namespace pw { +template struct matrix_transform { - template - constexpr static auto - scale_matrix(vector&& diag) noexcept -> matrix { - return matrix::from_diagonal( - std::forward>(diag)); + inline static + matrix_<4,4,T> scale_matrix(const vector3_& s) + { + matrix_<4,4,T> scale; scale.zero(); + scale(0,0) = s[0]; scale(1,1) = s[1]; scale(2,2) = s[2]; scale(3,3) = T(1); + return scale; } - template - constexpr static auto - frustum_matrix(const frustum& f) -> matrix { + inline static + matrix_<4,4,T> perspective_frustum_rh(const T &left,const T &right, + const T &bottom,const T &top, + const T &z_near,const T &z_far) + { + matrix_<4,4,T> frustum; frustum.zero(); - const auto Sx{Scalar{2} * f.z_near / (f.right - f.left)}; - const auto Sy{Scalar{2} * f.z_near / (f.top - f.bottom)}; + frustum(0,0) = T(2) * z_near / (right - left); + frustum(1,1) = T(2) * z_near / (top - bottom); - const auto A{(f.right + f.left) / (f.right - f.left)}; - const auto B{(f.top + f.bottom) / (f.top - f.bottom)}; - const auto C{-(f.z_far + f.z_near) / (f.z_far - f.z_near)}; - const auto D{-Scalar{2} * f.z_far * f.z_near / (f.z_far - f.z_near)}; + frustum(0,2) = (right+left)/(right-left); //A + frustum(1,2) = (top+bottom)/(top-bottom); //B + frustum(2,2) = -(z_far+z_near)/(z_far-z_near); //C + frustum(2,3) = -T(2) * z_far*z_near/(z_far-z_near); //D - return { - vector{Sx, 0, A, 0 }, // - vector{0, Sy, B, 0 }, // - vector{0, 0, C, D }, // - vector{0, 0, -1, Scalar{1}} // - }; - } + frustum(3,2) = -T(1); - template - constexpr static auto - look_at_matrix(vector3 position, vector3 target, - vector3 up) -> matrix { + return frustum; + } - const auto lofs = (target - position).normalized(); // line of sight - const auto side = lofs.cross(up).normalized(); // side vector - const auto upvc = side.cross(lofs).normalized(); // upvector - return {side.unproject(0), upvc.unproject(0), - lofs.unproject(0) * Scalar{-1}, position.unproject(1)}; - } -}; +// /// creates a projection from a frustum planes with a reversed depth mapped to [0..1] +// pub fn make_projection_rh_from_frustum_reversed( +// left: f32, +// right: f32, +// bottom: f32, +// top: f32, +// z_near: f32, +// z_far: f32, +// ) -> Mat4 { +// assert!(z_near > 0.0 && z_far > 0.0); -#if 0 +// // info!("near {:?}", z_near); - // /// creates a projection from a frustum planes with a reversed depth - // mapped to [0..1] pub fn make_projection_rh_from_frustum_reversed( - // left: f32, - // right: f32, - // bottom: f32, - // top: f32, - // z_near: f32, - // z_far: f32, - // ) -> Mat4 { - // assert!(z_near > 0.0 && z_far > 0.0); +// // +// // reversed z 0..1 projection +// // +// let a = (right + left) / (right - left); // position in frame horizontal +// let b = (top + bottom) / (top - bottom); // position in frame vertical - // // info!("near {:?}", z_near); +// let c = z_near / (z_far - z_near); // lower bound +// let d = z_far * z_near / (z_far - z_near); // upper bound - // // - // // reversed z 0..1 projection - // // - // let a = (right + left) / (right - left); // position in frame - // horizontal let b = (top + bottom) / (top - bottom); // position in - // frame vertical +// let sx = 2.0 * z_near / (right - left); // scale x +// let sy = 2.0 * z_near / (top - bottom); // scale y - // let c = z_near / (z_far - z_near); // lower bound - // let d = z_far * z_near / (z_far - z_near); // upper bound +// // reverse z 0..1 +// // -------------- +// // sx 0 a 0 +// // 0 sy b 0 +// // 0 0 c d +// // 0 0 -1 0 - // let sx = 2.0 * z_near / (right - left); // scale x - // let sy = 2.0 * z_near / (top - bottom); // scale y +// Mat4::from_cols( +// Vec4::new(sx, 0.0, 0.0, 0.0), +// Vec4::new(0.0, sy, 0.0, 0.0), +// Vec4::new(a, b, c, -1.0), +// Vec4::new(0.0, 0.0, d, 0.0), +// ) +// } + inline static + matrix_<4,4,T> perspective_projection(const T &field_of_view, + const T &aspect_ratio, + const T &z_near,const T &z_far) + { + const auto tan_half = tan(field_of_view / T(2)); + const auto right = tan_half * z_near / aspect_ratio; + const auto left = -right; + const auto top = right / aspect_ratio; + const auto bottom = -top; - // // reverse z 0..1 - // // -------------- - // // sx 0 a 0 - // // 0 sy b 0 - // // 0 0 c d - // // 0 0 -1 0 + return perspective_frustum_rh(left,right, + bottom,top, + z_near,z_far); + } - // Mat4::from_cols( - // Vec4::new(sx, 0.0, 0.0, 0.0), - // Vec4::new(0.0, sy, 0.0, 0.0), - // Vec4::new(a, b, c, -1.0), - // Vec4::new(0.0, 0.0, d, 0.0), - // ) - // } - inline static matrix_<4, 4, T> - perspective_projection(const T& field_of_view, const T& aspect_ratio, - const T& z_near, const T& z_far) { - const auto tan_half = tan(field_of_view / T(2)); - const auto right = tan_half * z_near / aspect_ratio; - const auto left = -right; - const auto top = right / aspect_ratio; - const auto bottom = -top; - return perspective_frustum_rh(left, right, bottom, top, z_near, z_far); - } + inline static + matrix_<4,4,T> orthographic_frustum(T left, T right, + T bottom,T top, + T z_near, T z_far) + { - inline static matrix_<4, 4, T> - orthographic_frustum(T left, T right, T bottom, T top, T z_near, T z_far) { + matrix_<4,4,T> ortho; ortho.fill(0); - matrix_<4, 4, T> ortho; - ortho.fill(0); + ortho(0,0) = static_cast(2) / (right-left); + ortho(1,1) = static_cast(2) / (top-bottom); + ortho(2,2) = -static_cast(2) / (z_far-z_near); - ortho(0, 0) = static_cast(2) / (right - left); - ortho(1, 1) = static_cast(2) / (top - bottom); - ortho(2, 2) = -static_cast(2) / (z_far - z_near); + ortho(3,0) = -(right+left)/(right-left); + ortho(3,1) = -(top+bottom)/(top-bottom); + ortho(3,2) = -(z_far+z_near)/(z_far-z_near); - ortho(3, 0) = -(right + left) / (right - left); - ortho(3, 1) = -(top + bottom) / (top - bottom); - ortho(3, 2) = -(z_far + z_near) / (z_far - z_near); - - ortho(3, 3) = 1; + ortho(3,3) = 1; return ortho; } - inline static matrix_<4, 4, T> orthographic_projection(T width, T height, - T z_near, T z_far) { - return orthographic_frustum(-width / 2, width / 2, -height / 2, - height / 2, z_near, z_far); - } + inline static + matrix_<4,4,T> orthographic_projection(T width,T height,T z_near, T z_far) + { + return orthographic_frustum(-width / 2, width / 2, + -height / 2, height / 2, + z_near,z_far); + } - inline static matrix_<4, 4, T> look_at(const vector3_& position, - const vector3_& target, - const vector3_& up) { - matrix_<4, 4, T> view_matrix; - view_matrix.set_identity(); - const vector3_ los = - (target - position).normalized(); // line of sight - const vector3_ sid = - vector3_::cross(los, up).normalized(); // side vector - const vector3_ upd = - vector3_::cross(sid, los).normalized(); // upvector + inline static + matrix_<4,4,T> look_at(const vector3_ &position, + const vector3_ &target, + const vector3_ &up) + { + matrix_<4,4,T> view_matrix; view_matrix.set_identity(); + + const vector3_ los = (target - position).normalized(); // line of sight + const vector3_ sid = vector3_::cross(los,up).normalized(); // side vector + const vector3_ upd = vector3_::cross(sid,los).normalized(); // upvector // set base vectors - view_matrix.set_slice(sid, 0, 0); - view_matrix.set_slice(upd, 0, 1); - view_matrix.set_slice(los * T(-1), 0, 2); - view_matrix.set_slice(position, 0, 3); + view_matrix.set_slice(sid, 0, 0); + view_matrix.set_slice(upd, 0, 1); + view_matrix.set_slice(los * T(-1), 0, 2); + view_matrix.set_slice(position, 0, 3); - return view_matrix; + return view_matrix; } - -#endif - -} // namespace pw +}; + +} #endif diff --git a/src/core/include/pw/core/matrixbase.hpp b/src/core/include/pw/core/matrixbase.hpp new file mode 100644 index 0000000..e3f3a3d --- /dev/null +++ b/src/core/include/pw/core/matrixbase.hpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) 1999-2021 Hartmut Seichter + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +#ifndef PW_CORE_MATRIXBASE_HPP +#define PW_CORE_MATRIXBASE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace pw { + +template +struct matrixbase_ { + + using value_type = T; + + Derived& derived() { return static_cast(*this); } + const Derived& derived() const { return static_cast(*this); } + + std::size_t size() const { + return std::extent::value; + } + + Derived& fill(const T& v) { + std::fill(std::begin(derived().data), std::end(derived().data), T(v)); + return derived(); + } + + Derived& zero() { + return derived().fill(0); + } + + inline T squared_norm() const { + return std::accumulate(std::begin(derived().data),std::end(derived().data), T(0), + [&](const T& a,const T& b){ + return a + b * b; + }); + } + + inline T norm() const { + return std::sqrt(squared_norm()); + } + + inline constexpr Derived normalized() const { + return *this / this->norm() ; + } + + inline void normalize() { + *this /= this->norm(); + } + + using iterator = T*; + using const_iterator = const T*; + iterator begin() { return &derived().data[0]; } + iterator end() { return &derived().data[0] + size(); } + const_iterator begin() const { return &derived().data[0]; } + const_iterator end() const { return &derived().data[0] + size(); } + + T& operator [] (std::size_t i) { + return derived().data[i]; + } + + const T& operator [] (std::size_t i) const { + return derived().data[i]; + } + + static constexpr T dot(const Derived &a,const Derived &b) + { + return std::inner_product(std::begin(a),std::end(a),std::begin(b),T(0)); + } + + static constexpr Derived lerp(const Derived &a,const Derived &b,const T& t) + { + return a + (b - a) * t; + } + + + inline void operator *= (const T& b) { for (auto & e : *this) e *= b; } + inline void operator /= (const T& b) { for (auto & e : *this) e /= b; } + inline void operator += (const T& b) { for (auto & e : *this) e += b; } + inline void operator -= (const T& b) { for (auto & e : *this) e -= b; } + + inline const Derived operator * (const T& b) const { Derived r(derived()); for (auto & e : r) e *= b; return r; } + inline const Derived operator / (const T& b) const { Derived r(derived()); for (auto & e : r) e /= b; return r; } + inline const Derived operator + (const T& b) const { Derived r(derived()); for (auto & e : r) e += b; return r; } + inline const Derived operator - (const T& b) const { Derived r(derived()); for (auto & e : r) e -= b; return r; } + + +}; + +} + + +#endif diff --git a/src/core/include/pw/core/mesh.hpp b/src/core/include/pw/core/mesh.hpp deleted file mode 100644 index a85b5c9..0000000 --- a/src/core/include/pw/core/mesh.hpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 1999-2024 Hartmut Seichter - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ -#ifndef PW_CORE_MESH_HPP -#define PW_CORE_MESH_HPP - -#include -#include - -#include -#include - -namespace pw { - -struct attribute final { - using mask_type = std::vector; - using int8_type = std::vector; - using int32_type = std::vector; - using float_type = std::vector; - using vector2_type = std::vector>; - using vector3_type = std::vector>; - using vector4_type = std::vector>; - - using attribute_data = - std::variant; - - enum attribute_type { - normals, - texture_coordinates, - }; - - attribute_type type{}; - attribute_data data{}; -}; - -struct mesh { - primitives geometry{}; - std::vector attributes; - - std::atomic change_count{0}; -}; - -} // namespace pw - -#endif diff --git a/src/core/include/pw/core/point.hpp b/src/core/include/pw/core/point.hpp index 9b08bc8..5a541ca 100644 --- a/src/core/include/pw/core/point.hpp +++ b/src/core/include/pw/core/point.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -8,8 +8,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -23,14 +23,32 @@ #ifndef PW_CORE_POINT_HPP #define PW_CORE_POINT_HPP -#include #include -#include namespace pw { -template using point = vector; +template +struct point_ { -} // namespace pw + using value_type = T_; + + T_ x {0}, y {0}; + + point_() = default; + point_(T_ x_,T_ y_) : x(x_), y(y_) {} + + template + point_ cast() const { return point_(static_cast(x),static_cast(y)); } + +}; + +using point = point_; + +using pointf = point_; +using pointd = point_; +using pointi = point_; + + +} #endif diff --git a/src/core/include/pw/core/quaternion.hpp b/src/core/include/pw/core/quaternion.hpp index 3ff5b1e..8ba1d34 100644 --- a/src/core/include/pw/core/quaternion.hpp +++ b/src/core/include/pw/core/quaternion.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -8,8 +8,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -23,313 +23,172 @@ #ifndef PW_CORE_QUATERNION_HPP #define PW_CORE_QUATERNION_HPP -#include -#include #include - -#include +#include namespace pw { /** * simplified quaternion class */ -template struct quaternion final { +template +struct quaternion_ : vector4_ { - using value_type = vector; + typedef vector4_ base_type; - value_type q_{value_type::basis(3)}; // preset to identity + using typename base_type::value_type; + using base_type::base_type; + using base_type::x; + using base_type::y; + using base_type::z; + using base_type::w; + using base_type::lerp; + using base_type::xyz; +// using base_type::operator*; +// using base_type::operator/; - auto&& x(this auto&& self) { - return std::forward(self).q_.x(); - } - auto&& y(this auto&& self) { - return std::forward(self).q_.y(); - } - auto&& z(this auto&& self) { - return std::forward(self).q_.z(); - } - auto&& w(this auto&& self) { - return std::forward(self).q_.w(); - } - constexpr auto - operator*(const quaternion& rhs) const noexcept -> quaternion { - return {rhs.w() * x() + rhs.x() * w() + rhs.y() * z() - rhs.z() * y(), - rhs.w() * y() - rhs.x() * z() + rhs.y() * w() + rhs.z() * x(), - rhs.w() * z() + rhs.x() * y() - rhs.y() * x() + rhs.z() * w(), - rhs.w() * w() - rhs.x() * x() - rhs.y() * y() - rhs.z() * z()}; - } + quaternion_(const base_type& other) : base_type(other) {} - constexpr auto conjugate() const noexcept -> quaternion { - return {-x(), -y(), -z(), w()}; - } + inline const quaternion_ operator * (const quaternion_& rhs) const { + return quaternion_( + rhs.w()*x() + rhs.x()*w() + rhs.y()*z() - rhs.z()*y(), + rhs.w()*y() - rhs.x()*z() + rhs.y()*w() + rhs.z()*x(), + rhs.w()*z() + rhs.x()*y() - rhs.y()*x() + rhs.z()*w(), + rhs.w()*w() - rhs.x()*x() - rhs.y()*y() - rhs.z()*z() + ); + } - constexpr auto norm() const noexcept -> Scalar { return q_.norm(); } + inline auto operator / (const T& rhs) const { + return quaternion_( { x() / rhs, y() / rhs, z() / rhs, w() / rhs, } ); + } - constexpr auto operator*(const Scalar& rhs) const noexcept -> quaternion { - return {.q_ = q_ * rhs}; - } + //! conjugate + inline auto conjugate() const { return quaternion_( { -x(),-y(),-z(),w() } ); } - constexpr auto operator/(const Scalar& rhs) const noexcept -> quaternion { - return operator*(Scalar{1} / rhs); - } + //! compute inverse + inline auto inverse() const { + return conjugate() / this->norm(); + } - constexpr auto normalized() const noexcept -> quaternion { - return {.q_ = q_.normalized()}; - } + inline static auto identity() { + return quaternion_({0,0,0,1}); + } - constexpr auto inverse() const noexcept -> quaternion { - return conjugate() / this->norm(); - } + const matrix4x4_ to_matrix() const { - constexpr auto dot(const quaternion& b) const noexcept -> Scalar { - return q_.dot(b.q_); - } + matrix4x4_ m; m.set_identity(); - constexpr auto to_matrix() const noexcept -> matrix { + T xx = x() * x(); + T xy = x() * y(); + T xz = x() * z(); + T xw = x() * w(); - const Scalar xx = x() * x(); - const Scalar xy = x() * y(); - const Scalar xz = x() * z(); - const Scalar xw = x() * w(); + T yy = y() * y(); + T yz = y() * z(); + T yw = y() * w(); - const Scalar yy = y() * y(); - const Scalar yz = y() * z(); - const Scalar yw = y() * w(); + T zz = z() * z(); + T zw = z() * w(); - const Scalar zz = z() * z(); - const Scalar zw = z() * w(); + m(0,0) = 1 - 2 * ( yy + zz ); + m(0,1) = 2 * ( xy - zw ); + m(0,2) = 2 * ( xz + yw ); - return { - vector{1 - 2 * (yy + zz), 2 * (xy - zw), 2 * (xz + yw)}, - vector{2 * (xy + zw), 1 - 2 * (xx + zz), 2 * (yz - xw)}, - vector{2 * (xz - yw), 2 * (yz + xw), 1 - 2 * (xx + yy)}, - }; - } + m(1,0) = 2 * ( xy + zw ); + m(1,1) = 1 - 2 * ( xx + zz ); + m(1,2) = 2 * ( yz - xw ); - static constexpr auto identity() noexcept -> quaternion { return {}; } + m(2,0) = 2 * ( xz - yw ); + m(2,1) = 2 * ( yz + xw ); + m(2,2) = 1 - 2 * ( xx + yy ); - static constexpr auto pi_around_x() noexcept -> quaternion { - return {Scalar{1}, Scalar{0}, Scalar{0}, Scalar{0}}; - } + return m; + } - static constexpr auto pi_around_y() noexcept -> quaternion { - return {Scalar{0}, Scalar{1}, Scalar{0}, Scalar{0}}; - } - - static constexpr auto pi_around_z() noexcept -> quaternion { - return {Scalar{0}, Scalar{0}, Scalar{1}, Scalar{0}}; - } - - static constexpr auto lerp(const quaternion& a, const quaternion& b, - const Scalar& t) -> quaternion { - return {value_type::lerp(a.q_, b.q_, t).normalized()}; - } - - /** - * @note: a and b need to be normalized - */ - static constexpr auto - slerp(const quaternion& a, const quaternion& b, const Scalar& t, - const Scalar& eps = Scalar{0.001}) -> quaternion { - - // Calculate angle between them. - const Scalar cos_half_theta{a.dot(b)}; - - // if qa=qb or qa=-qb then theta = 0 and we can return a - if (std::fabs(cos_half_theta) >= Scalar{1}) { - return a; - } - - // Calculate temporary values. - const Scalar half_theta{std::acos(cos_half_theta)}; - const Scalar sin_half_theta{ - std::sqrt(Scalar{1} - cos_half_theta * cos_half_theta)}; - - // if theta = 180 degrees then result is not fully defined - // we could rotate around any axis normal to a or b - const auto is_pi = std::fabs(sin_half_theta) < eps; - - // now do the lerp either halfway or across unit sphere - const Scalar ratio_a{is_pi ? Scalar{0.5} - : std::sin((Scalar{1} - t) * half_theta) / - sin_half_theta}; - - const Scalar ratio_b{is_pi ? Scalar{0.5} - : std::sin(t * half_theta) / sin_half_theta}; - return { - (a.x() * ratio_a + b.x() * ratio_b), // x - (a.y() * ratio_a + b.y() * ratio_b), // y - (a.z() * ratio_a + b.z() * ratio_b), // z - (a.w() * ratio_a + b.w() * ratio_b) // w - }; - } - - static constexpr auto - from_axisangle(const axisangle& aa) -> quaternion { - - const auto sin_half_angle{std::sin(aa.angle / Scalar{2})}; - - return { - aa.axis.x() * sin_half_angle, // x - aa.axis.y() * sin_half_angle, // y - aa.axis.z() * sin_half_angle, // z - std::cos(aa.angle / Scalar{2}) // w - }; - } - - constexpr static auto - from_matrix(const matrix& m) -> quaternion { - const auto wtemp = - std::sqrt(Scalar{1} + m[0][0] + m[1][1] + m[2][2]) / Scalar{2}; - const auto w4 = Scalar{4} * wtemp; - return { - (m[2][1] - m[1][2]) / w4, // x - (m[0][2] - m[2][0]) / w4, // y - (m[1][0] - m[0][1]) / w4, // z - wtemp // w - }; - } -}; - -// deduction guide for quaternion -template > -quaternion(U...) -> quaternion; - -using quaternionf = quaternion; -using quaterniond = quaternion; - -#if 0 - constexpr quaternion_ operator*(const quaternion_& rhs) const { - return quaternion_( - rhs.w() * x() + rhs.x() * w() + rhs.y() * z() - rhs.z() * y(), - rhs.w() * y() - rhs.x() * z() + rhs.y() * w() + rhs.z() * x(), - rhs.w() * z() + rhs.x() * y() - rhs.y() * x() + rhs.z() * w(), - rhs.w() * w() - rhs.x() * x() - rhs.y() * y() - rhs.z() * z()); - } - - inline auto operator/(const T& rhs) const { + static auto from_matrix(const matrix_<4,4,T> &m) { + using std::sqrt; + auto wtemp = sqrt(T(1) + m(0,0) + m(1,1) + m(2,2)) / T(2); + auto w4 = T(4.0) * wtemp; return quaternion_({ - x() / rhs, - y() / rhs, - z() / rhs, - w() / rhs, - }); - } + (m(2,1) - m(1,2)) / w4, + (m(0,2) - m(2,0)) / w4, + (m(1,0) - m(0,1)) / w4, + wtemp}); + } - //! conjugate - inline auto conjugate() const { - return quaternion_({-x(), -y(), -z(), w()}); - } + static auto normalized_lerp(const quaternion_ &a,const quaternion_ &b,const T &t) { + return quaternion_(lerp(a,b,t).normalized()); + } - //! compute inverse - inline auto inverse() const { return conjugate() / this->norm(); } + static auto slerp(const quaternion_& qa,const quaternion_& qb,const T& t) + { + using std::abs; + using std::sqrt; + using std::acos; - inline static auto identity() { return quaternion_({0, 0, 0, 1}); } + // quaternion to return + quaternion_ qm; + // Calculate angle between them. + T cosHalfTheta = qa.w() * qb.w() + qa.x() * qb.x() + qa.y() * qb.y() + qa.z() * qb.z(); + // if qa=qb or qa=-qb then theta = 0 and we can return qa + if (abs(cosHalfTheta) >= T(1)) { + return qa; + } - const matrix4x4_ to_matrix() const { + // Calculate temporary values. + const T halfTheta = acos(cosHalfTheta); + const T sinHalfTheta = sqrt(1.0 - cosHalfTheta * cosHalfTheta); + // if theta = 180 degrees then result is not fully defined + // we could rotate around any axis normal to qa or qb + if (abs(sinHalfTheta) < 0.001){ // fabs is floating point absolute + qm.w() = (qa.w() * T(0.5) + qb.w() * T(0.5)); + qm.x() = (qa.x() * T(0.5) + qb.x() * T(0.5)); + qm.y() = (qa.y() * T(0.5) + qb.y() * T(0.5)); + qm.z() = (qa.z() * T(0.5) + qb.z() * T(0.5)); + return qm; + } + const T ratioA = sin((value_type(1) - t) * halfTheta) / sinHalfTheta; + const T ratioB = sin(t * halfTheta) / sinHalfTheta; + //calculate Quaternion. + qm.w() = (qa.w() * ratioA + qb.w() * ratioB); + qm.x() = (qa.x() * ratioA + qb.x() * ratioB); + qm.y() = (qa.y() * ratioA + qb.y() * ratioB); + qm.z() = (qa.z() * ratioA + qb.z() * ratioB); - matrix4x4_ m; - m.set_identity(); + return qm; + } - T xx = x() * x(); - T xy = x() * y(); - T xz = x() * z(); - T xw = x() * w(); - T yy = y() * y(); - T yz = y() * z(); - T yw = y() * w(); + static auto from_axisangle(const axisangle_ &aa) { + using std::sin; + using std::cos; - T zz = z() * z(); - T zw = z() * w(); + const T sinHalfAngle( sin(aa.angle * T(0.5) )); - m(0, 0) = 1 - 2 * (yy + zz); - m(0, 1) = 2 * (xy - zw); - m(0, 2) = 2 * (xz + yw); + return quaternion_( { aa.axis.x() * sinHalfAngle, // x + aa.axis.y() * sinHalfAngle, // y + aa.axis.z() * sinHalfAngle, // z + cos(aa.angle * T(0.5)) // w + } + ); - m(1, 0) = 2 * (xy + zw); - m(1, 1) = 1 - 2 * (xx + zz); - m(1, 2) = 2 * (yz - xw); - - m(2, 0) = 2 * (xz - yw); - m(2, 1) = 2 * (yz + xw); - m(2, 2) = 1 - 2 * (xx + yy); - - return m; - } - - static auto from_matrix(const matrix_<4, 4, T>& m) { - using std::sqrt; - auto wtemp = sqrt(T(1) + m(0, 0) + m(1, 1) + m(2, 2)) / T(2); - auto w4 = T(4.0) * wtemp; - return quaternion_({(m(2, 1) - m(1, 2)) / w4, (m(0, 2) - m(2, 0)) / w4, - (m(1, 0) - m(0, 1)) / w4, wtemp}); - } - - static auto normalized_lerp(const quaternion_& a, const quaternion_& b, - const T& t) { - return quaternion_(lerp(a, b, t).normalized()); - } - - static auto slerp(const quaternion_& qa, const quaternion_& qb, - const T& t) { - using std::abs; - using std::acos; - using std::sqrt; - - // quaternion to return - quaternion_ qm; - // Calculate angle between them. - T cosHalfTheta = qa.w() * qb.w() + qa.x() * qb.x() + qa.y() * qb.y() + - qa.z() * qb.z(); - // if qa=qb or qa=-qb then theta = 0 and we can return qa - if (abs(cosHalfTheta) >= T(1)) { - return qa; - } - - // Calculate temporary values. - const T halfTheta = acos(cosHalfTheta); - const T sinHalfTheta = sqrt(1.0 - cosHalfTheta * cosHalfTheta); - // if theta = 180 degrees then result is not fully defined - // we could rotate around any axis normal to qa or qb - if (abs(sinHalfTheta) < 0.001) { // fabs is floating point absolute - qm.w() = (qa.w() * T(0.5) + qb.w() * T(0.5)); - qm.x() = (qa.x() * T(0.5) + qb.x() * T(0.5)); - qm.y() = (qa.y() * T(0.5) + qb.y() * T(0.5)); - qm.z() = (qa.z() * T(0.5) + qb.z() * T(0.5)); - return qm; - } - const T ratioA = sin((value_type(1) - t) * halfTheta) / sinHalfTheta; - const T ratioB = sin(t * halfTheta) / sinHalfTheta; - // calculate Quaternion. - qm.w() = (qa.w() * ratioA + qb.w() * ratioB); - qm.x() = (qa.x() * ratioA + qb.x() * ratioB); - qm.y() = (qa.y() * ratioA + qb.y() * ratioB); - qm.z() = (qa.z() * ratioA + qb.z() * ratioB); - - return qm; - } - - static auto from_axisangle(const axisangle_& aa) { - using std::cos; - using std::sin; - - const T sinHalfAngle(sin(aa.angle * T(0.5))); - - return quaternion_({ - aa.axis.x() * sinHalfAngle, // x - aa.axis.y() * sinHalfAngle, // y - aa.axis.z() * sinHalfAngle, // z - cos(aa.angle * T(0.5)) // w - }); - } + } }; -#endif +// +// +// +using quaternion = quaternion_; +using quaternionf = quaternion_; +using quaterniond = quaternion_; + + + +} + + -} // namespace pw #if 0 /** @@ -553,6 +412,9 @@ const quaternion_ quaternion_::slerp(const quaternion_& qa,const quater return qm; } -#endif + + +#endif + #endif diff --git a/src/core/include/pw/core/rectangle.hpp b/src/core/include/pw/core/rectangle.hpp index eea564a..96eef21 100644 --- a/src/core/include/pw/core/rectangle.hpp +++ b/src/core/include/pw/core/rectangle.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -8,8 +8,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -23,28 +23,53 @@ #ifndef PW_CORE_RECTANGLE_HPP #define PW_CORE_RECTANGLE_HPP +#include + #include #include namespace pw { -template struct rectangle final { +template +struct rectangle_ { - point position{}; - size size{}; + point_ position; + size_ size; - constexpr bool contains(const point& p) const noexcept { - return p.x >= position.x && p.x <= position.x + size.width && - p.y >= position.y && p.y <= position.y + size.height; + rectangle_() = default; + + rectangle_(const T_ l[4]) + : position(point_(l[0],l[1])) + , size(size_(l[2],l[3])) + { } - template - constexpr auto cast() const noexcept -> rectangle { - return {.position = position.template cast(), - .size = size.template cast()}; + rectangle_(const T_(&l)[4]) + : position(point_(l[0],l[1])) + , size(size_(l[2],l[3])) + { + } + + rectangle_(point_ const & p,size_ const & s) : size(s), position(p) {} + + bool contains(const point_& p) const noexcept + { + return p.x >= position.x && p.x <= position.x + size.width && + p.y >= position.y && p.y <= position.y + size.height; + } + + template + rectangle_ cast() const + { + return rectangle_(position.template cast(),size.template cast()); } }; -} // namespace pw +using rectangle = rectangle_; +using rectanglei = rectangle_; +using rectanglef = rectangle_; +using rectangled = rectangle_; + +} #endif diff --git a/src/core/include/pw/core/resource.hpp b/src/core/include/pw/core/resource.hpp index 2a92aa9..42c5649 100644 --- a/src/core/include/pw/core/resource.hpp +++ b/src/core/include/pw/core/resource.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,15 +28,18 @@ namespace pw { -struct resource final { +class resource { +public: + using change_t = std::atomic_int_fast64_t; - using change_t = std::atomic_int_fast64_t; + resource() = default; - constexpr int64_t changecount() const noexcept { return changecount_; } - void touch() { ++changecount_; }; + int64_t changecount() const { return _changecount; } + void dirty() { ++_changecount; }; protected: - change_t changecount_{}; + + change_t _changecount; }; } diff --git a/src/core/include/pw/core/serialize.hpp b/src/core/include/pw/core/serialize.hpp index 99c30af..f9b10ec 100644 --- a/src/core/include/pw/core/serialize.hpp +++ b/src/core/include/pw/core/serialize.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -8,8 +8,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -23,52 +23,31 @@ #ifndef PW_CORE_SERIALIZE_HPP #define PW_CORE_SERIALIZE_HPP -#include -#include #include -#include -#include -#include -#include + #include +#include namespace pw { struct serialize { - template - constexpr static std::string to_string(const vector& v) { - return std::accumulate(std::next(std::begin(v)), std::end(v), - std::string(std::to_string(v[0])), - [](const auto& str, const auto& e) { - return str + " " + std::to_string(e); - }); - } - - template - constexpr static std::string to_string(const matrix& m) { + template + inline static std::string matrix(const matrix_& m) { std::stringstream ss; - for (int r = 0; r < R; r++) { - ss << to_string(m[r]) << '\n'; + for (int r = 0; r < m.rows;r++) { + for (int c = 0; c < m.cols;c++) { + ss << m(r,c) << " "; + } + ss << std::endl; } return ss.str(); } - - template - constexpr static std::string to_string(const quaternion& v) { - std::stringstream ss; - ss << to_string(v.q_); - return ss.str(); - } - - constexpr static std::string to_string(const color& v) { - return to_string(v.rgba); - } }; -} // namespace pw +} #endif diff --git a/src/core/include/pw/core/size.hpp b/src/core/include/pw/core/size.hpp index ebe49f8..7e0d651 100644 --- a/src/core/include/pw/core/size.hpp +++ b/src/core/include/pw/core/size.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -8,8 +8,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -24,41 +24,32 @@ #define PW_CORE_SIZE_HPP #include -#include namespace pw { -template struct size { +template +struct size_ { - using value_type = Scalar; - Scalar width{}, height{}; + using value_type = T_; - constexpr auto area() const noexcept -> Scalar { - if constexpr (std::is_unsigned_v) { - return width * height; - } else { - return std::abs(width * height); - } - } + T_ width,height; - template - constexpr auto cast(this auto&& self) noexcept -> size { - return {.width = ScalarOut(self.width), - .height = ScalarOut(self.height)}; - } + size_() = default; + + size_(T_ w,T_ h) : width(w), height(h) {} + + T_ area() const { return std::abs(width * height); } + + template + size_ cast() const { return size_(static_cast(width),static_cast(height)); } - template - constexpr auto operator()(this auto&& self) noexcept { - return Other{self.width, self.height}; - } }; -// -// deduction guide -// -template > -size(U...) -> size; +typedef size_ size; -} // namespace pw +typedef size_ sizef; +typedef size_ sized; + +} #endif diff --git a/src/core/include/pw/core/time.hpp b/src/core/include/pw/core/time.hpp index 35db565..a24268b 100644 --- a/src/core/include/pw/core/time.hpp +++ b/src/core/include/pw/core/time.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -8,8 +8,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -32,13 +32,14 @@ namespace pw { /** * @brief A simple high resolution timer */ -struct time final { +class time { +public: - using tick_t = std::chrono::time_point; + using tick_t = std::chrono::time_point ; - time() = default; + time() = default; time(const time&) = default; - ~time() = default; /// d'tor + ~time() = default; /// d'tor /** * @brief reset timer to current system time @@ -57,10 +58,12 @@ struct time final { */ static double now(); - protected: - tick_t _start{std::chrono::high_resolution_clock::now()}; +protected: + + tick_t _start = std::chrono::high_resolution_clock::now(); }; -} // namespace pw +} + #endif diff --git a/src/core/include/pw/core/vector.hpp b/src/core/include/pw/core/vector.hpp index f01a120..08a28d3 100644 --- a/src/core/include/pw/core/vector.hpp +++ b/src/core/include/pw/core/vector.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -8,8 +8,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -23,321 +23,146 @@ #ifndef PW_CORE_VECTOR_HPP #define PW_CORE_VECTOR_HPP -#include - -#include -#include -#include -#include -#include +#include namespace pw { -template -concept Vector2 = (N == 2); +/** + * Basic vector types used in pixwerx. + */ -template -concept Vector3 = (N == 3); +template +struct vector2_ : matrix_<2,1,T> { -template -concept Vector4 = (N == 4); + typedef matrix_<2,1,T> base_type; -template struct vector final { + using base_type::base_type; + using base_type::operator = ; - static_assert(N > 0, "Undefined vector space."); + vector2_(const base_type& m) : base_type(m) {} + vector2_(T x_,T y_) : base_type({x_,y_}) {} - using value_type = Scalar; - using size_type = decltype(N); - using difference_type = std::ptrdiff_t; - using reference = value_type&; - using const_reference = const value_type&; - using pointer = value_type*; - using const_pointer = const value_type*; + inline const T& x() const { return (*this)[0]; } + inline T& x() { return (*this)[0]; } - static constexpr size_type coefficients{N}; + inline const T& y() const { return (*this)[1]; } + inline T& y() { return (*this)[1]; } - Scalar v_[N]{}; + inline auto homogenous(T w = 1) const { return matrix_<3,1,T>( { x(),y(),w } ); } - auto&& data(this auto&& self) { - return std::forward(self).v_; + static T angle_between(const vector2_ &a,const vector2_ &b) { + return std::acos( dot( a.normalized(), b.normalized() ) ); } - auto&& operator[](this auto&& self, size_type e) { - return std::forward(self).v_[e]; - } + static constexpr auto zero() { return vector2_(0,0); } - template - constexpr auto cast() const noexcept -> vector { - return [this](std::index_sequence) { - return vector{ScalarOut((*this)[Ss])...}; - }(std::make_index_sequence{}); - } +}; - static constexpr auto basis(const auto& d) noexcept { - return [&d](std::index_sequence) { - return vector{(d == Ss) ? Scalar(1) : Scalar(0)...}; - }(std::make_index_sequence{}); - } +template +struct vector3_ : matrix_<3,1,T> { - template - static constexpr auto - make(Args&&... values) noexcept -> vector { - static_assert(sizeof...(Args) == N, "Incorrect number of arguments."); - return {{Scalar(values)...}}; - } + typedef matrix_<3,1,T> base_type; - static constexpr auto all(Scalar value) noexcept -> vector { - return [&value](std::index_sequence) { - return vector{value + Scalar{Is * 0}...}; - }(std::make_index_sequence{}); - } + using base_type::base_type; + using base_type::operator = ; - template - constexpr auto swizzle(Args&&... indices) const noexcept - -> vector { - return {{Scalar{v_[indices]}...}}; - } + vector3_() : base_type() {} + vector3_(const base_type& m) : base_type(m) {} + vector3_(T x_,T y_,T z_) : base_type({x_,y_,z_}) {} + vector3_(const vector2_ &m, T w) : base_type({m(0),m(1),w}) {} - template - constexpr auto slice(std::integer_sequence, T offset = T{0}) - const noexcept -> vector { - return {{Scalar{v_[indices + offset]}...}}; - } + inline const T& x() const { return (*this)[0]; } + inline T& x() { return (*this)[0]; } + inline vector3_& set_x(T val) { (*this)[0] = val; return *this;} - constexpr auto minor(std::unsigned_integral auto d0) const noexcept { - return [this, &d0](std::index_sequence) { - return vector{ - (*this).v_[(Ss < d0) ? Ss : Ss + 1]...}; - }(std::make_index_sequence{}); - } + inline const T& y() const { return (*this)[1]; } + inline T& y() { return (*this)[1]; } + inline vector3_& set_y(T val) { (*this)[1] = val; return *this;} - static constexpr auto sequence(Scalar factor = Scalar{1}, - Scalar offset = Scalar{0}) noexcept { - return [&](std::index_sequence) { - return vector{{Scalar{Ss} * factor + offset...}}; - }(std::make_index_sequence{}); - } + inline const T& z() const { return (*this)[2]; } + inline T& z() { return (*this)[2]; } + inline vector3_& set_z(T val) { (*this)[2] = val; return *this;} - static constexpr auto lerp(const vector& A, const vector& B, - const Scalar& t) -> vector { - return [&](std::index_sequence) { - return vector{{A[Ss] + t * (B[Ss] - A[Ss])...}}; - }(std::make_index_sequence{}); - } + inline auto xy() const { return vector2_( { x(),y() } ); } + inline auto homogenous(T w = 1) const { return matrix_<4,1,T>( { x(),y(),z(),w } ); } - constexpr Scalar dot(const auto& other) const { - return [this, &other](std::index_sequence) { - return (... + (other[Ss] * (*this)[Ss])); - }(std::make_index_sequence{}); - } - - constexpr auto squared_norm() const noexcept { return dot(*this); } - - constexpr auto norm() const noexcept { - return std::sqrt(this->squared_norm()); - } - - constexpr vector operator*(const Scalar& v) const noexcept { - return [this, &v](std::index_sequence) { - return vector{{(*this)[Ss] * v...}}; - }(std::make_index_sequence{}); - } - - constexpr vector operator/(const Scalar& v) const noexcept { - return (*this).operator*(Scalar{1} / v); - } - - constexpr vector operator+(const vector& v) const noexcept { - return [this, &v](std::index_sequence) { - return vector{{(*this)[Ss] + v[Ss]...}}; - }(std::make_index_sequence{}); - } - - constexpr vector operator-(const vector& v) const noexcept { - return [this, &v](std::index_sequence) { - return vector{{(*this)[Ss] - v[Ss]...}}; - }(std::make_index_sequence{}); - } - - constexpr vector& operator*=(const Scalar& v) noexcept { - [this, &v](std::index_sequence) { - (((*this)[Ss] *= v), ...); - }(std::make_index_sequence{}); - return *this; - } - - constexpr vector& operator/=(const Scalar& v) noexcept { - return operator*=(Scalar{1} / v); - } - - constexpr vector& operator+=(const Scalar& v) noexcept { - [this, &v](std::index_sequence) { - (((*this)[Ss] += v), ...); - }(std::make_index_sequence{}); - return *this; - } - - constexpr vector& operator-=(const Scalar& v) noexcept { - return operator+=(-v); - } - - constexpr vector min(const vector& v) const noexcept { - return [this, &v](std::index_sequence) { - return pw::vector{(std::min(v[Ss], (*this)[Ss]))...}; - }(std::make_index_sequence{}); - } - - constexpr vector max(const vector& v) const noexcept { - return [this, &v](std::index_sequence) { - return pw::vector{(std::max(v[Ss], (*this)[Ss]))...}; - }(std::make_index_sequence{}); - } - - constexpr auto project() const noexcept -> vector { - return [this](std::index_sequence) { - return vector{{(*this)[Ss] / (*this)[N - 1]...}}; - }(std::make_index_sequence{}); - } - - constexpr auto - unproject(const Scalar& w) const noexcept -> vector { - return [this, &w](std::index_sequence) { - return vector{{(Ss < N) ? (*this)[Ss] : w...}}; - }(std::make_index_sequence{}); - } - - constexpr vector cross(const auto& rhs) const noexcept - requires(Vector3) + inline static constexpr vector3_ cross(const vector3_& lhs, + const vector3_& rhs) { - return {(*this)[1] * rhs[2] - rhs[1] * (*this)[2], - (*this)[2] * rhs[0] - rhs[2] * (*this)[0], - (*this)[0] * rhs[1] - rhs[0] * (*this)[1]}; + return vector3_( { + lhs[1] * rhs[2] - rhs[1] * lhs[2], + lhs[2] * rhs[0] - rhs[2] * lhs[0], + lhs[0] * rhs[1] - rhs[0] * lhs[1] + } + ); } - constexpr vector normalized() const noexcept { return (*this) / norm(); } - auto&& x(this auto&& self) - requires(Vector2 || Vector3 || Vector4) - { - return std::forward(self).v_[0]; - } + inline static constexpr vector3_ forward() { return vector3_ ( { T(0), T(0),-T(1) } ); } + inline static constexpr vector3_ backward() { return vector3_( { T(0), T(0), T(1) } ); } + inline static constexpr vector3_ right() { return vector3_ ( { T(1), T(0), T(0) } ); } + inline static constexpr vector3_ left() { return vector3_ ( {-T(1), T(0), T(0) } ); } + inline static constexpr vector3_ up() { return vector3_ ( { T(0), T(1), T(0) } ); } + inline static constexpr vector3_ down() { return vector3_ ( { T(0),-T(1), T(0) } ); } - auto&& y(this auto&& self) - requires(Vector2 || Vector3 || Vector4) - { - return std::forward(self).v_[1]; - } + inline static vector3_ x_axis() { return vector3_ ( { T(1), T(0), T(0) } ); } + inline static vector3_ y_axis() { return vector3_ ( { T(0), T(1), T(0) } ); } + inline static vector3_ z_axis() { return vector3_ ( { T(0), T(0), T(1) } ); } - auto&& z(this auto&& self) - requires(Vector3 || Vector4) - { - return std::forward(self).v_[2]; - } + static constexpr auto zero() { return vector3_(0,0,0); } +}; - auto&& w(this auto&& self) - requires(Vector4) - { - return std::forward(self).v_[3]; - } +template +struct vector4_ : matrix_<4,1,T> { - static constexpr vector right() noexcept - requires(Vector3) - { - return vector{1, 0, 0}; - }; + typedef matrix_<4,1,T> base_type; - static constexpr vector up() noexcept - requires(Vector3) - { - return vector{0, 1, 0}; - }; + using base_type::base_type; + using base_type::operator = ; - static constexpr vector forward() noexcept - requires(Vector3) - { - return vector{0, 0, -1}; - }; + vector4_(T x_,T y_,T z_,T w_) : base_type( {x_,y_,z_,w_} ) {} + vector4_(const base_type& m) : base_type(m) {} + vector4_(const vector3_ &m, T w) : base_type({m(0),m(1),m(2),w}) {} - static constexpr vector x_axis() noexcept - requires(Vector2 || Vector3 || Vector4) - { - return vector::basis(0); - }; + inline const T& x() const { return (*this)[0]; } + inline T& x() { return (*this)[0]; } - static constexpr vector y_axis() noexcept - requires(Vector2 || Vector3 || Vector4) - { - return vector::basis(1); - }; + inline const T& y() const { return (*this)[1]; } + inline T& y() { return (*this)[1]; } - static constexpr vector z_axis() noexcept - requires(Vector3 || Vector4) - { - return vector::basis(2); - }; + inline const T& z() const { return (*this)[2]; } + inline T& z() { return (*this)[2]; } - static constexpr vector w_axis() noexcept - requires(Vector4) - { - return vector::basis(3); - }; + inline const T& w() const { return (*this)[3]; } + inline T& w() { return (*this)[3]; } - // - // part of tuple-protocol - // - template auto get(this auto&& self) -> decltype(auto) { - static_assert(idx < N, "Out of bounds access to a member."); - // TODO: use forward_like when clang is catching up - // return std::forward_like(self.v_[idx]); - return std::forward(self).v_[idx]; - } + inline auto xyz() const { return vector3_({ x(),y(),z() } ); } - // - // Iterators - // - constexpr const_pointer begin() const { return &v_[0]; } + inline auto project() const { return vector3_({ x()/w(),y()/w(),z()/w() } ); } + + static constexpr auto zero() { return vector2_(0,0,0,0); } - constexpr const_pointer end() const { return &v_[N]; } }; // -// deduction guide // -template -vector(Scalar&&... s) - -> vector, sizeof...(Scalar)>; - // -// type aliases -// -template using vector2 = vector; -template using vector3 = vector; -template using vector4 = vector; -using vector2f = vector2; -using vector2d = vector2; -using vector2i = vector2; +using vector2f = vector2_; +using vector2d = vector2_; +using vector2i = vector2_; +using vector2 = vector2_; +using vector2_array = std::vector; -using vector3f = vector3; -using vector3d = vector3; -using vector3i = vector3; +using vector3f = vector3_; +using vector3d = vector3_; +using vector3 = vector3_; +using vector3_array = std::vector; -using vector4f = vector4; -using vector4d = vector4; -using vector4i = vector4; +using vector4f = vector4_; +using vector4d = vector4_; +using vector4 = vector4_; -} // namespace pw - -// -// tuple protocol -// -template -struct std::tuple_size> - : std::integral_constant {}; - -template -struct std::tuple_element> { - using type = Scalar; -}; +} #endif diff --git a/src/core/src/image.cpp b/src/core/src/image.cpp index 295f915..43b52a4 100644 --- a/src/core/src/image.cpp +++ b/src/core/src/image.cpp @@ -1,14 +1,12 @@ #include "pw/core/image.hpp" #include "pw/core/debug.hpp" -#include #include #include -#include namespace pw { -image::image(const ::pw::size &s, +image::image(const ::pw::size &s, image::pixel_layout t, const data_t *ptr) { @@ -17,11 +15,11 @@ image::image(const ::pw::size &s, } } -bool image::create(const ::pw::size &s, +bool image::create(const ::pw::size &s, image::pixel_layout t, const data_t *ptr) { - const auto n = bytes_per_pixel(t) * s.area(); + size_t n = bytes_per_pixel(t) * s.area(); _size = s; _layout = t; @@ -53,7 +51,7 @@ void image::generate_noise() void image::release(bool release_memory) { _data.clear(); - _size = size_type{}; + _size = pw::size(); if (release_memory) _data.shrink_to_fit(); } @@ -96,6 +94,10 @@ uint32_t image::components(image::pixel_layout t) return 0; } +::pw::size image::size() const +{ + return _size; +} image::pixel_layout image::layout() const { diff --git a/src/core/src/time.cpp b/src/core/src/time.cpp index 273cd19..65289b2 100644 --- a/src/core/src/time.cpp +++ b/src/core/src/time.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -42,3 +42,4 @@ double time::now() } } + diff --git a/src/core/tests/CMakeLists.txt b/src/core/tests/CMakeLists.txt index 372a981..895d118 100644 --- a/src/core/tests/CMakeLists.txt +++ b/src/core/tests/CMakeLists.txt @@ -1,16 +1,15 @@ macro(make_test arg1) - add_executable(${arg1} ${arg1}.cpp) - target_link_libraries(${arg1} pwcore) + add_executable(${arg1} + ${arg1}.cpp + ) + target_link_libraries(${arg1} + pwcore) endmacro() -make_test(pwcore_test_vector) + make_test(pwcore_test_matrix) +make_test(pwcore_test_vector) make_test(pwcore_test_axisangle) make_test(pwcore_test_quaternion) -make_test(pwcore_test_color) make_test(pwcore_test_transform_tools) -make_test(pwcore_test_aabb) -make_test(pwcore_test_frustum) make_test(pwcore_test_mesh) -make_test(pwcore_test_serialize) -make_test(pwcore_test_image) diff --git a/src/core/tests/pwcore_test_aabb.cpp b/src/core/tests/pwcore_test_aabb.cpp deleted file mode 100644 index aeb2017..0000000 --- a/src/core/tests/pwcore_test_aabb.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include -#include - -#include -#include - -auto main() -> int { - - auto vertices = - std::vector>{{-1.f, 1.f, 0}, - {2.f, -1.f, 3.f}, - {0, 0, -1.f}, - {-1'000.f, 2'000.f, 3'000.f}}; - - auto indices = std::vector{0, 1, 2}; - - auto aabb_1 = - pw::aabb::make(vertices); - - std::print("aabb::min -> {} {} {}\n", aabb_1.min.x(), aabb_1.min.y(), - aabb_1.min.z()); - - std::print("aabb::max -> {} {} {}\n", aabb_1.max.x(), aabb_1.max.y(), - aabb_1.max.z()); - - auto aabb_2 = pw::aabb:: - make_from_indexed_vertices(vertices, indices); - - std::print("aabb::min -> {} {} {}\n", aabb_2.min.x(), aabb_2.min.y(), - aabb_2.min.z()); - - std::print("aabb::max -> {} {} {}\n", aabb_2.max.x(), aabb_2.max.y(), - aabb_2.max.z()); -} diff --git a/src/core/tests/pwcore_test_axisangle.cpp b/src/core/tests/pwcore_test_axisangle.cpp index 62d0373..34b32c0 100644 --- a/src/core/tests/pwcore_test_axisangle.cpp +++ b/src/core/tests/pwcore_test_axisangle.cpp @@ -1,46 +1,53 @@ #include +#include #include #include -auto main() -> int { +int main(int argc,char **argv) { - auto aa = pw::axisangle(); + pw::axisangle_ aa = pw::axisangle_(); + +// pw::quaternionf qf = pw::quaternionf::from_axisangle(aa); +// std::cout << "aa as quaternion as matrix = " << pw::serialize::matrix(qf.to_matrix()) << std::endl; +// std::cout << "aa.matrix() = " << pw::serialize::matrix(qf.to_matrix()) << std::endl; std::cout << "x-axis" << std::endl; - aa.axis = pw::vector3f::x_axis(); + aa.axis = pw::vector3::x_axis(); aa.angle = pw::deg_to_rad(45.f); - std::cout << "aa.matrix() = " << std::endl - << pw::serialize::to_string(aa.to_matrix()) << std::endl; + std::cout << "aa.matrix() = " << std::endl << pw::serialize::matrix(aa.to_matrix()) << std::endl; + std::cout << "y-axis" << std::endl; - aa.axis = pw::vector3f::y_axis(); + aa.axis = pw::vector3::y_axis(); aa.angle = pw::deg_to_rad(45.f); - std::cout << "aa.matrix() = " << std::endl - << pw::serialize::to_string(aa.to_matrix()) << std::endl; + std::cout << "aa.matrix() = " << std::endl << pw::serialize::matrix(aa.to_matrix()) << std::endl; - std::cout << "z-axis" << std::endl; - aa.axis = pw::vector3f::z_axis(); - aa.angle = pw::deg_to_rad(45.f); - std::cout << "aa.matrix() = " << std::endl - << pw::serialize::to_string(aa.to_matrix()) << std::endl; + std::cout << "z-axis" << std::endl; - std::cout << "from matrix" << std::endl; + aa.axis = pw::vector3::z_axis(); + aa.angle = pw::deg_to_rad(45.f); - auto mrot = pw::matrix{}; - mrot[0][0] = 1; - mrot[2][1] = 1; - mrot[1][2] = -1; + std::cout << "aa.matrix() = " << std::endl << pw::serialize::matrix(aa.to_matrix()) << std::endl; + + + std::cout << "from matrix" << std::endl; + + pw::matrix4x4f mrot; mrot.zero(); + mrot(0,0) = 1; + mrot(2,1) = 1; + mrot(1,2) = -1; + + pw::axisanglef aa_fm = pw::axisangle::from_matrix(mrot); + + std::cout << pw::serialize::matrix(aa_fm.axis.transposed()) << " " << pw::rad_to_deg(aa_fm.angle) << "deg" << std::endl; - auto aa_fm = pw::axisanglef::from_matrix(mrot); - std::cout << pw::serialize::to_string(aa_fm.axis) << " " - << pw::rad_to_deg(aa_fm.angle) << "deg" << std::endl; return 0; } diff --git a/src/core/tests/pwcore_test_color.cpp b/src/core/tests/pwcore_test_color.cpp deleted file mode 100644 index 580d208..0000000 --- a/src/core/tests/pwcore_test_color.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include - -#include -#include - -auto main() -> int { - - pw::debug::d() << "pixwerx.color.test\n"; - - auto col = pw::color::from_rgb8888(255,0,0,255); - pw::debug::d() << "col -> \n" << pw::serialize::to_string(col); - - auto col_hx = pw::color::from_rgb8888(0xFF'EE'BB'AA); - pw::debug::d() << "col_hx(0xFFAABBAA) -> \n" << pw::serialize::to_string(col_hx); - - - - return 0; -} diff --git a/src/core/tests/pwcore_test_frustum.cpp b/src/core/tests/pwcore_test_frustum.cpp deleted file mode 100644 index 0d230e0..0000000 --- a/src/core/tests/pwcore_test_frustum.cpp +++ /dev/null @@ -1,22 +0,0 @@ - -#include - -#include -#include - -auto main() -> int { - - auto frustum_p = pw::frustum::make_perspective_symmetric( - 45.f, float{320} / 240, 0.1f, 1'000.f); - - auto frustum_o = pw::frustum::make_orthographic_symmetric( - 1.5f, float{320} / 240, 0.1f, 1'000.f); - - std::print("l:{} r:{} b:{} t:{} n:{} f:{}\n", frustum_p.left, - frustum_p.right, frustum_p.bottom, frustum_p.top, frustum_p.z_near, - frustum_p.z_far); - - std::print("l:{} r:{} b:{} t:{} n:{} f:{}\n", frustum_p.left, - frustum_o.right, frustum_o.bottom, frustum_o.top, frustum_o.z_near, - frustum_o.z_far); -} diff --git a/src/core/tests/pwcore_test_image.cpp b/src/core/tests/pwcore_test_image.cpp deleted file mode 100644 index b4b3932..0000000 --- a/src/core/tests/pwcore_test_image.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include - -namespace pw { - -struct image_layout { - - enum struct pixel_layout { RGB8, RGBA8, LUM8, DEPTH }; - - static constexpr auto bits_per_channel(pixel_layout layout) { - constexpr static auto lut = std::array{ - std::make_tuple(pixel_layout::RGB8, sizeof(std::uint8_t) << 3), - std::make_tuple(pixel_layout::RGBA8, sizeof(std::uint8_t) << 3), - std::make_tuple(pixel_layout::LUM8, sizeof(std::uint8_t) << 3), - std::make_tuple(pixel_layout::DEPTH, sizeof(float) << 3)}; - - const auto iter = std::find_if( - std::begin(lut), std::end(lut), - [&layout](const auto& v) { return std::get<0>(v) == layout; }); - - return iter != std::end(lut) ? std::get<1>(*iter) : 0u; - } - - static constexpr auto channels(pixel_layout layout) { - constexpr static auto lut = - std::array{std::make_tuple(pixel_layout::RGB8, 3), - std::make_tuple(pixel_layout::RGBA8, 4), - std::make_tuple(pixel_layout::LUM8, 1), - std::make_tuple(pixel_layout::DEPTH, 1)}; - - const auto iter = std::find_if( - std::begin(lut), std::end(lut), - [&layout](const auto& v) { return std::get<0>(v) == layout; }); - - return iter != std::end(lut) ? std::get<1>(*iter) : 0u; - } - - size size_{}; - pixel_layout layout_{pixel_layout::RGB8}; -}; - -struct image_new { - - using buffer_type = std::vector; - using size_type = pw::size; - - image_layout layout; - buffer_type buffer{}; - - static constexpr auto make(const image_new::size_type& size_, - image_layout::pixel_layout layout_) - -> image_new { - - return {.layout{.layout_ = layout_}, - .buffer{buffer_type{ - static_cast( - (image_layout::bits_per_channel(layout_) >> 3) * - size_.area() * image_layout::channels(layout_)), - buffer_type::value_type{0}}}}; - } -}; - -} // namespace pw - -auto main() -> int { - - std::print("RGB8 = {}bits per channel\n", - pw::image_layout::bits_per_channel( - pw::image_layout::pixel_layout::RGB8)); - std::print("DEPTH = {}bits per channel\n", - pw::image_layout::bits_per_channel( - pw::image_layout::pixel_layout::DEPTH)); - std::print("LUM8 = {}bits per channel\n", - pw::image_layout::bits_per_channel( - pw::image_layout::pixel_layout::LUM8)); - - std::print( - "RGB8 = {}channels\n", - pw::image_layout::channels(pw::image_layout::pixel_layout::RGB8)); - std::print( - "DEPTH = {}channels\n", - pw::image_layout::channels(pw::image_layout::pixel_layout::DEPTH)); - std::print( - "LUM8 = {}channels\n", - pw::image_layout::channels(pw::image_layout::pixel_layout::LUM8)); - // pw::image - - pw::image_new::make(pw::iamge, image_layout::pixel_layout layout_) -} diff --git a/src/core/tests/pwcore_test_matrix.cpp b/src/core/tests/pwcore_test_matrix.cpp index 94574c1..0ed0ae9 100644 --- a/src/core/tests/pwcore_test_matrix.cpp +++ b/src/core/tests/pwcore_test_matrix.cpp @@ -1,77 +1,130 @@ -#include -#include + + #include -#include #include +#include -#include -#include +#include -auto main() -> int { +#include +#include - pw::debug::d() << "pixwerx.matrix.test\n"; - auto m22 = pw::matrix{}; - pw::debug::d() << "matrix<2,2>{} -> \n" << pw::serialize::to_string(m22); +int main(int argc,char **argv) { - m22[0][0] = 1; - m22[0][1] = 2; - m22[1][0] = 3; - m22[1][1] = 4; + using namespace pw; - pw::debug::d() << "matrix<2,2>{1,2,3,4} -> \n" - << pw::serialize::to_string(m22); + matrix2x2f m22; m22.zero(); - auto m22_inv = m22.inverse(); - pw::debug::d() << "matrix<2,2>{1,2,3,4}.inverse() -> \n" - << pw::serialize::to_string(m22_inv); + m22(0,0) = 1; m22(0,1) = 2; + m22(1,0) = 3; m22(1,1) = 4; - auto m22_inv_inv = m22_inv.inverse(); - pw::debug::d() << "matrix<2,2>{1,2,3,4}.inverse().inverse() -> \n" - << pw::serialize::to_string(m22_inv_inv); + vector2f v2; + v2[0] = 1; v2[1] = 3; - auto row_1 = m22_inv[1]; - pw::debug::d() << "matrix<2,2>{1,2,3,4}.inverse()[1] -> \n" - << pw::serialize::to_string(row_1); + vector2f v3( { 1.f,2.f } ); - auto m22_tp = m22.transposed(); - pw::debug::d() << "matrix<2,2>{1,2,3,4}.transposed() -> \n" - << pw::serialize::to_string(m22_tp); - auto m22_tp_col1 = m22_tp.column(1); - pw::debug::d() << "matrix<2,2>{1,2,3,4}.transposed().column(1) -> \n" - << pw::serialize::to_string(m22_tp_col1); + auto m22_inv = m22.inverse(); + auto m22_id = m22_inv * m22; - auto& [r1, r2] = m22_inv; + auto v2_t = m22_id * v2; + auto v3_t = m22_id * v3; - auto& [r1_x, r1_y] = r1; + auto v2_f = m22 * v2; + auto v2_b = m22_inv * v2_f; - std::print("r1.x:{} r1.y:{}\n", r1_x, r1_y); + vector2_ r_m22 = m22.row(0).transposed(); + vector2_ c_m22 = m22.column(1); - auto m33 = pw::matrix::identity(); + auto r_m22_h = r_m22.homogenous(); - auto m22_slice = m33.slice<2, 2>(0, 0); + debug::d() << "offset(0,1) col-major " << m22.offset(0,1); + debug::d() << "det " << m22.determinant(); - std::print("{}\n", typeid(m22_slice).name()); + std::cout << "m22 " << pw::serialize::matrix(m22) << std::endl; + std::cout << "m22-1 " << pw::serialize::matrix(m22_inv) << std::endl; + std::cout << "m22-i " << pw::serialize::matrix(m22_id) << std::endl; + std::cout << "v22_t " << pw::serialize::matrix(v2_t) << std::endl; + std::cout << "v3_t " << pw::serialize::matrix(v3_t) << std::endl; - auto vvv = pw::vector{1.f, 2, 3, 4}; - auto vvv_swizzle = vvv.slice(std::make_index_sequence<2>{}); + std::cout << "v2_f " << pw::serialize::matrix(v2_f) << std::endl; + std::cout << "v2_b " << pw::serialize::matrix(v2_b) << std::endl; - pw::debug::d() << "matrix<3,3>.slice() -> \n" - << pw::serialize::to_string(m33) << "\n to \n" - << pw::serialize::to_string(m22_slice); + std::cout << "v2_b.norm " << v2_b.norm() << std::endl; - // octave/matlab style output - std::print("\nm33=[{}]\n", m33); +// v2_b.normalize(); + std::cout << "v2_b.normalized " << pw::serialize::matrix(v2_b.normalized()) << std::endl; - auto m44 = m33.unproject(1); +// std::cout << "v2_b~v3_t " << rad_to_deg(vector2f::angle_between(v2,v3)) << std::endl; - std::print("\nm44=[{}]\n", m44); - // auto m_init_ded = pw::matrix{ - // {1, 2}, - // {3, 4} - // }; + + + + +// vector2f v2 = m22.slice<2,1>(0,0); +// m22.set_slice<2,1>(v2,0,0); + +// v2 *= 2; +// v2 += 1; + +// m22 *= 3; + +// m22.determinant(); + +// debug::d() << sizeof(v2); + +// auto m22_i = m22.inverse(); + + + +#if 0 + + pw::matrix4x4d m; + + m.set_identity(); + + std::cout << "m = " << pw::serialize::matrix(m) << std::endl; + + std::cout << "row_stride() : " << m.row_stride() << std::endl; + std::cout << "col_stride() : " << m.col_stride() << std::endl; + std::cout << "rows() : " << m.rows() << std::endl; + std::cout << "cols() : " << m.cols() << std::endl; + std::cout << "data() : " << m.data() << std::endl; + std::cout << "data()[0] : " << m.data()[0] << std::endl; + std::cout << "at(0,0) : " << m.at(0,0) << std::endl; + std::cout << "determinant(): " << m.determinant() << std::endl; + + + pw::matrix4x4d mi = m.get_inverse(); + + std::cout << "mi.at(0,0) : " << mi.at(0,0) << std::endl; + + + pw::matrix4x4d mscale = m * 4.2; + + + std::cout << "mscale = " << pw::serialize::matrix(mscale) << std::endl; + + + pw::matrix4x4d a; + + for (int r = 0; r < m.rows(); r++) { + for (int c = 0; c < m.cols(); c++) { + a.at(r,c) = r * m.cols() + c; + } + } + std::cout << "a = " << pw::serialize::matrix(a) << std::endl; + + pw::matrix4x4d r = a * mscale; + + std::cout << "a * mscale = " << pw::serialize::matrix(r) << std::endl; + + + return 0; + +#endif } diff --git a/src/core/tests/pwcore_test_mesh.cpp b/src/core/tests/pwcore_test_mesh.cpp index 20f6d20..e45ec0f 100644 --- a/src/core/tests/pwcore_test_mesh.cpp +++ b/src/core/tests/pwcore_test_mesh.cpp @@ -1,39 +1,66 @@ -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include -#include -#include -#include +#include -namespace pw {} // namespace pw +int main(int argc,char **argv) { -auto main() -> int { + pw::geometry geo; - auto geom = pw::primitives{ - .vertices = {{1.2f, 2.4f, 4.8f}, - {2.4f, 1.2f, 4.8f}, - {1.2f, 4.8f, 2.4f}}, - .indices = {0, 1, 2}, + pw::vector3_array vs = { + { -1, 1, 0 }, + { -1,-1, 0 }, + { 1,-1, 0 }, + { 1, 1, 0 } + }; - .topology = pw::primitives::topology_type::triangle_list}; + pw::geometry::indices_t idx = { + 0, 1, 2, + 0, 2, 3 + }; - auto mesh = pw::mesh{ - .geometry = geom, - .attributes = {{.type = pw::attribute::normals, - .data = std::vector{pw::vector{1.2f, 2.4f, 4.8f}}}}}; - for (auto i : geom.indices) { - std::print("vertex[{}]({})\n", i, geom.vertices[i]); - } + geo.set_vertices(vs); + geo.set_indices(idx); + + geo.compute_normals(); + + + +// amesh.set_vertices(vs); + +// for (auto v : amesh.vertices()) { +// std::cout << pw::serialize::matrix(v.transposed()) << std::endl; +// } + +// auto scale = pw::matrix_transform::scale_matrix({2,2,2}); + +// amesh.transform(scale); + +// std::cout << "after scale" << std::endl; + +// for (auto v : amesh.vertices()) { +// std::cout << pw::serialize::matrix(v.transposed()) << std::endl; +// } + +// pw::axisangle aa; + +// aa.axis = pw::vector3({ 0, 0, 1 }); +// aa.angle = pw::deg_to_rad(90.0f); + +// auto rot_mat = aa.to_matrix(); + +// amesh.transform(rot_mat); + +// std::cout << "after rotate" << std::endl; + +// for (auto v : amesh.vertices()) { +// std::cout << pw::serialize::matrix(v.transposed()) << std::endl; +// } + - auto aabb = pw::aabb::make_from_indexed_vertices(geom.vertices, - geom.indices); - std::print("aabb.max = ({}) aabb.min=({})\n", aabb.max, aabb.min); } diff --git a/src/core/tests/pwcore_test_quaternion.cpp b/src/core/tests/pwcore_test_quaternion.cpp index 588e0d8..e04f906 100644 --- a/src/core/tests/pwcore_test_quaternion.cpp +++ b/src/core/tests/pwcore_test_quaternion.cpp @@ -1,46 +1,30 @@ -#include #include #include -auto main() -> int { +#include - pw::debug::d() << "pixwerx.quaternion.test\n"; +int main(int argc,char **argv) { - auto q0 = pw::quaternion{}; - auto q1 = pw::quaternion{1.f, 2.f, 3.f, 4.f}; + pw::quaternion_ qf; - pw::debug::d() << "q0 = quaternion{} -> \n" << pw::serialize::to_string(q0); - pw::debug::d() << "q1 = quaternion{1,2,3,4} -> \n" - << pw::serialize::to_string(q1); + std::cout << "qf = " << pw::serialize::matrix(qf) << std::endl; + std::cout << "qf.matrix() = " << pw::serialize::matrix(qf.to_matrix()) << std::endl; - q1 = q1.normalized(); - pw::debug::d() << "q1 = quaternion{1,2,3,4}.normalized() -> \n" - << pw::serialize::to_string(q1); + std::cout << "qf.squared_norm() = " << qf.squared_norm() << std::endl; +// std::cout << "qf.dot(qf) = " << qf.dot(qf) << std::endl; + std::cout << "qf.conjugate() = " << pw::serialize::matrix(qf.conjugate()) << std::endl; - auto q0_x_q1 = q0 * q1; - pw::debug::d() << "q0 * q1 -> \n" << pw::serialize::to_string(q0_x_q1); + pw::quaternionf qc = qf.conjugate(); + std::cout << "qf.conjugate() (qc) = " << pw::serialize::matrix(qc.to_matrix()) << std::endl; - auto q1_conj = q1.conjugate(); - pw::debug::d() << "q1.conjugate() -> \n" - << pw::serialize::to_string(q1_conj); + pw::quaternionf qi = qf.inverse(); + std::cout << "qf.inverse() (qi) = " << pw::serialize::matrix(qi.to_matrix()) << std::endl; - auto q1_conj_nml = q1_conj.normalized(); - pw::debug::d() << "q1.conjugate().normalized() -> \n" - << pw::serialize::to_string(q1_conj_nml); + pw::quaternionf qmid = pw::quaternionf::normalized_lerp(qi,qf,0.5f); +// std::cout << "qmid.dot() (half between qf and qi) = " << pw::rad_to_deg(quaternionf::angle_between()) << std::endl; - auto q1_conj_inv = q1_conj.inverse(); - pw::debug::d() << "q1.conjugate().inverse() -> \n" - << pw::serialize::to_string(q1_conj_inv); - pw::debug::d() << "quaternion::dot(q0,q1) -> " << q0.dot(q1); - auto lerp_q0_q1_half = decltype(q0)::lerp(q0, q1, 0.3f); - pw::debug::d() << "quaternion::lerp(q0,q1,0.3) -> \n" - << pw::serialize::to_string(lerp_q0_q1_half); - - auto slerp_q0_q1_half = decltype(q0)::slerp(q0, q1, 0.3f); - pw::debug::d() << "quaternion::slerp(q0,q1,0.3) -> \n" - << pw::serialize::to_string(slerp_q0_q1_half); return 0; } diff --git a/src/core/tests/pwcore_test_serialize.cpp b/src/core/tests/pwcore_test_serialize.cpp deleted file mode 100644 index f66461e..0000000 --- a/src/core/tests/pwcore_test_serialize.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include -#include - -#include - -auto main() -> int { - - auto vec = pw::vector{.333f, .444f, .555f}; - - std::cout << pw::serialize::to_string(vec) << '\n'; -} diff --git a/src/core/tests/pwcore_test_transform_tools.cpp b/src/core/tests/pwcore_test_transform_tools.cpp index 965b57b..1a4c0b0 100644 --- a/src/core/tests/pwcore_test_transform_tools.cpp +++ b/src/core/tests/pwcore_test_transform_tools.cpp @@ -1,38 +1,18 @@ -#include -#include -#include #include +#include +#include -auto main() -> int { +#include - pw::debug::d() << "pixwerx.matrix_transform.test\n"; +int main(int argc,char **argv) { - auto scale_123 = - pw::matrix_transform::scale_matrix({1.f, 2.f, 3.f, 1.f}); - pw::debug::d() << "matrix_transform::scale(1,2,3) -> \n" - << pw::serialize::to_string(scale_123); + auto perspective_mat = pw::matrix_transform::perspective_projection(45.f,1.3f,10,100); + auto ortho_mat = pw::matrix_transform::orthographic_frustum(-1,1,1,-1,10,100); + auto lookat_mat = pw::matrix_transform::look_at(pw::vector3(0,0,5),pw::vector3(0,0,0),pw::vector3(0,1,0)); - auto fm_default = - pw::matrix_transform::frustum_matrix(pw::frustum{}); - pw::debug::d() << "matrix_transform::frustum::default -> \n" - << pw::serialize::to_string(fm_default); - auto fm_45deg_1dot3 = pw::matrix_transform::frustum_matrix( - pw::frustum::make_perspective_symmetric(45.f, 1.3f, 0.1f, - 1000.f)); - pw::debug::d() << "matrix_transform::frustum::45deg -> \n" - << pw::serialize::to_string(fm_45deg_1dot3); - - auto fm_ortho = pw::matrix_transform::frustum_matrix( - pw::frustum::make_orthographic_symmetric(0.5f, 1.3f, 0.1f, - 1000.f)); - pw::debug::d() << "matrix_transform::frustum::ortho -> \n" - << pw::serialize::to_string(fm_ortho); - - auto lookat_mat = pw::matrix_transform::look_at_matrix( - pw::vector{0.f, 0, 5}, pw::vector{0.f, 0, 0}, pw::vector{0.f, 1, 0}); - - pw::debug::d() << "matrix_transform::look_at -> \n" - << pw::serialize::to_string(lookat_mat); + std::cout << pw::serialize::matrix(perspective_mat) << std::endl; + std::cout << pw::serialize::matrix(ortho_mat) << std::endl; + std::cout << pw::serialize::matrix(lookat_mat) << std::endl; } diff --git a/src/core/tests/pwcore_test_vector.cpp b/src/core/tests/pwcore_test_vector.cpp index 7d8bc04..e2e291a 100644 --- a/src/core/tests/pwcore_test_vector.cpp +++ b/src/core/tests/pwcore_test_vector.cpp @@ -1,88 +1,51 @@ -#include -#include #include +#include -#include -#include -#include +#include -auto main() -> int { +int main(int ,char **) { - auto v2_A = pw::vector{3.2, 1.2}; - auto v2_B = pw::vector{6.4, 2.4}; + pw::vector2_ v2_A = { 3.2, 1.2 }; + pw::vector2_ v2_B = { 3.2, 1.2 }; - auto AB_lerp = decltype(v2_A)::lerp(v2_A, v2_B, 0.5); + auto AB_lerp = pw::vector2f::lerp(v2_A,v2_B,0.5); - std::print("lerp A:({}) B:({}) t:({}) -> {}\n", - pw::serialize::to_string(v2_A), pw::serialize::to_string(v2_B), - 0.5, pw::serialize::to_string(AB_lerp)); + pw::vector4_ v4; + pw::vector3f v = pw::vector3f::backward(); - auto v4_14 = pw::vector4::all(1.4); - auto v4_sq = pw::vector4::sequence(1.4); - auto v3_fw = pw::vector3f::forward(); + v4.fill(1.5); - std::print("all(1.4) -> {}\n", pw::serialize::to_string(v4_14)); - std::print("sequence(1.4) -> {}\n", pw::serialize::to_string(v4_sq)); - std::print("forward() -> {}\n", pw::serialize::to_string(v3_fw)); + std::cout << "v4 = " << pw::serialize::matrix(v4) << std::endl; - auto v3_sw_1 = v4_sq.swizzle(0, 1); // xy - auto v3_sw_2 = v4_sq.swizzle(1, 0); // yx - auto v3_sw_3 = v4_sq.swizzle(0, 2); // xz +// std::cout << "rows() : " << v4.rows() << std::endl; +// std::cout << "cols() : " << v4.cols() << std::endl; + std::cout << "ptr() : " << v4.ptr() << std::endl; + std::cout << "ptr()[0] : " << v4.ptr()[0] << std::endl; + std::cout << "(0,0) : " << v4(0,0) << std::endl; - std::print("swizzle(0,1) aka xy -> {}\n", - pw::serialize::to_string(v3_sw_1)); - std::print("swizzle(1,0) aka yx -> {}\n", - pw::serialize::to_string(v3_sw_2)); - std::print("swizzle(0,2) aka xz -> {}\n", - pw::serialize::to_string(v3_sw_3)); + auto v3 = v4.xyz(); - auto v3_up_1 = v3_fw.unproject(1); - auto v3_pj_1 = v3_up_1.project(); + auto v3_p = v4.project(); - std::print("unproject(1) -> {}\n", pw::serialize::to_string(v3_up_1)); - std::print("project() -> {}\n", pw::serialize::to_string(v3_pj_1)); + auto v3_h = v.homogenous(); - auto v3_nlz = v3_up_1.normalized(); - std::print("normalized() -> {}\n", pw::serialize::to_string(v3_nlz)); +// auto v3_lerp = vector4f:: - auto e1 = pw::vector{2.0, 0.0, 0.0}; - auto e2 = pw::vector{0.0, 0.0, 2.0}; + std::cout << "v3 = " << pw::serialize::matrix(v3) << std::endl; + + std::cout << "v3.normalized() = " << pw::serialize::matrix(v3.normalized()) << std::endl; + + auto e1 = pw::vector3 { 2.0, 0.0, 0.0 }; + auto e2 = pw::vector3 { 0.0, 0.0, 2.0 }; auto e2_e1 = e1 - e2; - std::print("{} - {} -> {}\n", pw::serialize::to_string(e1), - pw::serialize::to_string(e2), pw::serialize::to_string(e2_e1)); + auto n_e1_e2 = pw::vector3::cross(e1,e2); - auto e1_cross_e2 = e1.cross(e2); - std::print("{} x {} -> {}\n", pw::serialize::to_string(e1), - pw::serialize::to_string(e2), - pw::serialize::to_string(e1_cross_e2)); + std::cout << "e1xe2 " << pw::serialize::matrix(n_e1_e2) << std::endl; - auto e1_dot_e2 = e1.dot(e2); - - std::print("{} * {} -> {}\n", pw::serialize::to_string(e1), - pw::serialize::to_string(e2), e1_dot_e2); - - auto vec3f = pw::vector{1.f, 2.f, 3.f}; - - std::print("y: {}\n", vec3f.get<1>()); - std::print("tuple size {}\n", std::tuple_size_v); - - auto& [x, y, z] = vec3f; - std::print("x:{} y:{} z:{}\n", x, y, z); - - x++; - y--; - z = 0; - std::print("x:{} y:{} z:{}\n", x, y, z); - - auto min_ab{vec3f.min(pw::vector{1.3f, 0.9f, 2.3f})}; - - std::print("min((1.3f,0.9f,2.3f),({} {} {})) -> ({} {} {})\n", vec3f.x(), - vec3f.y(), vec3f.z(), min_ab.x(), min_ab.y(), min_ab.z()); - - std::print("{}", vec3f); + std::cout << "e1xe2 " << pw::serialize::matrix(e2_e1) << std::endl; return 0; } diff --git a/src/deps/glad/CMakeLists.txt b/src/deps/glad/CMakeLists.txt index c10a525..4dc5f6e 100644 --- a/src/deps/glad/CMakeLists.txt +++ b/src/deps/glad/CMakeLists.txt @@ -1,11 +1,11 @@ -cmake_minimum_required(VERSION 3.20) +cmake_minimum_required(VERSION 3.8) project(glad) add_library(glad STATIC src/glad.c) target_include_directories( - glad - PUBLIC - include - ) + glad + PUBLIC + include + ) diff --git a/src/geometry/include/pw/geometry/primitives.hpp b/src/geometry/include/pw/geometry/primitives.hpp index 4d03787..7df5bce 100644 --- a/src/geometry/include/pw/geometry/primitives.hpp +++ b/src/geometry/include/pw/geometry/primitives.hpp @@ -1,22 +1,21 @@ #ifndef PW_GEOMETRY_PRIMITIVES_HPP #define PW_GEOMETRY_PRIMITIVES_HPP -#include +#include namespace pw { -struct primitives { + struct primitives { - static geometry box(real_t size_x, real_t size_y, real_t size_z); + static geometry box(real_t size_x, real_t size_y, real_t size_z); - static geometry sphere(real_t radius, int divisions_latitude, - int divisions_longitude); + static geometry sphere(real_t radius,int divisions_latitude,int divisions_longitude); - static geometry cone(); + static geometry cone(); + + static geometry pyramid(); + }; - static geometry pyramid(); }; -}; // namespace pw - #endif diff --git a/src/io/include/pw/io/image_io.hpp b/src/io/include/pw/io/image_io.hpp index 07978e7..f1646e1 100644 --- a/src/io/include/pw/io/image_io.hpp +++ b/src/io/include/pw/io/image_io.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -8,8 +8,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -28,22 +28,27 @@ namespace pw { -struct image_io final { +class image_io { +public: + static image_io& get(); - image read(std::string const& uri, uint32_t flags = 0); + image read(std::string const& uri,uint32_t flags = 0); - bool write(const std::string& uri, const image& img, uint32_t flags = 0); + bool write(const std::string &uri, const image &img, uint32_t flags = 0); ~image_io(); - protected: + +protected: + struct impl; std::unique_ptr _impl; image_io(); + }; -} // namespace pw +} #endif diff --git a/src/io/src/image_io.cpp b/src/io/src/image_io.cpp index b7f1c12..66db1c6 100644 --- a/src/io/src/image_io.cpp +++ b/src/io/src/image_io.cpp @@ -6,66 +6,77 @@ #include "stb_image.h" #define STB_IMAGE_WRITE_IMPLEMENTATION -#include "stb_image_write.h" + #include "stb_image_write.h" #include namespace pw { -struct image_io::impl { +struct image_io::impl +{ - image read_impl(const std::string& uri, uint32_t flags) { - int x{0}, y{0}, n{0}; + image read_impl(const std::string& uri,uint32_t flags) + { + int x{ 0 }, y{ 0 }, n{ 0 }; const auto data = stbi_load(uri.c_str(), &x, &y, &n, 4); if (data) { - image r; + image r; - r.create(size{x, y}.cast(), - image::pixel_layout::RGBA8, - reinterpret_cast(data)); + r.create(size(x,y),image::pixel_layout::RGBA8,reinterpret_cast(data)); - stbi_image_free(data); + stbi_image_free(data); return r; - } else { + } else { - debug::e() << stbi_failure_reason(); - } + debug::e() << stbi_failure_reason(); + } return image(); } - bool write(const std::string& uri, const image& img, uint32_t flags) { - auto res = - stbi_write_png(uri.c_str(), img.size().width, img.size().height, - image::components(img.layout()), img.data(), - img.size().width * image::components(img.layout())); + bool write(const std::string& uri, const image& img, uint32_t flags) + { + auto res = stbi_write_png(uri.c_str(),img.size().width,img.size().height, + image::components(img.layout()), + img.data(), + img.size().width * image::components(img.layout())); return 0 == res; } + }; -image_io& image_io::get() { + +image_io &image_io::get() +{ static image_io instance; return instance; } -image image_io::read(const std::string& uri, uint32_t flags) { - return _impl->read_impl(uri, flags); +image image_io::read(const std::string &uri, uint32_t flags) +{ + return _impl->read_impl(uri,flags); } -bool image_io::write(const std::string& uri, const image& img, uint32_t flags) { - return _impl->write(uri, img, flags); +bool image_io::write(const std::string &uri, const image& img, uint32_t flags) +{ + return _impl->write(uri,img,flags); } // // // -image_io::image_io() { _impl = make_unique(); } +image_io::image_io() +{ + _impl = make_unique(); +} -image_io::~image_io() {} +image_io::~image_io() +{ +} -} // namespace pw +} diff --git a/src/scene/include/pw/scene/components/camera.hpp b/src/scene/include/pw/scene/components/camera.hpp index 645f832..4181392 100644 --- a/src/scene/include/pw/scene/components/camera.hpp +++ b/src/scene/include/pw/scene/components/camera.hpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 1999-2024 Hartmut Seichter + * Copyright (C) 1999-2020 Hartmut Seichter * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,15 +32,17 @@ namespace pw { struct camera { - matrix4x4f projection = matrix4x4f::identity(); - matrix4x4f view = matrix_transform::look_at_matrix( - vector3f{}, vector3f::x_axis(), vector3f::y_axis()); + matrix4x4 view = matrix4x4::identity(); + matrix4x4 projection = matrix_transform::look_at(vector3{0,0,0}, + vector3{0,0,1}, + vector3{0,1,0}); - matrix4x4f viewport = pw::rectangle{{0.f, 0.f} {1.f, 1.f}}; + rectangle viewport = pw::rectangle({0, 0, 1, 1}); uint32_t mask = 0xFFFFFF; }; -} // namespace pw +} + #endif diff --git a/src/scene/include/pw/scene/components/projection.hpp b/src/scene/include/pw/scene/components/projection.hpp index b598174..28c6920 100644 --- a/src/scene/include/pw/scene/components/projection.hpp +++ b/src/scene/include/pw/scene/components/projection.hpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 1999-2024 Hartmut Seichter + * Copyright (C) 1999-2020 Hartmut Seichter * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -73,3 +73,4 @@ struct projection { } #endif + diff --git a/src/scene/include/pw/scene/components/relationship.hpp b/src/scene/include/pw/scene/components/relationship.hpp index 5b3049f..b00da04 100644 --- a/src/scene/include/pw/scene/components/relationship.hpp +++ b/src/scene/include/pw/scene/components/relationship.hpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 1999-2024 Hartmut Seichter + * Copyright (C) 1999-2020 Hartmut Seichter * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,6 +25,7 @@ #ifndef PW_SCENE_COMPONENTS_RELATIONSHIP_HPP #define PW_SCENE_COMPONENTS_RELATIONSHIP_HPP + #include namespace pw { @@ -33,16 +34,22 @@ namespace pw { * @brief entity relations are hidden and managed by the entity itself */ struct parent { + parent() = default; + parent(const parent&) = default; - entt::entity entity{entt::null}; + entt::entity entity { entt::null }; operator bool() const { return entity != entt::null; } }; struct children { + children() = default; + children(const children&) = default; + std::vector entities; }; -} // namespace pw + +} #endif diff --git a/src/scene/include/pw/scene/components/transform.hpp b/src/scene/include/pw/scene/components/transform.hpp index af940fd..4ec5a02 100644 --- a/src/scene/include/pw/scene/components/transform.hpp +++ b/src/scene/include/pw/scene/components/transform.hpp @@ -7,64 +7,65 @@ namespace pw { -struct transform final { +struct transform { - void set_global(const matrix4x4f& global) { - matrix4x4f diff = _global.inverse() * global; - _local = _local * diff; + transform() = default; + transform(const transform&) = default; + + inline const matrix4x4& local() const { return _local; } + void set_local(const matrix4x4 &local) + { + _local = local; + } + + inline const matrix4x4& global() const { return _global; } + + void set_global(const matrix4x4 &global) + { + matrix4x4 diff = _global.inverse() * global; + _local = _local * diff; _global = global; } - inline transform& translate(const float& x, const float& y, - const float& z) { - _local[0][3] += x; - _local[1][3] += y; - _local[2][3] += z; - return *this; - } + inline transform& translate(const real_t &x, const real_t &y, const real_t &z) { + _local(0,3) += x;_local(1,3) += y;_local(2,3) += z; + return *this; + } - inline transform& set_translation(const float& x, const float& y, - const float& z) { - _local[0][3] = x; - _local[1][3] = y; - _local[2][3] = z; - return *this; - } + inline transform& set_translation(const real_t &x, const real_t &y, const real_t &z) { + _local(0,3) = x;_local(1,3) = y;_local(2,3) = z; + return *this; + } - inline transform& rotate(const quaternionf& q) { - _local = _local * q.to_matrix().unproject(1); - return *this; - } + inline transform& rotate(const quaternion& q) { + _local = _local * q.to_matrix(); + return *this; + } - inline transform& set_rotation(const quaternionf& q) { - _local = q.to_matrix().unproject(1); - return *this; - } + inline transform& set_rotation(const quaternion& q) { + _local = q.to_matrix(); + return *this; + } - inline transform& scale(const float& sx, const float& sy, const float& sz) { - _local[0][0] *= sx; - _local[1][1] *= sy; - _local[2][2] *= sz; - return *this; - } + inline transform& scale(const real_t &sx, const real_t &sy, const real_t &sz) { + _local(0,0) *= sx; _local(1,1) *= sy; _local(2,2) *= sz; + return *this; + } - inline transform& set_scale(const float& sx, const float& sy, - const float& sz) { - _local[0][0] = sx; - _local[1][1] = sy; - _local[2][2] = sz; - return *this; - } + inline transform& set_scale(const real_t &sx, const real_t &sy, const real_t &sz) { + _local(0,0) = sx; _local(1,1) = sy; _local(2,2) = sz; + return *this; + } - inline transform& scale(const float& uniform_scale) { - return scale(uniform_scale, uniform_scale, uniform_scale); - } + inline transform& scale(const real_t& uniform_scale) { + return scale(uniform_scale,uniform_scale,uniform_scale); + } - matrix4x4f _local = matrix4x4f::identity(); - matrix4x4f _global = matrix4x4f::identity(); + matrix4x4 _local = matrix4x4::identity(); + matrix4x4 _global = matrix4x4::identity(); }; -} // namespace pw +} #endif diff --git a/src/scene/include/pw/scene/entity.hpp b/src/scene/include/pw/scene/entity.hpp index ff14ef9..aa2655a 100644 --- a/src/scene/include/pw/scene/entity.hpp +++ b/src/scene/include/pw/scene/entity.hpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 1999-2024 Hartmut Seichter + * Copyright (C) 1999-2020 Hartmut Seichter * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -150,6 +150,6 @@ private: #include #include -// #include +#include #endif diff --git a/src/scene/include/pw/scene/scene.hpp b/src/scene/include/pw/scene/scene.hpp index a89a6d5..d70c570 100644 --- a/src/scene/include/pw/scene/scene.hpp +++ b/src/scene/include/pw/scene/scene.hpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 1999-2024 Hartmut Seichter + * Copyright (C) 1999-2017 Hartmut Seichter * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,7 +33,9 @@ namespace pw { class entity; -struct scene final { +class scene { +public: + using registry = entt::registry; diff --git a/src/scene/src/entity.cpp b/src/scene/src/entity.cpp index 8d89992..5a914ae 100644 --- a/src/scene/src/entity.cpp +++ b/src/scene/src/entity.cpp @@ -7,6 +7,7 @@ namespace pw { namespace detail { + // entity identiy is hidden struct identity { @@ -14,23 +15,25 @@ struct identity { identity(const std::string& name) : name(name) {} identity(const identity&) = default; - bool enabled = true; - std::string name = ""; - std::vector tags = {}; + bool enabled = true; + std::string name = ""; + std::vector tags = {}; std::vector layers = {}; }; -} // namespace detail +} -entity::entity(scene& s, const std::string& name) - : _registry(s._registry), - _entity(s._registry ? _registry->create() : entt::null) { +entity::entity(scene &s,const std::string& name) + : _registry(s._registry) + , _entity(s._registry ? _registry->create() : entt::null) +{ if (s._registry) { this->add_component(name); } } -bool entity::add_child(entity& child) { +bool entity::add_child(entity &child) +{ // not mixing scenes (yet) if (child._registry != this->_registry) { debug::e() << "Cannot mix entities from different scenes"; @@ -44,13 +47,14 @@ bool entity::add_child(entity& child) { c.entities.push_back(child._entity); // declare parent - auto& p_r = child.get_or_create_component(); + auto& p_r = child.get_or_create_component(); p_r.entity = _entity; return true; } -bool entity::remove_child(entity& child) { +bool entity::remove_child(entity& child) +{ // not mixing scenes (yet) if (child._registry != this->_registry) { debug::e() << "Cannot mix entities from different scenes"; @@ -58,17 +62,19 @@ bool entity::remove_child(entity& child) { } // both need to have a relationship component - if (child.has_component() && this->has_component()) { + if (child.has_component() && + this->has_component()) + { // we need to check if the child is related to the parent auto r_p = child.get_component(); - if (r_p.entity == _entity) { + if (r_p.entity == _entity) + { // now go ahead delete parent r_p.entity = entt::null; // now remove all children auto& c = this->get_component(); - c.entities.erase(std::remove(c.entities.begin(), c.entities.end(), - child._entity)); + c.entities.erase(std::remove(c.entities.begin(),c.entities.end(),child._entity)); // flag success return true; @@ -77,24 +83,38 @@ bool entity::remove_child(entity& child) { return false; } -size_t entity::child_count() const { - return this->has_component() - ? get_component().entities.size() - : 0; + +size_t entity::child_count() const +{ + return this->has_component() ? + get_component().entities.size() : + 0; } -void entity::set_name(const std::string& n) { - auto& ident = get_or_create_component(); - ident.name = n; + +void entity::set_name(const std::string& n) +{ + auto &ident = get_or_create_component(); + ident.name = n; } -std::string entity::name() { - auto& ident = get_or_create_component(); +std::string entity::name() +{ + auto &ident = get_or_create_component(); return ident.name; } -entity::~entity() { this->destroy(); } -void entity::destroy() { _registry->destroy(_entity); } -} // namespace pw +entity::~entity() +{ + this->destroy(); +} + +void entity::destroy() +{ + _registry->destroy(_entity); +} + +} + diff --git a/src/scene/src/scene.cpp b/src/scene/src/scene.cpp index f1d4787..b984613 100644 --- a/src/scene/src/scene.cpp +++ b/src/scene/src/scene.cpp @@ -4,11 +4,23 @@ #include "pw/core/debug.hpp" #include "pw/core/serialize.hpp" -#include "pw/core/mesh.hpp" +#include "pw/core/geometry.hpp" #include "pw/core/matrix_transform.hpp" namespace pw { + +struct mesh { + geometry geom; +}; + +struct renderer { + std::unique_ptr state; +// std::vector mat; +}; + + + scene::scene() : _registry{ std::make_shared()} { @@ -16,6 +28,8 @@ scene::scene() // size_t scene::count_all_enties() const // { +// return _registry->storage(). + // size_t scene::count_alive_enties() const // { // return _registry->storage().alive(); @@ -27,7 +41,7 @@ void scene::update_transforms() //auto [t,r] = view.get(entity); -#if 0 +#if 1 // search for nodes with parent and transform (only find leaf nodes) auto view = _registry->view(entt::exclude); @@ -49,7 +63,7 @@ void scene::update_transforms() debug::d() << "\tpath length " << path.size(); std::reverse(path.begin(),path.end()); - auto m = pw::matrix4x4f::identity(); + auto m = pw::matrix4x4::identity(); for (auto& transform : path) { diff --git a/src/system/include/pw/system/input.hpp b/src/system/include/pw/system/input.hpp index 638690c..5e39f56 100644 --- a/src/system/include/pw/system/input.hpp +++ b/src/system/include/pw/system/input.hpp @@ -1,46 +1,54 @@ #ifndef PW_SYSTEM_INPUT_HPP #define PW_SYSTEM_INPUT_HPP -#include #include #include namespace pw { -struct input final { +class input { +public: static input& get(); - point mouse_position() const { return _mouse_position; } + point mouse_position() const { return _mouse_position; } bool mouse_pressed() const { return _mouse_pressed; } int mouse_button() const { return _mouse_button; } - bool has_input() const { return !_input_string.empty(); } + + bool has_input() const { return !_input_string.empty();} std::string input_string() const { return _input_string; } - ~input() = default; + ~input() = default; - enum mouse_button_state { pressed, released }; + enum mouse_button_state { + pressed, + released + }; void reset(); - protected: +protected: + friend class window; input() = default; - private: - point _mouse_position; - int _mouse_button; +private: + + point _mouse_position; + int _mouse_button; bool _mouse_pressed; int _key_code; bool _key_pressed; - std::string _input_string; + std::string _input_string; + + }; -} // namespace pw +} #endif diff --git a/src/system/include/pw/system/path.hpp b/src/system/include/pw/system/path.hpp index 4790366..553047e 100644 --- a/src/system/include/pw/system/path.hpp +++ b/src/system/include/pw/system/path.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -8,8 +8,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -27,33 +27,38 @@ namespace pw { -struct path final { + +class path { +public: + using path_list = std::vector; - static path& get(); - ~path(); + static path& get(); + ~path(); - std::string separator() const; + std::string separator() const; - std::string executable_path() const; + std::string executable_path() const; - path_list resource_paths() const { return _resource_paths; } + path_list resource_paths() const { return _resource_paths; } void set_resource_paths(path_list pl); - std::string find_file(const std::string& filename) const; + std::string find_file(const std::string &filename) const; - std::string get_filename(const std::string& filepath, - bool with_extension = true) const; + std::string get_filename(const std::string &filepath, bool with_extension = true) const; - private: - path_list _resource_paths; +protected: + + path_list _resource_paths; + + path(); + + struct impl; + std::unique_ptr _impl; - path(); - struct impl; - std::unique_ptr _impl; }; -} // namespace pw +} #endif diff --git a/src/system/include/pw/system/window.hpp b/src/system/include/pw/system/window.hpp index c1ca8fe..cc55bb3 100644 --- a/src/system/include/pw/system/window.hpp +++ b/src/system/include/pw/system/window.hpp @@ -1,33 +1,33 @@ #ifndef PW_SYSTEM_WINDOW_HPP #define PW_SYSTEM_WINDOW_HPP -#include #include -#include #include +#include #include namespace pw { -struct window final { +class window { +public: - using on_update_t = std::function; - using on_resize_t = std::function; + using on_update_t = std::function ; + using on_resize_t = std::function ; window(); ~window(); bool update(); - void set_title(const std::string& title); + void set_title(const std::string& title); - void set_size(const size& s); - pw::size size() const; - pw::size client_size() const; + void set_size(const size& s); + pw::size size() const; + pw::size client_size() const; - void set_position(const point& p); - point position() const; + void set_position(const point& p); + point position() const; typedef void drop_callback; @@ -39,15 +39,17 @@ struct window final { bool visible() const; void set_visible(bool is_visible); +protected: - protected: - struct impl; - std::unique_ptr _impl; + struct impl; + std::unique_ptr _impl; on_update_t _on_update; on_resize_t _on_resize; + + }; -} // namespace pw +} #endif diff --git a/src/system/src/window.cpp b/src/system/src/window.cpp index e1f2616..734db9e 100644 --- a/src/system/src/window.cpp +++ b/src/system/src/window.cpp @@ -1,100 +1,99 @@ #include "pw/system/window.hpp" -// clang-format off #include "glad/glad.h" #include "GLFW/glfw3.h" -// clang-format on -#include "pw/system/display.hpp" -#include "pw/system/input.hpp" #include "pw/visual/context.hpp" +#include "pw/system/input.hpp" +#include "pw/system/display.hpp" #include "pw/core/debug.hpp" #include -#include -#include #include +#include + +#include namespace pw { -// struct window_context : context +//struct window_context : context //{ -// virtual bool make_current() override; -// virtual void resize() override; -// // virtual context::size size() override; -// virtual void flush() override; -// }; +// virtual bool make_current() override; +// virtual void resize() override; +// // virtual context::size size() override; +// virtual void flush() override; +//}; -// bool window_context::make_current() +//bool window_context::make_current() //{ -// } +//} -// void window_context::resize() +//void window_context::resize() //{ -// } +//} -// void window_context::flush() +//void window_context::flush() //{ -// } +//} struct window::impl { window& _parent; - GLFWwindow* _window = nullptr; + GLFWwindow *_window = nullptr; - ::pw::size _old_size; - point _old_pos; + ::pw::size _old_size; + pointi _old_pos; // window_context _context; - static void error_callback(int error, const char* description) { - debug::e() << "GLFW error: " << description; + static void error_callback(int error, const char* description) + { + debug::e() << "GLFW error: " << description; } - static void drop_callback(GLFWwindow* window, int count, - const char** paths) { + static void drop_callback(GLFWwindow* window, int count, const char** paths) + { // std::cout << __FUNCTION__ << std::endl; // for (int i = 0; i < count; i++) // std::cout << "\t" << paths[i] << std::endl; } - static void scroll_callback(GLFWwindow* window, double xoffset, - double yoffset) { - // std::cout << __FUNCTION__ << std::endl; + static void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) + { + std::cout << __FUNCTION__ << std::endl; } - static void mouse_button_callback(GLFWwindow* window, int button, - int action, int mods) { + static void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) + { input::get()._mouse_button = button; - // std::cout << __FUNCTION__ << " " << button << " " << action << " " - // << mods << std::endl; + std::cout << __FUNCTION__ << " " << button << " " << action << " " << mods << std::endl; // input::get()._mouse_position } - static void cursor_pos_callback(GLFWwindow* window, double xpos, - double ypos) { - input::get()._mouse_position = vector{xpos, ypos}.cast(); + static void cursor_pos_callback(GLFWwindow* window, double xpos, double ypos) + { + input::get()._mouse_position = pointd(xpos,ypos).cast(); } - static void key_callback(GLFWwindow* window, int key, int scancode, - int action, int mods) { - input::get()._key_code = scancode; + + static void key_callback(GLFWwindow *window,int key, int scancode, int action, int mods) + { + input::get()._key_code = scancode; input::get()._key_pressed = action; // action 0,1,2 // std::cout << __FUNCTION__ << action << std::endl; } - // static void character_callback(GLFWwindow* window, unsigned int - // codepoint) + // static void character_callback(GLFWwindow* window, unsigned int codepoint) // { // std::cout << __FUNCTION__ << std::endl; // } - static void charmods_callback(GLFWwindow* window, unsigned int codepoint, - int mods) { + static void charmods_callback(GLFWwindow* window, unsigned int codepoint, int mods) + { // build the string from a Unicode code point std::wstring_convert, char32_t> converter; std::string u8str = converter.to_bytes(codepoint); @@ -102,30 +101,28 @@ struct window::impl { input::get()._input_string = u8str; } - static void framebuffer_size_callback(GLFWwindow* window, int width, - int height) { - window::impl* impl = - static_cast(glfwGetWindowUserPointer(window)); + static void framebuffer_size_callback(GLFWwindow* window, int width, int height) + { + window::impl* impl = static_cast(glfwGetWindowUserPointer(window)); impl->_parent._on_resize(impl->_parent); - // debug::d() << "window::frame_buffer_size_callback " << width - // << "x" << height; +// debug::d() << "window::frame_buffer_size_callback " << width << "x" << height; // impl->on_resize(width,height); - // std::cout << "framebuffer " << width << "x" << height << - // std::endl; - // glViewport(0, 0, width, height); + // std::cout << "framebuffer " << width << "x" << height << std::endl; +// glViewport(0, 0, width, height); } - void update_display_list() { + void update_display_list() + { display::_displays.clear(); // fetch all monitors - int monitor_count = 0; + int monitor_count = 0; GLFWmonitor** monitors = glfwGetMonitors(&monitor_count); - for (int i = 0; i < monitor_count; i++) { + for (int i = 0; i < monitor_count;i++) { display d; d._name = std::string(glfwGetMonitorName(monitors[i])); @@ -140,21 +137,24 @@ struct window::impl { // glfwGetMonitorPos( // glfwGetMonitorPhysicalSize( // glfwGetMonitorName(); + } - impl(window& w) : _parent(w) { + impl(window& w) + : _parent(w) + { // initialize - if (!glfwInit()) { + if (!glfwInit()) + { debug::e() << "Initalization error"; } - int glfw_major, glfx_minor, glfw_rev; - glfwGetVersion(&glfw_major, &glfx_minor, &glfw_rev); + int glfw_major, glfx_minor,glfw_rev; + glfwGetVersion(&glfw_major,&glfx_minor,&glfw_rev); - // debug::d() << "GLFW " << glfw_major << "." << glfx_minor << - // "." << glfw_rev; debug::d() << "GLFW header " << - // GLFW_VERSION_MAJOR << "." << GLFW_VERSION_MINOR << "." << - // GLFW_VERSION_REVISION; + +// debug::d() << "GLFW " << glfw_major << "." << glfx_minor << "." << glfw_rev; +// debug::d() << "GLFW header " << GLFW_VERSION_MAJOR << "." << GLFW_VERSION_MINOR << "." << GLFW_VERSION_REVISION; update_display_list(); @@ -175,7 +175,8 @@ struct window::impl { glfwMakeContextCurrent(_window); // load opengl - if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { + if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) + { debug::e() << "glad couldn't get OpenGL API"; } @@ -183,16 +184,14 @@ struct window::impl { int major, minor, rev; major = glfwGetWindowAttrib(_window, GLFW_CONTEXT_VERSION_MAJOR); minor = glfwGetWindowAttrib(_window, GLFW_CONTEXT_VERSION_MINOR); - rev = glfwGetWindowAttrib(_window, GLFW_CONTEXT_REVISION); + rev = glfwGetWindowAttrib(_window, GLFW_CONTEXT_REVISION); // maybe something to pass to the outside - // debug::d() << "OpenGL " << major << "." << minor << "." << - // rev; +// debug::d() << "OpenGL " << major << "." << minor << "." << rev; - glfwSetWindowUserPointer(_window, this); + glfwSetWindowUserPointer(_window,this); - glfwSetFramebufferSizeCallback(_window, - window::impl::framebuffer_size_callback); + glfwSetFramebufferSizeCallback(_window, window::impl::framebuffer_size_callback); glfwSetKeyCallback(_window, window::impl::key_callback); // glfwSetCharCallback(_window, character_callback); glfwSetCharModsCallback(_window, charmods_callback); @@ -204,17 +203,22 @@ struct window::impl { glfwSetMouseButtonCallback(_window, mouse_button_callback); glfwSetScrollCallback(_window, scroll_callback); + glfwSetErrorCallback(error_callback); - // glfwSetWindowCloseCallback(_window,close_callback); + //glfwSetWindowCloseCallback(_window,close_callback); } - ~impl() { glfwDestroyWindow(_window); } + ~impl() + { + glfwDestroyWindow(_window); + } - bool update() { - if (_window && !glfwWindowShouldClose(_window)) { - // TODO lock an unlock the current input system to allow for late - // events coming in + bool update() + { + if (_window && !glfwWindowShouldClose(_window)) + { + // TODO lock an unlock the current input system to allow for late events coming in input::get().reset(); // get new events @@ -230,60 +234,70 @@ struct window::impl { return false; } - void set_title(const std::string& title) { - glfwSetWindowTitle(_window, title.c_str()); + void set_title(const std::string& title) + { + glfwSetWindowTitle(_window,title.c_str()); } - void set_size(const ::pw::size& s) { - glfwSetWindowSize(_window, s.width, s.height); + void set_size(const ::pw::size& s) + { + glfwSetWindowSize(_window,s.width,s.height); } - ::pw::size size() const { - int w, h; - glfwGetWindowSize(_window, &w, &h); - return ::pw::size{w, h}; + ::pw::size size() const + { + int w,h; + glfwGetWindowSize(_window,&w,&h); + return ::pw::size(w,h); } - ::pw::size client_size() const { - int w, h; - glfwGetFramebufferSize(_window, &w, &h); - return ::pw::size{w, h}; + + ::pw::size client_size() const + { + int w,h; + glfwGetFramebufferSize(_window,&w,&h); + return ::pw::size(w,h); } - ::pw::point position() const { - int x, y; - glfwGetWindowPos(_window, &x, &y); - return {x, y}; + ::pw::point position() const + { + int x,y; + glfwGetWindowPos(_window,&x,&y); + return ::pw::point(x,y); } - void set_position(const point& p) { - glfwSetWindowPos(_window, p.x(), p.y()); + void set_position(const pointi& p) + { + glfwSetWindowPos(_window,p.x,p.y); } - void set_fullscreen(bool use_fullscreen) { + void set_fullscreen(bool use_fullscreen) + { if (fullscreen() == use_fullscreen) return; - if (use_fullscreen) { - glfwGetWindowPos(_window, &_old_pos.x(), &_old_pos.y()); - glfwGetWindowSize(_window, &_old_size.width, &_old_size.height); + if (use_fullscreen) + { + glfwGetWindowPos( _window, &_old_pos.x, &_old_pos.y ); + glfwGetWindowSize( _window, &_old_size.width, &_old_size.height ); - GLFWmonitor* monitor = glfwGetPrimaryMonitor(); - const GLFWvidmode* mode = glfwGetVideoMode(monitor); + GLFWmonitor * monitor = glfwGetPrimaryMonitor(); + const GLFWvidmode * mode = glfwGetVideoMode(monitor); - glfwSetWindowMonitor(_window, monitor, 0, 0, mode->width, - mode->height, 0); + glfwSetWindowMonitor( _window, monitor, 0, 0, mode->width, mode->height, 0 ); - } else { + } else + { - glfwSetWindowMonitor(_window, nullptr, _old_pos.x(), _old_pos.y(), - _old_size.width, _old_size.height, 0); + glfwSetWindowMonitor( _window, nullptr, _old_pos.x,_old_pos.y, _old_size.width,_old_size.height,0); } // glfwSetWindow } - bool fullscreen() const { return glfwGetWindowMonitor(_window) != nullptr; } + bool fullscreen() const { + return glfwGetWindowMonitor(_window) != nullptr; + } void set_visible(bool show) { (show) ? glfwShowWindow(_window) : glfwHideWindow(_window); @@ -294,39 +308,77 @@ struct window::impl { } }; + // // // window::window() - : _impl(std::make_unique(*this)), _on_update([](window&) {}), - _on_resize([](window&) {}) {} + : _impl(std::make_unique(*this)) + , _on_update([](window&){}) + , _on_resize([](window&){}) +{ +} -window::~window() {} +window::~window() +{ +} -bool window::update() { return _impl->update(); } +bool window::update() +{ + return _impl->update(); +} -void window::set_title(const std::string& title) { _impl->set_title(title); } +void window::set_title(const std::string& title) +{ + _impl->set_title(title); +} -void window::set_size(const ::pw::size& s) { _impl->set_size(s); } +void window::set_size(const ::pw::size& s) +{ + _impl->set_size(s.cast()); +} -size window::size() const { return _impl->size(); } +size window::size() const +{ + return _impl->size(); +} -size window::client_size() const { return _impl->client_size(); } +size window::client_size() const +{ + return _impl->client_size(); +} -void window::set_position(const point& p) { +void window::set_position(const point &p) +{ _impl->set_position(p.cast()); } -point window::position() const { return _impl->position(); } +point window::position() const +{ + return _impl->position(); +} -bool window::fullscreen() const { return _impl->fullscreen(); } +bool window::fullscreen() const +{ + return _impl->fullscreen(); +} -void window::set_fullscreen(bool use_fullscreen) { +void window::set_fullscreen(bool use_fullscreen) +{ _impl->set_fullscreen(use_fullscreen); } -bool window::visible() const { return _impl->visible(); } +bool window::visible() const +{ + return _impl->visible(); +} -void window::set_visible(bool is_visible) { _impl->set_visible(is_visible); } +void window::set_visible(bool is_visible) +{ + _impl->set_visible(is_visible); +} -} // namespace pw + + + +} diff --git a/src/visual/CMakeLists.txt b/src/visual/CMakeLists.txt index ce9ee81..36e6c8f 100644 --- a/src/visual/CMakeLists.txt +++ b/src/visual/CMakeLists.txt @@ -38,4 +38,4 @@ target_include_directories( include ) -target_link_libraries(pwvisual pwcore pwscene glad) +target_link_libraries(pwvisual pwscene glad) diff --git a/src/visual/include/pw/visual/context.hpp b/src/visual/include/pw/visual/context.hpp index 9b0c41d..5da31d4 100644 --- a/src/visual/include/pw/visual/context.hpp +++ b/src/visual/include/pw/visual/context.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -8,8 +8,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -24,15 +24,17 @@ #ifndef PW_VISUAL_CONTEXT_HPP #define PW_VISUAL_CONTEXT_HPP -#include #include -#include #include #include +#include +#include + namespace pw { -struct context final { +class context { +public: context(); ~context(); @@ -40,24 +42,24 @@ struct context final { void set_blend(); void set_depth(); - void set_viewport(const rectangle& v); - rectangle viewport() const; + void set_viewport(const rectangle& v); + rectangle viewport() const; - size viewport_size() const; - point viewport_origin() const; + size viewport_size() const; + point viewport_origin() const; - void set_clearcolor(const color& c); + void set_clearcolor(const color &c); color clearcolor() const; void clear(); uint32_t get_error() const; - protected: +protected: struct impl; std::unique_ptr _impl; }; -} // namespace pw +} #endif diff --git a/src/visual/include/pw/visual/framebuffer.hpp b/src/visual/include/pw/visual/framebuffer.hpp index 9423a09..2052fa9 100644 --- a/src/visual/include/pw/visual/framebuffer.hpp +++ b/src/visual/include/pw/visual/framebuffer.hpp @@ -6,20 +6,22 @@ namespace pw { -struct framebuffer final { +class framebuffer { +public: framebuffer(); ~framebuffer(); - bool create(const size& s); + bool create(const size& s); void bind(); void blit(); void unbind(); - protected: +protected: + struct impl; std::unique_ptr _impl; }; -} // namespace pw +} #endif diff --git a/src/visual/include/pw/visual/pipeline.hpp b/src/visual/include/pw/visual/pipeline.hpp index 486e4a5..c8a464f 100644 --- a/src/visual/include/pw/visual/pipeline.hpp +++ b/src/visual/include/pw/visual/pipeline.hpp @@ -1,42 +1,52 @@ #ifndef PW_VISUAL_PIPELINE_HPP #define PW_VISUAL_PIPELINE_HPP -#include -#include -#include #include +#include +#include +#include -#include #include +#include + #include namespace pw { + + + class pipeline { - public: - pipeline(); +public: + pipeline(); ~pipeline(); void draw(); - bool create(size s); + bool create(size s); + +protected: + struct impl; + std::unique_ptr _impl; - protected: - struct impl; - std::unique_ptr _impl; }; + + struct render_pass { - void submit(const geometry& g, const matrix4x4& model_mat, - const matrix4x4& view_mat, const matrix4x4& projection_mat); + void submit(const geometry& g, + const matrix4x4& model_mat, + const matrix4x4& view_mat, + const matrix4x4& projection_mat); shader _shader; renderer _renderer; }; -} // namespace pw + +} #endif diff --git a/src/visual/include/pw/visual/renderer.hpp b/src/visual/include/pw/visual/renderer.hpp index 8748bdd..8b0d2eb 100644 --- a/src/visual/include/pw/visual/renderer.hpp +++ b/src/visual/include/pw/visual/renderer.hpp @@ -1,33 +1,39 @@ #ifndef PW_VISUAL_MESH_RENDERER_HPP #define PW_VISUAL_MESH_RENDERER_HPP -#include #include +#include namespace pw { -struct mesh; +class geometry; /** - * @brief builds a renderer for meshes + * @brief builds a renderer for geometry */ -struct renderer final { +class renderer { +public: + renderer(); - renderer(const mesh& m); + renderer(const geometry& m); ~renderer(); - bool update(const mesh& m); - void release(); + bool update(const geometry &m); + void release(); - void draw(); - bool ready() const; + void draw(); + bool ready() const; + + uint64_t change_count() const; + void set_change_count(uint64_t n); +protected: + + struct impl; + std::unique_ptr _impl; - protected: - struct impl; - std::unique_ptr _impl; }; -} // namespace pw +} #endif diff --git a/src/visual/include/pw/visual/shader.hpp b/src/visual/include/pw/visual/shader.hpp index a40cc09..cbf8b8f 100644 --- a/src/visual/include/pw/visual/shader.hpp +++ b/src/visual/include/pw/visual/shader.hpp @@ -1,10 +1,11 @@ #ifndef PW_VISUAL_SHADER_HPP #define PW_VISUAL_SHADER_HPP -#include #include #include #include +#include + #include #include @@ -12,72 +13,77 @@ namespace pw { -struct shader final { - shader(); +class shader { +public: + + shader(); ~shader(); - enum class code_type { vertex, fragment, geometry, compute }; + enum class code_type { + vertex, + fragment, + geometry, + compute + }; void set_source(code_type t, const std::string& c) { _source[t] = c; } - std::string source(code_type t) { return _source[t]; } + std::string source(code_type t) { return _source[t]; } - bool ready() const; + bool ready() const; - using uniform_t = std::variant; - using uniform_entry_t = std::tuple; - - - shader& set_uniform_at_location(int location, float v); + shader& set_uniform_at_location(int location,float v); shader& set_uniform_at_location(int location, uint32_t v); - shader& set_uniform_at_location(int location, int32_t v); - shader& set_uniform_at_location(int location, matrix4x4f const& v); - shader& set_uniform_at_location(int location, vector4f const& v); - shader& set_uniform_at_location(int location, texture const& t); + shader &set_uniform_at_location(int location, int32_t v); + shader& set_uniform_at_location(int location,matrix4x4f const &v); + shader& set_uniform_at_location(int location,vector4f const &v); + shader& set_uniform_at_location(int location,texture const &t); /** * @brief retrieves the position of a uniform * @param name of the uniform * @return position of the uniform or negative if it doesn't exist */ - int uniform_location(std::string const& name) const; + int uniform_location(std::string const & name) const; /** * @brief check if a uniform with the given name exists * @param name of the uniform * @return true if found */ - bool has_uniform(std::string const& name) const { - return uniform_location(name) >= 0; - } + bool has_uniform(std::string const &name) const { return uniform_location(name) >= 0; } /** * sets data of the */ - template - shader& set_uniform(std::string const& name, T&& value) { - return set_uniform_at_location(uniform_location(name), - std::forward(value)); - } + template + shader & set_uniform(std::string const & name, T &&value) + { + return set_uniform_at_location( uniform_location(name), std::forward(value) ); + } - bool build(); + bool build(); void use(); + using uniform_t = std::variant; + using uniform_entry_t = std::tuple; - using uniform_cache_t = std::vector; + using uniform_cache_t = std::vector; - void set_uniforms(uniform_cache_t c); + void set_uniforms(uniform_cache_t c); uint32_t native_handle() const; - protected: - std::unordered_map _source; +protected: + + std::unordered_map _source; + + struct impl; + std::unique_ptr _impl; - struct impl; - std::unique_ptr _impl; }; -} // namespace pw + +} #endif diff --git a/src/visual/include/pw/visual/texture.hpp b/src/visual/include/pw/visual/texture.hpp index 1c7add2..d040844 100644 --- a/src/visual/include/pw/visual/texture.hpp +++ b/src/visual/include/pw/visual/texture.hpp @@ -1,55 +1,70 @@ #ifndef PW_VISUAL_TEXTURE_HPP #define PW_VISUAL_TEXTURE_HPP -#include #include #include +#include namespace pw { class texture { - public: - enum class data_type { color, normal }; +public: + enum class data_type { + color, + normal + }; - enum class data_layout { shape_1d, shape_2d, shape_3d }; + enum class data_layout { + shape_1d, + shape_2d, + shape_3d + }; - enum texture_dimension { dimension_r, dimension_s, dimension_t }; + enum texture_dimension { + dimension_r, + dimension_s, + dimension_t + }; - enum wrap_mode { - wrap_repeat, - wrap_clamp, - wrap_clamp_to_edge, - wrap_clamp_to_repeat - }; + enum wrap_mode { + wrap_repeat, + wrap_clamp, + wrap_clamp_to_edge, + wrap_clamp_to_repeat + }; texture(); - texture(const image& i, data_layout s); + texture(const image& i,data_layout s); ~texture(); void set_shape(data_layout s); - data_layout shape() const { return _shape; } + data_layout shape() const { return _shape; } - void set_wrap(wrap_mode w); - wrap_mode wrap() const { return _wrap; } + void set_wrap(wrap_mode w); + wrap_mode wrap() const { return _wrap; } uint32_t native_handle() const; - bool create(const image& i); - void update(const image& i); + bool create(const image &i); + void update(const image &i); void bind(); void unbind(); bool valid() const; - protected: - data_layout _shape = data_layout::shape_2d; - wrap_mode _wrap = wrap_mode::wrap_clamp_to_edge; +protected: + + data_layout _shape = data_layout::shape_2d; + wrap_mode _wrap = wrap_mode::wrap_clamp_to_edge; + + struct impl; + unique_ptr _impl; + - struct impl; - unique_ptr _impl; }; -} // namespace pw +} + #endif diff --git a/src/visual/src/context.cpp b/src/visual/src/context.cpp index 44e2172..49cff8b 100644 --- a/src/visual/src/context.cpp +++ b/src/visual/src/context.cpp @@ -2,60 +2,91 @@ #include "pw/core/vector.hpp" #include "glad/glad.h" -#include + namespace pw { struct context::impl { - vector4f _clear_color{0, 1, 0, 1}; + vector4f _clear_color { 0, 1, 0, 1}; - void set_viewport(const rectangle& v) { - glViewport(v.position.x(), v.position.y(), v.size.width, v.size.height); + void set_viewport(const rectangle& v) + { + glViewport(v.position.x,v.position.y,v.size.width,v.size.height); } - const rectangle viewport() { - auto vp = rectangle{0, 0, 1, 1}; - glGetFloatv(GL_VIEWPORT, vp.position.data()); - return vp.cast(); + const rectangle viewport() + { + float _viewport[4] = {0,0,1,1}; + glGetFloatv(GL_VIEWPORT,&_viewport[0]); + return rectangle(_viewport); } - void clear() { + void clear() + { glEnable(GL_CULL_FACE); glCullFace(GL_BACK); glFrontFace(GL_CCW); - glClearColor(_clear_color[0], _clear_color[1], _clear_color[2], - _clear_color[3]); + glClearColor(_clear_color[0],_clear_color[1],_clear_color[2],_clear_color[3]); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + } + + + + uint32_t get_error() const + { + return glGetError(); } - uint32_t get_error() const { return glGetError(); } }; -context::context() : _impl(std::make_unique()) {} +context::context() + : _impl(std::make_unique()) +{ +} -context::~context() {} +context::~context() +{ +} -void context::set_blend() {} +void context::set_blend() +{ -void context::set_viewport(const rectangle& v) { +} + +void context::set_viewport(const rectangle& v) +{ _impl->set_viewport(v); } -rectangle context::viewport() const { return _impl->viewport(); } - -void context::clear() { _impl->clear(); } - -u_int32_t context::get_error() const { return _impl->get_error(); } - -color context::clearcolor() const { - // return _impl->_clear_color; - return color{}; +rectangle context::viewport() const +{ + return _impl->viewport(); } -void context::set_clearcolor(const color& c) { - // _impl->_clear_color = c; +void context::clear() +{ + _impl->clear(); } -} // namespace pw +u_int32_t context::get_error() const +{ + return _impl->get_error(); +} + +color context::clearcolor() const +{ + return _impl->_clear_color; +} + +void context::set_clearcolor(const color& c) +{ + _impl->_clear_color = c; +} + + +} + + diff --git a/src/visual/src/framebuffer.cpp b/src/visual/src/framebuffer.cpp index d3c39c4..d0719c5 100644 --- a/src/visual/src/framebuffer.cpp +++ b/src/visual/src/framebuffer.cpp @@ -5,7 +5,6 @@ #include "glad/glad.h" -#include #include namespace pw { @@ -14,7 +13,7 @@ namespace pw { struct framebuffer::impl { - size _size; + size _size; GLuint _fbo_draw { std::numeric_limits::max() }; GLuint _fbo_msaa { std::numeric_limits::max() }; @@ -22,7 +21,7 @@ struct framebuffer::impl { GLuint _rbo_color { std::numeric_limits::max() }; GLuint _rbo_depth { std::numeric_limits::max() }; - bool create(const size &s) + bool create(const size &s) { // TODO mak color resolution and _size = s; @@ -108,7 +107,7 @@ framebuffer::~framebuffer() { } -bool framebuffer::create(const size &s) +bool framebuffer::create(const size &s) { return _impl->create(s); } diff --git a/src/visual/src/pipeline.cpp b/src/visual/src/pipeline.cpp index 2593c80..064b075 100644 --- a/src/visual/src/pipeline.cpp +++ b/src/visual/src/pipeline.cpp @@ -1,26 +1,30 @@ -#include "pw/core/axisangle.hpp" -#include "pw/core/geometry.hpp" -#include "pw/core/matrix.hpp" -#include "pw/core/matrix_transform.hpp" -#include "pw/core/serialize.hpp" #include "pw/core/size.hpp" +#include "pw/core/matrix.hpp" +#include "pw/core/geometry.hpp" #include "pw/core/time.hpp" +#include "pw/core/axisangle.hpp" +#include "pw/core/serialize.hpp" +#include "pw/core/matrix_transform.hpp" #include "pw/core/debug.hpp" -#include "pw/visual/framebuffer.hpp" #include "pw/visual/pipeline.hpp" -#include "pw/visual/renderer.hpp" #include "pw/visual/shader.hpp" +#include "pw/visual/renderer.hpp" +#include "pw/visual/framebuffer.hpp" #include "pw/visual/texture.hpp" #include "glad/glad.h" namespace pw { -void render_pass::submit(const geometry& g, const matrix4x4& model_mat, - const matrix4x4& view_mat, - const matrix4x4& projection_mat) { - if (!_shader.ready()) { // + +void render_pass::submit(const geometry &g, + const matrix4x4 &model_mat, + const matrix4x4 &view_mat, + const matrix4x4 &projection_mat) +{ + if (!_shader.ready()) + { // _shader.build(); } @@ -31,18 +35,22 @@ void render_pass::submit(const geometry& g, const matrix4x4& model_mat, // new version with ... shader::uniform_cache_t us; - // us.push_back(std::make_tuple("input_color",mat._color,-1)); - us.push_back(std::make_tuple("model", model_mat, -1)); - us.push_back(std::make_tuple("view", view_mat, -1)); - us.push_back(std::make_tuple("projection", projection_mat, -1)); +// us.push_back(std::make_tuple("input_color",mat._color,-1)); + us.push_back(std::make_tuple("model",model_mat,-1)); + us.push_back(std::make_tuple("view",view_mat,-1)); + us.push_back(std::make_tuple("projection",projection_mat,-1)); _shader.set_uniforms(us); _shader.use(); _renderer.draw(); + } -struct triangle_renderer { + +struct triangle_renderer +{ + texture tex; shader shader_p; @@ -50,12 +58,15 @@ struct triangle_renderer { renderer r; time::tick_t tick; - triangle_renderer() {} + triangle_renderer() + { + } - void setup() { + void setup() + { const float z_val = -5.f; - const float s = 1.0f; + const float s = 1.0f; // // 0 -- 1 @@ -64,23 +75,23 @@ struct triangle_renderer { // geometry vector3_array vertices = { - {-s, s, z_val} // 0 - , - {s, s, z_val} // 1 - , - {-s, -s, z_val} // 2 - , - {s, -s, z_val} // 3 + {-s, s, z_val} // 0 + ,{ s, s, z_val} // 1 + ,{-s, -s, z_val} // 2 + ,{ s, -s, z_val} // 3 }; // topology / indices - geometry::indices_t indices = {2, 1, 0, 2, 3, 1}; + geometry::indices_t indices = { 2, 1, 0, + 2, 3, 1}; + amesh.set_indices(indices); amesh.set_vertices(vertices); amesh.compute_normals(); + const char* vertex_shader_2 = R"( #version 400 uniform mat4 model; @@ -95,7 +106,7 @@ struct triangle_renderer { } )"; - const char* fragment_shader_2 = R"( + const char *fragment_shader_2 = R"( #version 400 uniform vec4 input_color = vec4(1.0, 0.0, 0.0, 1.0); out vec4 frag_colour; @@ -103,37 +114,38 @@ struct triangle_renderer { frag_colour = input_color; })"; - shader_p.set_source(shader::code_type::vertex, vertex_shader_2); - shader_p.set_source(shader::code_type::fragment, fragment_shader_2); + shader_p.set_source(shader::code_type::vertex,vertex_shader_2); + shader_p.set_source(shader::code_type::fragment,fragment_shader_2); if (!shader_p.build()) exit(-1); } - void draw() { + void draw() + { if (!r.ready()) r.create(amesh); + // input needed here - // model view projection shader_p.use(); - auto v_col = ping_pong(static_cast(time::now()), 1.0f); + auto v_col = ping_pong(static_cast(time::now()),1.0f); - vector4f col = {0.5f, 1 - v_col, v_col, 1.0f}; + vector4f col = {0.5f,1-v_col,v_col,1.0f}; - matrix4x4f model_mat; - model_mat.set_identity(); + matrix4x4f model_mat; model_mat.set_identity(); - auto v_angle = - ping_pong(static_cast(time::now()), 2 * ::pw::pi()); + auto v_angle = ping_pong(static_cast(time::now()),2 * ::pw::pi()); - axisangle rot(vector3::forward(), v_angle); + axisangle rot(vector3::forward(),v_angle); model_mat = rot.to_matrix(); - matrix4x4f view_mat = matrix_transform::look_at( - vector3({0, 0, 0}), vector3::forward(), vector3::up()); + matrix4x4f view_mat = matrix_transform::look_at(vector3({0,0,0}), + vector3::forward(), + vector3::up()); // materials should carry this #if 1 @@ -142,31 +154,35 @@ struct triangle_renderer { glFrontFace(GL_CCW); #endif + // now bind textures #if 1 - auto proj_mat = matrix_transform::orthographic_projection( - 1.3, 1.0, 0.2f, 100.f); + auto proj_mat = matrix_transform::orthographic_projection(1.3,1.0, + 0.2f,100.f); + #else - auto proj_mat = matrix_transform::perspective_projection( - deg_to_rad(60.f), 1.3f, 0.2f, 1000.f); + auto proj_mat = matrix_transform::perspective_projection(deg_to_rad(60.f), + 1.3f, + 0.2f,1000.f); #endif + #if 1 // highly inefficient - should be cached - - shader_p.set_uniform("input_color", col); - shader_p.set_uniform("model", model_mat); - shader_p.set_uniform("view", view_mat); - shader_p.set_uniform("projection", proj_mat); + shader_p.set_uniform("input_color",col); + shader_p.set_uniform("model",model_mat); + shader_p.set_uniform("view",view_mat); + shader_p.set_uniform("projection",proj_mat); #else // new version with ... shader::uniform_cache_t us; - us.push_back(std::make_tuple("input_color", col, -1)); - us.push_back(std::make_tuple("model", model_mat, -1)); - us.push_back(std::make_tuple("view", view_mat, -1)); - us.push_back(std::make_tuple("projection", proj_mat, -1)); + us.push_back(std::make_tuple("input_color",col,-1)); + us.push_back(std::make_tuple("model",model_mat,-1)); + us.push_back(std::make_tuple("view",view_mat,-1)); + us.push_back(std::make_tuple("projection",proj_mat,-1)); shader_p.set_uniforms(us); @@ -175,7 +191,7 @@ struct triangle_renderer { r.draw(); auto error = glGetError(); - if (error != GL_NO_ERROR) { + if (error != GL_NO_ERROR){ debug::e() << "GL error " << error; } @@ -183,6 +199,7 @@ struct triangle_renderer { } }; + struct pipeline::impl { #if 0 @@ -197,30 +214,35 @@ struct pipeline::impl { framebuffer fb; - // testing + + //testing triangle_renderer tr; bool create(size s); void draw(); - impl() = default; + + + impl() = default; ~impl() = default; + }; -GLuint generate_multisample_texture(const size& s, int samples) { +GLuint generate_multisample_texture(const size& s,int samples) +{ GLuint texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture); - glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGB8, - s.width, s.height, GL_TRUE); + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGB8, s.width, s.height, GL_TRUE); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); return texture; } -bool pipeline::impl::create(::pw::size s) { +bool pipeline::impl::create(::pw::size s) +{ #if 0 _size = s; @@ -271,14 +293,23 @@ bool pipeline::impl::create(::pw::size s) { glBindFramebuffer(GL_FRAMEBUFFER, 0); #endif + + tr.setup(); + return true; } -void pipeline::impl::draw() { - glClearColor(1.0, 0, 0, 1); + + +void pipeline::impl::draw() +{ + + + + glClearColor(1.0,0,0,1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // glViewport(0,0,800,600); @@ -289,8 +320,12 @@ void pipeline::impl::draw() { tr.draw(); + + // reset + + // actuall blitting #if 0 @@ -311,6 +346,7 @@ void pipeline::impl::draw() { #else + #if 0 glBindFramebuffer(GL_READ_FRAMEBUFFER, _fbo_msaa); // src FBO (multi-sample) @@ -336,76 +372,87 @@ void pipeline::impl::draw() { // fb.unbind(); GLenum err; - while ((err = glGetError()) != GL_NO_ERROR) { + while((err = glGetError()) != GL_NO_ERROR) + { std::string error; - switch (err) { - case GL_INVALID_OPERATION: - error = "INVALID_OPERATION"; - break; - case GL_INVALID_ENUM: - error = "INVALID_ENUM"; - break; - case GL_INVALID_VALUE: - error = "INVALID_VALUE"; - break; - case GL_OUT_OF_MEMORY: - error = "OUT_OF_MEMORY"; - break; - case GL_INVALID_FRAMEBUFFER_OPERATION: - error = "INVALID_FRAMEBUFFER_OPERATION"; - break; + switch(err) { + case GL_INVALID_OPERATION: error="INVALID_OPERATION"; break; + case GL_INVALID_ENUM: error="INVALID_ENUM"; break; + case GL_INVALID_VALUE: error="INVALID_VALUE"; break; + case GL_OUT_OF_MEMORY: error="OUT_OF_MEMORY"; break; + case GL_INVALID_FRAMEBUFFER_OPERATION: error="INVALID_FRAMEBUFFER_OPERATION"; break; } debug::e() << "OpenGL error:" << err << " " << error; } + } + // // // -pipeline::pipeline() : _impl(std::make_unique()) {} +pipeline::pipeline() + : _impl(std::make_unique()) +{ +} -pipeline::~pipeline() { +pipeline::~pipeline() +{ // } -void pipeline::draw() { _impl->draw(); } +void pipeline::draw() +{ + _impl->draw(); +} -bool pipeline::create(size s) { return _impl->create(s.cast()); } +bool pipeline::create(size s) +{ + return _impl->create(s.cast()); +} -} // namespace pw +} -// class pipeline; -// class pass + + +//class pipeline; + +//class pass //{ -// public: +//public: // virtual void apply(pipeline& p); -// }; +//}; -// class pipeline +//class pipeline //{ -// public: +//public: // void apply() // { // for (auto p : _passes) p.apply(*this); // } -// protected: +//protected: // std::vector _passes; -// }; +//}; -// pipeline > + + + + + + +//pipeline > // n*pass // shadow_pass -// lighting_pass +// lighting_pass // mesh_pass // compositor_pass -// compositor -// render to fbo > add a -// glBlitFramebuffer .. -// https://stackoverflow.com/questions/29254574/using-glblitframebuffer-to-display-a-texture +//compositor +// render to fbo > add a +// glBlitFramebuffer .. https://stackoverflow.com/questions/29254574/using-glblitframebuffer-to-display-a-texture diff --git a/src/visual/src/renderer.cpp b/src/visual/src/renderer.cpp index e85188d..81a7b23 100644 --- a/src/visual/src/renderer.cpp +++ b/src/visual/src/renderer.cpp @@ -1,115 +1,128 @@ #include "pw/visual/renderer.hpp" +#include "pw/core/geometry.hpp" +#include "pw/core/size.hpp" #include "pw/core/debug.hpp" #include "pw/core/matrix.hpp" -#include "pw/core/mesh.hpp" -#include "pw/core/primitives.hpp" -#include "pw/core/size.hpp" #include "glad/glad.h" #include -#include + namespace pw { struct renderer::impl { - std::atomic change_count{}; + uint64_t _change_count { 0 }; - uint32_t _vao{0}; - uint32_t _ebo{0}; - std::vector _vbos{}; + uint32_t _vao { 0 }; + uint32_t _ebo { 0 }; + std::vector _vbos { }; - GLint _mesh_elements = {0}; + + GLint _mesh_elements = { 0 }; impl() = default; - ~impl() { release(); } + ~impl() + { + release(); + } - bool ready() const { + bool ready() const + { return glIsVertexArray != nullptr && GL_TRUE == glIsVertexArray(_vao); } - bool update(const mesh& m) { - if (this->change_count == m.change_count) + bool update(const geometry& m) + { + if (_change_count == m.change_count()) return false; // reset if the renderer already in use if (ready()) release(); - _mesh_elements = m.geometry.indices.size(); + _mesh_elements = m.indices().size(); // - glGenVertexArrays(1, &_vao); + glGenVertexArrays(1,&_vao); glBindVertexArray(_vao); glGenBuffers(1, &_ebo); + // TODO binding separate VBOs to the // vertexarray should be avoided // indices glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, - m.geometry.indices.size() * sizeof(uint32_t), - m.geometry.indices.data(), GL_STATIC_DRAW); + m.indices().size() * sizeof (uint32_t), + m.indices().data(), + GL_STATIC_DRAW); - _vbos.resize(_vbos.size() + 1); + + _vbos.resize(_vbos.size()+1); glGenBuffers(1, &_vbos.back()); + // vertices glBindBuffer(GL_ARRAY_BUFFER, _vbos.back()); - glVertexAttribPointer(_vbos.size() - 1, vector3f::coefficients, GL_FLOAT, - GL_FALSE, 0, nullptr); + glVertexAttribPointer(_vbos.size()-1, vector3::coefficients, GL_FLOAT, GL_FALSE, 0, nullptr); glBufferData(GL_ARRAY_BUFFER, - m.geometry.vertices.size() * sizeof(vector3f), - m.geometry.vertices.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(_vbos.size() - 1); + m.vertices().size() * sizeof(vector3), + m.vertices().data(), + GL_STATIC_DRAW); + glEnableVertexAttribArray(_vbos.size()-1); - debug::d() << "vertices at " << _vbos.size() - 1; + debug::d() << "vertices at " << _vbos.size()-1; -#if 0 - - if (!m.normals().empty()) { - _vbos.resize(_vbos.size() + 1); + if (!m.normals().empty()) + { + _vbos.resize(_vbos.size()+1); glGenBuffers(1, &_vbos.back()); // normals - glBindBuffer(GL_ARRAY_BUFFER, _vbos.back()); - glVertexAttribPointer(_vbos.size() - 1, vector3f::coefficients, - GL_FLOAT, GL_FALSE, 0, nullptr); - glBufferData(GL_ARRAY_BUFFER, m.normals().size() * sizeof(vector3f), - m.normals().data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(_vbos.size() - 1); + glBindBuffer(GL_ARRAY_BUFFER,_vbos.back()); + glVertexAttribPointer(_vbos.size()-1, vector3::coefficients, GL_FLOAT, GL_FALSE, 0, nullptr); + glBufferData(GL_ARRAY_BUFFER, + m.normals().size() * sizeof(vector3), + m.normals().data(), + GL_STATIC_DRAW); + glEnableVertexAttribArray(_vbos.size()-1); + + debug::d() << "normals at " << _vbos.size()-1; - debug::d() << "normals at " << _vbos.size() - 1; } - if (!m.texture_coordinates().empty()) { - for (const auto& tc : m.texture_coordinates()) { - _vbos.resize(_vbos.size() + 1); + if (!m.texture_coordinates().empty()) + { + for (const auto& tc : m.texture_coordinates()) + { + _vbos.resize(_vbos.size()+1); glGenBuffers(1, &_vbos.back()); // texture coordinates - glBindBuffer(GL_ARRAY_BUFFER, _vbos.back()); - glVertexAttribPointer(_vbos.size() - 1, vector2::coefficients, - GL_FLOAT, GL_FALSE, 0, nullptr); - glBufferData(GL_ARRAY_BUFFER, tc.size() * sizeof(vector2), - tc.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(_vbos.size() - 1); + glBindBuffer(GL_ARRAY_BUFFER,_vbos.back()); + glVertexAttribPointer(_vbos.size()-1, vector2::coefficients, GL_FLOAT, GL_FALSE, 0, nullptr); + glBufferData(GL_ARRAY_BUFFER, + tc.size() * sizeof(vector2), + tc.data(), + GL_STATIC_DRAW); + glEnableVertexAttribArray(_vbos.size()-1); - debug::d() << "texture coordinates at " << _vbos.size() - 1; + debug::d() << "texture coordinates at " << _vbos.size()-1; } } -#endif - // stop binding glBindVertexArray(0); - this->change_count.store(m.change_count.load()); + + this->_change_count = m.change_count(); + #if 1 // get errors @@ -123,16 +136,19 @@ struct renderer::impl { return ready(); } - void release() { - for (auto& vbo : _vbos) - glDeleteBuffers(1, &vbo); - glDeleteBuffers(1, &_ebo); + void release() + { - glDeleteVertexArrays(1, &_vao); + for (auto vbo : _vbos) + glDeleteBuffers(1,&vbo); + glDeleteBuffers(1,&_ebo); + + glDeleteVertexArrays(1,&_vao); } - void draw() { + void draw() + { glBindVertexArray(_vao); glDrawElements(GL_TRIANGLES, _mesh_elements, GL_UNSIGNED_INT, nullptr); glBindVertexArray(0); @@ -147,28 +163,57 @@ struct renderer::impl { } // GLint get_mode(vertex_array::) + }; // // Outer wrapper // -renderer::renderer() : _impl(std::make_unique()) {} +renderer::renderer() + : _impl(std::make_unique()) +{ +} -renderer::renderer(const mesh& m) { +renderer::renderer(const geometry &m) +{ renderer(); // directly update _impl->update(m); } -renderer::~renderer() = default; +renderer::~renderer() +{ +} -bool renderer::ready() const { return _impl->ready(); } +bool renderer::ready() const +{ + return _impl->ready(); +} -bool renderer::update(const mesh& m) { return _impl->update(m); } +bool renderer::update(const geometry &m) +{ + return _impl->update(m); +} -void renderer::release() { _impl->release(); } +void renderer::release() +{ + _impl->release(); +} -void renderer::draw() { _impl->draw(); } +void renderer::draw() +{ + _impl->draw(); +} -} // namespace pw +uint64_t renderer::change_count() const +{ + return _impl->_change_count; +} + +void renderer::set_change_count(uint64_t n) +{ + _impl->_change_count = n; +} + +} diff --git a/src/visual/src/shader.cpp b/src/visual/src/shader.cpp index 2c7c286..630e428 100644 --- a/src/visual/src/shader.cpp +++ b/src/visual/src/shader.cpp @@ -6,240 +6,297 @@ namespace pw { -struct shader::impl { - shader& _shader; +struct shader::impl +{ + shader& _shader; - GLuint _shader_program; - std::vector _shader_stages; + GLuint _shader_program; + std::vector _shader_stages; - impl(shader& s) : _shader(s) {} + impl(shader& s) + : _shader(s) + { + } - ~impl() { destroy(); } + ~impl() + { + destroy(); + } - bool is_valid() { + bool is_valid() + { // we potentially haul in is_valid while no context is given return glIsProgram != nullptr && glIsProgram(_shader_program); - } + } - bool build() { - // if (!is_valid()) return false; + bool build() + { +// if (!is_valid()) return false; - for (const auto& [type, code] : _shader._source) { - GLuint shader_type = 0; + for (const auto & [type,code] : _shader._source) + { + GLuint shader_type = 0; switch (type) { - case shader::code_type::vertex: - shader_type = GL_VERTEX_SHADER; - break; - case shader::code_type::compute: - shader_type = GL_COMPUTE_SHADER; - break; - case shader::code_type::geometry: - shader_type = GL_GEOMETRY_SHADER; - break; - case shader::code_type::fragment: - shader_type = GL_FRAGMENT_SHADER; - break; + case shader::code_type::vertex: + shader_type = GL_VERTEX_SHADER; + break; + case shader::code_type::compute: + shader_type = GL_COMPUTE_SHADER; + break; + case shader::code_type::geometry: + shader_type = GL_GEOMETRY_SHADER; + break; + case shader::code_type::fragment: + shader_type = GL_FRAGMENT_SHADER; + break; default: debug::w() << " unknown shader type"; - } + } - GLuint shaderId = glCreateShader(shader_type); + GLuint shaderId = glCreateShader(shader_type); - char* src = const_cast(code.c_str()); + char* src = const_cast(code.c_str()); GLint size = static_cast(code.length()); - glShaderSource(shaderId, 1, &src, &size); + glShaderSource(shaderId , 1, &src, &size); - glCompileShader(shaderId); + glCompileShader(shaderId); - GLint is_compiled = GL_FALSE; - glGetShaderiv(shaderId, GL_COMPILE_STATUS, &is_compiled); - if (is_compiled == GL_FALSE) { + GLint is_compiled = GL_FALSE; + glGetShaderiv(shaderId, GL_COMPILE_STATUS, &is_compiled); + if(is_compiled == GL_FALSE) + { - GLint log_length; + GLint log_length; - glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &log_length); + glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &log_length); - std::vector log_buffer(static_cast(log_length)); + std::vector log_buffer(static_cast(log_length)); - glGetShaderInfoLog(shaderId, log_length, &log_length, - log_buffer.data()); + glGetShaderInfoLog(shaderId, log_length, &log_length, log_buffer.data()); - // TODO - handle errors! - debug::e() << log_buffer.data(); + // TODO - handle errors! + debug::e() << log_buffer.data(); - return false; - } + return false; + } - _shader_stages.push_back(shaderId); - } + _shader_stages.push_back(shaderId); - _shader_program = glCreateProgram(); + } + + _shader_program = glCreateProgram(); + + + for (auto s : _shader_stages) + glAttachShader(_shader_program,s); - for (auto s : _shader_stages) - glAttachShader(_shader_program, s); // TODO attribute binding ... - /* Bind attribute index 0 (coordinates) to in_Position and attribute - * index 1 (color) to in_Color */ - /* Attribute locations must be setup before calling glLinkProgram. */ - // glBindAttribLocation(shaderprogram, 0, "in_Position"); - // glBindAttribLocation(shaderprogram, 1, "in_Color"); + /* Bind attribute index 0 (coordinates) to in_Position and attribute index 1 (color) to in_Color */ + /* Attribute locations must be setup before calling glLinkProgram. */ + // glBindAttribLocation(shaderprogram, 0, "in_Position"); + // glBindAttribLocation(shaderprogram, 1, "in_Color"); - glLinkProgram(_shader_program); + glLinkProgram(_shader_program); - GLint is_linked = 0; - glGetProgramiv(_shader_program, GL_LINK_STATUS, &is_linked); - if (is_linked == GL_FALSE) { + GLint is_linked = 0; + glGetProgramiv(_shader_program, GL_LINK_STATUS, &is_linked); + if(is_linked == GL_FALSE) + { - GLint log_length; + GLint log_length; - /* Noticed that glGetProgramiv is used to get the length for a - * shader program, not glGetShaderiv. */ - glGetProgramiv(_shader_program, GL_INFO_LOG_LENGTH, &log_length); + /* Noticed that glGetProgramiv is used to get the length for a shader program, not glGetShaderiv. */ + glGetProgramiv(_shader_program, GL_INFO_LOG_LENGTH, &log_length); - /* The maxLength includes the NULL character */ - std::vector info_log(static_cast(log_length)); + /* The maxLength includes the NULL character */ + std::vector info_log(static_cast(log_length)); - /* Notice that glGetProgramInfoLog, not glGetShaderInfoLog. */ - glGetProgramInfoLog(_shader_program, log_length, &log_length, - info_log.data()); + /* Notice that glGetProgramInfoLog, not glGetShaderInfoLog. */ + glGetProgramInfoLog(_shader_program, log_length, &log_length, info_log.data()); - debug::e() << info_log.data(); + debug::e() << info_log.data(); - /* Handle the error in an appropriate way such as displaying a - * message or writing to a log file. */ - /* In this simple program, we'll just leave */ + /* Handle the error in an appropriate way such as displaying a message or writing to a log file. */ + /* In this simple program, we'll just leave */ - return false; - } + return false; + } - return true; - } + return true; + } - void use() { glUseProgram(_shader_program); } - void destroy() { + void use() + { + glUseProgram(_shader_program); + } + + void destroy() + { // potentially the GL driver hasn't been loaded if (is_valid()) { // deleting and detaching should happen much earlier - for (auto s : _shader_stages) { - glDeleteShader(s); + for (auto s : _shader_stages) + { + glDeleteShader(s); } // only program needs to be deleted glDeleteProgram(_shader_program); } + } + + int uniform_location(std::string const& name) const + { + return glGetUniformLocation(_shader_program,name.c_str()); + } + + void bind(int location,const matrix3x3f& m) + { + glUniformMatrix3fv(location,1,GL_FALSE,m.ptr()); + } + + void bind(int location,const matrix4x4f& m) + { + glUniformMatrix4fv(location,1,GL_FALSE,m.ptr()); + } + + void bind(int location,const vector4f& v) + { + glUniform4fv(location,1,v.ptr()); + } + + void bind(int location,const float& v) + { + glUniform1f(location,v); + } + + void bind(int location,const uint32_t& i) + { + glUniform1ui(location,i); } - int uniform_location(std::string const& name) const { - return glGetUniformLocation(_shader_program, name.c_str()); + void bind(int location,const int32_t& i) + { + glUniform1i(location,i); } - void bind(int location, const matrix3x3f& m) { - glUniformMatrix3fv(location, 1, GL_FALSE, m.data()); - } + void bind(int location,const texture& v) + { + this->bind(location,(int)v.native_handle()); - void bind(int location, const matrix4x4f& m) { - glUniformMatrix4fv(location, 1, GL_FALSE, m.data()); - } - - void bind(int location, const vector4f& v) { - glUniform4fv(location, 1, v.data()); - } - - void bind(int location, const float& v) { glUniform1f(location, v); } - - void bind(int location, const uint32_t& i) { glUniform1ui(location, i); } - - void bind(int location, const int32_t& i) { glUniform1i(location, i); } - - void bind(int location, const texture& v) { - this->bind(location, (int)v.native_handle()); } }; -shader::shader() { _impl = make_unique(*this); } -shader::~shader() {} +shader::shader() +{ + _impl = make_unique(*this); +} -bool shader::ready() const { return _impl->is_valid(); } +shader::~shader() +{ -shader& shader::set_uniform_at_location(int location, float v) { - _impl->bind(location, v); +} + +bool shader::ready() const +{ + return _impl->is_valid(); +} + +shader &shader::set_uniform_at_location(int location, float v) +{ + _impl->bind(location,v); return *this; } -shader& shader::set_uniform_at_location(int location, uint32_t v) { - _impl->bind(location, v); - return *this; +shader &shader::set_uniform_at_location(int location, uint32_t v) +{ + _impl->bind(location,v); return *this; } -shader& shader::set_uniform_at_location(int location, int32_t v) { - _impl->bind(location, v); - return *this; +shader &shader::set_uniform_at_location(int location, int32_t v) +{ + _impl->bind(location,v); return *this; } -shader& shader::set_uniform_at_location(int location, vector4f const& v) { - _impl->bind(location, v); - return *this; + +shader &shader::set_uniform_at_location(int location, vector4f const &v) +{ + _impl->bind(location,v); return *this; } -shader& shader::set_uniform_at_location(int location, matrix4x4f const& v) { - _impl->bind(location, v); - return *this; +shader &shader::set_uniform_at_location(int location, matrix4x4f const &v) +{ + _impl->bind(location,v); return *this; } -shader& shader::set_uniform_at_location(int location, texture const& v) { - _impl->bind(location, v); - return *this; + +shader &shader::set_uniform_at_location(int location, texture const &v) +{ + _impl->bind(location,v); return *this; } -bool shader::build() { return _impl->build(); } +bool shader::build() +{ + return _impl->build(); +} -void shader::use() { _impl->use(); } +void shader::use() +{ + _impl->use(); +} -void shader::set_uniforms(uniform_cache_t c) { +void shader::set_uniforms(uniform_cache_t c) +{ // TODO rewrite in proper C++17 - for (auto& u : c) { - // get name - std::string name = std::get<0>(u); - // get location - GLint loc = std::get<2>(u); + for (auto& u : c) { + // get name + std::string name = std::get<0>(u); + // get location + GLint loc = std::get<2>(u); - // if lower 0 check for location - if (loc < 0) { - loc = _impl->uniform_location(name); - std::get<2>(u) = loc; // cache location - } + // if lower 0 check for location + if (loc < 0) { + loc = _impl->uniform_location(name); + std::get<2>(u) = loc; // cache location + } - auto var = std::get<1>(u); + auto var = std::get<1>(u); + + std::visit([this,loc](auto&& arg) { - std::visit([this, loc](auto&& arg) { using T = std::decay_t; // TODO query the std::variant of uniform_t - if constexpr ((std::is_same_v) || - (std::is_same_v) || - (std::is_same_v)) { - set_uniform_at_location(loc, std::forward(arg)); - } else { + if constexpr ((std::is_same_v) || + (std::is_same_v) || + (std::is_same_v) ) { + set_uniform_at_location( loc, std::forward(arg)); + } else { debug::e() << "unknown uniform type"; - } - }, var); - } + } + }, var); + } } -uint32_t shader::native_handle() const { return _impl->_shader_program; } - -int shader::uniform_location(const std::string& name) const { - return _impl->uniform_location(name); +uint32_t shader::native_handle() const +{ + return _impl->_shader_program; } -} // namespace pw +int shader::uniform_location(const std::string &name) const +{ + return _impl->uniform_location(name); +} + + +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt deleted file mode 100644 index f6fa947..0000000 --- a/tests/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -include(FetchContent) - -FetchContent_Declare(snitch - GIT_REPOSITORY https://github.com/snitch-org/snitch.git - GIT_TAG v1.3.2) # update version number as needed - -FetchContent_MakeAvailable(snitch) - -set(pixwerx_test_files - pw_test_core.cpp - ) - -add_executable(pixwerx_tests ${pixwerx_test_files}) - -target_link_libraries(pixwerx_tests PRIVATE - snitch::snitch - pwcore - ) diff --git a/tests/pw_test_core.cpp b/tests/pw_test_core.cpp deleted file mode 100644 index bbd009a..0000000 --- a/tests/pw_test_core.cpp +++ /dev/null @@ -1,112 +0,0 @@ -#include - -#include -#include - -TEST_CASE("core", "[matrix]") { - - auto mat = pw::matrix{}; - - REQUIRE(mat[0][0] == 0); - REQUIRE(mat[0][1] == 0); - REQUIRE(mat[1][0] == 0); - REQUIRE(mat[1][1] == 0); - - auto mat_1 = pw::matrix{ - pw::vector{5.f, 4}, - pw::vector{3.f, 2} - }; - - REQUIRE(mat_1[0][0] == 5); - REQUIRE(mat_1[0][1] == 4); - REQUIRE(mat_1[1][0] == 3); - REQUIRE(mat_1[1][1] == 2); - - const auto val {42.42f}; - - auto mat_2 = pw::matrix::all(val); - - REQUIRE(mat_2[0][0] == val); - REQUIRE(mat_2[0][1] == val); - REQUIRE(mat_2[1][0] == val); - REQUIRE(mat_2[1][1] == val); - - mat_2 *= 2; - REQUIRE(mat_2[0][0] == (val * 2)); - REQUIRE(mat_2[0][1] == (val * 2)); - REQUIRE(mat_2[1][0] == (val * 2)); - REQUIRE(mat_2[1][1] == (val * 2)); - - - mat_2 = pw::matrix::identity(); - - REQUIRE(mat_2[0][0] == 1.0f); - REQUIRE(mat_2[0][1] == 0.0f); - REQUIRE(mat_2[1][0] == 0.0f); - REQUIRE(mat_2[1][1] == 1.0f); - - - auto mat_2_inv = mat_2.inverse(); - - REQUIRE(mat_2_inv[0][0] == 1.0f); - REQUIRE(mat_2_inv[0][1] == 0.0f); - REQUIRE(mat_2_inv[1][0] == 0.0f); - REQUIRE(mat_2_inv[1][1] == 1.0f); - - // auto m44_2 = pw::matrix2x2::make(0, 1, 2, 3); - - // REQUIRE(m44_2(0, 0) == 0.0f); - // REQUIRE(m44_2(1, 0) == 1.0f); - // REQUIRE(m44_2(0, 1) == 2.0f); - // REQUIRE(m44_2(1, 1) == 3.0f); - - - // pw::matrix2x2 m44_3 = {{},{1, 2, 3, 4}}; - - // REQUIRE(m44_3(0, 0) == 1.0f); - // REQUIRE(m44_3(1, 0) == 2.0f); - // REQUIRE(m44_3(0, 1) == 3.0f); - // REQUIRE(m44_3(1, 1) == 4.0f); - -} - - -TEST_CASE("core", "[vector.matrix]") { - - auto vec4_1 = pw::vector4{}; - - REQUIRE(vec4_1[0] == 0.0f); - REQUIRE(vec4_1[1] == 0.0f); - REQUIRE(vec4_1[2] == 0.0f); - REQUIRE(vec4_1[3] == 0.0f); - - - // auto mat4_1 = pw::matrix_<4,1,float>{}; - - - // mat4_1 = vec4_1; // down is easy - - // vec4_1 = mat4_1; - -} - -TEST_CASE("core", "[vector]") { - - // auto vec4_1 = pw::vector4_{}; - // auto vec4_2 = pw::vector4::make(1, 2, 3, 4); - - // pw::vector4 vec4_3 = vec4_1 + vec4_2; - - // REQUIRE(vec4_3[0] == 1.0f); - // REQUIRE(vec4_3[1] == 2.0f); - // REQUIRE(vec4_3[2] == 3.0f); - // REQUIRE(vec4_3[3] == 4.0f); - - // auto vec4_4 = vec4_3 * 2; - - // REQUIRE(vec4_4[0] == 1.0f * 2); - // REQUIRE(vec4_4[1] == 2.0f * 2); - // REQUIRE(vec4_4[2] == 3.0f * 2); - // REQUIRE(vec4_4[3] == 4.0f * 2); - -}