Merge pull request #8 from harfang3dadmin/main

3.2.1 release.
This commit is contained in:
HARFANG 3D (admin) 2022-05-02 17:38:15 +02:00 committed by GitHub
commit 6c8e499396
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
99 changed files with 1506 additions and 890 deletions

12
.gitmodules vendored
View File

@ -1,19 +1,19 @@
[submodule "extern/openal-soft"]
path = extern/openal-soft
url = https://github.com/kcat/openal-soft.git
branch = openal-soft-1.19.1
branch = 1.21.1
[submodule "extern/openvr"]
path = extern/openvr
url = https://github.com/ValveSoftware/openvr.git
branch = v.1.6.10b
branch = v.1.6.10b
[submodule "extern/googletest"]
path = extern/googletest
url = https://github.com/google/googletest.git
branch = release-1.8.0-2745-ge2239ee6
branch = release-1.11.0
[submodule "extern/glfw"]
path = extern/glfw
url = https://github.com/glfw/glfw.git
branch = 3.2.1-633-g53c8c72c
branch = 3.3.6
[submodule "extern/bgfx/bgfx"]
path = extern/bgfx/bgfx
url = https://github.com/bkaradzic/bgfx
@ -29,12 +29,10 @@
[submodule "extern/recastnavigation"]
path = extern/recastnavigation
url = https://github.com/recastnavigation/recastnavigation.git
branch = 1.5.0-117-g57610fa
[submodule "extern/meshoptimizer"]
path = extern/meshoptimizer
url = https://github.com/zeux/meshoptimizer.git
branch = v0.14-99-ge1edf79
branch = v0.17
[submodule "tools/assimp_converter/assimp"]
path = tools/assimp_converter/assimp
url = https://github.com/assimp/assimp
branch = Release3.1_RC1-8389-gc1120a4c0

View File

@ -1,57 +1,67 @@
cmake_minimum_required(VERSION 3.16.2)
include(CMakePackageConfigHelpers)
project(harfang CXX C)
set(CMAKE_CXX_STANDARD 14)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
include(CMakeDependentOption)
file(READ harfang/version.txt HG_VERSION)
string(STRIP ${HG_VERSION} HG_VERSION)
project(harfang
VERSION ${HG_VERSION}
LANGUAGES CXX C
HOMEPAGE_URL "harfang3D.com"
)
set(CMAKE_CXX_STANDARD 14)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/harfang/cmake")
# -----------------------------------------------------------------------------
# Debug/tooling options
# -----------------------------------------------------------------------------
option(HG_ENABLE_TSA "Harfang: Enable TSA" OFF)
option(HG_ENABLE_TSAN "Harfang: Enable TSAN" OFF)
option(HG_ENABLE_ASAN "Harfang: Enable ASAN" OFF)
# -----------------------------------------------------------------------------
# Build options
# -----------------------------------------------------------------------------
option(HG_BUILD_ASSIMP_CONVERTER "Harfang: Build Assimp converter" ON)
option(HG_BUILD_FBX_CONVERTER "Harfang: Build FBX converter" ON)
option(HG_BUILD_GLTF_EXPORTER "Harfang: Build GLTF exporter" ON)
option(HG_BUILD_GLTF_IMPORTER "Harfang: Build GLTF importer" ON)
option(HG_BUILD_ASSETC "Harfang: Build AssetC" ON)
option(HG_BUILD_CPP_SDK "Harfang: Build C++ SDK" OFF)
option(HG_BUILD_TESTS "Harfang: Build Unit tests" OFF)
option(HG_BUILD_DOCS "Harfang: Build documentation" OFF)
option(HG_BUILD_HG_LUA "Harfang: Build Harfang Lua extension" OFF)
option(HG_BUILD_HG_PYTHON "Harfang: Build Harfang CPython 3.2+ extension" OFF)
option(HG_BUILD_HG_GO "Harfang: Build Harfang Go extension" OFF)
option(HG_EMBEDDED "Harfang: Build for embedded system" OFF)
option(HG_USE_GLFW "Harfang: Use GLFW backend" ON)
option(HG_USE_GLFW_WAYLAND "Harfang: Use GLFW Wayland backend" OFF)
option(HG_REBUILD_GLFW "Harfang: Rebuild GLFW backend" ON)
option(HG_USE_EGL "Harfang: Use EGL for GL context management" OFF)
option(HG_ENABLE_BULLET3_SCENE_PHYSICS "Harfang: Scene physics using Bullet Dynamics" ON)
option(HG_ENABLE_RECAST_DETOUR_API "Harfang: Enable Recast/Detour API" ON)
option(HG_ENABLE_OPENVR_API "Harfang: Enable OpenVR API" OFF)
option(HG_ENABLE_SRANIPAL_API "Harfang: Enable VIVE Eye and Facial Tracking SDK (SRanipal) API" OFF)
cmake_dependent_option(HG_ENABLE_SRANIPAL_API "Harfang: Enable VIVE Eye and Facial Tracking SDK (SRanipal) API" OFF "HG_ENABLE_OPENVR_API;MSVC" OFF)
set(HG_FABGEN_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../fabgen" CACHE PATH "Harfang: Path to FabGen script installation")
get_filename_component(HG_FABGEN_PATH ${HG_FABGEN_PATH} REALPATH)
message(CHECK_START "Checking FabGen path")
if(EXISTS ${HG_FABGEN_PATH})
message(CHECK_PASS "ok")
else()
message(FATAL_ERROR "unable to access ${HG_FABGEN_PATH}")
endif()
# -----------------------------------------------------------------------------
# Configuration constraints
# -----------------------------------------------------------------------------
if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
message(STATUS "! Forcing build type to RelWithDebInfo since CMAKE_BUILD_TYPE is not set")
SET(CMAKE_BUILD_TYPE RelWithDebInfo)
@ -67,29 +77,16 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
set(HG_USE_GLFW OFF FORCE)
endif()
if(HG_EMBEDDED)
message(STATUS "! Forcing EGL for GL context management since building for embedded")
set(HG_USE_EGL ON FORCE)
endif()
if(NOT HG_BUILD_HG_PYTHON)
message(STATUS "! Disabling Harfang CPython install since the module is not being build")
endif()
if(NOT HG_BUILD_HG_GO)
message(STATUS "! Disabling Harfang Go install since the module is not being build")
endif()
if(HG_ENABLE_SRANIPAL_API)
if(HG_ENABLE_SRANIPAL_API AND MSVC)
if (NOT HG_ENABLE_OPENVR_API)
message(STATUS "! Enabling OpenVR API")
set(HG_ENABLE_OPENVR_API ON FORCE)
endif()
endif()
# -----------------------------------------------------------------------------
# Configuration flags
# -----------------------------------------------------------------------------
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
message(STATUS "Building for 64-bit")
add_definitions(-DMARCH_WORD_SIZE=64)
@ -98,18 +95,6 @@ elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
add_definitions(-DMARCH_WORD_SIZE=32)
endif()
if(HG_USE_GLFW_WAYLAND)
add_compile_definitions(HG_USE_GLFW_WAYLAND)
endif()
if(HG_USE_GLFW)
add_compile_definitions(HG_USE_GLFW)
endif()
if(HG_EMBEDDED)
add_compile_definitions(HG_EMBEDDED)
endif()
if(MSVC)
add_compile_options(/MP /fp:fast /permissive-) # use /GL for LTGC
add_compile_definitions(_CRT_SECURE_NO_WARNINGS _ENABLE_EXTENDED_ALIGNED_STORAGE)
@ -169,6 +154,10 @@ else()
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O0")
endif()
if(HG_EMBEDDED)
add_compile_definitions(HG_EMBEDDED)
endif()
if(HG_ENABLE_OPENVR_API)
add_compile_definitions(HG_ENABLE_OPENVR_API)
endif()
@ -185,21 +174,9 @@ if(HG_ENABLE_RECAST_DETOUR_API)
add_compile_definitions(HG_ENABLE_RECAST_DETOUR_API)
endif()
if(NOT HG_GRAPHIC_API)
if(MSVC)
set(HG_GRAPHIC_API "DX11")
elseif(HG_EMBEDDED)
set(HG_GRAPHIC_API "GLES")
else()
set(HG_GRAPHIC_API "GL")
endif()
endif(NOT HG_GRAPHIC_API)
add_compile_definitions(HG_GRAPHIC_API="${HG_GRAPHIC_API}")
# -----------------------------------------------------------------------------
# Dependencies
# -----------------------------------------------------------------------------
if(NOT Python3_FOUND)
if(HG_BUILD_HG_PYTHON)
find_package(Python3 COMPONENTS Interpreter Development REQUIRED)
@ -212,9 +189,9 @@ if(HG_BUILD_DOCS)
find_package(Doxygen REQUIRED)
endif()
# Install helper
# -----------------------------------------------------------------------------
# System configuration
# -----------------------------------------------------------------------------
if(NOT HG_HOST_PREFIX)
string(TOLOWER ${CMAKE_HOST_SYSTEM_NAME} HG_HOST_PREFIX)
if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64.*|x86_64.*|AMD64.*")
@ -253,10 +230,24 @@ if(_hasParent) # after 3.21 use if(NOT PROJECT_IS_TOP_LEVEL)
endif()
unset(_hasParent)
if(NOT HG_GRAPHIC_API)
if(MSVC)
set(HG_GRAPHIC_API "DX11")
elseif(NOT HG_GRAPHC_API)
set(HG_GRAPHIC_API "GL")
endif()
endif(NOT HG_GRAPHIC_API)
add_compile_definitions(HG_GRAPHIC_API="${HG_GRAPHIC_API}")
# -----------------------------------------------------------------------------
# Install helper
# -----------------------------------------------------------------------------
set(CppSdkLibraryDestination cppsdk/lib/$<CONFIG>)
set(CppSdkRuntimeDestination cppsdk/bin/$<CONFIG>)
set(CppSdkHeadersDestination cppsdk/include)
# helper function for cppsdk library install.
function(install_cppsdk_target TARGET)
if(NOT HG_BUILD_CPP_SDK)
return()
@ -279,9 +270,43 @@ function(install_cppsdk_target TARGET)
RUNTIME DESTINATION ${CppSdkRuntimeDestination}
INCLUDES DESTINATION ${CppSdkHeadersDestination}
)
if(CMAKE_CXX_LINKER_SUPPORTS_PDB)
if(TargetType STREQUAL "STATIC_LIBRARY")
install(DIRECTORY $<TARGET_PROPERTY:${TARGET},BINARY_DIR>/$<CONFIG>/ DESTINATION cppsdk/pdb OPTIONAL COMPONENT cppsdk FILES_MATCHING PATTERN "*.pdb")
else()
install(FILES $<TARGET_PDB_FILE:${TARGET}> DESTINATION cppsdk/pdb OPTIONAL COMPONENT cppsdk)
endif()
endif()
endfunction(install_cppsdk_target)
# All targets
# Helper function to deploy shared libraries of CPPSDK external dependencies.
# This function is used only when building CPPSDK.
# Its "SDK" counterpart is defined in harfangConfig.cmake.
function(install_cppsdk_dependencies Destination)
if (DEFINED ARGV1)
set(ComponentName ${ARGV1})
else()
set(ComponentName ${Destination})
endif()
if(HG_USE_GLFW)
install(FILES $<TARGET_FILE:glfw> DESTINATION ${Destination} COMPONENT ${ComponentName})
endif()
install(FILES $<TARGET_FILE:libluadll> DESTINATION ${Destination} COMPONENT ${ComponentName})
if(HG_ENABLE_OPENVR_API)
get_target_property(OpenVRTargetFiles OpenVR IMPORTED_LOCATION)
install(FILES ${OpenVRTargetFiles} DESTINATION ${Destination} COMPONENT ${ComponentName})
endif()
if(HG_ENABLE_SRANIPAL_API)
get_target_property(SRanipalTargetFiles SRanipal IMPORTED_LOCATION)
install(FILES ${SRanipalTargetFiles} DESTINATION ${Destination} COMPONENT ${ComponentName})
endif()
endfunction()
# -----------------------------------------------------------------------------
# Build targets
# -----------------------------------------------------------------------------
SET(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared libraries" FORCE)
@ -311,13 +336,13 @@ if(HG_BUILD_DOCS)
add_subdirectory(doc)
endif()
# -----------------------------------------------------------------------------
# Setup/recap dump
# -----------------------------------------------------------------------------
message(STATUS "")
message(STATUS "Configuration report:")
message(STATUS "=====================")
message(STATUS [[
=====================
Configuration report:
=====================]])
message(STATUS "Harfang version: " ${HG_VERSION})
message(STATUS "Build type: " ${CMAKE_BUILD_TYPE})
@ -327,30 +352,30 @@ message(STATUS "Graphic API: " ${HG_GRAPHIC_API})
message(STATUS "Host prefix: " ${HG_HOST_PREFIX})
message(STATUS "Target prefix: " ${HG_TARGET_PREFIX})
message(STATUS "Enable TSA=" ${HG_ENABLE_TSA})
message(STATUS "Enable TSAN=" ${HG_ENABLE_TSAN})
message(STATUS "Enable ASAN=" ${HG_ENABLE_ASAN})
message(STATUS "Enable TSA: " ${HG_ENABLE_TSA})
message(STATUS "Enable TSAN: " ${HG_ENABLE_TSAN})
message(STATUS "Enable ASAN: " ${HG_ENABLE_ASAN})
message(STATUS "Build Assimp converter=" ${HG_BUILD_ASSIMP_CONVERTER})
message(STATUS "Build FBX converter=" ${HG_BUILD_FBX_CONVERTER})
message(STATUS "Build GLTF exporter=" ${HG_BUILD_GLTF_EXPORTER})
message(STATUS "Build GLTF importer=" ${HG_BUILD_GLTF_IMPORTER})
message(STATUS "Build AssetC=" ${HG_BUILD_ASSETC})
message(STATUS "Build C++ SDK=" ${HG_BUILD_CPP_SDK})
message(STATUS "Build documentation=" ${HG_BUILD_DOCS})
message(STATUS "Build Assimp converter: " ${HG_BUILD_ASSIMP_CONVERTER})
message(STATUS "Build FBX converter: " ${HG_BUILD_FBX_CONVERTER})
message(STATUS "Build GLTF exporter: " ${HG_BUILD_GLTF_EXPORTER})
message(STATUS "Build GLTF importer: " ${HG_BUILD_GLTF_IMPORTER})
message(STATUS "Build AssetC: " ${HG_BUILD_ASSETC})
message(STATUS "Build C++ SDK: " ${HG_BUILD_CPP_SDK})
message(STATUS "Build documentation: " ${HG_BUILD_DOCS})
message(STATUS "Build Lua extension=" ${HG_BUILD_HG_LUA})
message(STATUS "Build Lua extension: " ${HG_BUILD_HG_LUA})
message(STATUS "Build CPython module=" ${HG_BUILD_HG_PYTHON})
message(STATUS "Build CPython module: " ${HG_BUILD_HG_PYTHON})
if(HG_BUILD_HG_PYTHON)
message(STATUS " Using CPython libraries: " ${Python3_LIBRARIES})
message(STATUS " Install CPython module to " ${Python3_EXECUTABLE})
endif()
message(STATUS "Build Go module=" ${HG_BUILD_HG_GO})
message(STATUS "Build Go module: " ${HG_BUILD_HG_GO})
message(STATUS "Embedded system build=" ${HG_EMBEDDED})
message(STATUS "Binding defines=" ${HG_BINDING_DEFINES})
message(STATUS "Embedded system build: " ${HG_EMBEDDED})
message(STATUS "Binding defines: " ${HG_BINDING_DEFINES})
message(STATUS "Available APIs:")
message(STATUS " - Core")
@ -367,20 +392,23 @@ if(HG_ENABLE_RECAST_DETOUR_API)
message(STATUS " - RecastDetour")
endif()
message(STATUS "Use GLFW backend=" ${HG_USE_GLFW})
message(STATUS "Use GLFW Wayland backend=" ${HG_USE_GLFW_WAYLAND})
message(STATUS "EGL for GL context management=" ${HG_USE_EGL})
message(STATUS "Use GLFW backend: " ${HG_USE_GLFW})
message(STATUS "Fabgen dir: " ${HG_FABGEN_PATH})
message(STATUS "Installation dir: " ${CMAKE_INSTALL_PREFIX})
message(STATUS "")
# -----------------------------------------------------------------------------
# Package configuration
# -----------------------------------------------------------------------------
# [WARNING] Don't forget to add any new shared library target to this list!
set(HG_SHARED_LIBRARY_TARGETS "hg::glfw;hg::libluadll")
if(HG_ENABLE_OPENVR_API)
list(APPEND HG_SHARED_LIBRARY_TARGETS OpenVR)
if(HG_ENABLE_SRANIPAL_API)
list(APPEND HG_SHARED_LIBRARY_TARGETS SRanipal)
endif()
endif()
if(HG_BUILD_CPP_SDK)
@ -398,4 +426,4 @@ if(HG_BUILD_CPP_SDK)
NAMESPACE hg::
COMPONENT cppsdk
)
endif()
endif()

View File

@ -475,7 +475,9 @@ static bgfx::FrameBufferHandle _OpenVREyeFrameBuffer_GetHandle(hg::OpenVREyeFram
gen.bind_function('hg::OpenVRGetColorTexture', 'hg::Texture', ['const hg::OpenVREyeFrameBuffer &eye'])
gen.bind_function('hg::OpenVRGetDepthTexture', 'hg::Texture', ['const hg::OpenVREyeFrameBuffer &eye'])
gen.bind_function('hg::OpenVRGetFrameBufferSize', 'hg::tVec2<int>', [])
def bind_sranipal(gen):
gen.add_include('engine/sranipal_api.h')
@ -593,9 +595,16 @@ static bool _dtCrowd_requestMoveTarget(dtCrowd *dt_crowd, const int idx, const h
def bind_platform(gen):
gen.add_include('platform/platform.h')
# hg::FileFilter
file_filter = gen.begin_class('hg::FileFilter')
gen.bind_members(file_filter, ['std::string name', 'std::string pattern'])
gen.end_class(file_filter)
bind_std_vector(gen, file_filter)
gen.bind_function('hg::OpenFolderDialog', 'bool', ['const std::string &title', 'std::string &folder_name', '?const std::string &initial_dir'], {'arg_in_out': ['folder_name']})
gen.bind_function('hg::OpenFileDialog', 'bool', ['const std::string &title', 'const std::string &filter', 'std::string &file', '?const std::string &initial_dir'], {'arg_in_out': ['file']})
gen.bind_function('hg::SaveFileDialog', 'bool', ['const std::string &title', 'const std::string &filter', 'std::string &file', '?const std::string &initial_dir'], {'arg_in_out': ['file']})
gen.bind_function('hg::OpenFileDialog', 'bool', ['const std::string &title', 'const std::vector<hg::FileFilter> &filters', 'std::string &file', '?const std::string &initial_dir'], {'arg_in_out': ['file']})
gen.bind_function('hg::SaveFileDialog', 'bool', ['const std::string &title', 'const std::vector<hg::FileFilter> &filters', 'std::string &file', '?const std::string &initial_dir'], {'arg_in_out': ['file']})
def bind_engine(gen):
@ -1117,6 +1126,10 @@ def bind_scene(gen):
gen.bind_method(node, 'StartOnInstantiateAnim', 'void', [])
gen.bind_method(node, 'StopOnInstantiateAnim', 'void', [])
gen.bind_method(node, 'GetWorld', 'hg::Mat4', [])
gen.bind_method(node, 'SetWorld', 'void', ['const hg::Mat4 &world'])
gen.bind_method(node, 'ComputeWorld', 'hg::Mat4', [])
gen.end_class(node)
bind_std_vector(gen, node)
@ -1496,6 +1509,10 @@ static std::vector<hg::ForwardPipelineLight> _GetSceneForwardPipelineLights(cons
])
gen.end_class(forward_pipeline_aaa_config)
gen.bind_function('hg::LoadForwardPipelineAAAConfigFromFile', 'bool', ['const char *path', 'hg::ForwardPipelineAAAConfig &config'])
gen.bind_function('hg::LoadForwardPipelineAAAConfigFromAssets', 'bool', ['const char *path', 'hg::ForwardPipelineAAAConfig &config'])
gen.bind_function('hg::SaveForwardPipelineAAAConfigToFile', 'bool', ['const char *path', 'const hg::ForwardPipelineAAAConfig &config'])
forward_pipeline_aaa = gen.begin_class('hg::ForwardPipelineAAA')
gen.bind_method(forward_pipeline_aaa, 'Flip', 'void', ['const hg::ViewState &view_state'])
gen.end_class(forward_pipeline_aaa)
@ -2136,10 +2153,10 @@ static void _SetViewTransform(bgfx::ViewId view_id, const hg::Mat4 &view, const
gen.insert_binding_code('static void _DestroyTexture(const hg::Texture &tex) { bgfx::destroy(tex.handle); }')
gen.bind_function('DestroyTexture', 'void', ['const hg::Texture &tex'], {'route': route_lambda('_DestroyTexture')})
gen.bind_function('hg::ProcessTextureLoadQueue', 'size_t', ['hg::PipelineResources &res', '?size_t limit'])
gen.bind_function('hg::ProcessTextureLoadQueue', 'size_t', ['hg::PipelineResources &res', '?hg::time_ns t_budget'])
gen.bind_function('hg::ProcessModelLoadQueue', 'size_t', ['hg::PipelineResources &res', '?size_t limit'])
gen.bind_function('hg::ProcessLoadQueues', 'size_t', ['hg::PipelineResources &res', '?size_t limit'])
gen.bind_function('hg::ProcessModelLoadQueue', 'size_t', ['hg::PipelineResources &res', '?hg::time_ns t_budget'])
gen.bind_function('hg::ProcessLoadQueues', 'size_t', ['hg::PipelineResources &res', '?hg::time_ns t_budget'])
# ModelRef/TextureRef/MaterialRef/PipelineProgramRef
model_ref = gen.begin_class('hg::ModelRef')
@ -2553,10 +2570,10 @@ def bind_model_builder(gen):
# ModelBuilder
model_builder = gen.begin_class('hg::ModelBuilder')
gen.bind_constructor(model_builder, [])
gen.bind_method(model_builder, 'AddVertex', 'uint16_t', ['const hg::Vertex &vtx'])
gen.bind_method(model_builder, 'AddTriangle', 'void', ['uint16_t a', 'uint16_t b', 'uint16_t c'])
gen.bind_method(model_builder, 'AddQuad', 'void', ['uint16_t a', 'uint16_t b', 'uint16_t c', 'uint16_t d'])
gen.bind_method(model_builder, 'AddPolygon', 'void', ['const std::vector<uint16_t> &idxs'])
gen.bind_method(model_builder, 'AddVertex', 'uint32_t', ['const hg::Vertex &vtx'])
gen.bind_method(model_builder, 'AddTriangle', 'void', ['uint32_t a', 'uint32_t b', 'uint32_t c'])
gen.bind_method(model_builder, 'AddQuad', 'void', ['uint32_t a', 'uint32_t b', 'uint32_t c', 'uint32_t d'])
gen.bind_method(model_builder, 'AddPolygon', 'void', ['const std::vector<uint32_t> &idxs'])
gen.bind_method(model_builder, 'GetCurrentListIndexCount', 'size_t', [])
gen.bind_method(model_builder, 'EndList', 'void', ['uint16_t material'])
gen.bind_method(model_builder, 'Clear', 'void', [])

View File

@ -0,0 +1 @@
Begin a named profiler section. Call [EndProfilerSection] to end the section.

View File

@ -0,0 +1,3 @@
Capture the current profiler frame but do not end it. See [EndProfilerFrame] to capture and end the current profiler frame.
See [PrintProfilerFrame] to print a profiler frame to the console.

View File

@ -0,0 +1,3 @@
End a profiler frame and return it.
See [PrintProfilerFrame] to print a profiler frame to the console.

View File

@ -0,0 +1 @@
End a named profiler section. Call [BeginProfilerSection] to begin a new section.

View File

@ -0,0 +1 @@
Print a profiler frame to the console. Print all sections in the frame, their duration and event count.

View File

@ -12,4 +12,6 @@ Time is internally stored in nanoseconds as a 64 bit integer, many functions are
- **Microsecond (10<sup>-6</sup>s):** [time_from_us]/[time_to_us] and [time_from_us_f]/[time_to_us_f]
- **Nanosecond (10<sup>-9</sup>s):** [time_from_ns]
*Note:* Storing time as integer is extremely important! As values in nanoseconds get very large, very fast, floating point representations will quickly loose precision due to quantization. If you really need time as a floating point value, you should perform fixed-point arithmetics on integer representation then convert the result to floating point as the very last step.
The current system time can be queried using [time_now].

BIN
doc/img/harfang.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

71
extern/CMakeLists.txt vendored
View File

@ -30,6 +30,24 @@ endfunction(install_cppsdk_external_target)
# glfw
if(HG_USE_GLFW)
# determine glfw backend (as we do not have access to glfw_config.h).
if(GLFW_USE_WAYLAND)
set(HG_GLFW_BACKEND "WAYLAND")
elseif (WIN32)
set(HG_GLFW_BACKEND "WIN32")
elseif (HG_APPLE)
set(HG_GLFW_BACKEND "COCOA")
elseif (UNIX)
set(HG_GLFW_BACKEND "X11")
else ()
message(ERROR "GLFW: unknown or unsupported backed")
endif()
set(HG_GLFW_BACKEND ${HG_GLFW_BACKEND} PARENT_SCOPE)
if(NOT DEFINED HG_REBUILD_GLFW)
set(HG_REBUILD_GLFW ON)
endif()
if(NOT HG_REBUILD_GLFW)
# use system package
find_package(glfw3 3.2)
@ -39,6 +57,8 @@ if(HG_USE_GLFW)
get_target_property(glfw_target_type glfw TYPE)
if(glfw_target_type STREQUAL "SHARED_LIBRARY")
set_target_properties(glfw PROPERTIES IMPORTED_GLOBAL TRUE)
# we set the corresponding compile definition. This define will be exported in the CMake configuration files.
target_compile_definitions(glfw INTERFACE GLFW_${HG_GLFW_BACKEND}=1)
else()
message(WARNING "Only the dynamic library version of GLFW is allowed")
set(HG_REBUILD_GLFW ON)
@ -53,6 +73,9 @@ if(HG_USE_GLFW)
# build it from sources
set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared libraries" FORCE)
set(GLFW_INSTALL OFF CACHE BOOL "")
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "")
set(GLFW_BUILD_TESTS OFF CACHE BOOL "")
set(GLFW_BUILD_DOCS OFF CACHE BOOL "")
add_subdirectory(glfw EXCLUDE_FROM_ALL)
# here we completly hijack glfw shared library output name.
# on *nix we don't want all the so names with versions (libgflw.so.3 libglfw.so.3.x etc...)
@ -68,7 +91,11 @@ if(HG_USE_GLFW)
INTERFACE_INCLUDE_DIRECTORIES
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/glfw/include>"
)
# we set the corresponding compile definition. This define will be exported in the CMake configuration files.
target_compile_definitions(glfw PUBLIC GLFW_${HG_GLFW_BACKEND}=1)
endif()
else()
set(HG_GLFW_BACKEND "NONE" PARENT_SCOPE)
endif()
# miniz
@ -95,6 +122,10 @@ install_cppsdk_external_target(nvtt)
install_cppsdk_external_target(pvrtc)
# Lua
if(UNIX AND NOT APPLE)
# lua links against libreadline but does not check for its availability.
find_package(readline REQUIRED)
endif()
add_subdirectory(lua EXCLUDE_FROM_ALL)
set_property(TARGET lua luac liblua libluadll PROPERTY FOLDER "harfang/3rdparty/lua")
if(HG_BUILD_CPP_SDK)
@ -181,6 +212,11 @@ target_include_directories(OpenAL PUBLIC $<BUILD_INTERFACE:${OpenAL_SOURCE_DIR}/
target_compile_definitions(OpenAL PUBLIC ALSOFT_EMBED_HRTF_DATA=1 AL_LIBTYPE_STATIC=1) # make sure to correctly propagate this flag to consuming librairies
set_target_properties(OpenAL PROPERTIES FOLDER "harfang/3rdparty")
# ... try to fix include directories
get_target_property(OpenAL_include_dirs OpenAL INTERFACE_INCLUDE_DIRECTORIES)
list(REMOVE_ITEM OpenAL_include_dirs "$<INSTALL_INTERFACE:include>")
set_property(TARGET OpenAL PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${OpenAL_include_dirs})
install_cppsdk_external_target(OpenAL)
# json.hpp
@ -229,13 +265,18 @@ if(HG_ENABLE_OPENVR_API)
set(OPENVR_DLL ${OPENVR_DLL} PARENT_SCOPE)
set_target_properties(OpenVR PROPERTIES
IMPORTED_IMPLIB ${OPENVR_LIBRARY}
IMPORTED_LOCATION ${OPENVR_DLL}
INTERFACE_INCLUDE_DIRECTORIES ${OPENVR_INCLUDE_PATH}
)
if(HG_BUILD_CPP_SDK)
install(FILES ${OPENVR_DLL} DESTINATION ${CppSdkRuntimeDestination} COMPONENT cppsdk)
endif()
else()
set_target_properties(OpenVR PROPERTIES
IMPORTED_LOCATION ${OPENVR_LIBRARY}
INTERFACE_INCLUDE_DIRECTORIES ${OPENVR_INCLUDE_PATH}
)
endif()
set_target_properties(OpenVR PROPERTIES IMPORTED_LOCATION $<IF:$<PLATFORM_ID:Windows>,${OPENVR_DLL},${OPENVR_LIBRARY}>)
if(HG_BUILD_CPP_SDK)
install(FILES ${OPENVR_LIBRARY} DESTINATION ${CppSdkLibraryDestination} COMPONENT cppsdk)
@ -249,22 +290,26 @@ endif()
# SRanipal
if(HG_ENABLE_SRANIPAL_API)
# [todo] linux
set(SRANIPAL_LIBRARY "${CMAKE_CURRENT_SOURCE_DIR}/sranipal/lib/SRanipal.lib")
find_library(SRANIPAL_LIBRARY name SRanipal PATHS ${CMAKE_CURRENT_SOURCE_DIR}/sranipal/lib NO_DEFAULT_PATH)
set(SRANIPAL_DLL
"${CMAKE_CURRENT_SOURCE_DIR}/sranipal/bin/libHTC_License.dll"
"${CMAKE_CURRENT_SOURCE_DIR}/sranipal/bin/nanomsg.dll"
"${CMAKE_CURRENT_SOURCE_DIR}/sranipal/bin/SRanipal.dll"
"${CMAKE_CURRENT_SOURCE_DIR}/sranipal/bin/SRWorks_Log.dll"
"${CMAKE_CURRENT_SOURCE_DIR}/sranipal/bin/ViveSR_Client.dll" PARENT_SCOPE)
add_library(SRanipal INTERFACE)
target_include_directories(SRanipal INTERFACE sranipal/include)
target_link_libraries(SRanipal INTERFACE ${SRANIPAL_LIBRARY})
${CMAKE_CURRENT_SOURCE_DIR}/sranipal/bin/libHTC_License.dll
${CMAKE_CURRENT_SOURCE_DIR}/sranipal/bin/nanomsg.dll
${CMAKE_CURRENT_SOURCE_DIR}/sranipal/bin/SRanipal.dll
${CMAKE_CURRENT_SOURCE_DIR}/sranipal/bin/SRWorks_Log.dll
${CMAKE_CURRENT_SOURCE_DIR}/sranipal/bin/ViveSR_Client.dll)
set(SRANIPAL_DLL ${SRANIPAL_DLL} PARENT_SCOPE)
add_library(SRanipal SHARED IMPORTED GLOBAL)
set_target_properties(SRanipal PROPERTIES
IMPORTED_IMPLIB ${CMAKE_CURRENT_SOURCE_DIR}/sranipal/lib/SRanipal.lib
IMPORTED_LOCATION "${SRANIPAL_DLL}"
INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/sranipal/include
)
if(HG_BUILD_CPP_SDK)
install(FILES ${SRANIPAL_DLL} DESTINATION ${CppSdkRuntimeDestination} COMPONENT cppsdk)
install(FILES ${SRANIPAL_LIBRARY} DESTINATION ${CppSdkLibraryDestination} COMPONENT cppsdk)
# install(DIRECTORY sranipal/include/ DESTINATION cppsdk/include/extern/sranipal COMPONENT cppsdk)
endif()
endif()
@ -300,7 +345,7 @@ if(UNIX)
endif()
# meshoptimizer
set(CMAKE_INSTALL_INCLUDEDIR ${CppSdkHeadersDestination}/extern)
add_subdirectory(meshoptimizer EXCLUDE_FROM_ALL)
set_target_properties(meshoptimizer PROPERTIES FOLDER "harfang/3rdparty")
install_cppsdk_external_target(meshoptimizer)

2
extern/bgfx/bgfx vendored

@ -1 +1 @@
Subproject commit 73db386165bfb30d4cfe053a84a02562617246a1
Subproject commit 3d4bd88c0635b614b453aac1003cc56a11d1ccf0

View File

@ -56,11 +56,6 @@ target_include_directories( bgfx
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/bgfx/include>
)
target_compile_definitions( bgfx PRIVATE "$<$<CONFIG:Debug>:BGFX_CONFIG_DEBUG=1>" )
if(BGFX_CONFIG_DEBUG)
target_compile_definitions( bgfx PRIVATE BGFX_CONFIG_DEBUG=1 )
endif()
if( MSVC )
target_compile_definitions( bgfx PRIVATE "_CRT_SECURE_NO_WARNINGS" )
endif()

2
extern/bgfx/bimg vendored

@ -1 +1 @@
Subproject commit 6693de0e50ff7e76a22d6f37251fa2dec12168cd
Subproject commit 663f724186e26caf46494e389ed82409106205fb

2
extern/bgfx/bx vendored

@ -1 +1 @@
Subproject commit 9768d3a728ebd90e66e9e3b8fd7f99cd577767ce
Subproject commit ad018d47c6c107e2fe2f3ba0716f9e728ed59a39

75
extern/bgfx/bx.cmake vendored
View File

@ -1,44 +1,46 @@
cmake_minimum_required(VERSION 3.1)
set( BX_SRCS
bx/src/allocator.cpp bx/src/bx.cpp bx/src/bx_p.h bx/src/commandline.cpp
bx/src/crtnone.cpp bx/src/dtoa.cpp bx/src/easing.cpp bx/src/file.cpp
bx/src/filepath.cpp bx/src/debug.cpp bx/src/hash.cpp bx/src/math.cpp
bx/src/mutex.cpp bx/src/os.cpp bx/src/process.cpp bx/src/semaphore.cpp
bx/src/settings.cpp bx/src/sort.cpp bx/src/string.cpp bx/src/thread.cpp
bx/src/timer.cpp bx/src/url.cpp
bx/src/allocator.cpp bx/src/debug.cpp bx/src/math.cpp bx/src/sort.cpp
bx/src/dtoa.cpp bx/src/mutex.cpp bx/src/string.cpp bx/src/settings.cpp
bx/src/bounds.cpp bx/src/easing.cpp bx/src/os.cpp bx/src/thread.cpp
bx/src/bx.cpp bx/src/file.cpp bx/src/process.cpp bx/src/timer.cpp
bx/src/commandline.cpp bx/src/filepath.cpp bx/src/semaphore.cpp bx/src/url.cpp
bx/src/crtnone.cpp bx/src/hash.cpp
)
set( BX_HDRS
bx/include/bx/allocator.h bx/include/bx/handlealloc.h bx/include/bx/ringbuffer.h
bx/include/bx/bx.h bx/include/bx/hash.h bx/include/bx/rng.h
bx/include/bx/commandline.h bx/include/bx/macros.h bx/include/bx/semaphore.h
bx/include/bx/config.h bx/include/bx/maputil.h bx/include/bx/settings.h
bx/include/bx/cpu.h bx/include/bx/math.h bx/include/bx/simd_t.h
bx/include/bx/debug.h bx/include/bx/mpscqueue.h bx/include/bx/sort.h
bx/include/bx/easing.h bx/include/bx/mutex.h bx/include/bx/spscqueue.h
bx/include/bx/endian.h bx/include/bx/os.h bx/include/bx/string.h
bx/include/bx/error.h bx/include/bx/pixelformat.h bx/include/bx/thread.h
bx/include/bx/file.h bx/include/bx/platform.h bx/include/bx/timer.h
bx/include/bx/filepath.h bx/include/bx/process.h bx/include/bx/uint32_t.h
bx/include/bx/float4x4_t.h bx/include/bx/readerwriter.h bx/include/bx/url.h
bx/include/bx/allocator.h bx/include/bx/handlealloc.h bx/include/bx/rng.h
bx/include/bx/bounds.h bx/include/bx/hash.h bx/include/bx/semaphore.h
bx/include/bx/bx.h bx/include/bx/macros.h bx/include/bx/settings.h
bx/include/bx/commandline.h bx/include/bx/maputil.h bx/include/bx/simd_t.h
bx/include/bx/config.h bx/include/bx/math.h bx/include/bx/sort.h
bx/include/bx/cpu.h bx/include/bx/mpscqueue.h bx/include/bx/spscqueue.h
bx/include/bx/debug.h bx/include/bx/mutex.h bx/include/bx/string.h
bx/include/bx/easing.h bx/include/bx/os.h bx/include/bx/thread.h
bx/include/bx/endian.h bx/include/bx/pixelformat.h bx/include/bx/timer.h
bx/include/bx/error.h bx/include/bx/platform.h bx/include/bx/uint32_t.h
bx/include/bx/file.h bx/include/bx/process.h bx/include/bx/url.h
bx/include/bx/filepath.h bx/include/bx/readerwriter.h
bx/include/bx/float4x4_t.h bx/include/bx/ringbuffer.h
)
set( BX_INLINE_HDRS
bx/include/bx/inline/allocator.inl bx/include/bx/inline/handlealloc.inl
bx/include/bx/inline/ringbuffer.inl bx/include/bx/inline/simd256_avx.inl
bx/include/bx/inline/bx.inl bx/include/bx/inline/hash.inl
bx/include/bx/inline/rng.inl bx/include/bx/inline/simd256_ref.inl
bx/include/bx/inline/cpu.inl bx/include/bx/inline/math.inl
bx/include/bx/inline/simd128_langext.inl bx/include/bx/inline/simd_ni.inl
bx/include/bx/inline/easing.inl bx/include/bx/inline/mpscqueue.inl
bx/include/bx/inline/simd128_neon.inl bx/include/bx/inline/sort.inl
bx/include/bx/inline/endian.inl bx/include/bx/inline/mutex.inl
bx/include/bx/inline/simd128_ref.inl bx/include/bx/inline/spscqueue.inl
bx/include/bx/inline/error.inl bx/include/bx/inline/pixelformat.inl
bx/include/bx/inline/simd128_sse.inl bx/include/bx/inline/string.inl
bx/include/bx/inline/float4x4_t.inl bx/include/bx/inline/readerwriter.inl
bx/include/bx/inline/simd128_swizzle.inl bx/include/bx/inline/uint32_t.inl
bx/include/bx/inline/allocator.inl bx/include/bx/inline/readerwriter.inl
bx/include/bx/inline/bounds.inl bx/include/bx/inline/ringbuffer.inl
bx/include/bx/inline/bx.inl bx/include/bx/inline/rng.inl
bx/include/bx/inline/cpu.inl bx/include/bx/inline/simd128_langext.inl
bx/include/bx/inline/easing.inl bx/include/bx/inline/simd128_neon.inl
bx/include/bx/inline/endian.inl bx/include/bx/inline/simd128_ref.inl
bx/include/bx/inline/error.inl bx/include/bx/inline/simd128_sse.inl
bx/include/bx/inline/float4x4_t.inl bx/include/bx/inline/simd128_swizzle.inl
bx/include/bx/inline/handlealloc.inl bx/include/bx/inline/simd256_avx.inl
bx/include/bx/inline/hash.inl bx/include/bx/inline/simd256_ref.inl
bx/include/bx/inline/math.inl bx/include/bx/inline/simd_ni.inl
bx/include/bx/inline/mpscqueue.inl bx/include/bx/inline/sort.inl
bx/include/bx/inline/mutex.inl bx/include/bx/inline/spscqueue.inl
bx/include/bx/inline/os.inl bx/include/bx/inline/string.inl
bx/include/bx/inline/pixelformat.inl bx/include/bx/inline/uint32_t.inl
)
add_library( bx STATIC ${BX_SRCS} ${BX_HDRS} ${BX_INLINE_HDRS} )
@ -67,10 +69,11 @@ target_compile_definitions( bx PUBLIC "__STDC_LIMIT_MACROS" )
target_compile_definitions( bx PUBLIC "__STDC_FORMAT_MACROS" )
target_compile_definitions( bx PUBLIC "__STDC_CONSTANT_MACROS" )
target_compile_definitions( bx PRIVATE "$<$<CONFIG:Debug>:BX_CONFIG_DEBUG=1>" )
if(BGFX_CONFIG_DEBUG)
target_compile_definitions( bx PRIVATE BX_CONFIG_DEBUG=1 )
endif()
target_compile_definitions( bx
PUBLIC
$<$<CONFIG:Debug>:BX_CONFIG_DEBUG=1>
$<$<CONFIG:Release>:BX_CONFIG_DEBUG=0>
)
if( UNIX AND NOT APPLE )
find_package( Threads )

2
extern/glfw vendored

@ -1 +1 @@
Subproject commit 56a4cb0a3a2c7a44a2fd8ab3335adf915e19d30c
Subproject commit 7d5a16ce714f0b5f4efa3262de22e4d948851525

2
extern/googletest vendored

@ -1 +1 @@
Subproject commit 16f637fbf4ffc3f7a01fa4eceb7906634565242f
Subproject commit e2239ee6043f73722e7aa812a459f54a28552929

@ -1 +1 @@
Subproject commit cd18beeea8caef407d355c35ac933c24d6685cda
Subproject commit 2126e7b71b2402992817ba9d2a527c827476adaa

2
extern/openal-soft vendored

@ -1 +1 @@
Subproject commit 6a3c4c09f838b0e9156b3f4c223281a3ed43817b
Subproject commit ae4eacf147e2c2340cc4e02a790df04c793ed0a9

@ -1 +1 @@
Subproject commit c5cbd53024c8a9d8d097a4371215e3342d2fdc87
Subproject commit 57610fa6ef31b39020231906f8c5d40eaa8294ae

View File

@ -0,0 +1,30 @@
#[[
Try to find libreadline
Provides the following target and variables:
* readline : library target
* READLINE_FOUND : set if libreadline was found
* READLINE_INCLUDE_DIR : libreadline include diretory
* READLINE_LIBRARY : libreadline library file
#]]
find_path(READLINE_INCLUDE_DIR
NAMES readline/readline.h
HINTS ${READLINE_ROOT_DIR}
)
find_library(READLINE_LIBRARY
NAMES readline
HINTS ${READLINE_ROOT_DIR}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(readline REQUIRED_VARS READLINE_LIBRARY READLINE_INCLUDE_DIR)
mark_as_advanced(READLINE_FOUND READLINE_LIBRARY READLINE_INCLUDE_DIR)
if(READLINE_FOUND AND NOT TARGET readline)
add_library(readline UNKNOWN IMPORTED)
set_target_properties(readline PROPERTIES
IMPORTED_LOCATION "${READLINE_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${READLINE_INCLUDE_DIR}"
)
endif()

View File

@ -2,6 +2,10 @@ set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_SYSTEM_VERSION 1)
set(HG_GRAPHIC_API "GLES" CACHE STRING "" FORCE)
set(HG_REBUILD_GLFW OFF CACHE BOOL "" FORCE)
set(GLFW_USE_WAYLAND ON CACHE BOOL "" FORCE)
if(DEFINED ENV{OECORE_TARGET_SYSROOT})
set(CMAKE_FIND_ROOT_PATH $ENV{OECORE_TARGET_SYSROOT})
else()
@ -18,8 +22,6 @@ else()
set(CMAKE_FIND_ROOT_PATH ${TARGET_SYSROOT} ${NATIVE_SYSROOT})
set(HG_EMBEDDED ON CACHE BOOL "" FORCE)
set(HG_USE_GLFW_WAYLAND ON CACHE BOOL "" FORCE)
add_compile_options("-DGLFW_INCLUDE_ES2")
endif()

View File

@ -7,10 +7,9 @@ set(HG_VERSION "@HG_VERSION@")
set(HG_GRAPHIC_API "@HG_GRAPHIC_API@")
set(HG_HOST_PREFIX "@HG_HOST_PREFIX@")
set(HG_TARGET_PREFIX "@HG_TARGET_PREFIX@")
set(HG_EMBEDDED @HG_EMBEDDED@)
set(HG_USE_GLFW @HG_USE_GLFW@)
set(HG_USE_GLFW_WAYLAND @HG_USE_GLFW_WAYLAND@)
set(HG_USE_EGL @HG_USE_EGL@)
set(HG_USE_GTK3 @HG_USE_GTK3@)
set(HG_GLFW_BACKEND "@HG_GLFW_BACKEND@")
set(HG_ENABLE_BULLET3_SCENE_PHYSICS @HG_ENABLE_BULLET3_SCENE_PHYSICS@)
set(HG_ENABLE_OPENVR_API @HG_ENABLE_OPENVR_API@)
set(HG_ENABLE_SRANIPAL_API @HG_ENABLE_SRANIPAL_API@)
@ -32,18 +31,10 @@ if(HG_ENABLE_RECAST_DETOUR_API)
add_compile_definitions(HG_ENABLE_RECAST_DETOUR_API)
endif()
if(HG_USE_GLFW_WAYLAND)
add_compile_definitions(HG_USE_GLFW_WAYLAND)
endif()
if(HG_USE_GLFW)
add_compile_definitions(HG_USE_GLFW)
endif()
if(HG_EMBEDDED)
add_compile_definitions(HG_EMBEDDED)
endif()
add_compile_definitions(HG_GRAPHIC_API="${HG_GRAPHIC_API}")
if(HG_GRAPHIC_API STREQUAL "GL")
set(HG_DEFAULT_RENDERER_TYPE bgfx::RendererType::OpenGL)
@ -66,6 +57,7 @@ add_compile_definitions(HG_DEFAULT_RENDERER_TYPE=${HG_DEFAULT_RENDERER_TYPE})
if(UNIX)
if(NOT @HG_REBUILD_GLFW@)
find_dependency(glfw3 3.2)
target_compile_definitions(glfw INTERFACE GLFW_@HG_GLFW_BACKEND@=1)
endif()
if(NOT APPLE AND NOT ANDROID AND NOT EMSCRIPTEN)
@ -76,11 +68,11 @@ if(UNIX)
find_library(JACK_LIBRARY jack)
find_library(SNDIO_LIBRARY sndio)
if( NOT HG_USE_GLFW_WAYLAND )
if( HG_GLFW_BACKEND STREQUAL "X11" )
find_dependency( X11 )
endif()
if( (NOT X11_FOUND) OR HG_USE_GLFW_WAYLAND )
if( (NOT X11_FOUND) OR (HG_GLFW_BACKEND STREQUAL "WAYLAND") )
find_dependency(ECM REQUIRED NO_MODULE)
list(APPEND CMAKE_MODULE_PATH "${ECM_MODULE_PATH}")
find_dependency(Wayland REQUIRED)
@ -94,7 +86,7 @@ if(UNIX)
endif()
endif()
if(NOT HG_EMBEDDED)
if(HG_USE_GTK3)
find_dependency(PkgConfig REQUIRED)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
endif()
@ -153,9 +145,58 @@ if(HG_ENABLE_OPENVR_API)
unset(_OPENVR_IMPORT_PREFIX)
endif()
# Recreate SRanipal target if needed
if(HG_ENABLE_SRANIPAL_API AND (CMAKE_SYSTEM_NAME STREQUAL "Windows"))
get_filename_component(_SRANIPAL_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY )
get_filename_component(_SRANIPAL_IMPORT_PREFIX "${_SRANIPAL_IMPORT_PREFIX}" DIRECTORY)
find_library(SRANIPAL_LIBRARY_RELEASE name SRanipal PATHS "${_SRANIPAL_IMPORT_PREFIX}/lib/Release" NO_DEFAULT_PATH)
find_library(SRANIPAL_LIBRARY_DEBUG name SRanipal PATHS "${_SRANIPAL_IMPORT_PREFIX}/lib/Debug" NO_DEFAULT_PATH)
if(NOT (SRANIPAL_LIBRARY_RELEASE OR SRANIPAL_LIBRARY_DEBUG))
message(FATAL_ERROR "SRanipal library not found")
endif()
add_library(SRanipal SHARED IMPORTED GLOBAL)
set(_SRANIPAL_IMPORTED_CONFIGS "")
if(SRANIPAL_LIBRARY_RELEASE)
list(APPEND _SRANIPAL_IMPORTED_CONFIGS RELEASE)
set(_SRANIPAL_DLLS "")
foreach(_dll libHTC_License nanomsg SRanipal SRWorks_Log ViveSR_Client)
find_file(${_dll}_RELEASE name "${_dll}${CMAKE_SHARED_LIBRARY_SUFFIX}" PATHS "${_SRANIPAL_IMPORT_PREFIX}/bin/Release" NO_DEFAULT_PATH)
list(APPEND _SRANIPAL_DLLS ${${_dll}_RELEASE})
endforeach(_dll)
set_target_properties(SRanipal PROPERTIES
IMPORTED_IMPLIB_RELEASE "${SRANIPAL_LIBRARY_RELEASE}"
IMPORTED_LOCATION_RELEASE "${_SRANIPAL_DLLS}"
)
unset(_SRANIPAL_DLLS)
endif()
if(SRANIPAL_LIBRARY_DEBUG)
list(APPEND _SRANIPAL_IMPORTED_CONFIGS DEBUG)
set(_SRANIPAL_DLLS "")
foreach(_dll libHTC_License nanomsg SRanipal SRWorks_Log ViveSR_Client)
find_file(${_dll}_DEBUG name "${_dll}${CMAKE_SHARED_LIBRARY_SUFFIX}" PATHS "${_SRANIPAL_IMPORT_PREFIX}/bin/Debug" NO_DEFAULT_PATH)
list(APPEND _SRANIPAL_DLLS ${${_dll}_DEBUG})
endforeach(_dll)
set_target_properties(SRanipal PROPERTIES
IMPORTED_IMPLIB_DEBUG "${SRANIPAL_LIBRARY_DEBUG}"
IMPORTED_LOCATION_DEBUG "${_SRANIPAL_DLLS}"
)
unset(_SRANIPAL_DLLS)
endif()
set_property(TARGET SRanipal PROPERTY IMPORTED_CONFIGURATIONS ${_SRANIPAL_IMPORTED_CONFIGS})
unset(_SRANIPAL_IMPORTED_CONFIGS)
unset(_SRANIPAL_IMPORT_PREFIX)
endif()
check_required_components(cppsdk)
# Helper function to deploy CPPSDK shared libraries
# Helper function to deploy shared libraries of CPPSDK external dependencies.
function(install_cppsdk_dependencies destination component)
foreach(_target @HG_SHARED_LIBRARY_TARGETS@)
if(TARGET ${_target})

View File

@ -141,6 +141,11 @@ if(HG_ENABLE_BULLET3_SCENE_PHYSICS)
target_link_libraries(engine PRIVATE BulletDynamics)
endif()
if(MSVC)
target_compile_options(engine PRIVATE "$<$<CONFIG:Release>:/Zi>")
target_link_options(engine PRIVATE "$<$<CONFIG:Release>:/DEBUG>")
endif()
set_property(TARGET engine PROPERTY PUBLIC_HEADER ${HDRS})
set_target_properties(engine PROPERTIES FOLDER "harfang")

View File

@ -12,7 +12,7 @@ struct AAABlur {
bgfx::UniformHandle u_dir = BGFX_INVALID_HANDLE;
bgfx::UniformHandle u_sigma = BGFX_INVALID_HANDLE;
bgfx::UniformHandle u_input = BGFX_INVALID_HANDLE;
bgfx::UniformHandle u_attr0 = BGFX_INVALID_HANDLE; // xyz: normal, w: linear depth
bgfx::UniformHandle u_attr0 = BGFX_INVALID_HANDLE; // xyz: normal, w: linear depth
};
AAABlur CreateAAABlurFromFile(const char *path);
@ -20,8 +20,8 @@ AAABlur CreateAAABlurFromAssets(const char *path);
void DestroyAAABlur(AAABlur &aaa_blur);
void ComputeAAABlur(bgfx::ViewId &view_id, const iRect &rect, const Texture &attr0, bgfx::FrameBufferHandle fb0,
bgfx::FrameBufferHandle fb1, const AAABlur &aaa_blur);
void ComputeAAABlur(
bgfx::ViewId &view_id, const iRect &rect, const Texture &attr0, bgfx::FrameBufferHandle fb0, bgfx::FrameBufferHandle fb1, const AAABlur &aaa_blur);
bool IsValid(const AAABlur &aaa_blur);

View File

@ -138,28 +138,29 @@ Asset OpenAsset(const char *name, bool silent) {
// look in archive
for (auto &p : assets_packages) {
int index = mz_zip_reader_locate_file(&p.archive, name, NULL, MZ_ZIP_FLAG_CASE_SENSITIVE);
const int index = mz_zip_reader_locate_file(&p.archive, name, NULL, MZ_ZIP_FLAG_CASE_SENSITIVE);
if (index == -1)
continue; // missing file
size_t size;
char *buffer = (char *)mz_zip_reader_extract_to_heap(&p.archive, index, &size, 0);
const char *buffer = (char *)mz_zip_reader_extract_to_heap(&p.archive, index, &size, 0);
if (buffer) {
std::string data(buffer, size);
return {assets.add_ref({{}, {std::move(data), 0}, Package_file_GetSize, Package_file_Read, Package_file_Seek, Package_file_Tell, Package_file_Close,
Package_file_is_EOF})};
} else {
mz_zip_error err = mz_zip_get_last_error(&p.archive);
error(format("Failed to open asset '%1' from file '%2' (asset was found but failed to open) : %3")
.arg(name)
.arg(p.filename)
.arg(mz_zip_get_error_string(err)));
const mz_zip_error err = mz_zip_get_last_error(&p.archive);
if (!silent)
error(format("Failed to open asset '%1' from file '%2' (asset was found but failed to open) : %3")
.arg(name)
.arg(p.filename)
.arg(mz_zip_get_error_string(err)));
break;
}
}
if (!silent)
error(format("Failed to open asset '%1'").arg(name));
error(format("Failed to open asset '%1' (file not found)").arg(name));
return {};
}

View File

@ -37,12 +37,10 @@ static Bloom CreateBloomFromAssets(const char *path, bgfx::BackbufferRatio::Enum
return CreateBloomFromAssets(path, RenderBufferResourceFactory::Backbuffer(), ratio);
}
void DestroyBloom(Bloom &bloom);
void ApplyBloom(bgfx::ViewId &view_id, const iRect &rect, const hg::Texture &input, const hg::iVec2 &fb_size, bgfx::FrameBufferHandle output,
const Bloom &bloom, float threshold,
float smoothness, float intensity);
const Bloom &bloom, float threshold, float smoothness, float intensity);
void ApplyBloom(bgfx::ViewId &view_id, const iRect &rect, const hg::Texture &input, bgfx::FrameBufferHandle output, const Bloom &bloom, float threshold,
float smoothness, float intensity);

View File

@ -14,7 +14,7 @@ Model CreateCubeModel(const bgfx::VertexLayout &decl, float x, float y, float z)
y /= 2.f;
z /= 2.f;
uint16_t a, b, c, d;
VtxIdxType a, b, c, d;
a = builder.AddVertex({{-x, -y, -z}, {0.f, 0.f, -1.f}, {}, {}, {0, 0}}); // -Z
b = builder.AddVertex({{-x, y, -z}, {0.f, 0.f, -1.f}, {}, {}, {0, 1}});
@ -140,7 +140,7 @@ Model CreateCylinderModel(const bgfx::VertexLayout &decl, float radius, float he
subdiv_x = 3;
}
std::vector<uint16_t> ref(subdiv_x * 2);
std::vector<VtxIdxType> ref(subdiv_x * 2);
const float z = height / 2.f;
for (int i = 0; i < subdiv_x; i++) {
float t = 2.f * Pi * i / static_cast<float>(subdiv_x);
@ -151,17 +151,17 @@ Model CreateCylinderModel(const bgfx::VertexLayout &decl, float radius, float he
ref[2 * i + 1] = builder.AddVertex({{x, -z, y}, {cs, 0.f, sn}});
}
uint16_t a = ref[2 * subdiv_x - 2];
uint16_t b = ref[2 * subdiv_x - 1];
VtxIdxType a = ref[2 * subdiv_x - 2];
VtxIdxType b = ref[2 * subdiv_x - 1];
for (int i = 0; i < subdiv_x; i++) {
uint16_t c = ref[2 * i + 1];
uint16_t d = ref[2 * i];
const auto c = ref[2 * i + 1];
const auto d = ref[2 * i];
builder.AddPolygon({a, b, c, d});
a = d;
b = c;
}
std::vector<uint16_t> cap(subdiv_x + 2);
std::vector<VtxIdxType> cap(subdiv_x + 2);
cap[0] = builder.AddVertex({{0, z, 0}, {0, 1, 0}});
for (int i = 0; i < subdiv_x; i++) {
cap[i + 1] = ref[2 * i];
@ -188,7 +188,7 @@ Model CreateConeModel(const bgfx::VertexLayout &decl, float radius, float height
subdiv_x = 3;
}
std::vector<uint16_t> ref(subdiv_x + 2);
std::vector<VtxIdxType> ref(subdiv_x + 2);
for (int i = 0; i < subdiv_x; i++) {
float t = 2.f * Pi * i / static_cast<float>(subdiv_x);
float cs = Cos(t);
@ -223,7 +223,7 @@ Model CreateCapsuleModel(const bgfx::VertexLayout &decl, float radius, float hei
ModelBuilder builder;
// cylinder
std::vector<uint16_t> ref(subdiv_x * 2);
std::vector<VtxIdxType> ref(subdiv_x * 2);
const float z = height / 2.f - radius;
for (int i = 0; i < subdiv_x; i++) {
float t = 2.f * Pi * i / static_cast<float>(subdiv_x);
@ -234,21 +234,21 @@ Model CreateCapsuleModel(const bgfx::VertexLayout &decl, float radius, float hei
ref[2 * i + 1] = builder.AddVertex({{x, -z, y}, {cs, 0.f, sn}});
}
uint16_t a0, b0, a1, b1;
VtxIdxType a0, b0, a1, b1;
a0 = ref[2 * subdiv_x - 2];
b0 = ref[2 * subdiv_x - 1];
for (int i = 0; i < subdiv_x; i++) {
uint16_t c0 = ref[2 * i + 1];
uint16_t d0 = ref[2 * i];
VtxIdxType c0 = ref[2 * i + 1];
VtxIdxType d0 = ref[2 * i];
builder.AddPolygon({a0, b0, c0, d0});
a0 = d0;
b0 = c0;
}
uint16_t top = builder.AddVertex({{0.f, height / 2.f, 0.f}, {0.f, 1.f, 0.f}});
uint16_t bottom = builder.AddVertex({{0.f, -height / 2.f, 0.f}, {0.f, -1.f, 0.f}});
VtxIdxType top = builder.AddVertex({{0.f, height / 2.f, 0.f}, {0.f, 1.f, 0.f}});
VtxIdxType bottom = builder.AddVertex({{0.f, -height / 2.f, 0.f}, {0.f, -1.f, 0.f}});
std::vector<uint16_t> fan(2 + subdiv_x);
std::vector<VtxIdxType> fan(2 + subdiv_x);
if (subdiv_y == 1) {
// top cap
@ -271,7 +271,7 @@ Model CreateCapsuleModel(const bgfx::VertexLayout &decl, float radius, float hei
}
// hemispherical caps
std::vector<uint16_t> cap(subdiv_x * 2 * (subdiv_y - 1));
std::vector<VtxIdxType> cap(subdiv_x * 2 * (subdiv_y - 1));
for (int i = 0, k = 0; i < subdiv_x; i++) {
float t0 = 2.f * Pi * i / static_cast<float>(subdiv_x);
float c0 = radius * Cos(t0);
@ -312,14 +312,14 @@ Model CreateCapsuleModel(const bgfx::VertexLayout &decl, float radius, float hei
b1 = cap[k + 1];
for (int i = 0; i < subdiv_x; i++) {
k = 2 * ((subdiv_y - 1) * i + j);
uint16_t c0 = cap[k + 2];
uint16_t d0 = cap[k];
VtxIdxType c0 = cap[k + 2];
VtxIdxType d0 = cap[k];
builder.AddPolygon({a0, b0, c0, d0});
a0 = d0;
b0 = c0;
uint16_t c1 = cap[k + 1];
uint16_t d1 = cap[k + 3];
VtxIdxType c1 = cap[k + 1];
VtxIdxType d1 = cap[k + 3];
builder.AddPolygon({a1, b1, c1, d1});
a1 = d1;
b1 = c1;
@ -335,11 +335,11 @@ Model CreateCapsuleModel(const bgfx::VertexLayout &decl, float radius, float hei
a1 = ref[offset + 1];
for (int i = 0; i < subdiv_x; i++) {
offset = 2 * i;
uint16_t c0 = ref[offset];
uint16_t d1 = ref[offset + 1];
VtxIdxType c0 = ref[offset];
VtxIdxType d1 = ref[offset + 1];
offset = 2 * ((subdiv_y - 1) * (i + 1) - 1);
uint16_t d0 = cap[offset];
uint16_t c1 = cap[offset + 1];
VtxIdxType d0 = cap[offset];
VtxIdxType c1 = cap[offset + 1];
builder.AddPolygon({a0, b0, c0, d0});
builder.AddPolygon({a1, b1, c1, d1});
a0 = d0;

View File

@ -9,16 +9,15 @@
namespace hg {
Picture RenderCubemap(bgfx::ViewId &view_id, const PipelineResources &resources, Scene &scene, const Mat4 &transform, CubemapLayout cube_layout,
uint16_t tex_size,
const ForwardPipelineAAAConfig *aaa_config, float znear, float zfar) {
uint16_t tex_size, bgfx::TextureFormat::Enum format, PictureFormat pic_format, const ForwardPipelineAAAConfig *aaa_config, float znear, float zfar) {
bgfx::TextureHandle cubemap[hg::CF_Max];
for (int i = 0; i < hg::CF_Max; i++) {
cubemap[i] = bgfx::createTexture2D(tex_size, tex_size, false, 1, bgfx::TextureFormat::RGBA8, BGFX_TEXTURE_BLIT_DST | BGFX_TEXTURE_READ_BACK);
cubemap[i] = bgfx::createTexture2D(tex_size, tex_size, false, 1, format, BGFX_TEXTURE_BLIT_DST | BGFX_TEXTURE_READ_BACK);
}
RenderCubemap(view_id, resources, scene, transform, cubemap, tex_size, aaa_config, znear, zfar);
RenderCubemap(view_id, resources, scene, transform, cubemap, tex_size, format, aaa_config, znear, zfar);
auto pic = hg::CreatePictureFromCubemap(cubemap, hg::CL_CubeCross, tex_size);
auto pic = hg::CreatePictureFromCubemap(cubemap, hg::CL_CubeCross, tex_size, pic_format);
for (int i = 0; i < hg::CF_Max; i++) {
bgfx::destroy(cubemap[i]);
@ -28,13 +27,12 @@ Picture RenderCubemap(bgfx::ViewId &view_id, const PipelineResources &resources,
}
void RenderCubemap(bgfx::ViewId &view_id, const PipelineResources &resources, Scene &scene, const Mat4 &transform, bgfx::TextureHandle tgt_textures[CF_Max],
uint16_t tex_size,
const ForwardPipelineAAAConfig *aaa_config, float znear, float zfar) {
uint16_t tex_size, bgfx::TextureFormat::Enum format, const ForwardPipelineAAAConfig *aaa_config, float znear, float zfar) {
ForwardPipeline pipeline = CreateForwardPipeline();
bgfx::TextureHandle texs[2] = {
bgfx::createTexture2D(tex_size, tex_size, false, 1, bgfx::TextureFormat::RGBA8, BGFX_TEXTURE_BLIT_DST | BGFX_TEXTURE_RT_MSAA_X8),
bgfx::createTexture2D(tex_size, tex_size, false, 1, format, BGFX_TEXTURE_BLIT_DST | BGFX_TEXTURE_RT_MSAA_X8),
bgfx::createTexture2D(tex_size, tex_size, false, 1, bgfx::TextureFormat::D32, BGFX_TEXTURE_RT_WRITE_ONLY | BGFX_TEXTURE_RT_MSAA_X8)};
const auto frame_buffer = bgfx::createFrameBuffer(2, texs, true);
@ -62,8 +60,8 @@ void RenderCubemap(bgfx::ViewId &view_id, const PipelineResources &resources, Sc
}
void RenderCubemap(bgfx::ViewId &view_id, const bgfx::FrameBufferHandle frame_buffer, ForwardPipeline &pipeline, const PipelineResources &resources,
Scene &scene, const Mat4 &transform,
bgfx::TextureHandle tgt_textures[CF_Max], uint16_t tex_size, ForwardPipelineAAA *aaa, const ForwardPipelineAAAConfig *aaa_config,
Scene &scene, const Mat4 &transform, bgfx::TextureHandle tgt_textures[CF_Max], uint16_t tex_size, ForwardPipelineAAA *aaa,
const ForwardPipelineAAAConfig *aaa_config,
float znear, float zfar) {
const auto debug_name = std::string("cubemap");
@ -136,10 +134,9 @@ void RenderCubemap(bgfx::ViewId &view_id, const bgfx::FrameBufferHandle frame_bu
}
Picture CreatePictureFromCubemap(bgfx::TextureHandle cubemap[CF_Max], CubemapLayout cube_layout, uint16_t tex_size) {
Picture CreatePictureFromCubemap(bgfx::TextureHandle cubemap[CF_Max], CubemapLayout cube_layout, uint16_t tex_size, PictureFormat pic_format) {
const auto pic_format = PictureFormat::PF_RGBA32;
const size_t size_pixel = 4;
const size_t size_pixel = hg::size_of(pic_format);
const uint16_t pic_width = 4 * tex_size;
const uint16_t pic_height = 3 * tex_size;

View File

@ -3,6 +3,8 @@
#pragma once
#include <stdint.h>
#include <bgfx/bgfx.h>
#include "engine/picture.h"
namespace bgfx {
struct TextureHandle;
@ -17,7 +19,6 @@ struct ForwardPipelineAAAConfig;
struct ForwardPipelineAAA;
class Scene;
struct Mat4;
class Picture;
enum CubemapFaces { CF_XP, CF_XN, CF_YP, CF_YN, CF_ZP, CF_ZN, CF_Max };
static_assert(CF_XP == 0, "");
@ -27,11 +28,12 @@ enum CubemapLayout {
};
// pass nullptr for aaa_config for forward rendering, and a config for AAA rendering
Picture RenderCubemap(bgfx::ViewId& view_id, const PipelineResources &resources, Scene &scene, const Mat4 &transform, CubemapLayout cube_layout, uint16_t tex_size,
const ForwardPipelineAAAConfig *aaa_config = nullptr, float znear = 0.01f, float zfar = 1000.f);
Picture RenderCubemap(bgfx::ViewId &view_id, const PipelineResources &resources, Scene &scene, const Mat4 &transform, CubemapLayout cube_layout,
uint16_t tex_size, bgfx::TextureFormat::Enum format, PictureFormat pic_format, const ForwardPipelineAAAConfig *aaa_config = nullptr, float znear = 0.01f,
float zfar = 1000.f);
void RenderCubemap(bgfx::ViewId &view_id, const PipelineResources &resources, Scene &scene, const Mat4 &transform, bgfx::TextureHandle tgt_textures[CF_Max],
uint16_t tex_size,
const ForwardPipelineAAAConfig *aaa_config, float znear, float zfar);
uint16_t tex_size, bgfx::TextureFormat::Enum format, const ForwardPipelineAAAConfig *aaa_config, float znear, float zfar);
// aaa currently needs 1 pipeline per cubemap as ForwardPipelineAAA stores the previous frame
void RenderCubemap(bgfx::ViewId &view_id, const bgfx::FrameBufferHandle frame_buffer, ForwardPipeline &pipeline, const PipelineResources &resources,
@ -39,6 +41,6 @@ void RenderCubemap(bgfx::ViewId &view_id, const bgfx::FrameBufferHandle frame_bu
const ForwardPipelineAAAConfig *aaa_config,
float znear, float zfar);
Picture CreatePictureFromCubemap(bgfx::TextureHandle cubemap[CF_Max], CubemapLayout cube_layout, uint16_t tex_size);
Picture CreatePictureFromCubemap(bgfx::TextureHandle cubemap[CF_Max], CubemapLayout cube_layout, uint16_t tex_size, PictureFormat pic_format);
} // namespace hg

View File

@ -330,10 +330,10 @@ void GenerateLinearShadowMapForForwardPipeline(bgfx::ViewId &view_id, const View
std::vector<ModelDisplayList> culled_display_lists = display_lists;
CullModelDisplayLists(frustum, culled_display_lists, mtxs, res);
DrawModelDisplayLists(view_id, culled_display_lists, 0, pipeline.uniform_values, pipeline.uniform_textures, mtxs, res);
DrawModelDisplayLists(view_id, culled_display_lists, 9, pipeline.uniform_values, pipeline.uniform_textures, mtxs, res); // config idx is 9 for FPS_DepthOnly
// FIXME cull skinned models!
DrawSkinnedModelDisplayLists(view_id, skinned_display_lists, 0, pipeline.uniform_values, pipeline.uniform_textures, mtxs, res);
DrawSkinnedModelDisplayLists(view_id, skinned_display_lists, 9, pipeline.uniform_values, pipeline.uniform_textures, mtxs, res); // config idx is 9 for FPS_DepthOnly
views[FPSP_Slot0LinearSplit0 + i] = view_id++;
}
@ -377,10 +377,10 @@ void GenerateSpotShadowMapForForwardPipeline(bgfx::ViewId &view_id, const std::v
std::vector<ModelDisplayList> culled_display_lists = display_lists;
CullModelDisplayLists(frustum, culled_display_lists, mtxs, res);
DrawModelDisplayLists(view_id, culled_display_lists, 0, pipeline.uniform_values, pipeline.uniform_textures, mtxs, res);
DrawModelDisplayLists(view_id, culled_display_lists, 9, pipeline.uniform_values, pipeline.uniform_textures, mtxs, res); // config idx is 9 for FPS_DepthOnly
// FIXME cull skinned models!
DrawSkinnedModelDisplayLists(view_id, skinned_display_lists, 0, pipeline.uniform_values, pipeline.uniform_textures, mtxs, res);
DrawSkinnedModelDisplayLists(view_id, skinned_display_lists, 9, pipeline.uniform_values, pipeline.uniform_textures, mtxs, res); // config idx is 9 for FPS_DepthOnly
views[FPSP_Slot1Spot] = view_id++;
}
@ -404,6 +404,9 @@ static const PipelineInfo forward_pipeline_info = {
{"FORWARD_PIPELINE_AAA=1", "FORWARD_PIPELINE=1", "SLOT0_SHADOWS=1"},
{"FORWARD_PIPELINE_AAA=1", "FORWARD_PIPELINE=1", "SLOT1_SHADOWS=1"},
{"FORWARD_PIPELINE_AAA=1", "FORWARD_PIPELINE=1", "SLOT0_SHADOWS=1", "SLOT1_SHADOWS=1"},
// depth only
{"DEPTH_ONLY=1"},
},
};

View File

@ -80,7 +80,7 @@ inline void DestroyForwardPipeline(ForwardPipeline &pipeline) { DestroyPipeline(
const PipelineInfo &GetForwardPipelineInfo();
//
enum ForwardPipelineStage { FPS_AttributeBuffers, FPS_Basic, FPS_Advanced };
enum ForwardPipelineStage { FPS_AttributeBuffers, FPS_Basic, FPS_Advanced, FPS_DepthOnly };
void SubmitModelToForwardPipeline(bgfx::ViewId view_id, const Model &mdl, const ForwardPipeline &pipeline, const PipelineProgram &prg, uint32_t prg_variant,
uint8_t pipeline_config_idx, const Color &ambient, const ForwardPipelineLights &lights, const ForwardPipelineFog &fog, const Mat4 &mtx);

View File

@ -559,10 +559,12 @@ static void GeometryToModelBuilder(const Geometry &geo, ModelBuilder &builder) {
for (auto &pol : geo.pol) {
if (pol.material == i_mat) {
#if 0 // [EJ] we're seeing very large meshes coming in lately so allow 32 bit indexes, we'll introduce a force 16 bit indice flag if required
if (builder.GetCurrentListIndexCount() + (pol.vtx_count - 2) * 3 > 65535) {
builder.EndList(i_mat);
bone_map.clear();
}
#endif
bool bone_map_ready = false;
@ -584,21 +586,22 @@ static void GeometryToModelBuilder(const Geometry &geo, ModelBuilder &builder) {
bool need_new_list = false;
for (int i = 0; i < 4; ++i) {
auto bone_idx = geo.skin[i_vtx].index[i];
const auto bone_idx = geo.skin[i_vtx].index[i];
if (bone_map.find(bone_idx) == bone_map.end()) {
auto redir_idx = uint16_t(bone_map.size());
if (redir_idx < max_skinned_model_matrix_count) {
bone_map[bone_idx] = redir_idx;
bone_indices_to_add.push_back(bone_idx);
} else {
need_new_list = true;
need_new_list = true; // too many bones, start a new list
break;
}
}
}
if (need_new_list) {
// too many bones, start a new list
builder.EndList(i_mat);
bone_map.clear();
bone_map_ready = false;
@ -664,7 +667,7 @@ bool SaveGeometryModelToFile(const char *path, const Geometry &geo, ModelOptimis
ModelBuilder builder;
GeometryToModelBuilder(geo, builder);
auto on_end_list = [](const bgfx::VertexLayout &, const MinMax &minmax, const std::vector<uint32_t> &idx32, const std::vector<uint8_t> &vtx,
auto on_end_list = [](const bgfx::VertexLayout &, const MinMax &minmax, const std::vector<VtxIdxType> &idx32, const std::vector<uint8_t> &vtx,
const std::vector<uint16_t> &bones_table, uint16_t mat, void *userdata) {
const auto &file = *reinterpret_cast<File *>(userdata);

View File

@ -25,6 +25,7 @@ static const uint32_t LSSF_DoNotLoadResources = 0x40000; // skip loading any res
static const uint32_t LSSF_QueueModelLoads = 0x80000;
static const uint32_t LSSF_DoNotChangeCurrentCameraIfValid = 0xa0000; // default behavior when loading a scene is to set the current camera if specified, when
// this flag is raised this will only be done if the current camera is invalid
static const uint32_t LSSF_Silent = 0xb0000; // do not log errors
static const uint32_t LSSF_QueueResourceLoads = LSSF_QueueTextureLoads | LSSF_QueueModelLoads;

View File

@ -59,7 +59,7 @@ static bool operator==(const Vertex &a, const Vertex &b) {
return a.pos == b.pos && a.normal == b.normal && a.tangent == b.tangent && a.binormal == b.binormal && uv && c && i && w;
}
uint16_t ModelBuilder::AddVertex(const Vertex &vtx) {
VtxIdxType ModelBuilder::AddVertex(const Vertex &vtx) {
auto &list = lists.back();
size_t idx = list.vtx.size();
@ -68,10 +68,10 @@ uint16_t ModelBuilder::AddVertex(const Vertex &vtx) {
const auto i_vtx = list.vtx_lookup.find(hash);
if (i_vtx == std::end(list.vtx_lookup)) {
list.vtx_lookup[hash] = uint16_t(idx); // store hash
list.vtx_lookup[hash] = VtxIdxType(idx); // store hash
list.vtx.push_back(vtx); // commit candidate
} else {
const uint16_t hashed_idx = i_vtx->second;
const auto hashed_idx = i_vtx->second;
if (list.vtx[hashed_idx] == vtx) {
idx = hashed_idx;
@ -85,11 +85,11 @@ uint16_t ModelBuilder::AddVertex(const Vertex &vtx) {
list.vtx.push_back(vtx); // commit candidate
}
}
return uint16_t(idx);
return VtxIdxType(idx);
}
//
void ModelBuilder::AddTriangle(uint16_t a, uint16_t b, uint16_t c) {
void ModelBuilder::AddTriangle(VtxIdxType a, VtxIdxType b, VtxIdxType c) {
auto &list = lists.back();
list.idx.push_back(a);
@ -97,7 +97,7 @@ void ModelBuilder::AddTriangle(uint16_t a, uint16_t b, uint16_t c) {
list.idx.push_back(c);
}
void ModelBuilder::AddQuad(uint16_t a, uint16_t b, uint16_t c, uint16_t d) {
void ModelBuilder::AddQuad(VtxIdxType a, VtxIdxType b, VtxIdxType c, VtxIdxType d) {
auto &list = lists.back();
list.idx.push_back(a);
@ -106,7 +106,7 @@ void ModelBuilder::AddQuad(uint16_t a, uint16_t b, uint16_t c, uint16_t d) {
list.idx.push_back(d);
}
void ModelBuilder::AddPolygon(const std::vector<uint16_t> &idxs) {
void ModelBuilder::AddPolygon(const std::vector<VtxIdxType> &idxs) {
for (int i = 1; i < idxs.size() - 1; ++i)
AddTriangle(idxs[0], idxs[i], idxs[i + 1]);
}
@ -122,7 +122,7 @@ void ModelBuilder::Make(
const bgfx::VertexLayout &decl, end_list_cb on_end_list, void *userdata, ModelOptimisationLevel optimisation_level, bool verbose) const {
ProfilerPerfSection section("ModelBuilder::Make");
const uint16_t stride = decl.getStride();
const auto stride = decl.getStride();
Model model;
model.lists.reserve(lists.size());
@ -226,10 +226,11 @@ Model ModelBuilder::MakeModel(const bgfx::VertexLayout &decl, ModelOptimisationL
Make(
decl,
[](const bgfx::VertexLayout &decl, const MinMax &minmax, const std::vector<uint32_t> &idx_data, const std::vector<uint8_t> &vtx_data,
[](const bgfx::VertexLayout &decl, const MinMax &minmax, const std::vector<VtxIdxType> &idx_data, const std::vector<uint8_t> &vtx_data,
const std::vector<uint16_t> &bones_table, uint16_t mat, void *userdata) {
Model &model = *reinterpret_cast<Model *>(userdata);
// TODO [EJ] this is always 32 bit and very wasteful
const auto idx_hnd = bgfx::createIndexBuffer(bgfx::copy(idx_data.data(), uint32_t(idx_data.size() * sizeof(uint32_t))), BGFX_BUFFER_INDEX32);
const auto vtx_hnd = bgfx::createVertexBuffer(bgfx::copy(vtx_data.data(), uint32_t(vtx_data.size())), decl);

View File

@ -12,6 +12,8 @@
namespace hg {
using VtxIdxType = uint32_t;
enum ModelOptimisationLevel {
MOL_None, // fastest
MOL_Minimal, // improve index cache hit
@ -21,11 +23,11 @@ enum ModelOptimisationLevel {
struct ModelBuilder {
ModelBuilder();
uint16_t AddVertex(const Vertex &v);
VtxIdxType AddVertex(const Vertex &v);
void AddTriangle(uint16_t a, uint16_t b, uint16_t c);
void AddQuad(uint16_t a, uint16_t b, uint16_t c, uint16_t d);
void AddPolygon(const std::vector<uint16_t> &idxs);
void AddTriangle(VtxIdxType a, VtxIdxType b, VtxIdxType c);
void AddQuad(VtxIdxType a, VtxIdxType b, VtxIdxType c, VtxIdxType d);
void AddPolygon(const std::vector<VtxIdxType> &idxs);
void AddBoneIdx(uint16_t AddBoneIdx);
size_t GetCurrentListIndexCount() const;
@ -35,7 +37,7 @@ struct ModelBuilder {
void Clear();
using end_list_cb = void (*)(const bgfx::VertexLayout &decl, const MinMax &minmax, const std::vector<uint32_t> &idx_data,
using end_list_cb = void (*)(const bgfx::VertexLayout &decl, const MinMax &minmax, const std::vector<VtxIdxType> &idx_data,
const std::vector<uint8_t> &vtx_data, const std::vector<uint16_t> &bones_table, uint16_t mat, void *userdata);
void Make(const bgfx::VertexLayout &decl, end_list_cb on_end_list, void *userdata, ModelOptimisationLevel optimisation_level = MOL_None,
@ -44,14 +46,14 @@ struct ModelBuilder {
Model MakeModel(const bgfx::VertexLayout &decl, ModelOptimisationLevel optimisation_level = MOL_None, bool verbose = false) const;
private:
uint32_t hash_collision{};
size_t hash_collision{};
struct List {
std::vector<uint32_t> idx;
std::vector<VtxIdxType> idx;
std::vector<Vertex> vtx;
std::vector<uint16_t> bones_table;
std::map<uint64_t, uint16_t> vtx_lookup;
std::map<uint64_t, VtxIdxType> vtx_lookup;
uint16_t mat;
MinMax minmax{Vec3::Max, Vec3::Min};

View File

@ -251,6 +251,16 @@ void Node::RemoveScript(size_t slot_idx) {
scene_ref->scene->RemoveNodeScript(ref, slot_idx);
}
//
Mat4 Node::GetWorld() const { return scene_ref && scene_ref->scene ? scene_ref->scene->GetNodeWorldMatrix(ref) : Mat4::Identity; }
void Node::SetWorld(const Mat4 &world) {
if (scene_ref && scene_ref->scene)
scene_ref->scene->SetNodeWorldMatrix(ref, world);
}
Mat4 Node::ComputeWorld() const { return scene_ref && scene_ref->scene ? scene_ref->scene->ComputeNodeWorldMatrix(ref) : Mat4::Identity; }
//
bool GetNodesMinMax(const std::vector<Node> &nodes, const PipelineResources &resources, MinMax &minmax) {
if (nodes.empty())

View File

@ -361,6 +361,20 @@ struct Node { // 16B on 64 bit
void RemoveScript(size_t slot_idx);
void RemoveScript(const Script &c) { RemoveScript(c.ref); }
/// Get world matrix from the scene graph
Mat4 GetWorld() const;
/*!
@short Set node world matrix.
Set a node world matrix and flag it as updated so that it won't be computed by the next call to ComputeWorldMatrices().
@note This function INTENTIONALLY does not decompose the provided matrix to the transfrom position/rotation/scale fields.
*/
void SetWorld(const Mat4 &world);
/*!
@short Compute node world matrix from scratch on-the-fly.
This function is slow but useful when scene matrices are not yet up-to-date.
*/
Mat4 ComputeWorld() const;
//
intrusive_shared_ptr_st<SceneRef> scene_ref;
NodeRef ref;

View File

@ -1,5 +1,8 @@
// HARFANG(R) Copyright (C) 2021 Emmanuel Julien, NWNC HARFANG. Released under GPL/LGPL/Commercial Licence, see licence.txt for details.
#include <cstring>
#include <vector>
#include "ogg_audio_stream.h"
#include "foundation/cext.h"
@ -13,9 +16,6 @@
#include <stb_vorbis/stb_vorbis.c>
#include <cstring>
#include <vector>
namespace hg {
struct OGGStream {
@ -24,7 +24,7 @@ struct OGGStream {
Handle handle;
AudioFrameFormat fmt{AFF_Unsupported};
stb_vorbis *vorbis{NULL};
AudioStreamRef *ref{NULL};
@ -53,7 +53,7 @@ static void ogg_io_close(void *user) {
stream.provider->close(stream.handle);
}
static int ogg_io_read(void* user, char* data, int size) {
static int ogg_io_read(void *user, char *data, int size) {
AudioStreamRef *ref = reinterpret_cast<AudioStreamRef *>(user);
if (!(ref && IsValid(*ref))) {
return 0;
@ -83,7 +83,7 @@ static int ogg_io_seek(void *user, int offset, enum STBVorbisIOSeekMode mode) {
return stream.reader->seek(stream.handle, offset, whence) ? 0 : 1;
}
static int ogg_io_tell(void* user) {
static int ogg_io_tell(void *user) {
AudioStreamRef *ref = reinterpret_cast<AudioStreamRef *>(user);
if (!(ref && IsValid(*ref))) {
return 0;
@ -92,7 +92,7 @@ static int ogg_io_tell(void* user) {
return stream.reader->tell(stream.handle);
}
static int ogg_io_eof(void* user) {
static int ogg_io_eof(void *user) {
AudioStreamRef *ref = reinterpret_cast<AudioStreamRef *>(user);
if (!(ref && IsValid(*ref))) {
return 1;
@ -104,7 +104,7 @@ static int ogg_io_eof(void* user) {
static int OGGAudioStreamStartup() { return 1; }
static void OGGAudioStreamShutdown() {
for (auto &stream: g_streams) {
for (auto &stream : g_streams) {
stb_vorbis_close(stream.vorbis);
if (stream.ref) {
delete stream.ref;
@ -120,13 +120,7 @@ static bool OpenOGG(OGGStream &stream) {
if (!reader.is_valid(handle))
return false;
stbv_io_callbacks callbacks = {
ogg_io_close,
ogg_io_read,
ogg_io_seek,
ogg_io_tell,
ogg_io_eof
};
stbv_io_callbacks callbacks = {ogg_io_close, ogg_io_read, ogg_io_seek, ogg_io_tell, ogg_io_eof};
int error = VORBIS__no_error;
stream.vorbis = stb_vorbis_open_from_callbacks(&callbacks, stream.ref, &error, NULL);
@ -237,7 +231,7 @@ static int OGGAudioStreamGetFrame(AudioStreamRef ref, uintptr_t *data, int *size
auto &stream = g_streams[ref];
stb_vorbis_info info = stb_vorbis_get_info(stream.vorbis);
int n = stb_vorbis_get_frame_short_interleaved(stream.vorbis, info.channels, (short*)&stream.buffer[0], stream.buffer.size());
int n = stb_vorbis_get_frame_short_interleaved(stream.vorbis, info.channels, (short *)&stream.buffer[0], stream.buffer.size());
int error = stb_vorbis_get_error(stream.vorbis);
if (n == 0) {
return 0;

View File

@ -219,6 +219,11 @@ void OpenVRShutdown() {
vr_system = nullptr;
}
//
iVec2 OpenVRGetFrameBufferSize() {
return iVec2(rt_width, rt_height);
}
//
OpenVRState OpenVRGetState(const Mat4 &body, float znear, float zfar) {
vr::TrackedDevicePose_t m_rTrackedDevicePose[vr::k_unMaxTrackedDeviceCount];
@ -344,6 +349,8 @@ void OpenVRShutdown() {}
OpenVREyeFrameBuffer OpenVRCreateEyeFrameBuffer(OpenVRAA aa) { return {}; }
void OpenVRDestroyEyeFrameBuffer(OpenVREyeFrameBuffer &) {}
iVec2 OpenVRGetFrameBufferSize() { return iVec2::Zero; }
OpenVRState OpenVRGetState(const Mat4 &, float, float) { return {}; }
void OpenVRStateToViewState(const OpenVRState &, ViewState &, ViewState &) {}

View File

@ -2,6 +2,7 @@
#pragma once
#include "foundation/vector2.h"
#include "foundation/matrix4.h"
#include "foundation/matrix44.h"
@ -29,6 +30,7 @@ struct OpenVREyeFrameBuffer {
uintptr_t native{0};
};
iVec2 OpenVRGetFrameBufferSize();
OpenVREyeFrameBuffer OpenVRCreateEyeFrameBuffer(OpenVRAA aa = OVRAA_None);
void OpenVRDestroyEyeFrameBuffer(OpenVREyeFrameBuffer &eye_fb);

View File

@ -10,6 +10,9 @@
#include "engine/stb_image.h"
#include "engine/stb_image_write.h"
#include "bimg/encode.h"
#include "bx/allocator.h"
#include <bx/file.h>
namespace hg {
@ -241,6 +244,64 @@ bool SaveBMP(const Picture &pic, const char *path) {
return stbi_write_bmp_to_func(STB_write, &file, pic.GetWidth(), pic.GetHeight(), size_of(pic.GetFormat()), pic.GetData()) != 0;
}
class AlignedAllocator : public bx::AllocatorI {
public:
AlignedAllocator(bx::AllocatorI *_allocator, size_t _minAlignment) : m_allocator(_allocator), m_minAlignment(_minAlignment) {}
virtual void *realloc(void *_ptr, size_t _size, size_t _align, const char *_file, uint32_t _line) {
return m_allocator->realloc(_ptr, _size, bx::max(_align, m_minAlignment), _file, _line);
}
bx::AllocatorI *m_allocator;
size_t m_minAlignment;
};
static bool SaveBimg(const Picture& pic, const char* path, bool fast, bimg::TextureFormat::Enum format) {
if (!pic.GetHeight() || !pic.GetWidth())
return false;
bx::DefaultAllocator defaultAllocator;
AlignedAllocator allocator(&defaultAllocator, 16);
auto input_format = bimg::TextureFormat::RGBA8;
switch (pic.GetFormat()) {
case PF_RGB24:
input_format = bimg::TextureFormat::RGB8;
break;
case PF_RGBA32:
input_format = bimg::TextureFormat::RGBA8;
break;
case PF_RGBA32F:
input_format = bimg::TextureFormat::RGBA32F;
break;
default:
assert(false);
return false;
}
uint16_t depth = 1; // not sure what it is
auto input = bimg::imageAlloc(
&allocator, input_format, pic.GetWidth(), pic.GetHeight(), depth, 1 /*_numLayers*/, false /*_cubeMap*/, false /*_hasMips*/, pic.GetData());
auto output = bimg::imageEncode(&allocator, format, fast ? bimg::Quality::Fastest : bimg::Quality::Highest, *input);
bimg::imageFree(input);
bx::FileWriter writer;
bx::Error err;
if (bx::open(&writer, path, false, &err)) {
bimg::imageWriteDds(&writer, *output, output->m_data, output->m_size, &err);
}
bimg::imageFree(output);
return true;
}
bool SaveBC6H(const Picture &pic, const char *path, bool fast) { return SaveBimg(pic, path, fast, bimg::TextureFormat::BC6H); }
bool SaveBC7(const Picture& pic, const char* path, bool fast) { return SaveBimg(pic, path, fast, bimg::TextureFormat::BC7); }
bool SaveTGA(const Picture &pic, const char *path) {
ProfilerPerfSection section("SaveTGA", path);

View File

@ -75,5 +75,7 @@ bool LoadPicture(Picture &pic, const char *path);
bool SavePNG(const Picture &pic, const char *path);
bool SaveTGA(const Picture &pic, const char *path);
bool SaveBMP(const Picture &pic, const char *path);
bool SaveBC6H(const Picture &pic, const char *path, bool fast);
bool SaveBC7(const Picture &pic, const char *path, bool fast);
} // namespace hg

View File

@ -567,39 +567,44 @@ static std::map<bgfx::ProgramHandle, std::vector<bgfx::ShaderHandle>, ProgramCom
std::vector<bgfx::ShaderHandle> GetProgramShaders(bgfx::ProgramHandle prg_h) { return program_shaders[prg_h]; }
//
bgfx::ProgramHandle LoadProgram(const Reader &ir, const ReadProvider &ip, const char *vs_name, const char *fs_name) {
bgfx::ProgramHandle LoadProgram(const Reader &ir, const ReadProvider &ip, const char *vs_name, const char *fs_name, bool silent) {
ProfilerPerfSection section("LoadProgram", vs_name);
ScopedReadHandle vs_h(ip, vs_name), fs_h(ip, fs_name);
ScopedReadHandle vs_h(ip, vs_name, silent), fs_h(ip, fs_name, silent);
if (!ir.is_valid(vs_h)) {
error(format("Vertex shader '%1' not found").arg(vs_name));
if (!silent)
error(format("Vertex shader '%1' not found").arg(vs_name));
return BGFX_INVALID_HANDLE;
}
if (!ir.is_valid(fs_h)) {
error(format("Fragment shader '%1' not found").arg(fs_name));
if (!silent)
error(format("Fragment shader '%1' not found").arg(fs_name));
return BGFX_INVALID_HANDLE;
}
const auto vs = LoadShader(ir, vs_h, vs_name);
if (!bgfx::isValid(vs)) {
error(format("Failed to load vertex shader '%1'").arg(vs_name));
if (!silent)
error(format("Failed to load vertex shader '%1'").arg(vs_name));
return BGFX_INVALID_HANDLE;
}
const auto fs = LoadShader(ir, fs_h, fs_name);
if (!bgfx::isValid(fs)) {
error(format("Failed to load fragment shader '%1'").arg(vs_name));
if (!silent)
error(format("Failed to load fragment shader '%1'").arg(vs_name));
return BGFX_INVALID_HANDLE;
}
const auto prg_h = bgfx::createProgram(vs, fs, true);
if (!bgfx::isValid(prg_h)) {
error(format("Failed to create program from shader '%1' and '%2'").arg(vs_name).arg(fs_name));
if (!silent)
error(format("Failed to create program from shader '%1' and '%2'").arg(vs_name).arg(fs_name));
return BGFX_INVALID_HANDLE;
}
@ -608,32 +613,35 @@ bgfx::ProgramHandle LoadProgram(const Reader &ir, const ReadProvider &ip, const
return prg_h;
}
bgfx::ProgramHandle LoadProgram(const Reader &ir, const ReadProvider &ip, const char *name) {
bgfx::ProgramHandle LoadProgram(const Reader &ir, const ReadProvider &ip, const char *name, bool silent) {
const std::string _name(name);
return LoadProgram(ir, ip, (_name + ".vsb").c_str(), (_name + ".fsb").c_str());
return LoadProgram(ir, ip, (_name + ".vsb").c_str(), (_name + ".fsb").c_str(), silent);
}
bgfx::ProgramHandle LoadComputeProgram(const Reader &ir, const ReadProvider &ip, const char *cs_name) {
bgfx::ProgramHandle LoadComputeProgram(const Reader &ir, const ReadProvider &ip, const char *cs_name, bool silent) {
ProfilerPerfSection section("LoadComputeProgram", cs_name);
ScopedReadHandle cs_h(ip, cs_name);
if (!ir.is_valid(cs_h)) {
error(format("Compute shader '%1' not found").arg(cs_name));
if (!silent)
error(format("Compute shader '%1' not found").arg(cs_name));
return BGFX_INVALID_HANDLE;
}
const auto cs = LoadShader(ir, cs_h, nullptr);
if (!bgfx::isValid(cs)) {
error(format("Failed to load compute shader '%1'").arg(cs_name));
if (!silent)
error(format("Failed to load compute shader '%1'").arg(cs_name));
return BGFX_INVALID_HANDLE;
}
const auto prg_h = bgfx::createProgram(cs, BGFX_INVALID_HANDLE, true);
if (!bgfx::isValid(prg_h)) {
error(format("Failed to create program from shader '%1'").arg(cs_name));
if (!silent)
error(format("Failed to create program from shader '%1'").arg(cs_name));
return BGFX_INVALID_HANDLE;
}
@ -643,37 +651,30 @@ bgfx::ProgramHandle LoadComputeProgram(const Reader &ir, const ReadProvider &ip,
}
//
bgfx::ProgramHandle LoadProgramFromFile(const char *vs, const char *fs) { return LoadProgram(g_file_reader, g_file_read_provider, vs, fs); }
bgfx::ProgramHandle LoadProgramFromAssets(const char *vs, const char *fs) { return LoadProgram(g_assets_reader, g_assets_read_provider, vs, fs); }
bgfx::ProgramHandle LoadProgramFromFile(const char *vs, const char *fs, bool silent) {
return LoadProgram(g_file_reader, g_file_read_provider, vs, fs, silent);
}
bgfx::ProgramHandle LoadProgramFromAssets(const char *vs, const char *fs, bool silent) {
return LoadProgram(g_assets_reader, g_assets_read_provider, vs, fs, silent);
}
bgfx::ProgramHandle LoadProgramFromFile(const char *path) { return LoadProgram(g_file_reader, g_file_read_provider, path); }
bgfx::ProgramHandle LoadProgramFromAssets(const char *name) { return LoadProgram(g_assets_reader, g_assets_read_provider, name); }
bgfx::ProgramHandle LoadProgramFromFile(const char *path, bool silent) { return LoadProgram(g_file_reader, g_file_read_provider, path, silent); }
bgfx::ProgramHandle LoadProgramFromAssets(const char *name, bool silent) { return LoadProgram(g_assets_reader, g_assets_read_provider, name, silent); }
bgfx::ProgramHandle LoadComputeProgramFromFile(const char *cs_path) { return LoadComputeProgram(g_file_reader, g_file_read_provider, cs_path); }
bgfx::ProgramHandle LoadComputeProgramFromAssets(const char *cs_name) { return LoadComputeProgram(g_assets_reader, g_assets_read_provider, cs_name); }
bgfx::ProgramHandle LoadComputeProgramFromFile(const char *cs_path, bool silent) {
return LoadComputeProgram(g_file_reader, g_file_read_provider, cs_path, silent);
}
bgfx::ProgramHandle LoadComputeProgramFromAssets(const char *cs_name, bool silent) {
return LoadComputeProgram(g_assets_reader, g_assets_read_provider, cs_name, silent);
}
//
std::vector<PipelineProgramFeature> LoadPipelineProgramFeatures(const Reader &ir, const ReadProvider &ip, const char *name, bool &success) {
std::vector<PipelineProgramFeature> LoadPipelineProgramFeatures(const Reader &ir, const ReadProvider &ip, const char *name, bool &success, bool silent) {
ProfilerPerfSection section("LoadPipelineProgramFeatures", name);
success = false;
const auto json_text = LoadString(ir, ScopedReadHandle(ip, name));
if (json_text.empty()) {
if (!ends_with(name, ".hps"))
warn(format("Request to load pipeline program features from a path not ending with '.hps' ('%1')").arg(name));
const auto js = LoadJson(ir, ScopedReadHandle(ip, name, true), &success);
if (!success)
return {};
}
json js;
try {
js = json::parse(json_text);
} catch (...) {
debug(format("Failed to parse json '%1'").arg(name));
return {};
}
std::vector<PipelineProgramFeature> features;
@ -720,7 +721,7 @@ std::vector<PipelineProgramFeature> LoadPipelineProgramFeatures(const Reader &ir
features.push_back(OptionalSkinning);
else if (feat == "OptionalAlphaCut")
features.push_back(OptionalAlphaCut);
else
else if (!silent)
warn(format("Ignoring unknown pipeline shader feature '%1' in '%2'").arg(feat).arg(name));
}
}
@ -730,31 +731,30 @@ std::vector<PipelineProgramFeature> LoadPipelineProgramFeatures(const Reader &ir
return features;
}
std::vector<PipelineProgramFeature> LoadPipelineProgramFeaturesFromFile(const char *path, bool &success) {
std::vector<PipelineProgramFeature> LoadPipelineProgramFeaturesFromFile(const char *path, bool &success, bool silent) {
try {
return LoadPipelineProgramFeatures(g_file_reader, g_file_read_provider, path, success);
return LoadPipelineProgramFeatures(g_file_reader, g_file_read_provider, path, success, silent);
} catch (...) { debug(format("Failed to read program features from file '%1'").arg(path)); }
return {};
}
std::vector<PipelineProgramFeature> LoadPipelineProgramFeaturesFromAssets(const char *name, bool &success) {
std::vector<PipelineProgramFeature> LoadPipelineProgramFeaturesFromAssets(const char *name, bool &success, bool silent) {
try {
return LoadPipelineProgramFeatures(g_assets_reader, g_assets_read_provider, name, success);
return LoadPipelineProgramFeatures(g_assets_reader, g_assets_read_provider, name, success, silent);
} catch (...) { debug(format("Failed to read program features from asset '%1'").arg(name)); }
return {};
}
//
bool LoadPipelineProgramUniforms(const Reader &ir, const ReadProvider &ip, const char *name, std::vector<TextureUniform> &texs, std::vector<Vec4Uniform> &vecs,
PipelineResources &resources) {
PipelineResources &resources, bool silent) {
ProfilerPerfSection section("LoadPipelineProgramUniforms", name);
const auto json_text = LoadString(ir, ScopedReadHandle(ip, name, true));
if (json_text.empty())
bool result;
const auto js = LoadJson(ir, ScopedReadHandle(ip, name, true), &result);
if (!result)
return false;
const auto js = json::parse(json_text);
const auto i = js.find("uniforms");
if (i == std::end(js))
return true; // [EJ] if there's no uniforms declared look no further
@ -793,7 +793,7 @@ bool LoadPipelineProgramUniforms(const Reader &ir, const ReadProvider &ip, const
if (v->is_string()) {
const auto path = v->get<std::string>();
const auto flags = LoadTextureFlags(ir, ip, path);
u.tex_ref = LoadTexture(ir, ip, path.c_str(), flags, resources);
u.tex_ref = LoadTexture(ir, ip, path.c_str(), flags, resources, silent);
}
texs.push_back(u);
@ -806,27 +806,30 @@ bool LoadPipelineProgramUniforms(const Reader &ir, const ReadProvider &ip, const
return true;
}
bool LoadPipelineProgramUniformsFromFile(const char *path, std::vector<TextureUniform> &texs, std::vector<Vec4Uniform> &vecs, PipelineResources &resources) {
return LoadPipelineProgramUniforms(g_file_reader, g_file_read_provider, path, texs, vecs, resources);
bool LoadPipelineProgramUniformsFromFile(
const char *path, std::vector<TextureUniform> &texs, std::vector<Vec4Uniform> &vecs, PipelineResources &resources, bool silent) {
return LoadPipelineProgramUniforms(g_file_reader, g_file_read_provider, path, texs, vecs, resources, silent);
}
bool LoadPipelineProgramUniformsFromAssets(const char *name, std::vector<TextureUniform> &texs, std::vector<Vec4Uniform> &vecs, PipelineResources &resources) {
return LoadPipelineProgramUniforms(g_assets_reader, g_assets_read_provider, name, texs, vecs, resources);
bool LoadPipelineProgramUniformsFromAssets(
const char *name, std::vector<TextureUniform> &texs, std::vector<Vec4Uniform> &vecs, PipelineResources &resources, bool silent) {
return LoadPipelineProgramUniforms(g_assets_reader, g_assets_read_provider, name, texs, vecs, resources, silent);
}
//
PipelineProgram LoadPipelineProgram(const Reader &ir, const ReadProvider &ip, const char *name, PipelineResources &resources, const PipelineInfo &pipeline) {
PipelineProgram LoadPipelineProgram(
const Reader &ir, const ReadProvider &ip, const char *name, PipelineResources &resources, const PipelineInfo &pipeline, bool silent) {
PipelineProgram prg;
bool success;
prg.features = LoadPipelineProgramFeatures(ir, ip, name, success);
prg.features = LoadPipelineProgramFeatures(ir, ip, name, success, silent);
if (!success)
error(format("Failed to load pipeline program features '%1'").arg(name));
else
prg.programs.resize(GetPipelineProgramVariantCount(prg.features) * pipeline.configs.size());
if (!LoadPipelineProgramUniforms(ir, ip, name, prg.texture_uniforms, prg.vec4_uniforms, resources))
if (!LoadPipelineProgramUniforms(ir, ip, name, prg.texture_uniforms, prg.vec4_uniforms, resources, silent))
error(format("Failed to load pipeline program uniforms '%1'").arg(name));
prg.name = CutFileExtension(name);
@ -837,12 +840,12 @@ PipelineProgram LoadPipelineProgram(const Reader &ir, const ReadProvider &ip, co
return prg;
}
PipelineProgram LoadPipelineProgramFromFile(const char *path, PipelineResources &resources, const PipelineInfo &pipeline) {
return LoadPipelineProgram(g_file_reader, g_file_read_provider, path, resources, pipeline);
PipelineProgram LoadPipelineProgramFromFile(const char *path, PipelineResources &resources, const PipelineInfo &pipeline, bool silent) {
return LoadPipelineProgram(g_file_reader, g_file_read_provider, path, resources, pipeline, silent);
}
PipelineProgram LoadPipelineProgramFromAssets(const char *name, PipelineResources &resources, const PipelineInfo &pipeline) {
return LoadPipelineProgram(g_assets_reader, g_assets_read_provider, name, resources, pipeline);
PipelineProgram LoadPipelineProgramFromAssets(const char *name, PipelineResources &resources, const PipelineInfo &pipeline, bool silent) {
return LoadPipelineProgram(g_assets_reader, g_assets_read_provider, name, resources, pipeline, silent);
}
//
@ -939,7 +942,7 @@ static void CreateMissingMaterialSampler(
TextureRef ref{};
if (!tex.empty()) {
debug(format("Loading missing material sampler uniform texture %1").arg(tex));
ref = LoadTexture(ir, ip, tex.c_str(), 0, resources);
ref = LoadTexture(ir, ip, tex.c_str(), 0, resources, true);
}
SetMaterialTexture(mat, name.c_str(), ref, stage);
@ -1018,21 +1021,21 @@ void UpdateMaterialPipelineProgramVariant(Material &mat, const PipelineResources
static bx::DefaultAllocator g_allocator;
//
json LoadResourceMeta(const Reader &ir, const ReadProvider &ip, const std::string &name) {
json LoadResourceMeta(const Reader &ir, const ReadProvider &ip, const std::string &name, bool silent) {
const auto meta_path = name + ".meta";
return LoadJson(ir, ScopedReadHandle(ip, meta_path.c_str(), true));
return LoadJson(ir, ScopedReadHandle(ip, meta_path.c_str(), silent));
}
json LoadResourceMetaFromFile(const std::string &path) { return LoadResourceMeta(g_file_reader, g_file_read_provider, path); }
json LoadResourceMetaFromAssets(const std::string &name) { return LoadResourceMeta(g_assets_reader, g_assets_read_provider, name); }
json LoadResourceMetaFromFile(const std::string &path, bool silent) { return LoadResourceMeta(g_file_reader, g_file_read_provider, path, silent); }
json LoadResourceMetaFromAssets(const std::string &name, bool silent) { return LoadResourceMeta(g_assets_reader, g_assets_read_provider, name, silent); }
bool SaveResourceMetaToFile(const std::string &path, const json &meta) { return SaveJsonToFile(meta, (path + ".meta").c_str()); }
//
TextureMeta LoadTextureMeta(const Reader &ir, const ReadProvider &ip, const std::string &name) {
TextureMeta LoadTextureMeta(const Reader &ir, const ReadProvider &ip, const std::string &name, bool silent) {
ProfilerPerfSection section("LoadTextureMeta", name);
const auto js = LoadResourceMeta(ir, ip, name);
const auto js = LoadResourceMeta(ir, ip, name, silent);
TextureMeta meta;
@ -1089,14 +1092,16 @@ TextureMeta LoadTextureMeta(const Reader &ir, const ReadProvider &ip, const std:
return meta;
}
TextureMeta LoadTextureMetaFromFile(const std::string &path) { return LoadTextureMeta(g_file_reader, g_file_read_provider, path); }
TextureMeta LoadTextureMetaFromAssets(const std::string &name) { return LoadTextureMeta(g_assets_reader, g_assets_read_provider, name); }
TextureMeta LoadTextureMetaFromFile(const std::string &path, bool silent) { return LoadTextureMeta(g_file_reader, g_file_read_provider, path, silent); }
TextureMeta LoadTextureMetaFromAssets(const std::string &name, bool silent) { return LoadTextureMeta(g_assets_reader, g_assets_read_provider, name, silent); }
//
uint64_t LoadTextureFlags(const Reader &ir, const ReadProvider &ip, const std::string &name) { return LoadTextureMeta(ir, ip, name).flags; }
uint64_t LoadTextureFlags(const Reader &ir, const ReadProvider &ip, const std::string &name, bool silent) {
return LoadTextureMeta(ir, ip, name, silent).flags;
}
uint64_t LoadTextureFlagsFromFile(const std::string &path) { return LoadTextureFlags(g_file_reader, g_file_read_provider, path); }
uint64_t LoadTextureFlagsFromAssets(const std::string &name) { return LoadTextureFlags(g_assets_reader, g_assets_read_provider, name); }
uint64_t LoadTextureFlagsFromFile(const std::string &path, bool silent) { return LoadTextureFlags(g_file_reader, g_file_read_provider, path, silent); }
uint64_t LoadTextureFlagsFromAssets(const std::string &name, bool silent) { return LoadTextureFlags(g_assets_reader, g_assets_read_provider, name, silent); }
//
Texture CreateTexture(int width, int height, const char *name, uint64_t flags, bgfx::TextureFormat::Enum texture_format) {
@ -1144,17 +1149,19 @@ void UpdateTextureFromPicture(Texture &tex, const Picture &pic) {
}
//
Texture LoadTexture(const Reader &ir, const ReadProvider &ip, const char *name, uint64_t flags, bgfx::TextureInfo *info, bimg::Orientation::Enum *orientation) {
Texture LoadTexture(
const Reader &ir, const ReadProvider &ip, const char *name, uint64_t flags, bgfx::TextureInfo *info, bimg::Orientation::Enum *orientation, bool silent) {
ProfilerPerfSection section("LoadTexture", name);
log(format("Loading texture '%1'").arg(name).c_str());
if (!silent)
log(format("Loading texture '%1'").arg(name).c_str());
bgfx::TextureHandle handle = BGFX_INVALID_HANDLE;
const auto data = LoadData(ir, ScopedReadHandle(ip, name));
const auto data = LoadData(ir, ScopedReadHandle(ip, name, silent));
if (data.GetSize() > 0) {
if (auto container = bimg::imageParse(&g_allocator, data.GetData(), uint32_t(data.GetSize()), bimg::TextureFormat::Count)) {
if (auto container = bimg::imageParse(&g_allocator, data.GetData(), numeric_cast<uint32_t>(data.GetSize()), bimg::TextureFormat::Count)) {
const auto *mem = bgfx::makeRef(
container->m_data, container->m_size, [](void *ptr, void *user) { BX_ALIGNED_FREE(&g_allocator, user, 16); }, container);
@ -1175,7 +1182,8 @@ Texture LoadTexture(const Reader &ir, const ReadProvider &ip, const char *name,
}
if (!bgfx::isValid(handle)) {
error(format("Failed to load texture '%1', unsupported format").arg(name).c_str());
if (!silent)
error(format("Failed to load texture '%1', unsupported format").arg(name).c_str());
static const uint32_t dummy = 0xff00ffff;
handle = bgfx::createTexture2D(1, 1, false, 1, bgfx::TextureFormat::RGBA8, BGFX_SAMPLER_NONE, bgfx::copy(&dummy, 4));
@ -1184,18 +1192,19 @@ Texture LoadTexture(const Reader &ir, const ReadProvider &ip, const char *name,
if (bgfx::isValid(handle))
bgfx::setName(handle, name);
} else {
error(format("Failed to load texture '%1', could not load data").arg(name).c_str());
if (!silent)
error(format("Failed to load texture '%1', could not load data").arg(name).c_str());
}
return MakeTexture(handle, flags);
}
Texture LoadTextureFromFile(const char *name, uint64_t flags, bgfx::TextureInfo *info, bimg::Orientation::Enum *orientation) {
return LoadTexture(g_file_reader, g_file_read_provider, name, flags, info, orientation);
Texture LoadTextureFromFile(const char *name, uint64_t flags, bgfx::TextureInfo *info, bimg::Orientation::Enum *orientation, bool silent) {
return LoadTexture(g_file_reader, g_file_read_provider, name, flags, info, orientation, silent);
}
Texture LoadTextureFromAssets(const char *name, uint64_t flags, bgfx::TextureInfo *info, bimg::Orientation::Enum *orientation) {
return LoadTexture(g_assets_reader, g_assets_read_provider, name, flags, info, orientation);
Texture LoadTextureFromAssets(const char *name, uint64_t flags, bgfx::TextureInfo *info, bimg::Orientation::Enum *orientation, bool silent) {
return LoadTexture(g_assets_reader, g_assets_read_provider, name, flags, info, orientation, silent);
}
RenderBufferResourceFactory RenderBufferResourceFactory::Custom(uint16_t width, uint16_t height) {
@ -1346,26 +1355,26 @@ template <typename T> T GetOptional(const json &js, const char *key, T dflt) {
}
TextureRef SkipLoadOrQueueTextureLoad(
const Reader &ir, const ReadProvider &ip, const char *path, PipelineResources &resources, bool queue_load, bool do_not_load) {
const Reader &ir, const ReadProvider &ip, const char *path, PipelineResources &resources, bool queue_load, bool do_not_load, bool silent) {
if (do_not_load)
return resources.textures.Add(path, {});
auto ref = resources.textures.Has(path);
if (ref == InvalidTextureRef) {
const auto meta = LoadTextureMeta(ir, ip, path);
const auto meta = LoadTextureMeta(ir, ip, path, silent);
if (queue_load)
ref = QueueLoadTexture(ir, ip, path, meta.flags, resources);
else
ref = LoadTexture(ir, ip, path, meta.flags, resources);
ref = LoadTexture(ir, ip, path, meta.flags, resources, silent);
}
return ref;
}
Material LoadMaterial(const json &js, const Reader &deps_ir, const ReadProvider &deps_ip, PipelineResources &resources, const PipelineInfo &pipeline,
bool queue_texture_loads, bool do_not_load_resources) {
bool queue_texture_loads, bool do_not_load_resources, bool silent) {
Material mat;
const std::string prg_name = js.at("program");
@ -1373,7 +1382,7 @@ Material LoadMaterial(const json &js, const Reader &deps_ir, const ReadProvider
if (do_not_load_resources)
mat.program = resources.programs.Add(prg_name.c_str(), {});
else
mat.program = LoadPipelineProgramRef(deps_ir, deps_ip, prg_name.c_str(), resources, pipeline);
mat.program = LoadPipelineProgramRef(deps_ir, deps_ip, prg_name.c_str(), resources, pipeline, silent);
const auto i_values = js.find("values");
@ -1417,7 +1426,7 @@ Material LoadMaterial(const json &js, const Reader &deps_ir, const ReadProvider
}
if (!path.empty())
t.texture = SkipLoadOrQueueTextureLoad(deps_ir, deps_ip, path.c_str(), resources, queue_texture_loads, do_not_load_resources);
t.texture = SkipLoadOrQueueTextureLoad(deps_ir, deps_ip, path.c_str(), resources, queue_texture_loads, do_not_load_resources, silent);
t.uniform = BGFX_INVALID_HANDLE;
if (IsRenderUp())
@ -1457,7 +1466,7 @@ Material LoadMaterial(const json &js, const Reader &deps_ir, const ReadProvider
}
Material LoadMaterial(const Reader &ir, const Handle &h, const Reader &deps_ir, const ReadProvider &deps_ip, PipelineResources &resources,
const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources) {
const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources, bool silent) {
ProfilerPerfSection section("LoadMaterial");
Material mat;
@ -1468,7 +1477,7 @@ Material LoadMaterial(const Reader &ir, const Handle &h, const Reader &deps_ir,
if (do_not_load_resources)
mat.program = resources.programs.Add(name.c_str(), {});
else
mat.program = LoadPipelineProgramRef(deps_ir, deps_ip, name.c_str(), resources, pipeline);
mat.program = LoadPipelineProgramRef(deps_ir, deps_ip, name.c_str(), resources, pipeline, silent);
const auto value_count = Read<uint16_t>(ir, h);
@ -1508,7 +1517,7 @@ Material LoadMaterial(const Reader &ir, const Handle &h, const Reader &deps_ir,
Read(ir, h, dummy_flags);
if (!tex_name.empty())
t.texture = SkipLoadOrQueueTextureLoad(deps_ir, deps_ip, tex_name.c_str(), resources, queue_texture_loads, do_not_load_resources);
t.texture = SkipLoadOrQueueTextureLoad(deps_ir, deps_ip, tex_name.c_str(), resources, queue_texture_loads, do_not_load_resources, silent);
}
t.uniform = BGFX_INVALID_HANDLE;
@ -1526,34 +1535,34 @@ Material LoadMaterial(const Reader &ir, const Handle &h, const Reader &deps_ir,
}
Material LoadMaterialFromFile(
const char *path, PipelineResources &resources, const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources) {
const char *path, PipelineResources &resources, const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources, bool silent) {
return LoadMaterial(g_file_reader, ScopedReadHandle(g_file_read_provider, path), g_file_reader, g_file_read_provider, resources, pipeline,
queue_texture_loads, do_not_load_resources);
queue_texture_loads, do_not_load_resources, silent);
}
Material LoadMaterialFromAssets(
const char *path, PipelineResources &resources, const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources) {
const char *path, PipelineResources &resources, const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources, bool silent) {
return LoadMaterial(g_assets_reader, ScopedReadHandle(g_assets_read_provider, path), g_assets_reader, g_assets_read_provider, resources, pipeline,
queue_texture_loads, do_not_load_resources);
queue_texture_loads, do_not_load_resources, silent);
}
//
PipelineProgramRef LoadPipelineProgramRef(
const Reader &ir, const ReadProvider &ip, const char *name, PipelineResources &resources, const PipelineInfo &pipeline) {
const Reader &ir, const ReadProvider &ip, const char *name, PipelineResources &resources, const PipelineInfo &pipeline, bool silent) {
auto ref = resources.programs.Has(name);
if (ref == InvalidPipelineProgramRef) {
auto prg = LoadPipelineProgram(ir, ip, name, resources, pipeline);
auto prg = LoadPipelineProgram(ir, ip, name, resources, pipeline, silent);
ref = resources.programs.Add(name, std::move(prg));
}
return ref;
}
PipelineProgramRef LoadPipelineProgramRefFromFile(const char *path, PipelineResources &resources, const PipelineInfo &pipeline) {
return LoadPipelineProgramRef(g_file_reader, g_file_read_provider, path, resources, pipeline);
PipelineProgramRef LoadPipelineProgramRefFromFile(const char *path, PipelineResources &resources, const PipelineInfo &pipeline, bool silent) {
return LoadPipelineProgramRef(g_file_reader, g_file_read_provider, path, resources, pipeline, silent);
}
PipelineProgramRef LoadPipelineProgramRefFromAssets(const char *name, PipelineResources &resources, const PipelineInfo &pipeline) {
return LoadPipelineProgramRef(g_assets_reader, g_assets_read_provider, name, resources, pipeline);
PipelineProgramRef LoadPipelineProgramRefFromAssets(const char *name, PipelineResources &resources, const PipelineInfo &pipeline, bool silent) {
return LoadPipelineProgramRef(g_assets_reader, g_assets_read_provider, name, resources, pipeline, silent);
}
//
@ -1603,28 +1612,35 @@ bgfx::VertexLayout VertexLayoutPosFloatNormUInt8TexCoord0UInt8() {
}
//
size_t ProcessModelLoadQueue(PipelineResources &res, size_t limit) {
size_t ProcessModelLoadQueue(PipelineResources &res, time_ns t_budget, bool silent) {
ProfilerPerfSection section("ProcessModelLoadQueue");
size_t processed = 0;
for (; limit > 0 && !res.model_loads.empty(); --limit) {
const auto t_start = time_now();
while (!res.model_loads.empty()) {
const auto &m = res.model_loads.front();
if (res.models.IsValidRef(m.ref)) {
auto &mdl = res.models.Get(m.ref);
const auto name = res.models.GetName(m.ref);
debug(format("Queued model load '%1'").arg(name));
if (!silent)
debug(format("Queued model load '%1'").arg(name));
ModelInfo info;
ScopedReadHandle h(m.ip, name.c_str(), false);
mdl = LoadModel(m.ir, h, name.c_str(), &info);
ScopedReadHandle h(m.ip, name.c_str(), silent);
mdl = LoadModel(m.ir, h, name.c_str(), &info, silent);
res.model_infos[m.ref.ref] = info;
}
res.model_loads.pop_front();
++processed;
const auto elapsed = time_now() - t_start;
if (elapsed >= t_budget)
break;
}
return processed;
@ -1646,7 +1662,8 @@ ModelRef QueueLoadModelFromAssets(const char *name, PipelineResources &resources
return QueueLoadModel(g_assets_reader, g_assets_read_provider, name, resources);
}
ModelRef SkipLoadOrQueueModelLoad(const Reader &ir, const ReadProvider &ip, const char *path, PipelineResources &resources, bool queue_load, bool do_not_load) {
ModelRef SkipLoadOrQueueModelLoad(
const Reader &ir, const ReadProvider &ip, const char *path, PipelineResources &resources, bool queue_load, bool do_not_load, bool silent) {
if (do_not_load)
return resources.models.Add(path, {});
@ -1656,37 +1673,41 @@ ModelRef SkipLoadOrQueueModelLoad(const Reader &ir, const ReadProvider &ip, cons
if (queue_load)
ref = QueueLoadModel(ir, ip, path, resources);
else
ref = LoadModel(ir, ip, path, resources);
ref = LoadModel(ir, ip, path, resources, silent);
}
return ref;
}
//
Model LoadModel(const Reader &ir, const Handle &h, const char *name, ModelInfo *info) {
Model LoadModel(const Reader &ir, const Handle &h, const char *name, ModelInfo *info, bool silent) {
ProfilerPerfSection section("LoadModel", name);
const auto t = time_now();
if (!ir.is_valid(h)) {
error(format("Cannot load model '%1', invalid file handle").arg(name));
if (!silent)
error(format("Cannot load model '%1', invalid file handle").arg(name));
return {};
}
if (Read<uint32_t>(ir, h) != HarfangMagic) {
error(format("Cannot load model '%1', invalid magic marker").arg(name));
if (!silent)
error(format("Cannot load model '%1', invalid magic marker").arg(name));
return {};
}
if (Read<uint8_t>(ir, h) != ModelMarker) {
error(format("Cannot load model '%1', invalid file marker").arg(name));
if (!silent)
error(format("Cannot load model '%1', invalid file marker").arg(name));
return {};
}
const auto version = Read<uint8_t>(ir, h);
if (version > 2) {
error(format("Cannot load model '%1', unsupported version %2").arg(name).arg(version));
if (!silent)
error(format("Cannot load model '%1', unsupported version %2").arg(name).arg(version));
return {};
}
@ -1720,14 +1741,24 @@ Model LoadModel(const Reader &ir, const Handle &h, const char *name, ModelInfo *
tri_count += (size / idx_type_size) / 3;
const auto idx_hnd = bgfx::createIndexBuffer(idx_mem, idx_type_size == 4 ? BGFX_BUFFER_INDEX32 : BGFX_BUFFER_NONE);
bgfx::setName(idx_hnd, name);
if (!bgfx::isValid(idx_hnd)) {
error(format("%1: failed to create index buffer").arg(name));
break;
}
bgfx::setName(idx_hnd, name);
// vertex buffer
size = Read<uint32_t>(ir, h);
const auto vtx_mem = bgfx::alloc(size);
ir.read(h, vtx_mem->data, vtx_mem->size);
const auto vtx_hnd = bgfx::createVertexBuffer(vtx_mem, vs_decl);
if (!bgfx::isValid(vtx_hnd)) {
error(format("%1: failed to create vertex buffer").arg(name));
bgfx::destroy(idx_hnd);
break;
}
bgfx::setName(vtx_hnd, name);
// bones table
@ -1755,18 +1786,24 @@ Model LoadModel(const Reader &ir, const Handle &h, const char *name, ModelInfo *
Read(ir, h, model.bind_pose[j]);
}
log(format("Load model '%1' (%2 triangles, %3 lists), took %4 ms")
.arg(name)
.arg(tri_count)
.arg(model.lists.size())
.arg(time_to_ms(time_now() - t))
.c_str());
if (!silent)
log(format("Load model '%1' (%2 triangles, %3 lists), took %4 ms")
.arg(name)
.arg(tri_count)
.arg(model.lists.size())
.arg(time_to_ms(time_now() - t))
.c_str());
return model;
}
Model LoadModelFromFile(const char *path, ModelInfo *info) { return LoadModel(g_file_reader, ScopedReadHandle(g_file_read_provider, path), path, info); }
Model LoadModelFromFile(const char *path, ModelInfo *info, bool silent) {
return LoadModel(g_file_reader, ScopedReadHandle(g_file_read_provider, path, silent), path, info, silent);
}
Model LoadModelFromAssets(const char *name, ModelInfo *info) { return LoadModel(g_assets_reader, ScopedReadHandle(g_assets_read_provider, name), name, info); }
Model LoadModelFromAssets(const char *name, ModelInfo *info, bool silent) {
return LoadModel(g_assets_reader, ScopedReadHandle(g_assets_read_provider, name, silent), name, info, silent);
}
//
size_t GetModelMaterialCount(const Model &model) {
@ -2164,48 +2201,54 @@ void DrawSkinnedModelDisplayLists(bgfx::ViewId view_id, const std::vector<Skinne
}
//
ModelRef LoadModel(const Reader &ir, const ReadProvider &ip, const char *path, PipelineResources &resources) {
ModelRef LoadModel(const Reader &ir, const ReadProvider &ip, const char *path, PipelineResources &resources, bool silent) {
auto ref = resources.models.Has(path);
if (ref == InvalidModelRef) {
auto mdl = LoadModel(ir, ScopedReadHandle(ip, path), path);
auto mdl = LoadModel(ir, ScopedReadHandle(ip, path), path, nullptr, silent);
ref = resources.models.Add(path, std::move(mdl));
}
return ref;
}
ModelRef LoadModelFromFile(const char *path, PipelineResources &resources) { return LoadModel(g_file_reader, g_file_read_provider, path, resources); }
ModelRef LoadModelFromFile(const char *path, PipelineResources &resources, bool silent) {
return LoadModel(g_file_reader, g_file_read_provider, path, resources, silent);
}
ModelRef LoadModelFromAssets(const char *path, PipelineResources &resources) { return LoadModel(g_assets_reader, g_assets_read_provider, path, resources); }
ModelRef LoadModelFromAssets(const char *path, PipelineResources &resources, bool silent) {
return LoadModel(g_assets_reader, g_assets_read_provider, path, resources, silent);
}
MaterialRef LoadMaterialRef(const Reader &ir, const Handle &h, const char *path, const Reader &deps_ir, const ReadProvider &deps_ip,
PipelineResources &resources, const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources) {
PipelineResources &resources, const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources, bool silent) {
auto ref = resources.materials.Has(path);
if (ref == InvalidMaterialRef) {
auto mat = LoadMaterial(ir, h, deps_ir, deps_ip, resources, pipeline, queue_texture_loads, do_not_load_resources);
auto mat = LoadMaterial(ir, h, deps_ir, deps_ip, resources, pipeline, queue_texture_loads, do_not_load_resources, silent);
ref = resources.materials.Add(path, std::move(mat));
}
return ref;
}
MaterialRef LoadMaterialRefFromFile(
const char *path, PipelineResources &resources, const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources) {
const char *path, PipelineResources &resources, const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources, bool silent) {
return LoadMaterialRef(g_file_reader, ScopedReadHandle(g_file_read_provider, path), path, g_file_reader, g_file_read_provider, resources, pipeline,
queue_texture_loads, do_not_load_resources);
queue_texture_loads, do_not_load_resources, silent);
}
MaterialRef LoadMaterialRefFromAssets(
const char *path, PipelineResources &resources, const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources) {
const char *path, PipelineResources &resources, const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources, bool silent) {
return LoadMaterialRef(g_assets_reader, ScopedReadHandle(g_assets_read_provider, path), path, g_assets_reader, g_assets_read_provider, resources, pipeline,
queue_texture_loads, do_not_load_resources);
queue_texture_loads, do_not_load_resources, silent);
}
//
size_t ProcessTextureLoadQueue(PipelineResources &res, size_t limit) {
size_t ProcessTextureLoadQueue(PipelineResources &res, time_ns t_budget, bool silent) {
ProfilerPerfSection section("ProcessTextureLoadQueue");
size_t processed = 0;
for (; limit > 0 && !res.texture_loads.empty(); --limit) {
const auto t_start = time_now();
while (!res.texture_loads.empty()) {
const auto &t = res.texture_loads.front();
if (res.textures.IsValidRef(t.ref)) {
@ -2214,13 +2257,17 @@ size_t ProcessTextureLoadQueue(PipelineResources &res, size_t limit) {
debug(format("Queued texture load '%1'").arg(name));
bgfx::TextureInfo info;
tex = LoadTexture(t.ir, t.ip, name.c_str(), tex.flags, &info);
tex = LoadTexture(t.ir, t.ip, name.c_str(), tex.flags, &info, nullptr, silent);
res.texture_infos[t.ref.ref] = info;
}
res.texture_loads.pop_front();
++processed;
const auto elapsed = time_now() - t_start;
if (elapsed >= t_budget)
break;
}
return processed;
@ -2245,23 +2292,23 @@ TextureRef QueueLoadTextureFromAssets(const char *name, uint64_t flags, Pipeline
}
//
TextureRef LoadTexture(const Reader &ir, const ReadProvider &ip, const char *name, uint64_t flags, PipelineResources &resources) {
TextureRef LoadTexture(const Reader &ir, const ReadProvider &ip, const char *name, uint64_t flags, PipelineResources &resources, bool silent) {
auto ref = resources.textures.Has(name);
if (ref == InvalidTextureRef) {
bgfx::TextureInfo info;
const auto tex = LoadTexture(ir, ip, name, flags, &info);
const auto tex = LoadTexture(ir, ip, name, flags, &info, nullptr, silent);
ref = resources.textures.Add(name, tex);
resources.texture_infos[ref.ref] = info;
}
return ref;
}
TextureRef LoadTextureFromFile(const char *path, uint64_t flags, PipelineResources &resources) {
return LoadTexture(g_file_reader, g_file_read_provider, path, flags, resources);
TextureRef LoadTextureFromFile(const char *path, uint64_t flags, PipelineResources &resources, bool silent) {
return LoadTexture(g_file_reader, g_file_read_provider, path, flags, resources, silent);
}
TextureRef LoadTextureFromAssets(const char *name, uint64_t flags, PipelineResources &resources) {
return LoadTexture(g_assets_reader, g_assets_read_provider, name, flags, resources);
TextureRef LoadTextureFromAssets(const char *name, uint64_t flags, PipelineResources &resources, bool silent) {
return LoadTexture(g_assets_reader, g_assets_read_provider, name, flags, resources, silent);
}
//
@ -2271,18 +2318,15 @@ uint32_t CaptureTexture(const PipelineResources &resources, const TextureRef &t,
}
//
size_t ProcessLoadQueues(PipelineResources &res, size_t limit) {
size_t GetQueuedResourceCount(const PipelineResources &res) { return res.model_loads.size() + res.texture_loads.size(); }
size_t ProcessLoadQueues(PipelineResources &res, time_ns t_budget, bool silent) {
ProfilerPerfSection section("ProcessLoadQueues");
size_t total = 0, processed;
size_t total = 0;
processed = ProcessModelLoadQueue(res, limit);
limit -= processed;
total += processed;
processed = ProcessTextureLoadQueue(res, limit);
limit -= processed;
total += processed;
total += ProcessModelLoadQueue(res, t_budget, silent);
total += ProcessTextureLoadQueue(res, t_budget, silent);
return total;
}

View File

@ -15,6 +15,7 @@
#include "foundation/matrix44.h"
#include "foundation/minmax.h"
#include "foundation/rw_interface.h"
#include "foundation/time.h"
#include "foundation/vector2.h"
#include <bgfx/bgfx.h>
@ -95,24 +96,24 @@ void SetViewOrthographic(bgfx::ViewId id, int x, int y, int res_x, int res_y, co
const Vec2 &aspect_ratio = {});
//
bgfx::ProgramHandle LoadProgram(const Reader &ir, const ReadProvider &ip, const char *vs_name, const char *fs_name);
bgfx::ProgramHandle LoadProgram(const Reader &ir, const ReadProvider &ip, const char *name);
bgfx::ProgramHandle LoadComputeProgram(const Reader &ir, const ReadProvider &ip, const char *cs_name);
bgfx::ProgramHandle LoadProgram(const Reader &ir, const ReadProvider &ip, const char *vs_name, const char *fs_name, bool silent = false);
bgfx::ProgramHandle LoadProgram(const Reader &ir, const ReadProvider &ip, const char *name, bool silent = false);
bgfx::ProgramHandle LoadComputeProgram(const Reader &ir, const ReadProvider &ip, const char *cs_name, bool silent = false);
bgfx::ProgramHandle LoadProgramFromFile(const char *vs_path, const char *fs_path);
bgfx::ProgramHandle LoadProgramFromAssets(const char *vs_name, const char *fs_name);
bgfx::ProgramHandle LoadProgramFromFile(const char *path);
bgfx::ProgramHandle LoadProgramFromAssets(const char *name);
bgfx::ProgramHandle LoadComputeProgramFromFile(const char *cs_path);
bgfx::ProgramHandle LoadComputeProgramFromAssets(const char *cs_name);
bgfx::ProgramHandle LoadProgramFromFile(const char *vs_path, const char *fs_path, bool silent = false);
bgfx::ProgramHandle LoadProgramFromAssets(const char *vs_name, const char *fs_name, bool silent = false);
bgfx::ProgramHandle LoadProgramFromFile(const char *path, bool silent = false);
bgfx::ProgramHandle LoadProgramFromAssets(const char *name, bool silent = false);
bgfx::ProgramHandle LoadComputeProgramFromFile(const char *cs_path, bool silent = false);
bgfx::ProgramHandle LoadComputeProgramFromAssets(const char *cs_name, bool silent = false);
//
std::vector<bgfx::ShaderHandle> GetProgramShaders(bgfx::ProgramHandle prg_h);
//
json LoadResourceMeta(const Reader &ir, const ReadProvider &ip, const std::string &name);
json LoadResourceMetaFromFile(const std::string &path);
json LoadResourceMetaFromAssets(const std::string &name);
json LoadResourceMeta(const Reader &ir, const ReadProvider &ip, const std::string &name, bool silent = false);
json LoadResourceMetaFromFile(const std::string &path, bool silent = false);
json LoadResourceMetaFromAssets(const std::string &name, bool silent = false);
bool SaveResourceMetaToFile(const std::string &path, const json &meta);
@ -150,9 +151,9 @@ enum PipelineProgramFeature {
Count,
};
std::vector<PipelineProgramFeature> LoadPipelineProgramFeatures(const Reader &ir, const ReadProvider &ip, const char *name, bool &success);
std::vector<PipelineProgramFeature> LoadPipelineProgramFeaturesFromFile(const char *path, bool &success);
std::vector<PipelineProgramFeature> LoadPipelineProgramFeaturesFromAssets(const char *name, bool &success);
std::vector<PipelineProgramFeature> LoadPipelineProgramFeatures(const Reader &ir, const ReadProvider &ip, const char *name, bool &success, bool silent = false);
std::vector<PipelineProgramFeature> LoadPipelineProgramFeaturesFromFile(const char *path, bool &success, bool silent = false);
std::vector<PipelineProgramFeature> LoadPipelineProgramFeaturesFromAssets(const char *name, bool &success, bool silent = false);
//
struct PipelineProgram;
@ -200,17 +201,20 @@ struct PipelineProgram {
Reader ir;
};
PipelineProgram LoadPipelineProgram(const Reader &ir, const ReadProvider &ip, const char *name, PipelineResources &resources, const PipelineInfo &pipeline);
PipelineProgram LoadPipelineProgramFromFile(const char *path, PipelineResources &resources, const PipelineInfo &pipeline);
PipelineProgram LoadPipelineProgramFromAssets(const char *name, PipelineResources &resources, const PipelineInfo &pipeline);
PipelineProgram LoadPipelineProgram(
const Reader &ir, const ReadProvider &ip, const char *name, PipelineResources &resources, const PipelineInfo &pipeline, bool silent = false);
PipelineProgram LoadPipelineProgramFromFile(const char *path, PipelineResources &resources, const PipelineInfo &pipeline, bool silent = false);
PipelineProgram LoadPipelineProgramFromAssets(const char *name, PipelineResources &resources, const PipelineInfo &pipeline, bool silent = false);
void Destroy(PipelineProgram &pipeline_program);
//
bool LoadPipelineProgramUniforms(const Reader &ir, const ReadProvider &ip, const char *name, std::vector<TextureUniform> &texs, std::vector<Vec4Uniform> &vecs,
PipelineResources &resources);
bool LoadPipelineProgramUniformsFromFile(const char *path, std::vector<TextureUniform> &texs, std::vector<Vec4Uniform> &vecs, PipelineResources &resources);
bool LoadPipelineProgramUniformsFromAssets(const char *name, std::vector<TextureUniform> &texs, std::vector<Vec4Uniform> &vecs, PipelineResources &resources);
PipelineResources &resources, bool silent = false);
bool LoadPipelineProgramUniformsFromFile(
const char *path, std::vector<TextureUniform> &texs, std::vector<Vec4Uniform> &vecs, PipelineResources &resources, bool silent = false);
bool LoadPipelineProgramUniformsFromAssets(
const char *name, std::vector<TextureUniform> &texs, std::vector<Vec4Uniform> &vecs, PipelineResources &resources, bool silent = false);
//
struct DisplayList { // 4B
@ -225,14 +229,16 @@ Texture CreateTextureFromPicture(const Picture &pic, const char *name, uint64_t
void UpdateTextureFromPicture(Texture &tex, const Picture &pic);
uint64_t LoadTextureFlags(const Reader &ir, const ReadProvider &ip, const std::string &name);
uint64_t LoadTextureFlagsFromFile(const std::string &path);
uint64_t LoadTextureFlagsFromAssets(const std::string &name);
uint64_t LoadTextureFlags(const Reader &ir, const ReadProvider &ip, const std::string &name, bool silent = false);
uint64_t LoadTextureFlagsFromFile(const std::string &path, bool silent = false);
uint64_t LoadTextureFlagsFromAssets(const std::string &name, bool silent = false);
Texture LoadTexture(const Reader &ir, const ReadProvider &ip, const char *name, uint64_t flags, bgfx::TextureInfo *info = nullptr,
bimg::Orientation::Enum *orientation = nullptr);
Texture LoadTextureFromFile(const char *path, uint64_t flags, bgfx::TextureInfo *info = nullptr, bimg::Orientation::Enum *orientation = nullptr);
Texture LoadTextureFromAssets(const char *name, uint64_t flags, bgfx::TextureInfo *info = nullptr, bimg::Orientation::Enum *orientation = nullptr);
bimg::Orientation::Enum *orientation = nullptr, bool silent = false);
Texture LoadTextureFromFile(
const char *path, uint64_t flags, bgfx::TextureInfo *info = nullptr, bimg::Orientation::Enum *orientation = nullptr, bool silent = false);
Texture LoadTextureFromAssets(
const char *name, uint64_t flags, bgfx::TextureInfo *info = nullptr, bimg::Orientation::Enum *orientation = nullptr, bool silent = false);
void Destroy(Texture &texture);
@ -416,9 +422,9 @@ struct ModelInfo {
uint32_t tri_count{};
};
Model LoadModel(const Reader &ir, const Handle &h, const char *name, ModelInfo *info = nullptr);
Model LoadModelFromFile(const char *path, ModelInfo *info = nullptr);
Model LoadModelFromAssets(const char *name, ModelInfo *info = nullptr);
Model LoadModel(const Reader &ir, const Handle &h, const char *name, ModelInfo *info = nullptr, bool silent = false);
Model LoadModelFromFile(const char *path, ModelInfo *info = nullptr, bool silent = false);
Model LoadModelFromAssets(const char *name, ModelInfo *info = nullptr, bool silent = false);
size_t GetModelMaterialCount(const Model &model);
@ -458,33 +464,34 @@ struct PipelineResources {
};
//
size_t ProcessTextureLoadQueue(PipelineResources &resources, size_t limit = 1);
size_t ProcessTextureLoadQueue(PipelineResources &resources, time_ns t_budget = time_from_ms(4), bool silent = false);
TextureRef QueueLoadTexture(const Reader &ir, const ReadProvider &ip, const char *name, uint64_t flags, PipelineResources &resources);
TextureRef QueueLoadTextureFromFile(const char *path, uint64_t flags, PipelineResources &resources);
TextureRef QueueLoadTextureFromAssets(const char *name, uint64_t flags, PipelineResources &resources);
TextureRef SkipLoadOrQueueTextureLoad(
const Reader &ir, const ReadProvider &ip, const char *path, PipelineResources &resources, bool queue_load, bool do_not_load);
const Reader &ir, const ReadProvider &ip, const char *path, PipelineResources &resources, bool queue_load, bool do_not_load, bool silent = false);
//
size_t ProcessModelLoadQueue(PipelineResources &resources, size_t limit = 1);
size_t ProcessModelLoadQueue(PipelineResources &resources, time_ns t_budget = time_from_ms(4), bool silent = false);
ModelRef QueueLoadModel(const Reader &ir, const ReadProvider &ip, const char *name, PipelineResources &resources);
ModelRef QueueLoadModelFromFile(const char *path, PipelineResources &resources);
ModelRef QueueLoadModelFromAssets(const char *name, PipelineResources &resources);
ModelRef SkipLoadOrQueueModelLoad(const Reader &ir, const ReadProvider &ip, const char *path, PipelineResources &resources, bool queue_load, bool do_not_load);
ModelRef SkipLoadOrQueueModelLoad(
const Reader &ir, const ReadProvider &ip, const char *path, PipelineResources &resources, bool queue_load, bool do_not_load, bool silent = false);
//
Material LoadMaterial(const json &js, const Reader &deps_ir, const ReadProvider &deps_ip, PipelineResources &resources, const PipelineInfo &pipeline,
bool queue_texture_loads, bool do_not_load_resources);
bool queue_texture_loads, bool do_not_load_resources, bool silent = false);
Material LoadMaterial(const Reader &ir, const Handle &h, const Reader &deps_ir, const ReadProvider &deps_ip, PipelineResources &resources,
const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources);
const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources, bool silent = false);
Material LoadMaterialFromFile(
const char *path, PipelineResources &resources, const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources);
const char *path, PipelineResources &resources, const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources, bool silent = false);
Material LoadMaterialFromAssets(
const char *path, PipelineResources &resources, const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources);
const char *path, PipelineResources &resources, const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources, bool silent = false);
bool SaveMaterial(const Material &mat, json &js, const PipelineResources &resources);
bool SaveMaterial(const Material &mat, const Writer &iw, const Handle &h, const PipelineResources &resources);
@ -492,37 +499,38 @@ bool SaveMaterialToFile(const char *path, const Material &m, const PipelineResou
//
PipelineProgramRef LoadPipelineProgramRef(
const Reader &ir, const ReadProvider &ip, const char *name, PipelineResources &resources, const PipelineInfo &pipeline);
PipelineProgramRef LoadPipelineProgramRefFromFile(const char *path, PipelineResources &resources, const PipelineInfo &pipeline);
PipelineProgramRef LoadPipelineProgramRefFromAssets(const char *name, PipelineResources &resources, const PipelineInfo &pipeline);
const Reader &ir, const ReadProvider &ip, const char *name, PipelineResources &resources, const PipelineInfo &pipeline, bool silent = false);
PipelineProgramRef LoadPipelineProgramRefFromFile(const char *path, PipelineResources &resources, const PipelineInfo &pipeline, bool silent = false);
PipelineProgramRef LoadPipelineProgramRefFromAssets(const char *name, PipelineResources &resources, const PipelineInfo &pipeline, bool silent = false);
ModelRef LoadModel(const Reader &ir, const ReadProvider &ip, const char *path, PipelineResources &resources);
ModelRef LoadModelFromFile(const char *path, PipelineResources &resources);
ModelRef LoadModelFromAssets(const char *path, PipelineResources &resources);
ModelRef LoadModel(const Reader &ir, const ReadProvider &ip, const char *path, PipelineResources &resources, bool silent = false);
ModelRef LoadModelFromFile(const char *path, PipelineResources &resources, bool silent = false);
ModelRef LoadModelFromAssets(const char *path, PipelineResources &resources, bool silent = false);
struct TextureMeta {
uint64_t flags{};
};
TextureMeta LoadTextureMeta(const Reader &ir, const ReadProvider &ip, const std::string &name);
TextureMeta LoadTextureMetaFromFile(const std::string &path);
TextureMeta LoadTextureMetaFromAssets(const std::string &name);
TextureMeta LoadTextureMeta(const Reader &ir, const ReadProvider &ip, const std::string &name, bool silent = false);
TextureMeta LoadTextureMetaFromFile(const std::string &path, bool silent = false);
TextureMeta LoadTextureMetaFromAssets(const std::string &name, bool silent = false);
TextureRef LoadTexture(const Reader &ir, const ReadProvider &ip, const char *path, uint64_t flags, PipelineResources &resources);
TextureRef LoadTextureFromFile(const char *path, uint64_t flags, PipelineResources &resources);
TextureRef LoadTextureFromAssets(const char *path, uint64_t flags, PipelineResources &resources);
TextureRef LoadTexture(const Reader &ir, const ReadProvider &ip, const char *path, uint64_t flags, PipelineResources &resources, bool silent = false);
TextureRef LoadTextureFromFile(const char *path, uint64_t flags, PipelineResources &resources, bool silent = false);
TextureRef LoadTextureFromAssets(const char *path, uint64_t flags, PipelineResources &resources, bool silent = false);
uint32_t CaptureTexture(const PipelineResources &resources, const TextureRef &t, Picture &pic);
MaterialRef LoadMaterialRef(const Reader &ir, const Handle &h, const char *path, const Reader &deps_ir, const ReadProvider &deps_ip,
PipelineResources &resources, const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources);
PipelineResources &resources, const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources, bool silent = false);
MaterialRef LoadMaterialRefFromFile(
const char *path, PipelineResources &resources, const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources);
const char *path, PipelineResources &resources, const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources, bool silent = false);
MaterialRef LoadMaterialRefFromAssets(
const char *path, PipelineResources &resources, const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources);
const char *path, PipelineResources &resources, const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources, bool silent = false);
//
size_t ProcessLoadQueues(PipelineResources &res, size_t limit = 1);
size_t GetQueuedResourceCount(const PipelineResources &res);
size_t ProcessLoadQueues(PipelineResources &res, time_ns t_budget = time_from_ms(4), bool silent = false);
//
std::vector<int> GetMaterialPipelineProgramFeatureStates(const Material &mat, const std::vector<PipelineProgramFeature> &features);
@ -659,7 +667,7 @@ void DrawSprites(bgfx::ViewId view_id, const Mat3 &inv_view_R, bgfx::VertexLayou
uint32_t depth = 0);
//
static const float default_shadow_bias = 0.00001f;
static const float default_shadow_bias = 0.0001f;
static const Vec4 default_pssm_split = {10.f, 50.f, 100.f, 500.f};
//

View File

@ -204,9 +204,7 @@ size_t Scene::GarbageCollectPass() {
}
// cleanup anims
{
removed_count += GarbageCollectAnims();
}
{ removed_count += GarbageCollectAnims(); }
return removed_count;
}
@ -750,6 +748,24 @@ void Scene::SetNodeWorldMatrix(NodeRef ref, const Mat4 &world) {
}
}
//
Mat4 Scene::ComputeNodeWorldMatrix(NodeRef ref) const {
if (auto node_ = this->GetNode_(ref)) {
const auto trs_ref = node_->components[NCI_Transform];
if (transforms.is_valid(trs_ref)) {
const auto &trs = transforms[trs_ref.idx];
auto mtx = TransformationMat4(trs.TRS.pos, trs.TRS.rot, trs.TRS.scl);
if (trs.parent != InvalidNodeRef)
mtx = ComputeNodeWorldMatrix(trs.parent) * mtx;
return mtx;
}
}
return Mat4::Identity;
}
//
ComponentRef Scene::GetNodeCameraRef(NodeRef ref) const { return GetNodeComponentRef_<NCI_Camera>(ref); }
@ -1114,12 +1130,14 @@ bool Scene::NodeSetupInstance(
if (i == std::end(node_instance))
return false;
const auto host_is_enabled = IsNodeEnabled(ref);
if (instances.is_valid(i->second)) {
LoadSceneContext ctx = {recursion_level};
{
const auto &i_ = instances[i->second.idx];
if (!LoadScene(ir, ScopedReadHandle(ip, i_.name.c_str()), i_.name.c_str(), *this, ir, ip, resources, pipeline, ctx, flags))
if (!LoadScene(ir, ScopedReadHandle(ip, i_.name.c_str(), flags & LSSF_Silent), i_.name.c_str(), *this, ir, ip, resources, pipeline, ctx, flags))
return false;
}
@ -1130,6 +1148,9 @@ bool Scene::NodeSetupInstance(
n.flags |= NF_Instantiated; // flag as instantiated
if (!host_is_enabled)
n.flags |= NF_InstanceDisabled; // flag as disabled through host
if (auto trs = GetComponent_(transforms, n.components[NCI_Transform]))
if (trs->parent == InvalidNodeRef)
trs->parent = ref; // parent node to the instance node
@ -1608,23 +1629,21 @@ bool LoadSceneBinaryFromData(const Data &data, const char *name, Scene &scene, c
static bool LoadScene(const Reader &ir, const Handle &h, const char *name, Scene &scene, const Reader &deps_ir, const ReadProvider &deps_ip,
PipelineResources &resources, const PipelineInfo &pipeline, LoadSceneContext &ctx, uint32_t flags) {
if (!ir.is_valid(h)) {
error(format("Cannot load scene '%1', invalid read handle").arg(name));
if (!ir.is_valid(h))
return false;
}
return IsBinaryScene(ir, h) ? scene.Load_binary(ir, h, name, deps_ir, deps_ip, resources, pipeline, ctx, flags)
: LoadSceneJson(ir, h, name, scene, deps_ir, deps_ip, resources, pipeline, ctx, flags);
}
bool LoadSceneFromFile(const char *path, Scene &scene, PipelineResources &resources, const PipelineInfo &pipeline, LoadSceneContext &ctx, uint32_t flags) {
return LoadScene(
g_file_reader, ScopedReadHandle(g_file_read_provider, path), path, scene, g_file_reader, g_file_read_provider, resources, pipeline, ctx, flags);
return LoadScene(g_file_reader, ScopedReadHandle(g_file_read_provider, path, flags & LSSF_Silent), path, scene, g_file_reader, g_file_read_provider,
resources, pipeline, ctx, flags);
}
bool LoadSceneFromAssets(const char *name, Scene &scene, PipelineResources &resources, const PipelineInfo &pipeline, LoadSceneContext &ctx, uint32_t flags) {
return LoadScene(
g_assets_reader, ScopedReadHandle(g_assets_read_provider, name), name, scene, g_assets_reader, g_assets_read_provider, resources, pipeline, ctx, flags);
return LoadScene(g_assets_reader, ScopedReadHandle(g_assets_read_provider, name, flags & LSSF_Silent), name, scene, g_assets_reader, g_assets_read_provider,
resources, pipeline, ctx, flags);
}
//
@ -1784,11 +1803,51 @@ BoundToSceneAnim Scene::BindSceneAnim(AnimRef anim_ref) const {
if (!anims.is_valid(anim_ref))
return {};
return {}; // TODO
const auto &anim = anims[anim_ref.idx];
BoundToSceneAnim bound_anim;
bound_anim.anim = anim_ref;
std::fill(std::begin(bound_anim.float_track), std::end(bound_anim.float_track), -1);
for (size_t i = 0; i < anim.float_tracks.size(); ++i) {
__ASSERT__(i < 128);
const auto &t = anim.float_tracks[i];
if (t.target == "FogNear")
bound_anim.float_track[SFAT_FogNear] = int8_t(i);
else if (t.target == "FogFar")
bound_anim.float_track[SFAT_FogFar] = int8_t(i);
}
std::fill(std::begin(bound_anim.color_track), std::end(bound_anim.color_track), -1);
for (size_t i = 0; i < anim.color_tracks.size(); ++i) {
__ASSERT__(i < 128);
const auto &t = anim.color_tracks[i];
if (t.target == "AmbientColor")
bound_anim.color_track[SCAT_AmbientColor] = int8_t(i);
else if (t.target == "FogColor")
bound_anim.color_track[SCAT_FogColor] = int8_t(i);
}
return bound_anim;
}
void Scene::EvaluateBoundAnim(const BoundToSceneAnim &bound_anim, time_ns t) {
// TODO
if (anims.is_valid(bound_anim.anim)) {
const auto &anim = anims[bound_anim.anim.idx];
if (bound_anim.float_track[SFAT_FogNear] != -1)
Evaluate(anim.float_tracks[bound_anim.float_track[SFAT_FogNear]], t, environment.fog_near);
if (bound_anim.float_track[SFAT_FogFar] != -1)
Evaluate(anim.float_tracks[bound_anim.float_track[SFAT_FogFar]], t, environment.fog_far);
if (bound_anim.color_track[SCAT_FogColor] != -1)
Evaluate(anim.color_tracks[bound_anim.color_track[SCAT_FogColor]], t, environment.fog_color);
if (bound_anim.color_track[SCAT_AmbientColor] != -1)
Evaluate(anim.color_tracks[bound_anim.color_track[SCAT_AmbientColor]], t, environment.ambient);
}
}
static bool SplitMaterialPropertyName(const std::string &name, size_t &slot_idx, std::string &value) {
@ -2053,7 +2112,7 @@ SceneAnimRef Scene::GetSceneAnim(const char *name) const {
SceneBoundAnim Scene::BindAnim(const SceneAnim &scene_anim) const {
SceneBoundAnim bound_anim;
if (scene_anims.is_valid(scene_anim.scene_anim))
if (anims.is_valid(scene_anim.scene_anim))
bound_anim.bound_scene_anim = BindSceneAnim(scene_anim.scene_anim);
for (const auto &i : scene_anim.node_anims)
@ -2212,10 +2271,6 @@ std::string Scene::GetValue(const std::string &key) const {
void Scene::SetValue(const std::string &key, const std::string &value) { key_values[key] = value; }
//
Vec3 GetAnimableScenePropertyVec3(const Scene &scene, const std::string &name) { return {}; }
void SetAnimableScenePropertyVec3(Scene &scene, const std::string &name, const Vec3 &v) {}
//
bool GetAnimableNodePropertyBool(const Scene &scene, NodeRef ref, const std::string &name) {
if (const auto node = scene.GetNode(ref)) {
@ -2233,6 +2288,21 @@ void SetAnimableNodePropertyBool(Scene &scene, NodeRef ref, const std::string &n
}
//
float GetAnimableScenePropertyFloat(const Scene &scene, const std::string &name) {
if (name == "FogNear")
return scene.environment.fog_near;
if (name == "FogFar")
return scene.environment.fog_far;
return 1.f;
}
void SetAnimableScenePropertyFloat(Scene &scene, const std::string &name, float v) {
if (name == "FogNear")
scene.environment.fog_near = v;
else if (name == "FogFar")
scene.environment.fog_far = v;
}
float GetAnimableNodePropertyFloat(const Scene &scene, NodeRef ref, const std::string &name) {
if (const auto node = scene.GetNode(ref)) {
if (name == "Light.DiffuseIntensity")
@ -2315,8 +2385,20 @@ void SetAnimableNodePropertyVec4(Scene &scene, NodeRef ref, const std::string &n
}
//
Color GetAnimableScenePropertyColor(const Scene &scene, const std::string &name) { return {}; }
void SetAnimableScenePropertyColor(Scene &scene, const std::string &name, const Color &v) {}
Color GetAnimableScenePropertyColor(const Scene &scene, const std::string &name) {
if (name == "FogColor")
return scene.environment.fog_color;
if (name == "AmbientColor")
return scene.environment.ambient;
return {};
}
void SetAnimableScenePropertyColor(Scene &scene, const std::string &name, const Color &v) {
if (name == "FogColor")
scene.environment.fog_color = v;
else if (name == "AmbientColor")
scene.environment.ambient = v;
}
Color GetAnimableNodePropertyColor(const Scene &scene, NodeRef ref, const std::string &name) {
if (const auto node = scene.GetNode(ref)) {

View File

@ -51,7 +51,7 @@ using AnimRef = gen_ref;
extern const AnimRef InvalidAnimRef;
enum NodeBoolAnimTarget { NBAT_Enable, NBAT_Count };
enum NodeFloatAnimTarget { NFAT_LightDiffuseIntensity, NFAT_LightSpecularIntensity, NFAT_Count };
enum NodeFloatAnimTarget { NFAT_LightDiffuseIntensity, NFAT_LightSpecularIntensity, NFAT_FogNear, NFAT_FogFar, NFAT_Count };
enum NodeVec3AnimTarget { NV3AT_TransformPosition, NV3AT_TransformRotation, NV3AT_TransformScale, NV3AT_Count };
enum NodeVec4AnimTarget { NV4AT_Count };
enum NodeQuatAnimTarget { NQAT_TransformRotation, NQAT_Count };
@ -87,8 +87,12 @@ struct BoundToNodeAnim {
mutable BoundToNodeInstanceAnim bound_to_node_instance_anim;
};
enum SceneFloatAnimTarget { SFAT_FogNear, SFAT_FogFar, SFAT_Count };
enum SceneColorAnimTarget { SCAT_FogColor, SCAT_AmbientColor, SCAT_Count };
struct BoundToSceneAnim {
std::array<int8_t, NV3AT_Count> vec3_track;
std::array<int8_t, SFAT_Count> float_track;
std::array<int8_t, SCAT_Count> color_track;
AnimRef anim; // 8B
};
@ -243,6 +247,11 @@ public:
void SetTransformParent(ComponentRef ref, const NodeRef &v);
void SetTransformLocalMatrix(ComponentRef ref, const Mat4 &local);
/*!
@short Set and decompose transform world matrix.
The provided matrix is decomposed over the position, rotation and scale members of the Transform.
@see SetNodeWorldMatrix to set a node world matrix in the scene graph without affecting the Transform component.
*/
void SetTransformWorldMatrix(ComponentRef ref, const Mat4 &world);
Transform CreateTransform(const Vec3 &pos, const Vec3 &rot = {0, 0, 0}, const Vec3 &scl = {1, 1, 1}, NodeRef parent = {});
@ -259,11 +268,18 @@ public:
Mat4 GetNodeWorldMatrix(NodeRef ref) const;
/*!
Set a node world matrix and flag it as update so that it won't be computed by the next call to ComputeWorldMatrices().
Note: This function INTENTIONALLY does not decompose the provided matrix to the transfrom position/rotation/scale fields.
@short Set node world matrix.
Set a node world matrix and flag it as updated so that it won't be computed by the next call to ComputeWorldMatrices().
@note This function INTENTIONALLY does not decompose the provided matrix to the transfrom position/rotation/scale fields.
*/
void SetNodeWorldMatrix(NodeRef ref, const Mat4 &world);
/*!
@short Compute node world matrix from scratch on-the-fly.
This function is slow but useful when scene matrices are not yet up-to-date.
*/
Mat4 ComputeNodeWorldMatrix(NodeRef ref) const;
//
void StorePreviousWorldMatrices();
void ReadyWorldMatrices();
@ -728,7 +744,7 @@ private:
float radius{0.f};
float inner_angle{Deg(30.f)}, outer_angle{Deg(45.f)};
Vec4 pssm_split{10.f, 50.f, 100.f, 500.f};
Vec4 pssm_split{10.f, 50.f, 100.f, 200.f};
float priority{0.f};
float shadow_bias{default_shadow_bias};
@ -792,7 +808,7 @@ private:
friend void LoadComponent(Transform_ *data_, const Reader &ir, const Handle &h);
friend void LoadComponent(Camera_ *data_, const Reader &ir, const Handle &h);
friend void LoadComponent(Object_ *data_, const Reader &ir, const Handle &h, const Reader &deps_ir, const ReadProvider &deps_ip,
PipelineResources &resources, const PipelineInfo &pipeline, bool queue_model_loads, bool queue_texture_loads, bool do_not_load_resources);
PipelineResources &resources, const PipelineInfo &pipeline, bool queue_model_loads, bool queue_texture_loads, bool do_not_load_resources, bool silent);
friend void LoadComponent(Light_ *data_, const Reader &ir, const Handle &h);
friend void LoadComponent(RigidBody_ *data_, const Reader &ir, const Handle &h);
friend void LoadComponent(Collision_ *data_, const Reader &ir, const Handle &h);
@ -962,6 +978,8 @@ void DumpSceneMemoryFootprint();
bool GetAnimableNodePropertyBool(const Scene &scene, NodeRef ref, const std::string &name);
void SetAnimableNodePropertyBool(Scene &scene, NodeRef ref, const std::string &name, bool v);
float GetAnimableScenePropertyFloat(const Scene &scene, const std::string &name);
void SetAnimableScenePropertyFloat(Scene &scene, const std::string &name, float v);
float GetAnimableNodePropertyFloat(const Scene &scene, NodeRef ref, const std::string &name);
void SetAnimableNodePropertyFloat(Scene &scene, NodeRef ref, const std::string &name, float v);

View File

@ -270,7 +270,7 @@ void SceneBullet3Physics::NodeCreatePhysics(const Node &node, const Reader &ir,
auto trs = node.GetTransform();
btTransform bt_trs = btTransform::getIdentity();
if (trs)
bt_trs = to_btTransform(TransformationMat4(trs.GetPos(), trs.GetRot(), Vec3::One)); // most up to date transform
bt_trs = to_btTransform(Normalize(node.ComputeWorld())); // require most up-to-date world matrix
if (!shapes.empty()) {
btCollisionShape *root_shape;
@ -413,8 +413,14 @@ void SceneBullet3Physics::SyncTransformsFromScene(const Scene &scene) {
const auto flags = body->getCollisionFlags();
if (flags == btRigidBody::CF_KINEMATIC_OBJECT) {
const auto world = scene.GetNodeWorldMatrix(i.first);
const auto world_no_scale = TransformationMat4(GetT(world), GetR(world), Vec3::One);
/*
[EJ] ComputeNodeWorldMatrix is wasteful and only required so that the first frame
synchronization is correct as the scene matrices have not been computed yet.
We count on the fact that kinematic objects are a minority in the scene graph for
this change to not impact performances too much.
*/
const auto world_no_scale = Normalize(scene.ComputeNodeWorldMatrix(i.first));
body->setWorldTransform(to_btTransform(world_no_scale));
}
}

View File

@ -11,11 +11,12 @@
#include "fabgen.h"
#include <json/json.hpp>
namespace bgfx {
void getTextureSizeFromRatio(BackbufferRatio::Enum _ratio, uint16_t &_width, uint16_t &_height);
} // namespace bgfx
namespace hg {
void UpdateForwardPipeline(ForwardPipeline &pipeline, const ForwardPipelineShadowData &shadow_data, const Color &ambient, const ForwardPipelineLights &lights,
@ -35,6 +36,61 @@ void ForwardPipelineAAA::Flip(const ViewState &view_state) {
prv_view_state = view_state;
}
//
bool LoadForwardPipelineAAAConfig(const json &js, ForwardPipelineAAAConfig &config) {
config.temporal_aa_weight = js["taa_weight"];
config.sample_count = js["sample_count"];
config.max_distance = js["max_distance"];
config.z_thickness = js["z_thickness"];
config.bloom_threshold = js["bloom_threshold"];
config.bloom_bias = js["bloom_bias"];
config.bloom_intensity = js["bloom_intensity"];
config.motion_blur = js["motion_blur"];
config.exposure = js["exposure"];
config.gamma = js["gamma"];
return true;
}
void SaveForwardPipelineAAAConfig(json &js, const ForwardPipelineAAAConfig &config) {
js["taa_weight"] = config.temporal_aa_weight;
js["sample_count"] = config.sample_count;
js["max_distance"] = config.max_distance;
js["z_thickness"] = config.z_thickness;
js["bloom_threshold"] = config.bloom_threshold;
js["bloom_bias"] = config.bloom_bias;
js["bloom_intensity"] = config.bloom_intensity;
js["motion_blur"] = config.motion_blur;
js["exposure"] = config.exposure;
js["gamma"] = config.gamma;
}
bool LoadForwardPipelineAAAConfigFromFile(const char *path, ForwardPipelineAAAConfig &config) {
bool result;
const auto js = LoadJsonFromFile(path, &result);
return result ? LoadForwardPipelineAAAConfig(js, config) : false;
}
bool LoadForwardPipelineAAAConfigFromAssets(const char *name, ForwardPipelineAAAConfig &config) {
bool result;
const auto js = LoadJsonFromAssets(name, &result);
return result ? LoadForwardPipelineAAAConfig(js, config) : false;
}
bool SaveForwardPipelineAAAConfigToFile(const char *path, const ForwardPipelineAAAConfig &config) {
json js;
SaveForwardPipelineAAAConfig(js, config);
return SaveJsonToFile(js, path);
}
//
bool IsValid(const ForwardPipelineAAA &aaa) {
for (auto &tex : aaa.noise) {
@ -87,7 +143,7 @@ bool IsValid(const ForwardPipelineAAA &aaa) {
}
static ForwardPipelineAAA _CreateForwardPipelineAAA(const Reader &ir, const ReadProvider &ip, const char *path, const ForwardPipelineAAAConfig &config,
const RenderBufferResourceFactory& rb_factory, bgfx::BackbufferRatio::Enum ssgi_ratio, bgfx::BackbufferRatio::Enum ssr_ratio) {
const RenderBufferResourceFactory &rb_factory, bgfx::BackbufferRatio::Enum ssgi_ratio, bgfx::BackbufferRatio::Enum ssr_ratio) {
ForwardPipelineAAA aaa;
const uint64_t flags = attribute_texture_flags;
@ -178,10 +234,10 @@ static ForwardPipelineAAA _CreateForwardPipelineAAA(const Reader &ir, const Read
aaa.frame_hdr_fb = bgfx::createFrameBuffer(2, texs, false);
aaa.work_frame_hdr_fb = rb_factory.create_framebuffer(bgfx::BackbufferRatio::Equal, bgfx::TextureFormat::RGBA16F, flags);
aaa.prv_frame_hdr_fb = rb_factory.create_framebuffer(bgfx::BackbufferRatio::Equal, bgfx::TextureFormat::RGBA16F, flags); // (reprojected) input to SSR/SSGI
aaa.next_frame_hdr_fb =
rb_factory.create_framebuffer(bgfx::BackbufferRatio::Equal, bgfx::TextureFormat::RGBA16F, flags); // current frame with SSR/SSGI
aaa.prv_frame_hdr_fb =
rb_factory.create_framebuffer(bgfx::BackbufferRatio::Equal, bgfx::TextureFormat::RGBA16F, flags); // (reprojected) input to SSR/SSGI
aaa.next_frame_hdr_fb = rb_factory.create_framebuffer(bgfx::BackbufferRatio::Equal, bgfx::TextureFormat::RGBA16F, flags); // current frame with SSR/SSGI
}
{
@ -237,13 +293,13 @@ ForwardPipelineAAA CreateForwardPipelineAAAFromAssets(
return _CreateForwardPipelineAAA(g_assets_reader, g_assets_read_provider, path, config, rb_factory, ssgi_ratio, ssr_ratio);
}
ForwardPipelineAAA CreateForwardPipelineAAAFromFile(const char* path, const ForwardPipelineAAAConfig& config, uint16_t rb_width, uint16_t rb_height,
ForwardPipelineAAA CreateForwardPipelineAAAFromFile(const char *path, const ForwardPipelineAAAConfig &config, uint16_t rb_width, uint16_t rb_height,
bgfx::BackbufferRatio::Enum ssgi_ratio, bgfx::BackbufferRatio::Enum ssr_ratio) {
auto rb_factory = RenderBufferResourceFactory::Custom(rb_width, rb_height);
return _CreateForwardPipelineAAA(g_file_reader, g_file_read_provider, path, config, rb_factory, ssgi_ratio, ssr_ratio);
}
ForwardPipelineAAA CreateForwardPipelineAAAFromAssets(const char* path, const ForwardPipelineAAAConfig& config, uint16_t rb_width, uint16_t rb_height,
ForwardPipelineAAA CreateForwardPipelineAAAFromAssets(const char *path, const ForwardPipelineAAAConfig &config, uint16_t rb_width, uint16_t rb_height,
bgfx::BackbufferRatio::Enum ssgi_ratio, bgfx::BackbufferRatio::Enum ssr_ratio) {
auto rb_factory = RenderBufferResourceFactory::Custom(rb_width, rb_height);
return _CreateForwardPipelineAAA(g_assets_reader, g_assets_read_provider, path, config, rb_factory, ssgi_ratio, ssr_ratio);
@ -434,6 +490,9 @@ static int ComputeForwardPipelineConfigurationIdx(ForwardPipelineStage pipeline_
if (pipeline_stage == FPS_AttributeBuffers)
return 0;
if (pipeline_stage == FPS_DepthOnly)
return 9;
int light_config_idx = 0;
if (lights.lights[0].shadow_type == FPST_Map)
@ -531,13 +590,15 @@ void SubmitSceneToForwardPipeline(bgfx::ViewId &view_id, const Scene &scene, con
// update pipeline
UpdateForwardPipeline(pipeline, render_data.shadow_data, scene.environment.ambient, render_data.pipe_lights, render_data.fog, fb_size);
UpdateForwardPipelineAAA(pipeline, rect, view_state.view, view_state.proj, aaa.prv_view_state.view, aaa.prv_view_state.proj, TAAProjectionJitter8(frame),
UpdateForwardPipelineAAA(pipeline, rect, view_state.view, view_state.proj, aaa.prv_view_state.view, aaa.prv_view_state.proj, TAAHaltonJitter8(frame),
aaa.ssgi_ratio, aaa.ssr_ratio, aaa_config.temporal_aa_weight, aaa_config.motion_blur, aaa_config.exposure, aaa_config.gamma, aaa_config.sample_count,
aaa_config.max_distance); // [todo] ssgi_ratio/ssr_ratio
// TAA jittered projection matrix
const auto jitter = TAAProjectionJitter8(frame) / Vec2(float(GetWidth(rect)), float(GetHeight(rect)));
const auto proj_jittered = to_bgfx(TranslationMat4({jitter.x, jitter.y, 0}) * view_state.proj);
const auto jitter = TAAHaltonJitter8(frame) / Vec2(float(GetWidth(rect)), float(GetHeight(rect)));
auto proj_jittered = to_bgfx(view_state.proj);
proj_jittered[8] += jitter.x;
proj_jittered[9] += jitter.y;
// fill attribute buffers (linear depth/normal/velocity)
{
@ -722,8 +783,8 @@ void SubmitSceneToForwardPipeline(bgfx::ViewId &view_id, const Scene &scene, con
view_id, rect, {attribute_texture_flags, bgfx::getTexture(aaa.next_frame_hdr_fb)}, aaa.attr0, aaa.attr1, noise, aaa.work_frame_hdr_fb, aaa.motion_blur);
// bloom
ApplyBloom(view_id, rect, {attribute_texture_flags, bgfx::getTexture(aaa.work_frame_hdr_fb)}, fb_size, aaa.frame_hdr_fb, aaa.bloom, aaa_config.bloom_threshold,
aaa_config.bloom_bias, aaa_config.bloom_intensity);
ApplyBloom(view_id, rect, {attribute_texture_flags, bgfx::getTexture(aaa.work_frame_hdr_fb)}, fb_size, aaa.frame_hdr_fb, aaa.bloom,
aaa_config.bloom_threshold, aaa_config.bloom_bias, aaa_config.bloom_intensity);
// final compositing for presentation (exposure/gamma correction)
{
@ -768,7 +829,6 @@ void SubmitSceneToForwardPipeline(bgfx::ViewId &view_id, const Scene &scene, con
SubmitSceneToForwardPipeline(view_id, scene, rect, view_state, pipeline, render_data, resources, views, aaa, aaa_config, frame, 0, 0, fb, debug_name);
}
// basic rendering path
void SubmitSceneToForwardPipeline(bgfx::ViewId &view_id, const Scene &scene, const Rect<int> &rect, const ViewState &view_state, ForwardPipeline &pipeline,
const SceneForwardPipelineRenderData &render_data, const PipelineResources &resources, SceneForwardPipelinePassViewId &views, bgfx::FrameBufferHandle fb,
@ -776,8 +836,8 @@ void SubmitSceneToForwardPipeline(bgfx::ViewId &view_id, const Scene &scene, con
std::fill(std::begin(views), std::end(views), 65535);
// update pipeline
UpdateForwardPipeline(pipeline, render_data.shadow_data, scene.environment.ambient, render_data.pipe_lights, render_data.fog,
hg::iVec2(GetWidth(rect), GetHeight(rect)));
UpdateForwardPipeline(
pipeline, render_data.shadow_data, scene.environment.ambient, render_data.pipe_lights, render_data.fog, hg::iVec2(GetWidth(rect), GetHeight(rect)));
// UpdateForwardPipelineAAA(pipeline, rect, view_state.view, view_state.proj, view_state.view, view_state.proj, {});
{

View File

@ -47,6 +47,10 @@ struct ForwardPipelineAAAConfig {
ForwardPipelineAAADebugBuffer debug_buffer = FPAAADB_None;
};
bool LoadForwardPipelineAAAConfigFromFile(const char *path, ForwardPipelineAAAConfig &config);
bool LoadForwardPipelineAAAConfigFromAssets(const char *name, ForwardPipelineAAAConfig &config);
bool SaveForwardPipelineAAAConfigToFile(const char *path, const ForwardPipelineAAAConfig &config);
//
struct ForwardPipelineAAA {
std::array<Texture, 64> noise;
@ -141,7 +145,6 @@ ForwardPipelineAAA CreateForwardPipelineAAAFromFile(const char *path, const Forw
ForwardPipelineAAA CreateForwardPipelineAAAFromAssets(const char *path, const ForwardPipelineAAAConfig &config, uint16_t rb_width, uint16_t rb_height,
bgfx::BackbufferRatio::Enum ssgi_ratio = bgfx::BackbufferRatio::Half, bgfx::BackbufferRatio::Enum ssr_ratio = bgfx::BackbufferRatio::Half);
void DestroyForwardPipelineAAA(ForwardPipelineAAA &aaa);
bool IsValid(const ForwardPipelineAAA &aaa);
@ -204,8 +207,7 @@ void SubmitSceneToForwardPipeline(bgfx::ViewId &view_id, const Scene &scene, con
void SubmitSceneToForwardPipeline(bgfx::ViewId &view_id, const Scene &scene, const Rect<int> &rect, const ViewState &view_state, ForwardPipeline &pipeline,
const SceneForwardPipelineRenderData &render_data, const PipelineResources &resources, SceneForwardPipelinePassViewId &views, ForwardPipelineAAA &aaa,
const ForwardPipelineAAAConfig &aaa_config, int frame, bgfx::FrameBufferHandle fb = BGFX_INVALID_HANDLE,
const char *debug_name = "scene");
const ForwardPipelineAAAConfig &aaa_config, int frame, bgfx::FrameBufferHandle fb = BGFX_INVALID_HANDLE, const char *debug_name = "scene");
/// High-level submit scene to forward pipeline using a custom view state.
void SubmitSceneToPipeline(bgfx::ViewId &view_id, const Scene &scene, const Rect<int> &rect, const ViewState &view_state, ForwardPipeline &pipeline,

View File

@ -105,17 +105,17 @@ void LoadComponent(Scene::Camera_ *data_, const Reader &ir, const Handle &h) {
}
void LoadComponent(Scene::Object_ *data_, const Reader &ir, const Handle &h, const Reader &deps_ir, const ReadProvider &deps_ip, PipelineResources &resources,
const PipelineInfo &pipeline, bool queue_model_loads, bool queue_texture_loads, bool do_not_load_resources) {
const PipelineInfo &pipeline, bool queue_model_loads, bool queue_texture_loads, bool do_not_load_resources, bool silent) {
std::string name;
Read(ir, h, name);
if (!name.empty())
data_->model = SkipLoadOrQueueModelLoad(deps_ir, deps_ip, name.c_str(), resources, queue_model_loads, do_not_load_resources);
data_->model = SkipLoadOrQueueModelLoad(deps_ir, deps_ip, name.c_str(), resources, queue_model_loads, do_not_load_resources, silent);
const auto mat_count = Read<uint16_t>(ir, h);
data_->materials.resize(mat_count);
for (auto i = 0; i < mat_count; ++i)
data_->materials[i] = LoadMaterial(ir, h, deps_ir, deps_ip, resources, pipeline, queue_texture_loads, do_not_load_resources);
data_->materials[i] = LoadMaterial(ir, h, deps_ir, deps_ip, resources, pipeline, queue_texture_loads, do_not_load_resources, silent);
data_->material_infos.resize(mat_count);
for (auto i = 0; i < mat_count; ++i)
@ -473,25 +473,30 @@ bool Scene::Load_binary(const Reader &ir, const Handle &h, const char *name, con
ProfilerPerfSection section("Scene::Load_binary");
const auto t_start = time_now();
const auto silent = load_flags & LSSF_Silent;
if (!ir.is_valid(h)) {
error(format("Cannot load scene '%1', invalid read handle").arg(name));
if (!silent)
error(format("Cannot load scene '%1', invalid read handle").arg(name));
return false;
}
if (Read<uint32_t>(ir, h) != HarfangMagic) {
error(format("Cannot load scene '%1', invalid magic marker").arg(name));
if (!silent)
error(format("Cannot load scene '%1', invalid magic marker").arg(name));
return false;
}
if (Read<uint8_t>(ir, h) != SceneMarker) {
error(format("Cannot load scene '%1', invalid scene marker").arg(name));
if (!silent)
error(format("Cannot load scene '%1', invalid scene marker").arg(name));
return false;
}
const auto version = Read<uint32_t>(ir, h);
if (version != GetSceneBinaryFormatVersion()) {
error(format("Cannot load scene '%1', unsupported binary version %2").arg(name).arg(version));
if (!silent)
error(format("Cannot load scene '%1', unsupported binary version %2").arg(name).arg(version));
return false;
}
@ -520,7 +525,7 @@ bool Scene::Load_binary(const Reader &ir, const Handle &h, const char *name, con
for (size_t i = 0; i < object_count; ++i) {
const auto ref = object_refs[i] = CreateObject().ref;
LoadComponent(&objects[ref.idx], ir, h, deps_ir, deps_ip, resources, pipeline, load_flags & LSSF_QueueModelLoads, load_flags & LSSF_QueueTextureLoads,
load_flags & LSSF_DoNotLoadResources);
load_flags & LSSF_DoNotLoadResources, silent);
}
const auto light_count = Read<uint32_t>(ir, h);
@ -677,17 +682,17 @@ bool Scene::Load_binary(const Reader &ir, const Handle &h, const char *name, con
Read(ir, h, name);
if (!name.empty())
environment.irradiance_map = SkipLoadOrQueueTextureLoad(
deps_ir, deps_ip, name.c_str(), resources, load_flags & LSSF_QueueTextureLoads, load_flags & LSSF_DoNotLoadResources);
deps_ir, deps_ip, name.c_str(), resources, load_flags & LSSF_QueueTextureLoads, load_flags & LSSF_DoNotLoadResources, silent);
Read(ir, h, name);
if (!name.empty())
environment.radiance_map = SkipLoadOrQueueTextureLoad(
deps_ir, deps_ip, name.c_str(), resources, load_flags & LSSF_QueueTextureLoads, load_flags & LSSF_DoNotLoadResources);
deps_ir, deps_ip, name.c_str(), resources, load_flags & LSSF_QueueTextureLoads, load_flags & LSSF_DoNotLoadResources, silent);
Read(ir, h, name);
if (!name.empty())
environment.brdf_map = SkipLoadOrQueueTextureLoad(
deps_ir, deps_ip, name.c_str(), resources, load_flags & LSSF_QueueTextureLoads, load_flags & LSSF_DoNotLoadResources);
deps_ir, deps_ip, name.c_str(), resources, load_flags & LSSF_QueueTextureLoads, load_flags & LSSF_DoNotLoadResources, silent);
}
Read(ir, h, canvas.clear_z);
@ -815,7 +820,9 @@ bool Scene::Load_binary(const Reader &ir, const Handle &h, const char *name, con
}
//
debug(format("Load scene '%1' took %2 ms").arg(name).arg(time_to_ms(time_now() - t_start)));
if (!silent)
debug(format("Load scene '%1' took %2 ms").arg(name).arg(time_to_ms(time_now() - t_start)));
return true;
}

View File

@ -511,7 +511,7 @@ bool Scene::Save_json(json &js, const PipelineResources &resources, uint32_t sav
{"name", scene_anim.name},
{"t_start", scene_anim.t_start},
{"t_end", scene_anim.t_end},
{"anim", scene_anim.scene_anim},
{"anim", scene_anim.scene_anim.idx},
{"frame_duration", scene_anim.frame_duration},
};
@ -842,10 +842,15 @@ bool Scene::Load_json(const json &js, const char *name, const Reader &deps_ir, c
js_scene_anim.at("name").get_to(scene_anim.name);
scene_anim.t_start = js_scene_anim.at("t_start");
scene_anim.t_end = js_scene_anim.at("t_end");
scene_anim.scene_anim = js_scene_anim.at("anim");
scene_anim.frame_duration = js_scene_anim.at("frame_duration");
const auto &i_scene_anim = anim_refs.find(scene_anim.scene_anim.idx);
uint32_t scene_anim_idx = invalid_gen_ref.idx;
const auto &i_anim = js_scene_anim.find("anim");
if (i_anim != std::end(js_scene_anim))
if (!i_anim->is_null()) // [EJ] legacy format field was broken
scene_anim_idx = i_anim->get<uint32_t>();
const auto &i_scene_anim = anim_refs.find(scene_anim_idx);
if (i_scene_anim != std::end(anim_refs))
scene_anim.scene_anim = i_scene_anim->second;

View File

@ -6,6 +6,7 @@
#include "foundation/format.h"
#include "foundation/path_tools.h"
#include "foundation/matrix3.h"
namespace hg {
@ -24,6 +25,8 @@ std::string ExportNodeToOBJ(const Node &node, const std::string &model_dir, cons
const auto world = trs.GetWorld();
Mat3 normal = Transpose(Mat3(InverseFast(world)));
//
auto mdl_ref = node.GetObject().GetModelRef();
if (!resources.models.IsValidRef(mdl_ref))
@ -39,8 +42,8 @@ std::string ExportNodeToOBJ(const Node &node, const std::string &model_dir, cons
out += format("# %1 vertices\n").arg(geo.vtx.size()).str();
for (const auto &vtx : geo.vtx) {
const auto tv = vtx * world;
out += format("v %1 %2 %3\n").arg(tv.x).arg(tv.y).arg(tv.z).str();
const auto tv = world * vtx;
out += format("v %1 %2 %3\n").arg(-tv.x).arg(tv.y).arg(tv.z).str();
}
out += "\n";
@ -50,8 +53,10 @@ std::string ExportNodeToOBJ(const Node &node, const std::string &model_dir, cons
out += "\n";
out += format("# %1 normals\n").arg(geo.normal.size()).str();
for (const auto &n : geo.normal)
out += format("vn %1 %2 %3\n").arg(n.x).arg(n.y).arg(n.z).str();
for (const auto &n : geo.normal) {
const auto tn = normal * n;
out += format("vn %1 %2 %3\n").arg(-tn.x).arg(tn.y).arg(tn.z).str();
}
out += "\n";
const auto pol_idx = ComputePolygonIndex(geo);

View File

@ -37,7 +37,7 @@ bool SRanipalInit() {
if (err == ViveSR::Error::WORK) {
eye_tracking_enabled = true;
info("Eye tracking API successfully initialized");
log("Eye tracking API successfully initialized");
return true;
} else if (err == ViveSR::Error::RUNTIME_NOT_FOUND) {
error("SRanipal runtime not found, please follow the SDK guide on how to install it");

View File

@ -81,4 +81,18 @@ Vec2 TAAProjectionJitter16(int frame) {
return grid[frame & 15];
}
Vec2 TAAHaltonJitter8(int frame) {
static const Vec2 grid[8] = {Vec2(0.000000f, -0.333333f), Vec2(-0.500000f, 0.333333f), Vec2(0.500000f, -0.777778f), Vec2(-0.750000f, -0.111111f),
Vec2(0.250000f, 0.555556f), Vec2(-0.250000f, -0.555556f), Vec2(0.750000f, 0.111111f), Vec2(-0.875000f, 0.777778f)};
return grid[frame & 7];
}
Vec2 TAAHaltonJitter16(int frame) {
static const Vec2 grid[16] = {Vec2(0.000000f, -0.333333f), Vec2(-0.500000f, 0.333333f), Vec2(0.500000f, -0.777778f), Vec2(-0.750000f, -0.111111f),
Vec2(0.250000f, 0.555556f), Vec2(-0.250000f, -0.555556f), Vec2(0.750000f, 0.111111f), Vec2(-0.875000f, 0.777778f), Vec2(0.125000f, -0.925926f),
Vec2(-0.375000f, -0.259259f), Vec2(0.625000f, 0.407407f), Vec2(-0.625000f, -0.703704f), Vec2(0.375000f, -0.037037f), Vec2(-0.125000f, 0.629630f),
Vec2(0.875000f, -0.481481f), Vec2(-0.937500f, 0.185185f)};
return grid[frame & 15];
}
} // namespace hg

View File

@ -27,6 +27,9 @@ void ApplyTAA(bgfx::ViewId &view_id, const iRect &rect, const Texture &color, co
Vec2 TAAProjectionJitter8(int frame);
Vec2 TAAProjectionJitter16(int frame);
Vec2 TAAHaltonJitter8(int frame);
Vec2 TAAHaltonJitter16(int frame);
bool IsValid(const TAA &taa);
} // namespace hg

View File

@ -9,9 +9,9 @@ namespace hg {
struct TemporalAccumulation {
bgfx::ProgramHandle compute = BGFX_INVALID_HANDLE;
bgfx::UniformHandle u_previous = BGFX_INVALID_HANDLE;
bgfx::UniformHandle u_current = BGFX_INVALID_HANDLE;
bgfx::UniformHandle u_attr1 = BGFX_INVALID_HANDLE; // xyz: velocity
bgfx::UniformHandle u_previous = BGFX_INVALID_HANDLE;
bgfx::UniformHandle u_current = BGFX_INVALID_HANDLE;
bgfx::UniformHandle u_attr1 = BGFX_INVALID_HANDLE; // xyz: velocity
};
TemporalAccumulation CreateTemporalAccumulationFromFile(const char *path);
@ -19,7 +19,8 @@ TemporalAccumulation CreateTemporalAccumulationFromAssets(const char *path);
void DestroyTemporalAccumulation(TemporalAccumulation &temporal_acc);
void ComputeTemporalAccumulation(bgfx::ViewId &view_id, const iRect &rect, const Texture &current, const Texture &previous, const Texture &attr1, bgfx::FrameBufferHandle output, const TemporalAccumulation &temporal_acc);
void ComputeTemporalAccumulation(bgfx::ViewId &view_id, const iRect &rect, const Texture &current, const Texture &previous, const Texture &attr1,
bgfx::FrameBufferHandle output, const TemporalAccumulation &temporal_acc);
bool IsValid(const TemporalAccumulation &temporal_acc);

View File

@ -127,6 +127,8 @@ static inline bgfx::TextureFormat::Enum VideoFrameTextureFormat(VideoFrameFormat
return bgfx::TextureFormat::RG8;
case VFF_RGB24:
return bgfx::TextureFormat::RGB8;
case VFF_RGBA32:
return bgfx::TextureFormat::RGBA8;
default:
return bgfx::TextureFormat::Unknown;
}
@ -184,7 +186,7 @@ bool UpdateTexture(IVideoStreamer &streamer, VideoStreamHandle &handle, hg::Text
helper->id = id;
helper->handle = handle;
pitch = 0;
const auto *mem = bgfx::makeRef(data, width*height*3, ReleaseFrame, helper);
const auto *mem = bgfx::makeRef(data, pitch * height, ReleaseFrame, helper);
bgfx::updateTexture2D(texture.handle, 0, 0, 0, 0, width, height, mem);
return true;
}

View File

@ -23,7 +23,8 @@
enum VideoFrameFormat {
VFF_UNKNOWN = -1, ///< Unknown/Unsupported
VFF_YUV422 = 0, ///< 16 bits per pixels. 2 channels per pixel. 8 bits per channel. U and V are shared between two pixels.
VFF_RGB24 ///< 24 bits per pixels. 8 bits per channel (Red, Green, Blue).
VFF_RGB24, ///< 24 bits per pixels. 8 bits per channel (Red, Green, Blue).
VFF_RGBA32, ///< 32 bits per pixels. 8 bits per channel (Red, Green, Blue, Alpha).
};
/// Opaque handle for video stream.

View File

@ -1,5 +1,3 @@
message("Generating build_info.cpp")
add_custom_command(
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/build_info.cpp
COMMAND ${Python3_EXECUTABLE} gen_build_info_cpp.py --host_prefix=${HG_HOST_PREFIX} --target_prefix=${HG_TARGET_PREFIX}
@ -152,6 +150,10 @@ if(NOT WIN32)
target_link_libraries(foundation PUBLIC uuid)
else()
target_link_libraries(foundation PUBLIC Iphlpapi)
if(MSVC)
target_compile_options(foundation PRIVATE "$<$<CONFIG:Release>:/Zi>")
target_link_options(foundation PRIVATE "$<$<CONFIG:Release>:/DEBUG>")
endif()
endif()
install_cppsdk_target(foundation)

View File

@ -3,6 +3,8 @@
#include "foundation/dir.h"
#include "foundation/cext.h"
#include "foundation/file.h"
#include "foundation/format.h"
#include "foundation/log.h"
#include "foundation/path_tools.h"
#include "foundation/rand.h"
#include "foundation/string.h"
@ -11,6 +13,7 @@
#if _WIN32
#include <direct.h>
#define WIN32_LEAN_AND_MEAN
#include "platform/win32/platform.h"
#include <Windows.h>
#include <shlwapi.h>
#else /* POSIX */
@ -29,13 +32,13 @@ std::vector<DirEntry> ListDir(const char *path, int mask) {
#if _WIN32
WIN32_FIND_DATAW data;
auto find_path = utf8_to_utf16(PathJoin({path, "*.*"}));
auto hFind = FindFirstFileW(reinterpret_cast<LPCWSTR>(find_path.data()), &data);
auto wfind_path = utf8_to_wchar(PathJoin({path, "*.*"}));
auto hFind = FindFirstFileW(wfind_path.c_str(), &data);
if (hFind == INVALID_HANDLE_VALUE)
return entries;
do {
auto name = utf16_to_utf8(std::u16string(reinterpret_cast<std::u16string::value_type *>(data.cFileName)));
auto name = wchar_to_utf8(data.cFileName);
if (name == "." || name == "..")
continue;
@ -80,12 +83,12 @@ std::vector<DirEntry> ListDirRecursive(const char *path, int mask) {
std::vector<DirEntry> entries = ListDir(path, mask);
#if _WIN32
WIN32_FIND_DATAW data;
auto find_path = utf8_to_utf16(PathJoin({path, "*"}));
auto hFind = FindFirstFileW(reinterpret_cast<LPCWSTR>(find_path.data()), &data);
auto wfind_path = utf8_to_wchar(PathJoin({path, "*"}));
auto hFind = FindFirstFileW(wfind_path.c_str(), &data);
if (hFind == INVALID_HANDLE_VALUE)
return entries;
do {
auto name = utf16_to_utf8(std::u16string(reinterpret_cast<std::u16string::value_type *>(data.cFileName)));
auto name = wchar_to_utf8(data.cFileName);
if (name == "." || name == "..")
continue;
if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
@ -117,67 +120,92 @@ std::vector<DirEntry> ListDirRecursive(const char *path, int mask) {
}
//
bool MkDir(const char *path, int permissions) {
size_t GetDirSize(const char *path) {
const auto entries = hg::ListDirRecursive(path);
size_t size = 0;
for (const auto &e : entries)
if (e.type == hg::DE_File) {
const auto fpath = hg::PathJoin({path, e.name});
const auto finfo = hg::GetFileInfo(fpath.c_str());
size += finfo.size;
}
return size;
}
//
bool MkDir(const char *path, int permissions, bool verbose) {
#if _WIN32
return CreateDirectoryW(reinterpret_cast<const wchar_t *>(utf8_to_utf16(path).data()), nullptr) == TRUE;
const auto res = CreateDirectoryW(utf8_to_wchar(path).c_str(), nullptr) != 0;
if (!verbose && !res)
error(format("MkDir(%1) failed with error: %2").arg(path).arg(GetLastError_Win32()));
return res;
#else
return mkdir(path, permissions) == 0;
#endif
}
bool RmDir(const char *path) {
bool RmDir(const char *path, bool verbose) {
#if _WIN32
return RemoveDirectoryW(reinterpret_cast<const wchar_t *>(utf8_to_utf16(path).data())) == TRUE;
const auto res = RemoveDirectoryW(utf8_to_wchar(path).c_str()) != 0;
if (verbose && !res)
error(format("RmDir(%1) failed with error: %2").arg(path).arg(GetLastError_Win32()));
return res;
#else
return false;
#endif
}
bool MkTree(const char *path, int permissions) {
bool MkTree(const char *path, int permissions, bool verbose) {
const auto dirs = split(CleanPath(path), "/");
std::string p;
for (auto &dir : dirs) {
p += dir + "/";
if (ends_with(dir.c_str(), ":"))
continue; // skip c:
if (Exists(p.c_str()))
continue;
if (!MkDir(p.c_str(), permissions))
if (!MkDir(p.c_str(), permissions, verbose))
return false;
}
return true;
}
bool RmTree(const char *path) {
bool RmTree(const char *path, bool verbose) {
#if _WIN32
std::string _path(path);
if (!ends_with(_path, "/"))
_path += "/";
const std::wstring w_path = reinterpret_cast<const wchar_t *>(utf8_to_utf16(_path).data()), w_filter = w_path + L"*.*";
const std::wstring wpath = utf8_to_wchar(_path);
const std::wstring wfilter = wpath + L"*.*";
WIN32_FIND_DATAW FindFileData;
ZeroMemory(&FindFileData, sizeof(FindFileData));
HANDLE hFind = FindFirstFileW(w_filter.c_str(), &FindFileData);
HANDLE hFind = FindFirstFileW(wfilter.c_str(), &FindFileData);
if (hFind != nullptr && hFind != INVALID_HANDLE_VALUE) {
while (FindNextFileW(hFind, &FindFileData) != 0) {
if (wcscmp(FindFileData.cFileName, L".") != 0 && wcscmp(FindFileData.cFileName, L"..") != 0) {
if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
const std::u16string upath = reinterpret_cast<const char16_t *>((w_path + std::wstring(FindFileData.cFileName)).c_str());
RmTree(utf16_to_utf8(upath).c_str());
if (!RmTree(wchar_to_utf8(wpath + std::wstring(FindFileData.cFileName)).c_str(), verbose))
return false;
} else {
DeleteFileW((w_path + std::wstring(FindFileData.cFileName)).c_str());
if (!DeleteFileW((wpath + std::wstring(FindFileData.cFileName)).c_str()))
return false;
}
}
}
FindClose(hFind);
}
RemoveDirectoryW(w_path.c_str());
return true;
return RemoveDirectoryW(wpath.c_str());
#else
return false;
#endif
@ -186,8 +214,7 @@ bool RmTree(const char *path) {
bool IsDir(const char *path) {
#if WIN32
struct _stat info;
const auto path_utf16 = utf8_to_utf16(path);
if (_wstat(LPCWSTR(path_utf16.c_str()), &info) != 0)
if (_wstat(utf8_to_wchar(path).c_str(), &info) != 0)
return false;
#else
struct stat info;
@ -279,8 +306,13 @@ bool CopyDirRecursive(const char *src, const char *dst) {
}
bool Exists(const char *path) {
#if _WIN32
struct _stat info;
return _wstat(utf8_to_wchar(path).data(), &info) == 0;
#else
struct stat info;
return stat(path, &info) == 0;
#endif
}
} // namespace hg

View File

@ -20,11 +20,13 @@ struct DirEntry {
std::vector<DirEntry> ListDir(const char *path, int mask = DE_All);
std::vector<DirEntry> ListDirRecursive(const char *path, int mask = DE_All);
bool MkDir(const char *path, int permissions = 01777);
bool RmDir(const char *path);
size_t GetDirSize(const char *path);
bool MkTree(const char *path, int permissions = 01777);
bool RmTree(const char *path);
bool MkDir(const char *path, int permissions = 01777, bool verbose = false);
bool RmDir(const char *path, bool verbose = false);
bool MkTree(const char *path, int permissions = 01777, bool verbose = false);
bool RmTree(const char *path, bool verbose = false);
/// tmplt should end with at least six trailing 'x' characters
char *MkTempDir(const char *tmplt);

View File

@ -30,15 +30,16 @@ static std::mutex files_mutex;
static FILE *_Open(const char *path, const char *mode, bool silent = false) {
FILE *file = nullptr;
#if _WIN32
auto path_utf16 = utf8_to_utf16(path);
auto mode_utf16 = utf8_to_utf16(mode);
const auto err = _wfopen_s(&file, LPCWSTR(path_utf16.data()), LPCWSTR(mode_utf16.data()));
if (!silent)
if (err != 0) {
char errmsg[256];
strerror_s(errmsg, 255, err);
error(format("Failed to open file '%1' mode '%2', error code %3 (%4)").arg(path).arg(mode).arg(err).arg(errmsg));
}
auto wpath = utf8_to_wchar(path);
auto wmode = utf8_to_wchar(mode);
const auto err = _wfopen_s(&file, wpath.data(), wmode.data());
if (!silent && err != 0) {
char errmsg[256];
strerror_s(errmsg, 255, err);
error(format("Failed to open file '%1' mode '%2', error code %3 (%4)").arg(path).arg(mode).arg(err).arg(errmsg));
}
#else
file = fopen(path, mode);
#endif
@ -207,8 +208,8 @@ void Rewind(File file) {
FileInfo GetFileInfo(const char *path) {
#if WIN32
struct _stat info;
const auto path_utf16 = utf8_to_utf16(path);
if (_wstat(LPCWSTR(path_utf16.c_str()), &info) != 0)
const auto wpath = utf8_to_wchar(path);
if (_wstat(wpath.c_str(), &info) != 0)
return {false, 0, 0, 0};
#else
struct stat info;
@ -222,8 +223,8 @@ FileInfo GetFileInfo(const char *path) {
bool IsFile(const char *path) {
#if WIN32
struct _stat info;
const auto path_utf16 = utf8_to_utf16(path);
if (_wstat(LPCWSTR(path_utf16.c_str()), &info) != 0)
const auto wpath = utf8_to_wchar(path);
if (_wstat(wpath.c_str(), &info) != 0)
return false;
#else
struct stat info;
@ -238,8 +239,8 @@ bool IsFile(const char *path) {
bool Unlink(const char *path) {
#if _WIN32
const auto path_utf16 = utf8_to_utf16(path);
return DeleteFileW(LPCWSTR(path_utf16.c_str())) == TRUE;
const auto wpath = utf8_to_wchar(path);
return DeleteFileW(wpath.c_str()) == TRUE;
#else
return unlink(path) == 0;
#endif
@ -248,9 +249,9 @@ bool Unlink(const char *path) {
//
bool CopyFile(const char *src, const char *dst) {
#if _WIN32
const auto src_utf16 = utf8_to_utf16(src);
const auto dst_utf16 = utf8_to_utf16(dst);
return ::CopyFileW((LPCWSTR)src_utf16.c_str(), (LPCWSTR)dst_utf16.c_str(), FALSE) ? true : false;
const auto wsrc = utf8_to_wchar(src);
const auto wdst = utf8_to_wchar(dst);
return ::CopyFileW(wsrc.c_str(), wdst.c_str(), FALSE) ? true : false;
#else
ScopedFile in(Open(src));
if (!in)
@ -272,9 +273,9 @@ bool CopyFile(const char *src, const char *dst) {
}
//
Data FileToData(const char *path) {
Data FileToData(const char *path, bool silent) {
Data data;
File file = Open(path);
File file = Open(path, silent);
if (IsValid(file)) {
data.Resize(GetSize(file));
@ -286,8 +287,8 @@ Data FileToData(const char *path) {
}
//
std::string FileToString(const char *path) {
ScopedFile in(Open(path));
std::string FileToString(const char *path, bool silent) {
ScopedFile in(Open(path, silent));
const auto size = GetSize(in);
std::string str(size, 0);

View File

@ -65,10 +65,10 @@ template <typename T> bool Write(File file, const T &v) { return Write(file, &v,
bool CopyFile(const char *src, const char *dst);
std::string FileToString(const char *path);
std::string FileToString(const char *path, bool silent = false);
bool StringToFile(const char *path, const char *str);
Data FileToData(const char *path);
Data FileToData(const char *path, bool silent = false);
//
struct ScopedFile {

View File

@ -51,7 +51,7 @@ Mat3 CrossProductMat3(const Vec3 &v) { return {0, -v.z, v.y, v.z, 0, -v.x, -v.y,
Mat3 Normalize(const Mat3 &m) { return {Normalize(GetRow(m, 0)), Normalize(GetRow(m, 1)), Normalize(GetRow(m, 2))}; }
Mat3 Orthonormalize(const Mat3 &m) {
auto x = GetRow(m, 0), y = GetRow(m, 1), z = Normalize(Cross(x, y));
const auto x = GetRow(m, 0), y = GetRow(m, 1), z = Normalize(Cross(x, y));
return {Normalize(x), Normalize(Cross(z, x)), z};
}

View File

@ -149,10 +149,10 @@ void SetScale(Mat3 &m, const Vec3 &S);
void SetAxises(Mat3 &m, const Vec3 &x, const Vec3 &y, const Vec3 &z);
/// Return this matrix after normalization.
Mat3 Normalize(const Mat3 &m);
/// Normalize as orthonormal base.
/// Orthonormalize matrix.
Mat3 Orthonormalize(const Mat3 &m);
/// Normalize matrix.
Mat3 Normalize(const Mat3 &m);
/// Return an Euler orientation equivalent to this matrix.
Vec3 ToEuler(const Mat3 &m, RotationOrder order = RO_Default);

View File

@ -293,7 +293,13 @@ Mat4 InverseFast(const Mat4 &m) {
//
Mat4 Orthonormalize(const Mat4 &m) {
return Mat4(Orthonormalize(Mat3(m.m[0][0], m.m[1][0], m.m[2][0], m.m[0][1], m.m[1][1], m.m[2][1], m.m[0][2], m.m[1][2], m.m[2][2])));
const auto T = GetT(m);
return TransformationMat4(T, Orthonormalize(Mat3(m)));
}
Mat4 Normalize(const Mat4 &m) {
const auto T = GetT(m);
return TransformationMat4(T, Normalize(Mat3(m)));
}
//

View File

@ -42,8 +42,10 @@ bool Inverse(const Mat4 &m, Mat4 &i);
/// Return the inverse of an affine transformation matrix.
Mat4 InverseFast(const Mat4 &m);
/// Normalize matrix.
/// Ortho-normalize matrix.
Mat4 Orthonormalize(const Mat4 &m);
/// Normalize matrix.
Mat4 Normalize(const Mat4 &m);
/// Decompose a transformation matrix into a position vector, a scale vector and a 3x3 rotation matrix.
void Decompose(const Mat4 &m, Vec3 *position, Mat3 *rotation = nullptr, Vec3 *scale = nullptr);

View File

@ -219,13 +219,10 @@ std::string CleanFileName(const std::string &filename) {
std::string GetCurrentWorkingDirectory() {
WCHAR path[1024];
GetCurrentDirectoryW(1024 - 1, path); // poorly worded documentation makes it unclear if nBufferLength should account for the terminator or not...
return utf16_to_utf8(std::u16string(reinterpret_cast<const std::u16string::value_type *>(path)));
return wchar_to_utf8(path);
}
bool SetCurrentWorkingDirectory(const std::string &path) {
auto utf16 = utf8_to_utf16(path);
return SetCurrentDirectoryW(reinterpret_cast<LPCWSTR>(utf16.data())) == TRUE;
}
bool SetCurrentWorkingDirectory(const std::string &path) { return SetCurrentDirectoryW(utf8_to_wchar(path).c_str()) == TRUE; }
std::string GetUserFolder() {
HRESULT res;

View File

@ -246,18 +246,6 @@ std::string strip_prefix(const std::string &str, const std::string &prefix) { re
std::string strip_suffix(const std::string &str, const std::string &suffix) { return ends_with(str, suffix) ? slice(str, 0, -int(suffix.length())) : str; }
//
std::string utf16_to_utf8(const std::u16string &str) {
std::vector<unsigned char> utf8string;
utf8::utf16to8(str.begin(), str.end(), std::back_inserter(utf8string));
return std::string((char *)utf8string.data(), utf8string.size());
}
std::u16string utf8_to_utf16(const std::string &str) {
std::vector<uint16_t> utf16string;
utf8::utf8to16(str.begin(), str.end(), std::back_inserter(utf16string));
return std::u16string(reinterpret_cast<char16_t *>(utf16string.data()), utf16string.size());
}
std::string utf32_to_utf8(const std::u32string &str) {
std::vector<unsigned char> utf8string;
utf8::utf32to8(str.begin(), str.end(), std::back_inserter(utf8string));
@ -297,6 +285,7 @@ std::wstring ansi_to_wchar(const std::string &str) {
std::string ansi_to_utf8(const std::string &string) { return wchar_to_utf8(ansi_to_wchar(string)); }
//
void tolower_inplace(std::string &str, size_t start, size_t end) {
transform(std::begin(str) + start, end ? std::begin(str) + end : std::end(str), std::begin(str) + start,
[](char c) -> char { return c >= 65 && c <= 90 ? c + (97 - 65) : c; });

View File

@ -111,9 +111,6 @@ template <typename T> std::string join(T begin_it, T end_it, const std::string &
bool contains(const std::string &in, const std::string &what);
std::string utf16_to_utf8(const std::u16string &str);
std::u16string utf8_to_utf16(const std::string &str);
std::string utf32_to_utf8(const std::u32string &str);
std::u32string utf8_to_utf32(const std::string &str);
@ -123,7 +120,6 @@ std::wstring utf8_to_wchar(const std::string &str);
std::wstring ansi_to_wchar(const std::string &str);
std::string ansi_to_utf8(const std::string &str);
void tolower_inplace(std::string &inplace_str, size_t start = 0, size_t end = 0);
std::string tolower(std::string str, size_t start = 0, size_t end = 0);
void toupper_inplace(std::string &inplace_str, size_t start = 0, size_t end = 0);

View File

@ -14,10 +14,6 @@ set(SRCS
window_system_base.cpp)
if(HG_USE_GLFW)
list(APPEND HDRS
glfw/input_system_glfw.h
)
list(APPEND SRCS
glfw/input_system_glfw.cpp
glfw/window_system.cpp
@ -87,6 +83,10 @@ if(WIN32)
target_link_libraries(platform foundation User32 Gdi32 Ws2_32 Wldap32 Winmm DbgHelp Shlwapi)
target_include_directories(platform PUBLIC ${GLFW_INCLUDE_DIRS})
target_link_libraries(platform foundation glfw)
if(MSVC)
target_compile_options(platform PRIVATE "$<$<CONFIG:Release>:/Zi>")
target_link_options(platform PRIVATE "$<$<CONFIG:Release>:/DEBUG>")
endif()
elseif(ANDROID)
target_include_directories(platform PRIVATE ${ANDROID_NDK}/sources/android/native_app_glue)
target_link_libraries(platform foundation android log)
@ -95,12 +95,15 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
else()
target_include_directories(platform PUBLIC ${GLFW_INCLUDE_DIRS})
target_link_libraries(platform foundation glfw)
if(UNIX AND NOT APPLE)
if(NOT HG_EMBEDDED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
target_include_directories(platform PRIVATE ${GTK3_INCLUDE_DIRS})
target_link_libraries(platform ${GTK3_LIBRARIES})
if(UNIX AND NOT APPLE AND NOT EMSCRIPTEN)
find_package(PkgConfig)
if(PkgConfig_FOUND)
pkg_check_modules(GTK3 gtk+-3.0)
if(GTK3_FOUND)
target_include_directories(platform PRIVATE ${GTK3_INCLUDE_DIRS})
target_link_libraries(platform ${GTK3_LIBRARIES})
target_compile_definitions(platform PUBLIC HG_USE_GTK3)
endif()
endif()
target_link_libraries(platform dl)
endif()

View File

@ -575,7 +575,7 @@ template <int ID> std::string DeviceNameJoystick() {
//
static Signal<void(const Window *)>::Connection on_new_window_connection;
void RegisterGLFW3InputSystem() {
void InputInit() {
on_new_window_connection = new_window_signal.Connect(&OnNewWindow);
AddMouseReader("default", ReadMouse);
@ -627,6 +627,6 @@ void RegisterGLFW3InputSystem() {
#endif
}
void UnregisterGLFW3InputSystem() { new_window_signal.Disconnect(on_new_window_connection); }
void InputShutdown() { new_window_signal.Disconnect(on_new_window_connection); }
} // namespace hg

View File

@ -1,10 +0,0 @@
// HARFANG(R) Copyright (C) 2021 Emmanuel Julien, NWNC HARFANG. Released under GPL/LGPL/Commercial Licence, see licence.txt for details.
#pragma once
namespace hg {
void RegisterGLFW3InputSystem();
void UnregisterGLFW3InputSystem();
} // namespace hg

View File

@ -12,16 +12,16 @@
#include <map>
#if defined(WIN32)
#if defined(GLFW_WIN32)
#define GLFW_EXPOSE_NATIVE_WIN32
#define GLFW_GET_NATIVE_WINDOW_HANDLE glfwGetWin32Window
#elif defined(__APPLE__)
#elif defined(GLFW_COCOA)
#define GLFW_EXPOSE_NATIVE_COCOA
#define GLFW_GET_NATIVE_WINDOW_HANDLE glfwGetCocoaWindow
#elif defined(HG_USE_GLFW_WAYLAND)
#elif defined(GLFW_WAYLAND)
#define GLFW_EXPOSE_NATIVE_WAYLAND
#define GLFW_GET_NATIVE_WINDOW_HANDLE glfwGetWaylandWindow
#elif defined(__linux__)
#elif defined(GLFW_X11)
#define GLFW_EXPOSE_NATIVE_X11
#define GLFW_GET_NATIVE_WINDOW_HANDLE glfwGetX11Window
#else
@ -30,9 +30,9 @@
#include <GLFW/glfw3native.h>
#if defined(HG_USE_GLFW_WAYLAND)
#if defined(GLFW_WAYLAND)
#include <wayland-egl.h>
#endif // HG_USE_GLFW_WAYLAND
#endif // GLFW_WAYLAND
namespace hg {
@ -52,9 +52,9 @@ void *main_window_handle = nullptr;
struct GLFWWindowData {
char *title;
#if defined(HG_USE_GLFW_WAYLAND)
#if GLFW_WAYLAND
struct wl_egl_window *egl_win;
#endif // HG_USE_GLFW_WAYLAND
#endif // GLFW_WAYLAND
};
static void ErrorCallback(int error_code, const char *description) { error(description); }
@ -156,9 +156,9 @@ struct Window {
};
void *GetDisplay() {
#if defined(HG_USE_GLFW_WAYLAND)
#if GLFW_WAYLAND
return glfwGetWaylandDisplay();
#elif defined(__linux__)
#elif GLFW_LINUX
return glfwGetX11Display();
#else
return nullptr;
@ -169,7 +169,7 @@ void *GetWindowHandle(const Window *w) {
if (!w) {
return nullptr;
}
#if defined(HG_USE_GLFW_WAYLAND)
#if GLFW_WAYLAND
GLFWwindow *glfw_win = (GLFWwindow *)w;
GLFWWindowData *data = reinterpret_cast<GLFWWindowData *>(glfwGetWindowUserPointer(glfw_win));
if (!data) {
@ -187,7 +187,7 @@ void *GetWindowHandle(const Window *w) {
return data->egl_win;
#else
return (void *)GLFW_GET_NATIVE_WINDOW_HANDLE((GLFWwindow *)w);
#endif // HG_USE_GLFW_WAYLAND
#endif // GLFW_WAYLAND
}
static void WindowFocusCallback(GLFWwindow *window, int focused) {
@ -215,12 +215,12 @@ static Window *NewGLFWWindow(int width, int height, int bpp, const GLFWmonitor *
if (window) {
GLFWWindowData *data = new GLFWWindowData;
data->title = strdup(g_default_window_title);
#if defined(HG_USE_GLFW_WAYLAND)
#if GLFW_WAYLAND
struct wl_surface *surface = (struct wl_surface *)glfwGetWaylandWindow(window);
if (surface) {
data->egl_win = wl_egl_window_create(surface, width, height);
}
#endif // HG_USE_GLFW_WAYLAND
#endif // GLFW_WAYLAND
glfwSetWindowUserPointer(window, data);
glfwSetWindowFocusCallback(window, WindowFocusCallback);
glfwSetWindowCloseCallback(window, WindowCloseCallback);
@ -318,11 +318,11 @@ bool DestroyWindow(Window *w) {
if (data->title) {
free(data->title);
}
#if defined(HG_USE_GLFW_WAYLAND)
#if GLFW_WAYLAND
if (data->egl_win) {
wl_egl_window_destroy(data->egl_win);
}
#endif // HG_USE_GLFW_WAYLAND
#endif // GLFW_WAYLAND
free(data);
}
@ -345,7 +345,7 @@ bool SetWindowClientSize(Window *w, int width, int height) {
return false;
glfwSetWindowSize((GLFWwindow *)w, width, height);
#if defined(HG_USE_GLFW_WAYLAND)
#if GLFW_WAYLAND
GLFWWindowData *data = reinterpret_cast<GLFWWindowData *>(glfwGetWindowUserPointer((GLFWwindow *)w));
if (data) {
struct wl_surface *surface = (struct wl_surface *)glfwGetWaylandWindow((GLFWwindow *)w);
@ -357,7 +357,7 @@ bool SetWindowClientSize(Window *w, int width, int height) {
}
data->egl_win = wl_egl_window_create(surface, width, height);
}
#endif // HG_USE_GLFW_WAYLAND
#endif // GLFW_WAYLAND
return true;
}

View File

@ -4,9 +4,6 @@
#include "foundation/log.h"
#include "platform/input_system.h"
#if HG_USE_GLFW
#include "glfw/input_system_glfw.h"
#endif
#include <algorithm>
#include <cstring>
@ -250,17 +247,4 @@ VRGenericTracker::VRGenericTracker(const char *n) : name(n) {}
void VRGenericTracker::Update() { state = ReadVRGenericTracker(name.c_str()); }
//
void InputInit() {
#if HG_USE_GLFW
RegisterGLFW3InputSystem();
#endif
}
void InputShutdown() {
#if HG_USE_GLFW
UnregisterGLFW3InputSystem();
#endif
}
} // namespace hg

View File

@ -3,18 +3,25 @@
#pragma once
#include <string>
#include <vector>
namespace hg {
/// Return the platform locale.
std::string GetPlatformLocale();
/// File filter.
struct FileFilter {
std::string name;
std::string pattern;
};
/// Open a file dialog
bool OpenFolderDialog(const std::string &title, std::string &output, const std::string &initial_dir = {});
/// Open a file dialog
bool OpenFileDialog(const std::string &title, const std::string &filter, std::string &output, const std::string &initial_dir = {});
bool OpenFileDialog(const std::string &title, const std::vector<FileFilter> &filters, std::string &output, const std::string &initial_dir = {});
/// Open a save file dialog
bool SaveFileDialog(const std::string &title, const std::string &filter, std::string &output, const std::string &initial_dir = {});
bool SaveFileDialog(const std::string &title, const std::vector<FileFilter> &filters, std::string &output, const std::string &initial_dir = {});
/// Platform specific initialization.
bool InitPlatform();

View File

@ -1,45 +1,78 @@
// HARFANG(R) Copyright (C) 2021 Emmanuel Julien, NWNC HARFANG. Released under GPL/LGPL/Commercial Licence, see licence.txt for details.
#include "../platform.h"
#include <cstdio>
#include <cstdlib>
#include <sstream>
#include <string>
#if !(defined(EMSCRIPTEN) || defined(HG_EMBEDDED))
#if HG_USE_GTK3
#include <gtk/gtk.h>
#endif
#ifdef HG_USE_GLFW
#include "platform/glfw/input_system_glfw.h"
#endif
#include "foundation/string.h"
namespace hg {
bool InitPlatform() {
#ifdef HG_USE_GLFW
RegisterGLFW3InputSystem();
#endif
return true;
}
bool OpenFileDialog(const std::string &title, const std::string &filter, std::string &OUTPUT, const std::string &initial_dir) {
#if !(defined(EMSCRIPTEN) || defined(HG_EMBEDDED))
enum class Action : int {
FileOpen = 0,
FileSave,
SelectFolder,
Count
};
static bool FileChooserImpl(const std::string &title, const std::vector<FileFilter> &filters, std::string &output, const std::string &initial_dir, Action file_chooser_action) {
#if HG_USE_GTK3
GtkFileChooserAction action_id;
const char *action_str;
switch(file_chooser_action) {
case Action::FileSave:
action_id = GTK_FILE_CHOOSER_ACTION_SAVE;
action_str = "_Save";
break;
case Action::SelectFolder:
action_id = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
action_str = "_Open";
break;
//case Action::FileOpen:
default:
action_id = GTK_FILE_CHOOSER_ACTION_OPEN;
action_str = "_Open";
break;
}
if (!gtk_init_check(NULL, NULL))
return false;
GtkWidget *dialog = gtk_file_chooser_dialog_new(title.c_str(),
NULL,
GTK_FILE_CHOOSER_ACTION_OPEN,
action_id,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Open", GTK_RESPONSE_ACCEPT,
action_str, GTK_RESPONSE_ACCEPT,
NULL);
if (!initial_dir.empty())
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), initial_dir.c_str());
for(auto &it: filters) {
GtkFileFilter *filter = gtk_file_filter_new();
gtk_file_filter_set_name(filter, it.name.c_str());
for(auto pat : split(it.pattern, ";")) {
gtk_file_filter_add_pattern(filter, pat.c_str());
}
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
}
bool res = false;
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
char *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
OUTPUT = filename;
output = filename;
g_free(filename);
res = true;
}
@ -54,16 +87,20 @@ bool OpenFileDialog(const std::string &title, const std::string &filter, std::st
return res;
#else
return false;
return true;
#endif
}
bool SaveFileDialog(const std::string &title, const std::string &filter, std::string &OUTPUT, const std::string &initial_dir) {
return false;
bool OpenFileDialog(const std::string &title, const std::vector<FileFilter> &filters, std::string &output, const std::string &initial_dir) {
return FileChooserImpl(title, filters, output, initial_dir, Action::FileOpen);
}
bool OpenFolderDialog(const std::string &title, std::string &OUTPUT, const std::string &initial_dir) {
return false;
bool SaveFileDialog(const std::string &title, const std::vector<FileFilter> &filters, std::string &output, const std::string &initial_dir) {
return FileChooserImpl(title, filters, output, initial_dir, Action::FileSave);
}
bool OpenFolderDialog(const std::string &title, std::string &output, const std::string &initial_dir) {
return FileChooserImpl(title, {}, output, initial_dir, Action::SelectFolder);
}
void DebugBreak() { /* STUB */ }

View File

@ -222,4 +222,7 @@ void RegisterInputDevices(InputSystem &system) {
system.RegisterDirectDevice("keyboard", std::make_shared<Keyboard>());
}
void InputInit() {}
void InputShutdown() {}
} // namespace hg

View File

@ -1,5 +1,6 @@
#include "foundation/string.h"
#include "platform/call_stack.h"
#include <sstream>
#define WINDOWS_LEAN_AND_MEAN
@ -17,7 +18,7 @@ void win32_trigger_assert(const char *source, int line, const char *function, co
CaptureCallstack(callstack);
description << "\nCallstack:\n" << to_string(callstack);
MessageBoxW(nullptr, (LPCWSTR)utf8_to_utf16(description.str()).c_str(), L"Assertion failed", MB_ICONSTOP);
MessageBoxW(nullptr, utf8_to_wchar(description.str()).c_str(), L"Assertion failed", MB_ICONSTOP);
#if _DEBUG || MIXED_RELEASE
DebugBreak();
#endif

View File

@ -86,9 +86,9 @@ static std::string GetTempFilename(const char *prefix) {
GetTempPathW(MAX_PATH, temp_path);
WCHAR filename[MAX_PATH + 1];
GetTempFileNameW(temp_path, (LPCWSTR)utf8_to_utf16(prefix).c_str(), 0, filename);
GetTempFileNameW(temp_path, utf8_to_wchar(prefix).c_str(), 0, filename);
return utf16_to_utf8((std::u16string::value_type *)filename);
return wchar_to_utf8(filename);
}
LONG WINAPI TopLevelExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) {
@ -96,14 +96,14 @@ LONG WINAPI TopLevelExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) {
std::string _minidump_filename = minidump_filename ? minidump_filename : GetTempFilename("hfg_dump");
if (write_crash_minidump)
WriteMiniDump(pExceptionInfo, (LPCWSTR)utf8_to_utf16(_minidump_filename).c_str());
WriteMiniDump(pExceptionInfo, utf8_to_wchar(_minidump_filename).c_str());
// output report
std::string _report_filename = report_filename ? report_filename : GetTempFilename("hfg_crash_report");
if (write_crash_report) {
#if WIN32
std::ofstream f((wchar_t *)utf8_to_utf16(_report_filename).c_str(), std::ios::out | std::ios::trunc);
std::ofstream f(utf8_to_wchar(_report_filename).c_str(), std::ios::out | std::ios::trunc);
#else
std::ofstream f(_report_filename.c_str(), std::ios::out | std::ios::trunc);
#endif
@ -259,7 +259,7 @@ LONG WINAPI TopLevelExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) {
if (write_crash_minidump)
msg += "* Dump: " + _minidump_filename + "\n";
}
MessageBoxW(nullptr, (LPCWSTR)utf8_to_utf16(msg).c_str(), L"Fatal error", MB_ICONSTOP);
MessageBoxW(nullptr, utf8_to_wchar(msg).c_str(), L"Fatal error", MB_ICONSTOP);
return EXCEPTION_CONTINUE_SEARCH;
}

View File

@ -1,5 +1,7 @@
// HARFANG(R) Copyright (C) 2021 Emmanuel Julien, NWNC HARFANG. Released under GPL/LGPL/Commercial Licence, see licence.txt for details.
#include "platform/platform.h"
#include "platform/win32/platform.h"
#include "foundation/assert.h"
#include "foundation/format.h"
#include "foundation/log.h"
@ -7,7 +9,6 @@
#include "foundation/string.h"
#include "platform/input_system.h"
#include "platform/win32/assert.h"
#include "platform/win32/platform.h"
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
@ -21,15 +22,15 @@ bool InitPlatform() {
}
std::string GetPlatformLocale() {
char16_t locale_name[LOCALE_NAME_MAX_LENGTH];
wchar_t locale_name[LOCALE_NAME_MAX_LENGTH];
if (!GetSystemDefaultLocaleName((LPWSTR)locale_name, LOCALE_NAME_MAX_LENGTH)) {
warn("Failed to retrieve system locale");
locale_name[0] = 0;
}
return utf16_to_utf8(std::u16string(locale_name));
return wchar_to_utf8(locale_name);
}
bool OpenFolderDialog(const std::string &title, std::string &OUTPUT, const std::string &initial_dir) {
bool OpenFolderDialog(const std::string &title, std::string &output, const std::string &initial_dir) {
IFileOpenDialog *pFileOpen;
// create the FileOpenDialog object
@ -38,19 +39,16 @@ bool OpenFolderDialog(const std::string &title, std::string &OUTPUT, const std::
if (SUCCEEDED(hr)) {
// set title
if (!title.empty()) {
const auto wtitle = utf8_to_utf16(title);
pFileOpen->SetTitle((LPCWSTR)wtitle.c_str());
}
if (!title.empty())
pFileOpen->SetTitle(utf8_to_wchar(title).c_str());
// set base folder
if (!initial_dir.empty()) {
auto win_path = initial_dir;
replace_all(win_path, "/", "\\");
const auto winitial_dir = utf8_to_utf16(win_path);
IShellItem *psiFolder;
const auto hr = SHCreateItemFromParsingName((LPCWSTR)winitial_dir.c_str(), NULL, IID_PPV_ARGS(&psiFolder));
const auto hr = SHCreateItemFromParsingName(utf8_to_wchar(win_path).c_str(), NULL, IID_PPV_ARGS(&psiFolder));
if (SUCCEEDED(hr)) {
pFileOpen->SetFolder(psiFolder);
@ -77,7 +75,7 @@ bool OpenFolderDialog(const std::string &title, std::string &OUTPUT, const std::
// display the file name to the user
if (SUCCEEDED(hr))
OUTPUT = CleanPath(utf16_to_utf8(std::u16string((char16_t *)pszFilePath)));
output = CleanPath(wchar_to_utf8(pszFilePath));
pItem->Release();
}
}
@ -87,7 +85,7 @@ bool OpenFolderDialog(const std::string &title, std::string &OUTPUT, const std::
return SUCCEEDED(hr);
}
bool OpenFileDialog(const std::string &title, const std::string &filter, std::string &OUTPUT, const std::string &initial_dir) {
bool OpenFileDialog(const std::string &title, const std::vector<hg::FileFilter> &filters, std::string &output, const std::string &initial_dir) {
IFileOpenDialog *pFileOpen;
// create the FileOpenDialog object
@ -96,19 +94,16 @@ bool OpenFileDialog(const std::string &title, const std::string &filter, std::st
if (SUCCEEDED(hr)) {
// set title
if (!title.empty()) {
const auto wtitle = utf8_to_utf16(title);
pFileOpen->SetTitle((LPCWSTR)wtitle.c_str());
}
if (!title.empty())
pFileOpen->SetTitle(utf8_to_wchar(title).c_str());
// set base folder
if (!initial_dir.empty()) {
auto win_path = initial_dir;
replace_all(win_path, "/", "\\");
const auto winitial_dir = utf8_to_utf16(win_path);
IShellItem *psiFolder;
hr = SHCreateItemFromParsingName((LPCWSTR)winitial_dir.c_str(), NULL, IID_PPV_ARGS(&psiFolder));
hr = SHCreateItemFromParsingName(utf8_to_wchar(win_path).c_str(), NULL, IID_PPV_ARGS(&psiFolder));
if (SUCCEEDED(hr)) {
hr = pFileOpen->SetDefaultFolder(psiFolder);
@ -121,9 +116,20 @@ bool OpenFileDialog(const std::string &title, const std::string &filter, std::st
}
// add filters
auto wfilter = utf8_to_utf16(filter);
COMDLG_FILTERSPEC filters[] = {{L"", (LPCWSTR)wfilter.c_str()}};
pFileOpen->SetFileTypes(1, filters);
std::vector<COMDLG_FILTERSPEC> w32_filters;
std::vector<std::wstring> wstring_buffer;
if (!filters.empty()) {
w32_filters.resize(filters.size());
wstring_buffer.reserve(2 * filters.size());
for (size_t i = 0; i < filters.size(); i++) {
wstring_buffer.emplace_back(utf8_to_wchar(filters[i].name));
w32_filters[i].pszName = wstring_buffer.back().c_str();
wstring_buffer.emplace_back(utf8_to_wchar(filters[i].pattern));
w32_filters[i].pszSpec = wstring_buffer.back().c_str();
}
pFileOpen->SetFileTypes(static_cast<UINT>(w32_filters.size()), w32_filters.data());
}
// show the open dialog box
hr = pFileOpen->Show(NULL);
@ -138,7 +144,7 @@ bool OpenFileDialog(const std::string &title, const std::string &filter, std::st
// display the file name to the user
if (SUCCEEDED(hr))
OUTPUT = CleanPath(utf16_to_utf8(std::u16string((char16_t *)pszFilePath)));
output = CleanPath(wchar_to_utf8(pszFilePath));
pItem->Release();
}
}
@ -147,7 +153,7 @@ bool OpenFileDialog(const std::string &title, const std::string &filter, std::st
return SUCCEEDED(hr);
}
bool SaveFileDialog(const std::string &title, const std::string &filter, std::string &OUTPUT, const std::string &initial_dir) {
bool SaveFileDialog(const std::string &title, const std::vector<hg::FileFilter> &filters, std::string &output, const std::string &initial_dir) {
IFileSaveDialog *pFileSave;
// create the FilSaveDialog object
@ -157,25 +163,20 @@ bool SaveFileDialog(const std::string &title, const std::string &filter, std::st
if (SUCCEEDED(hr)) {
// set title
if (!title.empty()) {
const auto wtitle = utf8_to_utf16(title);
pFileSave->SetTitle((LPCWSTR)wtitle.c_str());
}
if (!title.empty())
pFileSave->SetTitle(utf8_to_wchar(title).c_str());
// set file name
if (!OUTPUT.empty()) {
const auto wfile = utf8_to_utf16(OUTPUT);
pFileSave->SetFileName((LPCWSTR)wfile.c_str());
}
if (!output.empty())
pFileSave->SetFileName(utf8_to_wchar(output).c_str());
// set base folder
if (!initial_dir.empty()) {
auto win_path = initial_dir;
replace_all(win_path, "/", "\\");
const auto winitial_dir = utf8_to_utf16(win_path);
IShellItem *psiFolder;
hr = SHCreateItemFromParsingName((LPCWSTR)winitial_dir.c_str(), NULL, IID_PPV_ARGS(&psiFolder));
hr = SHCreateItemFromParsingName(utf8_to_wchar(win_path).c_str(), NULL, IID_PPV_ARGS(&psiFolder));
if (SUCCEEDED(hr)) {
hr = pFileSave->SetFolder(psiFolder);
@ -186,10 +187,20 @@ bool SaveFileDialog(const std::string &title, const std::string &filter, std::st
}
// add filters
auto wfilter = utf8_to_utf16(filter);
COMDLG_FILTERSPEC filters[] = {{L"", (LPCWSTR)wfilter.c_str()}};
pFileSave->SetFileTypes(1, filters);
pFileSave->SetDefaultExtension((LPCWSTR)wfilter.c_str());
std::vector<COMDLG_FILTERSPEC> w32_filters;
std::vector<std::wstring> wstring_buffer;
if (!filters.empty()) {
w32_filters.resize(filters.size());
wstring_buffer.reserve(2 * filters.size());
for (size_t i = 0; i < filters.size(); i++) {
wstring_buffer.emplace_back(utf8_to_wchar(filters[i].name));
w32_filters[i].pszName = wstring_buffer.back().c_str();
wstring_buffer.emplace_back(utf8_to_wchar(filters[i].pattern));
w32_filters[i].pszSpec = wstring_buffer.back().c_str();
}
pFileSave->SetFileTypes(static_cast<UINT>(w32_filters.size()), w32_filters.data());
}
// show the Save dialog box
hr = pFileSave->Show(NULL);
@ -204,7 +215,7 @@ bool SaveFileDialog(const std::string &title, const std::string &filter, std::st
// display the file name to the user
if (SUCCEEDED(hr))
OUTPUT = CleanPath(utf16_to_utf8(std::u16string((char16_t *)pszFilePath)));
output = CleanPath(wchar_to_utf8(pszFilePath));
pItem->Release();
}
}
@ -217,14 +228,15 @@ void DebugBreak() { ::DebugBreak(); }
//
std::string GetLastError_Win32() {
std::string err;
LPWSTR err_win32 = NULL;
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&err_win32, 0, NULL);
std::string err;
if (err_win32) {
err = utf16_to_utf8(std::u16string(reinterpret_cast<const char16_t *>(err_win32)));
err = wchar_to_utf8(err_win32);
LocalFree(err_win32);
}

View File

@ -17,12 +17,12 @@
namespace hg {
bool SetSharedLibraryPath(const char *path) { return SetDllDirectoryW((LPCWSTR)utf8_to_utf16(path).c_str()) != 0; }
bool SetSharedLibraryPath(const char *path) { return SetDllDirectoryW(utf8_to_wchar(path).c_str()) != 0; }
SharedLib LoadSharedLibrary(const char *path) {
static_assert(sizeof(SharedLib) >= sizeof(HMODULE), "cannot fit HMODULE in SharedLib structure");
HMODULE mod = LoadLibraryW((LPCWSTR)utf8_to_utf16(path).c_str());
HMODULE mod = LoadLibraryW(utf8_to_wchar(path).c_str());
if (mod == 0)
error(format("LoadSharedLibrary('%1') failed, reason: %2").arg(path).arg(GetLastError_Win32()).c_str());

View File

@ -67,7 +67,3 @@ install(TARGETS tests
LIBRARY DESTINATION cppsdk/bin/$<CONFIG>
COMPONENT cppsdk
)
if(CMAKE_CXX_LINKER_SUPPORTS_PDB)
install(FILES $<TARGET_PDB_FILE:tests> DESTINATION cppsdk/pdb OPTIONAL COMPONENT cppsdk)
endif()

View File

@ -50,9 +50,9 @@ TEST(string, Upper) {
TEST(string, ToUCS2AndBack) {
std::string in("D:/test.bin_!@#{]]}/*-=This is a TEST,;'");
auto u16 = utf8_to_utf16(in);
auto out = utf16_to_utf8(u16);
EXPECT_EQ(in, out);
auto wide = utf8_to_wchar(in);
auto narrow = wchar_to_utf8(wide);
EXPECT_EQ(in, narrow);
}
TEST(string, Slicing) {

View File

@ -1 +1 @@
3.2.0
3.2.1

View File

@ -42,22 +42,6 @@ install(FILES
COMPONENT go
)
install(TARGETS libluadll
RUNTIME DESTINATION hg_go
LIBRARY DESTINATION hg_go
COMPONENT go
)
if(HG_USE_GLFW)
install(FILES $<TARGET_FILE:glfw> DESTINATION hg_go COMPONENT go)
endif()
if(HG_ENABLE_OPENVR_API)
install(FILES ${OPENVR_DLL} DESTINATION hg_go COMPONENT go)
endif()
if(HG_ENABLE_SRANIPAL_API)
install(FILES ${SRANIPAL_DLL} DESTINATION hg_go COMPONENT go)
endif()
install_cppsdk_dependencies(hg_go go)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS OFF)

View File

@ -28,16 +28,6 @@ elseif(UNIX)
target_compile_definitions(hg_lua PUBLIC LUA_USE_LINUX)
endif()
install(TARGETS hg_lua lua libluadll RUNTIME DESTINATION hg_lua LIBRARY DESTINATION hg_lua COMPONENT lua)
install(TARGETS hg_lua lua RUNTIME DESTINATION hg_lua LIBRARY DESTINATION hg_lua COMPONENT lua)
if(HG_USE_GLFW)
install(FILES $<TARGET_FILE:glfw> DESTINATION hg_lua COMPONENT lua)
endif()
if(HG_ENABLE_OPENVR_API)
install(FILES ${OPENVR_DLL} DESTINATION hg_lua COMPONENT lua)
endif()
if(HG_ENABLE_SRANIPAL_API)
install(FILES ${SRANIPAL_DLL} DESTINATION hg_lua COMPONENT lua)
endif()
install_cppsdk_dependencies(hg_lua lua)

View File

@ -44,7 +44,7 @@ install(FILES __init__.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/bdist_wheel/ha
install(
TARGETS
hg_python libluadll
hg_python
RUNTIME DESTINATION
${CMAKE_CURRENT_BINARY_DIR}/bdist_wheel/harfang
LIBRARY DESTINATION
@ -52,17 +52,7 @@ install(
COMPONENT
python)
if(HG_USE_GLFW)
install(FILES $<TARGET_FILE:glfw> DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/bdist_wheel/harfang COMPONENT python)
endif()
if(HG_ENABLE_OPENVR_API)
install(FILES ${OPENVR_DLL} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/bdist_wheel/harfang COMPONENT python)
endif()
if(HG_ENABLE_SRANIPAL_API)
install(FILES ${SRANIPAL_DLL} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/bdist_wheel/harfang COMPONENT python)
endif()
install_cppsdk_dependencies(${CMAKE_CURRENT_BINARY_DIR}/bdist_wheel/harfang python)
if(WIN32)
set(BDIST_WHEEL_LIMITED_API_FLAGS "") # broken feature on Windows

View File

@ -1,3 +1,58 @@
# [3.2.1] - 2022-04-10
This minor release brings both code and submodules maintenance, several fixes in the toolchain, in the scenegraph and physics interchange and in the rendering pipeline.
### Source code maintenance
- Updated GLFW (3.3.6).
- Updated BGFX to the latest version.
- Updated OpenAL (v.1.6.10b).
- Updated OpenVR (v1.16.8).
- Fixed the debug build with Visual Studio Build Tools 2022.
- Fixed the installation of PDB files.
- CMake misc. fixes and updates.
### Toolchain
- FBX Importer: changed the unit of command line argument `max smoothing angle` to degrees and fixed the internal vertex/tangent computation.
- GLTF Importer: improved the way non-Windows-compliant filenames are handled.
### Engine
- Fixed an issue in the Wavefront OBJ export that flipped the model on the X axis.
- Improve the error message issued by OpenAssets in case of missing file.
- Fixed a crash when parsing a corrupted .HPS file.
- Added `hg::Picture::SaveBC7` and `hg::Picture::SaveBC6H` functions.
- Switched to a time limit based resource queue processing
- Return the size on disk of a folder
- Implemented a _ComputeNodeWorldMatrix_ to compute a node world matrix on the fly (`ComputeWorld`, `GetWorld`, `SetWorld`). :warning: This function is slow but useful when scene matrices are not yet up-to-date
- Improved the way unicode paths are handled on Windows
- Preliminary support for scene properties animation (`AmbientColor`, `FogNear`, `FogFar`, `FogColor`) while preserving the legacy file format.
- Add an `LSSF_Silent` scene flag, add many boolean flags to silence errors in the rendering IO.
- Allow 32 bit indices in geometries (In the future we might introduce a _force 16 bit indice flag_ if required).
- Validate index and vertex buffer handles when creating geometries.
- Flag instantiated nodes as `NF_InstanceDisabled` if the host node is disabled.
- Added file filter descriptions to the file selector dialogs (`OpenFileDialog`, `SaveFileDialog`).
### Rendering
- Added a _depth only_ pass to render shadow maps (`DEPTH_ONLY=1`).
- Set a higher probe resolution by default (from 64 to 512, using the `--glossScale 20` `--glossBias 0` parameters sent to CMFT).
- Load/save AAA config (`LoadForwardPipelineAAAConfigFromFile`, `LoadForwardPipelineAAAConfigFromAssets`, `SaveForwardPipelineAAAConfigToFile`)
- Tweaked the default light values (_default_shadow_bias_ set to 0.0001, _pssm_split_ of a the linear light set to 200m).
- Switched the jitter sequence to Halton (2,3).
- Added a function to retrieve the size of the OpenVR framebuffers
- Added a `RGBA32` pixel format to improve the performance when playing a video stream.
### Physics
- Fixed an issue in synchronizing state from scene to kinematic body
### Documentation
- Added an explanation of why using integer representation for time is important.
- Documented the profiler API.
- Added a HARFANG logo in the Doxygen documentation
# [3.2.0] - 2022-02-21
This minor release brings several fixes, performance improvements and new features to the rendering, physics and audio APIs.

View File

@ -13,9 +13,9 @@ if(UNIX)
endif()
# assetc installation
install(TARGETS assetc libluadll RUNTIME DESTINATION assetc LIBRARY DESTINATION assetc COMPONENT assetc)
install(TARGETS assetc RUNTIME DESTINATION assetc LIBRARY DESTINATION assetc COMPONENT assetc)
install(FILES $<TARGET_FILE:glfw> DESTINATION assetc COMPONENT assetc)
install_cppsdk_dependencies(assetc)
if(NOT ASSETC_TARGET_PREFIX)
set(ASSETC_TARGET_PREFIX ${HG_TARGET_PREFIX})

View File

@ -190,7 +190,14 @@ static std::string FullInputPath(const std::string &path) { return PathJoin({inp
static std::string FullOutputPath(const std::string &path) { return PathJoin({output_dir, path}); }
static std::string FullOutputDir(const std::string &path) { return CutFileName(FullOutputPath(path)); }
static void MkOutputTree(const std::string &path) { MkTree(FullOutputDir(path).c_str()); }
static bool MkOutputTree(const std::string &path) {
const auto res = MkTree(FullOutputDir(path).c_str());
if (!res) {
const json json_err = {{"type", "FailedToMkOutputTree"}, {"path", path}};
log_error(json_err);
}
return res;
}
#if HASH_METHOD == 0
using Hash = SHA1Hash;
@ -336,15 +343,20 @@ void Reset() {
//
void SetInputDir(const std::string &path) { input_dir = CleanPath(path); }
void SetOutputDir(const std::string &path) {
bool SetOutputDir(const std::string &path) {
output_dir = CleanPath(path);
MkTree(output_dir.c_str());
const auto res = MkTree(output_dir.c_str());
if (!res) {
const json json_err = {{"type", "SetOutputDirFailedToMkTree"}, {"path", output_dir}};
log_error(json_err);
}
return res;
}
//
static json LoadMeta(const std::string &path) {
ProfilerPerfSection perf("Manage/LoadMeta");
return LoadResourceMetaFromFile(FullInputPath(path));
return LoadResourceMetaFromFile(FullInputPath(path), true);
}
//
@ -900,7 +912,7 @@ void Texture(std::map<std::string, Hash> &hashes, std::string path) {
GetMetaValue(meta_db, "generate-mips", generate_mips, profile);
bool generate_probe = false;
GetMetaValue(meta_db, "generate-probe", generate_probe, profile);
int max_probe_size = 64;
int max_probe_size = 512;
GetMetaValue(meta_db, "max-probe-size", max_probe_size, profile);
bool radiance_edge_fixup = false;
GetMetaValue(meta_db, "radiance-edge-fixup", radiance_edge_fixup, profile);
@ -979,6 +991,8 @@ void Texture(std::map<std::string, Hash> &hashes, std::string path) {
Data build_ctx;
Write(build_ctx, max_probe_size);
Write(build_ctx, radiance_edge_fixup);
Write(build_ctx, 20); // gloss scale
Write(build_ctx, 0); // gloss bias
if (toolchain.cmft.empty()) {
warn(" Skipping, no compiler found for radiance probe resource");
@ -987,8 +1001,8 @@ void Texture(std::map<std::string, Hash> &hashes, std::string path) {
MkOutputTree(path + ".radiance");
CleanOutputs({path + ".radiance"});
const auto cmd = format("%1 --input \"%2\" --output0 \"%3\" --output0params dds,rgba16f,cubemap --useOpenCL false --filter radiance "
"--srcFaceSize %4 --edgeFixup %5")
const auto cmd = format("%1 --input \"%2\" --output0 \"%3\" --output0params dds,rgba16f,cubemap --useOpenCL true --filter radiance "
"--srcFaceSize %4 --edgeFixup %5 --glossScale 20 --glossBias 0")
.arg(toolchain.cmft)
.arg(src)
.arg(dst)
@ -1250,10 +1264,10 @@ static void BuildPipelineShaderVariant(std::map<std::string, Hash> &hashes, cons
const std::string &fs_path, const std::string &varying_path, const std::string &defines) {
ProfilerPerfSection perf("Manage/BuildPipelineShaderVariant");
size_t stage = 0;
size_t config = 0;
for (auto &variant : pipeline.configs) {
log(format(" Pipeline shader variant '%1' for pipeline config %2").arg(name).arg(stage));
const auto variant_name = format("%1_pipe-%2-cfg-%3").arg(name).arg(pipeline.name).arg(stage++);
log(format(" Pipeline shader variant '%1' for pipeline config %2").arg(name).arg(config));
const auto variant_name = format("%1_pipe-%2-cfg-%3").arg(name).arg(pipeline.name).arg(config++);
const auto variant_defines = join(std::begin(variant), std::end(variant), ";") + ";" + defines;
BuildShader(hashes, variant_name, vs_path, fs_path, varying_path, global_shader_defines + variant_defines);
}
@ -1276,7 +1290,7 @@ static bool IterateProgramFeatureStates(const std::vector<PipelineProgramFeature
process_states(feats, states);
}
return true;
};
}
static std::string GetDefines(const std::vector<PipelineProgramFeature> &feats, const std::vector<int> &states) {
std::vector<std::string> defines;
@ -1744,7 +1758,7 @@ static void OutputUsage(const CmdLineFormat &cmd_format) {
int wmain(int narg, wchar_t **argv) {
std::vector<std::string> args_utf8(narg + 1);
for (int i = 0; i < narg; ++i)
args_utf8[i] = hg::utf16_to_utf8(std::u16string((const char16_t *)argv[i]));
args_utf8[i] = hg::wchar_to_utf8(argv[i]);
std::vector<const char *> _args(narg + 1);
for (int i = 0; i < narg; ++i)

View File

@ -23,12 +23,11 @@ set_target_properties(assimp_converter PROPERTIES FOLDER "harfang/tools")
# add_dependencies(assimp_converter bind_hg_lua)
install(FILES $<TARGET_FILE:assimp_converter> DESTINATION assimp_converter COMPONENT assimp_converter)
install(TARGETS assimp_converter libluadll
install(TARGETS assimp_converter
RUNTIME DESTINATION assimp_converter
LIBRARY DESTINATION assimp_converter
COMPONENT assimp_converter
)
install(FILES $<TARGET_FILE:glfw> DESTINATION assimp_converter COMPONENT assimp_converter)
install_cppsdk_dependencies(assimp_converter)
install(TARGETS assimp_converter RUNTIME DESTINATION assimp_converter COMPONENT assimp_converter)

View File

@ -1,6 +1,11 @@
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
set(FBXSDK_ROOT_DIR ${HG_FBX_SDK})
if(UNIX AND NOT APPLE)
find_package(LibXml2 REQUIRED)
endif()
find_package(FBXSDK)
add_executable(fbx_converter fbx_converter.cpp)
@ -13,17 +18,9 @@ set_target_properties(fbx_converter PROPERTIES FOLDER "harfang/tools")
add_dependencies(fbx_converter bind_hg_lua)
install(FILES $<TARGET_FILE:fbxsdk> DESTINATION fbx_converter COMPONENT fbx_converter)
install(TARGETS libluadll fbx_converter LIBRARY DESTINATION fbx_converter RUNTIME DESTINATION fbx_converter COMPONENT fbx_converter)
install(TARGETS fbx_converter LIBRARY DESTINATION fbx_converter RUNTIME DESTINATION fbx_converter COMPONENT fbx_converter)
install(FILES $<TARGET_FILE:glfw> DESTINATION fbx_converter COMPONENT fbx_converter)
if(HG_ENABLE_OPENVR_API)
install(FILES ${OPENVR_DLL} DESTINATION fbx_converter COMPONENT fbx_converter)
endif()
if(HG_ENABLE_SRANIPAL_API)
install(FILES ${SRANIPAL_DLL} DESTINATION fbx_converter COMPONENT fbx_converter)
endif()
install_cppsdk_dependencies(fbx_converter)
if(HG_BUILD_TESTS)
add_subdirectory(tests)

View File

@ -98,46 +98,48 @@ find_package_handle_standard_args(FBXSDK
set(FBX_SDK_LIBRARIES ${FBX_SDK_LIBRARY})
if(FBXSDK_FOUND)
if(NOT TARGET fbxsdk)
add_library(fbxsdk SHARED IMPORTED)
set_target_properties(fbxsdk PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FBXSDK_INCLUDE_DIRECTORY}")
if(FBXSDK_FOUND AND NOT TARGET fbxsdk)
add_library(fbxsdk SHARED IMPORTED)
set_target_properties(fbxsdk PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FBXSDK_INCLUDE_DIRECTORY}")
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
if(FBXSDK_LIBRARY_RELEASE)
set_property(TARGET fbxsdk APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(fbxsdk PROPERTIES
IMPORTED_LOCATION_RELEASE ${FBXSDK_SHARED_LIBRARY_RELEASE}
IMPORTED_IMPLIB_RELEASE ${FBXSDK_LIBRARY_RELEASE}
)
endif()
if(FBXSDK_LIBRARY_DEBUG)
set_property(TARGET fbxsdk APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(fbxsdk PROPERTIES
IMPORTED_LOCATION_DEBUG ${FBXSDK_SHARED_LIBRARY_DEBUG}
IMPORTED_IMPLIB_DEBUG ${FBXSDK_LIBRARY_DEBUG}
)
endif()
if(NOT FBXSDK_LIBRARY_RELEASE AND NOT FBXSDK_LIBRARY_DEBUG)
set_property(TARGET fbxsdk APPEND PROPERTY IMPORTED_LOCATION "${FBXSDK_SHARED_LIBRARY}")
set_property(TARGET fbxsdk APPEND PROPERTY IMPORTED_IMPLIB "${FBXSDK_LIBRARY}")
endif()
else()
if(FBXSDK_LIBRARY_RELEASE)
set_property(TARGET fbxsdk APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(fbxsdk PROPERTIES IMPORTED_LOCATION_RELEASE "${FBXSDK_LIBRARY_RELEASE}")
endif()
if(FBXSDK_LIBRARY_DEBUG)
set_property(TARGET fbxsdk APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(fbxsdk PROPERTIES IMPORTED_LOCATION_DEBUG "${FBXSDK_LIBRARY_DEBUG}")
endif()
if(NOT FBXSDK_LIBRARY_RELEASE AND NOT FBXSDK_LIBRARY_DEBUG)
set_property(TARGET fbxsdk APPEND PROPERTY IMPORTED_LOCATION "${FBXSDK_LIBRARY}")
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
if(FBXSDK_LIBRARY_RELEASE)
set_property(TARGET fbxsdk APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(fbxsdk PROPERTIES
IMPORTED_LOCATION_RELEASE ${FBXSDK_SHARED_LIBRARY_RELEASE}
IMPORTED_IMPLIB_RELEASE ${FBXSDK_LIBRARY_RELEASE}
)
endif()
if(FBXSDK_LIBRARY_DEBUG)
set_property(TARGET fbxsdk APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(fbxsdk PROPERTIES
IMPORTED_LOCATION_DEBUG ${FBXSDK_SHARED_LIBRARY_DEBUG}
IMPORTED_IMPLIB_DEBUG ${FBXSDK_LIBRARY_DEBUG}
)
endif()
if(NOT FBXSDK_LIBRARY_RELEASE AND NOT FBXSDK_LIBRARY_DEBUG)
set_property(TARGET fbxsdk APPEND PROPERTY IMPORTED_LOCATION "${FBXSDK_SHARED_LIBRARY}")
set_property(TARGET fbxsdk APPEND PROPERTY IMPORTED_IMPLIB "${FBXSDK_LIBRARY}")
endif()
else()
if(FBXSDK_LIBRARY_RELEASE)
set_property(TARGET fbxsdk APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(fbxsdk PROPERTIES IMPORTED_LOCATION_RELEASE "${FBXSDK_LIBRARY_RELEASE}")
endif()
if(FBXSDK_LIBRARY_DEBUG)
set_property(TARGET fbxsdk APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(fbxsdk PROPERTIES IMPORTED_LOCATION_DEBUG "${FBXSDK_LIBRARY_DEBUG}")
endif()
if(NOT FBXSDK_LIBRARY_RELEASE AND NOT FBXSDK_LIBRARY_DEBUG)
set_property(TARGET fbxsdk APPEND PROPERTY IMPORTED_LOCATION "${FBXSDK_LIBRARY}")
endif()
if(UNIX AND NOT APPLE)
set_target_properties(fbxsdk PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES LibXml2::LibXml2)
endif()
endif()
endif()
endif()

View File

@ -68,7 +68,7 @@ struct Config {
float anim_simplify_color_tolerance = 0.001f;
bool fix_geo_orientation{false}; // FBX fix
float max_smoothing_angle{0.7f};
float max_smoothing_angle{45.f};
bool recalculate_normal{false}, recalculate_tangent{false};
bool calculate_normal_if_missing{false}, calculate_tangent_if_missing{false};
bool detect_geometry_instances{false};
@ -1010,8 +1010,10 @@ hg::ModelRef DoExportGeometry(FbxMesh *fbx_mesh, FbxNode *pNode, hg::Object &obj
if (use_skin)
ExportGeometrySkin(fbx_skin, geo);
float max_smoothing_angle = hg::Deg(config.max_smoothing_angle);
const auto vtx_to_pol = hg::ComputeVertexToPolygon(geo);
const auto vtx_normal = hg::ComputeVertexNormal(geo, vtx_to_pol, hg::Deg(45.f));
const auto vtx_normal = hg::ComputeVertexNormal(geo, vtx_to_pol, max_smoothing_angle);
// recalculate normals
bool recalculate_normal = config.recalculate_normal;
@ -1031,7 +1033,7 @@ hg::ModelRef DoExportGeometry(FbxMesh *fbx_mesh, FbxNode *pNode, hg::Object &obj
if (recalculate_tangent) {
hg::debug(" - Recalculate tangent frames (MikkT)");
if (!geo.uv[0].empty())
geo.tangent = hg::ComputeVertexTangent(geo, vtx_normal, 0, hg::Deg(45.f));
geo.tangent = hg::ComputeVertexTangent(geo, vtx_normal, 0, max_smoothing_angle);
}
// materials
@ -1671,7 +1673,7 @@ int main(int argc, const char **argv) {
config.calculate_normal_if_missing = hg::GetCmdLineFlagValue(cmd_content, "-calculate-normal-if-missing");
config.calculate_tangent_if_missing = hg::GetCmdLineFlagValue(cmd_content, "-calculate-tangent-if-missing");
config.max_smoothing_angle = hg::GetCmdLineSingleValue(cmd_content, "-max-smoothing-angle", 0.7f);
config.max_smoothing_angle = hg::GetCmdLineSingleValue(cmd_content, "-max-smoothing-angle", config.max_smoothing_angle);
config.calculate_tangent_if_missing = hg::GetCmdLineFlagValue(cmd_content, "-calculate-tangent-if-missing");
config.detect_geometry_instances = hg::GetCmdLineFlagValue(cmd_content, "-detect-geometry-instances");

View File

@ -15,17 +15,9 @@ function(gltf_build_tool name)
add_dependencies(${name} bind_hg_lua)
install(TARGETS ${name} libluadll RUNTIME DESTINATION ${name} LIBRARY DESTINATION ${name} COMPONENT ${name})
install(TARGETS ${name} RUNTIME DESTINATION ${name} LIBRARY DESTINATION ${name} COMPONENT ${name})
install(FILES $<TARGET_FILE:glfw> DESTINATION ${name} COMPONENT ${name})
if(HG_ENABLE_OPENVR_API)
install(FILES ${OPENVR_DLL} DESTINATION ${name} COMPONENT ${name})
endif()
if(HG_ENABLE_SRANIPAL_API)
install(FILES ${SRANIPAL_DLL} DESTINATION ${name} COMPONENT ${name})
endif()
install_cppsdk_dependencies(${name})
endfunction()

View File

@ -1191,7 +1191,7 @@ static void ExportObject(const Model &model, const Node &gltf_node, hg::Node &no
if (gltf_node.mesh >= 0) {
auto gltf_mesh = model.meshes[gltf_node.mesh];
if(!gltf_mesh.name.empty())
path = hg::CutFileExtension(gltf_mesh.name);
path = hg::CleanFileName(hg::CutFileExtension(gltf_mesh.name));
for (auto meshPrimitive : gltf_mesh.primitives)
// add id index to be sure to have this one particular geo
ids += std::to_string(meshPrimitive.indices) + "_";