Merge pull request #15 from harfang3dadmin/main

3.2.3 Release.
This commit is contained in:
HARFANG 3D (admin) 2022-07-25 09:32:04 +02:00 committed by GitHub
commit b2ff839cbd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 2905 additions and 73 deletions

View File

@ -101,6 +101,10 @@ if(MSVC)
#add_compile_options(/Od /Zi /Zo)
add_link_options(/DEBUG)
#add_link_options(/LTCG)
# Don't forget to remove this as soon as CMake is fixed.
# Tells MSVC to update __cplusplus value, otherwise it will be stuck to 199711L and libraries like bx (if updated) won't compile anymore even if we set CMAKE_CXX_STANDARD to C++14.
add_compile_options(/Zc:__cplusplus)
elseif(ANDROID)
add_compile_definitions(ANDROID)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")

View File

@ -1300,6 +1300,8 @@ def bind_scene(gen):
gen.bind_member(scene, 'hg::Scene::Environment environment')
gen.bind_method(scene, 'SetProbe', 'void', ['hg::TextureRef irradiance', 'hg::TextureRef radiance', 'hg::TextureRef brdf'])
#
gen.bind_method(scene, 'GetCurrentCamera', 'hg::Node', [])
gen.bind_method(scene, 'SetCurrentCamera', 'void', ['const hg::Node &camera'])
@ -1698,13 +1700,13 @@ static void __LuaVM_DestroyScripts(hg::SceneLuaVM *vm, const std::vector<hg::Scr
static hg::LuaObject __LuaVM_GetScriptEnv(hg::SceneLuaVM *vm, const hg::Script &script) { return vm->GetScriptEnv(script.ref); }
static hg::LuaObject __LuaVM_GetScriptValue(hg::SceneLuaVM *vm, const hg::Script &script, const std::string &name) { return vm->GetScriptValue(script.ref, name); }
static bool __LuaVM_SetScriptValue(hg::SceneLuaVM *vm, const hg::Script &script, const std::string &name, const hg::LuaObject &value) { return vm->SetScriptValue(script.ref, name, value); }
static bool __LuaVM_SetScriptValue(hg::SceneLuaVM *vm, const hg::Script &script, const std::string &name, const hg::LuaObject &value, bool notify = true) { return vm->SetScriptValue(script.ref, name, value, notify); }
''')
gen.bind_method(vm, 'GetScriptEnv', 'hg::LuaObject', ['const hg::Script &script'], {'route': route_lambda('__LuaVM_GetScriptEnv')})
gen.bind_method(vm, 'GetScriptValue', 'hg::LuaObject', ['const hg::Script &script', 'const std::string &name'], {'route': route_lambda('__LuaVM_GetScriptValue')})
gen.bind_method(vm, 'SetScriptValue', 'bool', ['const hg::Script &script', 'const std::string &name', 'const hg::LuaObject &value'], {'route': route_lambda('__LuaVM_SetScriptValue')})
gen.bind_method(vm, 'SetScriptValue', 'bool', ['const hg::Script &script', 'const std::string &name', 'const hg::LuaObject &value', '?bool notify'], {'route': route_lambda('__LuaVM_SetScriptValue')})
gen.bind_method_overloads(vm, 'Call', expand_std_vector_proto(gen, [
('bool', ['const hg::Script &script', 'const std::string &function', 'const std::vector<hg::LuaObject> &args', 'std::vector<hg::LuaObject> *ret_vals'], {'arg_out': ['ret_vals']})
@ -2658,8 +2660,8 @@ def bind_forward_pipeline(gen):
gen.end_class(fog)
# submit model to forward pipeline stage
gen.bind_function('hg::SubmitModelToForwardPipeline', 'void', ['bgfx::ViewId &view_id', 'const hg::Model &mdl', 'const hg::ForwardPipeline &pipeline', 'const hg::PipelineProgram &prg', 'uint32_t prg_variant',
'uint8_t pipeline_stage', 'const hg::Color &ambient', 'const hg::ForwardPipelineLights &lights', 'const hg::ForwardPipelineFog &fog', 'const hg::Mat4 &mtx'], {'arg_in_out': ['view_id']})
#gen.bind_function('hg::SubmitModelToForwardPipeline', 'void', ['bgfx::ViewId &view_id', 'const hg::Model &mdl', 'const hg::ForwardPipeline &pipeline', 'const hg::PipelineProgram &prg', 'uint32_t prg_variant',
#'uint8_t pipeline_stage', 'const hg::Color &ambient', 'const hg::ForwardPipelineLights &lights', 'const hg::ForwardPipelineFog &fog', 'const hg::Mat4 &mtx'], {'arg_in_out': ['view_id']})
def bind_file(gen):
gen.add_include('foundation/file.h')
@ -3609,11 +3611,10 @@ def bind_imgui(gen):
gen.bind_named_enum('ImGuiCond', ['ImGuiCond_Always', 'ImGuiCond_Once', 'ImGuiCond_FirstUseEver', 'ImGuiCond_Appearing'], 'int', namespace='')
gen.bind_named_enum('ImGuiMouseButton', [
'ImGuiPopupFlags_None',
'ImGuiPopupFlags_MouseButtonLeft', 'ImGuiPopupFlags_MouseButtonRight', 'ImGuiPopupFlags_MouseButtonMiddle',
'ImGuiPopupFlags_NoOpenOverExistingPopup', 'ImGuiPopupFlags_NoOpenOverItems',
'ImGuiPopupFlags_AnyPopupId', 'ImGuiPopupFlags_AnyPopupLevel', 'ImGuiPopupFlags_AnyPopup'
gen.bind_named_enum('ImGuiMouseButton', [
'ImGuiMouseButton_Left',
'ImGuiMouseButton_Right',
'ImGuiMouseButton_Middle',
], 'int', namespace='')
gen.bind_named_enum('ImGuiHoveredFlags', [

View File

@ -7,4 +7,5 @@
* François Gutherz
* Emmanuel Julien
* Eric Kernin
* Elie Michel
* Thomas "Scorpheus" Simonnet

View File

@ -1 +1 @@
A function taking a time value as parameter with no return value, see [man.UnitSystem].
A function taking a time value as parameter with no return value, see [man.CoordinateAndUnitSystem].

View File

@ -61,18 +61,18 @@ This file is a JSON file listing the supported features and additional uniforms.
The following features are supported and have the following effect on the compilation process.
Feature | States | Preprocessor Directive | Uniform | Stage channel
Feature | States | Preprocessor Directive | Uniform | Recommended channel
------- | ----------- | ---------------------- | ------- |--------------
OptionalBaseColorOpacityMap | 2 | USE_BASE_COLOR_OPACITY_MAP=[1 or 0] | uBaseOpacityMap | 0
OptionalDiffuseMap | 2 | USE_DIFFUSE_MAP=[1 or 0] | uDiffuseMap | 0
OptionalOcclusionRoughnessMetalnessMap | 2 | USE_OCCLUSION_ROUGHNESS_METALNESS_MAP=[1 or 0] | uOcclusionRoughnessMetalnessMap| 1
OptionalDiffuseMap | 2 | USE_DIFFUSE_MAP=[1 or 0] | uDiffuseMap | 3
OptionalSpecularMap | 2 | USE_SPECULAR_MAP=[1 or 0] | uSpecularMap | 1
OptionalNormalMap | 2 | USE_NORMAL_MAP=[1 or 0] | uNormalMap | 2
OptionalLightMap | 2 | USE_LIGHT_MAP=[1 or 0] | uLightMap | 3
OptionalSelfMap | 2 | USE_SELF_MAP=[1 or 0] | uSelfMap | 4
OptionalOpacityMap | 2 | USE_OPACITY_MAP=[1 or 0] | uOpacityMap | 5
OptionalAmbientMap | 2 | USE_AMBIENT_MAP=[1 or 0] | uAmbientMap | 6
OptionalReflectionMap | 2 | USE_REFLECTION_MAP=[1 or 0] | uReflectionMap | 7
OptionalNormalMap | 2 | USE_NORMAL_MAP=[1 or 0] | uNormalMap | 2
NormalMapInWorldSpace | 2 | NORMAL_MAP_IN_WORLD_SPACE=[1 or 0] | - | -
DiffuseUV1 | 2 | DIFFUSE_UV_CHANNEL=[1 or 0] | - | -
SpecularUV1 | 2 | SPECULAR_UV_CHANNEL=[1 or 0] | - | -

View File

@ -8,7 +8,7 @@ Once you have a functioning installation of Harfang for your language of choice:
Follow the following steps:
1. Download the tutorials from Github [here](https://github.com/harfang3d/tutorials-hg2.git) and unzip them to your computer _(eg. in `d:/tutorials-hg2`)_.
1. Download _assetc_ for your platform from [here](https://www.harfang3d.com/releases) to compile the tutorial resources.
1. Download _assetc_ for your platform from [here](https://dev.harfang3d.com/releases) to compile the tutorial resources.
1. Drag and drop the tutorial resources folder on the assetc executable **-OR-** execute assetc passing it the path to the tutorial resources folder _(eg. `assetc d:/tutorials-hg2/resources`)_.
![assetc drag & drop](/images/docs/${HG_VERSION}/assetc.gif)

View File

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

View File

@ -133,6 +133,17 @@ static bool Package_file_is_EOF(Asset_ &asset) { return asset.pkg_file.cursor >=
//
static generational_vector_list<Asset_> assets;
std::string FindAssetPath(const char *name) {
std::lock_guard<std::mutex> lock(assets_mutex);
for (auto &p : assets_folders) {
const auto asset_path = hg::PathJoin({p, name});
if (IsFile(asset_path.c_str()))
return asset_path;
}
return "";
}
Asset OpenAsset(const char *name, bool silent) {
std::lock_guard<std::mutex> lock(assets_mutex);

View File

@ -25,6 +25,7 @@ struct Asset {
gen_ref ref;
};
std::string FindAssetPath(const char *name);
Asset OpenAsset(const char *name, bool silent = false);
void Close(Asset asset);

View File

@ -386,6 +386,10 @@ static void ALChannelSetState(ALint src, const StereoSourceState &state, bool st
__AL_CALL(alSourcei(src, AL_LOOPING, !stream && state.repeat == SR_Loop ? AL_TRUE : AL_FALSE)); // [EJ20190512] looping is handled manually with streaming
__AL_CALL(alSource3f(src, AL_POSITION, state.panning, 0.f, sqrtf(1.f - state.panning * state.panning)));
const ALfloat o[6] = {0, 0, -1, 0, 1, 0};
__AL_CALL(alSourcefv(src, AL_ORIENTATION, o));
const ALfloat v[3] = {0, 0, 0};
__AL_CALL(alSourcefv(src, AL_VELOCITY, v));
}
static void ALChannelSetState(ALint src, const SpatializedSourceState &state, bool stream) {

View File

@ -64,7 +64,6 @@ enum ForwardPipelineUniformTexture {
UT_BrdfMap,
UT_NoiseMap,
UT_AmbientOcclusion,
UT_LinearShadowMap,
UT_SpotShadowMap,
@ -176,7 +175,7 @@ void UpdateForwardPipelineProbe(
}
void UpdateForwardPipelineNoise(ForwardPipeline &pipeline, Texture noise) { pipeline.uniform_textures[UT_NoiseMap].texture = noise; }
void UpdateForwardPipelineAO(ForwardPipeline &pipeline, Texture ao) { pipeline.uniform_textures[UT_AmbientOcclusion].texture = ao; }
void UpdateForwardPipelineAO(ForwardPipeline &pipeline, Texture ao) { /*pipeline.uniform_textures[UT_AmbientOcclusion].texture = ao;*/ }
//
static float backbuffer_ratio[bgfx::BackbufferRatio::Count] = {1.f, 2.f, 4.f, 8.f, 16.f, 0.5f};
@ -204,19 +203,6 @@ void UpdateForwardPipelineAAA(ForwardPipeline &pipeline, Texture ssgi, Texture s
}
//
void SubmitModelToForwardPipeline(bgfx::ViewId view_id, const Model &mdl, const ForwardPipeline &pipeline, const PipelineProgram &prg, uint32_t prg_variant,
uint8_t pipeline_stage, const Color &ambient, const ForwardPipelineLights &lights, const ForwardPipelineFog &fog, const Mat4 &mtx) {
const auto _mtx = to_bgfx(mtx);
/*
const auto pipeline_set_draw_env = [&](int mat_idx) {
UpdateForwardPipelineUniforms(pipeline.uniforms, ambient, lights, fog);
set_draw_env(mat_idx);
};
RenderModel(view_id, mdl, prg.variants[prg_variant][pipeline_stage], pipeline_set_draw_env, mtx);
*/
}
static Mat4 ComputeCropMatrix() {
const bgfx::Caps *caps = bgfx::getCaps();
const float sy = caps->originBottomLeft ? 0.5f : -0.5f;
@ -494,13 +480,12 @@ ForwardPipeline CreateForwardPipeline(int shadow_map_resolution, bool spot_16bit
__ASSERT__(pipeline.uniform_values.size() == UV_Count);
pipeline.uniform_textures = {
MakeUniformSetTexture("uIrradianceMap", {}, 7),
MakeUniformSetTexture("uRadianceMap", {}, 8),
MakeUniformSetTexture("uSSIrradianceMap", {}, 9),
MakeUniformSetTexture("uSSRadianceMap", {}, 10),
MakeUniformSetTexture("uBrdfMap", {}, 11),
MakeUniformSetTexture("uNoiseMap", {}, 12),
MakeUniformSetTexture("uAmbientOcclusion", {}, 13),
MakeUniformSetTexture("uIrradianceMap", {}, 8),
MakeUniformSetTexture("uRadianceMap", {}, 9),
MakeUniformSetTexture("uSSIrradianceMap", {}, 10),
MakeUniformSetTexture("uSSRadianceMap", {}, 11),
MakeUniformSetTexture("uBrdfMap", {}, 12),
MakeUniformSetTexture("uNoiseMap", {}, 13),
MakeUniformSetTexture("uLinearShadowMap", {BGFX_TEXTURE_RT | BGFX_SAMPLER_COMPARE_LEQUAL, pipeline.textures["linear_shadow_map"]}, 14),
MakeUniformSetTexture("uSpotShadowMap", {BGFX_TEXTURE_RT | BGFX_SAMPLER_COMPARE_LEQUAL, pipeline.textures["spot_shadow_map"]}, 15),
};

View File

@ -96,9 +96,6 @@ const PipelineInfo &GetForwardPipelineInfo();
//
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);
//
enum ForwardPipelineShadowPass { FPSP_Slot0LinearSplit0, FPSP_Slot0LinearSplit1, FPSP_Slot0LinearSplit2, FPSP_Slot0LinearSplit3, FPSP_Slot1Spot, FPSP_Count };

View File

@ -35,8 +35,7 @@ static HiZ _CreateHiZ(
hiz.pyramid_infos.format = bgfx::TextureFormat::RG32F;
bgfx::TextureHandle handle = rb_factory.create_texture2d(
ratio, hiz.pyramid_infos.numMips > 0,
hiz.pyramid_infos.numLayers, hiz.pyramid_infos.format, BGFX_TEXTURE_COMPUTE_WRITE | flags);
ratio, hiz.pyramid_infos.numMips > 0, hiz.pyramid_infos.numLayers, hiz.pyramid_infos.format, BGFX_TEXTURE_COMPUTE_WRITE | flags);
hiz.pyramid = MakeTexture(handle, BGFX_TEXTURE_COMPUTE_WRITE | flags);
hiz.prg_copy = LoadComputeProgram(ir, ip, format("%1/shader/hiz_copy_cs.sc").arg(path));
@ -66,11 +65,9 @@ void DestroyHiZ(HiZ &hiz) {
bgfx_Destroy(hiz.u_projection);
}
void ComputeHiZ(
bgfx::ViewId &view_id, const hg::iVec2 &fb_size, const iRect &rect, const Mat44 &proj, float z_thickness, const Texture &depth, HiZ &hiz) {
void ComputeHiZ(bgfx::ViewId &view_id, const hg::iVec2 &fb_size, const iRect &rect, const Mat44 &proj, float z_thickness, const Texture &depth, HiZ &hiz) {
__ASSERT__(IsValid(hiz));
int div = 1;
switch (hiz.ratio) {
case bgfx::BackbufferRatio::Half:
@ -88,7 +85,8 @@ void ComputeHiZ(
default:
div = 1;
break;
};
}
auto width = fb_size.x;
auto height = fb_size.y;
bgfx::calcTextureSize(hiz.pyramid_infos, width / div, height / div, hiz.pyramid_infos.depth, hiz.pyramid_infos.cubeMap, hiz.pyramid_infos.numMips,

View File

@ -15,6 +15,7 @@
#include "stb_image.h"
#include "stb_image_write.h"
#include "stb_image_resize.h"
namespace hg {
@ -143,7 +144,13 @@ void Picture::Clear() {
// TODO EJ implement these
Picture Crop(const Picture &picture, uint16_t width, uint16_t height) { return picture; }
Picture Resize(const Picture &picture, uint16_t width, uint16_t height) { return picture; }
Picture Resize(const Picture &picture, uint16_t width, uint16_t height) {
Picture pic(width, height, picture.GetFormat());
stbir_resize_uint8(picture.GetData(), picture.GetWidth(), picture.GetHeight(), picture.GetWidth() * size_of(picture.GetFormat()),
pic.GetData(), pic.GetWidth(), pic.GetHeight(), pic.GetWidth() * size_of(pic.GetFormat()), size_of(pic.GetFormat()));
return pic;
}
//
Color GetPixelRGBA(const Picture &pic, uint16_t x, uint16_t y) {

View File

@ -400,7 +400,8 @@ void SetMaterialSkinning(Material &m, bool enable);
bool GetMaterialAlphaCut(const Material &m);
void SetMaterialAlphaCut(Material &m, bool enable);
/// Compute a render state to control subsequent render calls culling mode, blending mode, Z mask, etc... The same render state can be used by different render calls.
/// Compute a render state to control subsequent render calls culling mode, blending mode, Z mask, etc... The same render state can be used by different render
/// calls.
/// @see DrawLines, DrawTriangles and DrawModel.
RenderState ComputeRenderState(BlendMode blend, bool write_z, bool write_r = true, bool write_g = true, bool write_b = true, bool write_a = true);
RenderState ComputeRenderState(BlendMode blend, DepthTest test = DT_Less, FaceCulling culling = FC_Clockwise, bool write_z = true, bool write_r = true,
@ -526,7 +527,8 @@ TextureRef LoadTextureFromAssets(const char *path, uint64_t flags, PipelineResou
/// Capture a texture content to a Picture. Return the frame counter at which the capture will be complete.
/// A Picture object can be accessed by the CPU.
/// This function is asynchronous and its result will not be available until the returned frame counter is equal or greater to the frame counter returned by Frame.
/// This function is asynchronous and its result will not be available until the returned frame counter is equal or greater to the frame counter returned by
/// Frame.
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,

View File

@ -30,6 +30,14 @@ Scene::~Scene() {
scene_ref->scene = nullptr;
}
//
void Scene::SetProbe(TextureRef irradiance, TextureRef radiance, TextureRef brdf) {
environment.probe = {};
environment.probe.irradiance_map = irradiance;
environment.probe.radiance_map = radiance;
environment.brdf_map = brdf;
}
//
static void _ResizeComponents(std::vector<ComponentRef> &cs) {
ptrdiff_t i;
@ -2631,6 +2639,24 @@ void SetAnimableNodePropertyColor(Scene &scene, NodeRef ref, const std::string &
}
}
//
std::vector<hg::Material *> Scene::GetMaterialsWithName(const std::string &name) {
std::vector<hg::Material *> mats;
mats.reserve(objects.size() / 8); // guesstimate
for (auto ref = objects.first_ref(); objects.is_valid(ref); ref = objects.next_ref(ref)) {
auto &obj = objects[ref.idx];
const auto mat_count = obj.material_infos.size();
for (size_t i = 0; i < mat_count; ++i)
if (obj.material_infos[i].name == name)
mats.push_back(&obj.materials[i]);
}
return mats;
}
//
std::string GetAnimableNodePropertyString(const Scene &scene, NodeRef ref, const std::string &name) {
if (const auto node = scene.GetNode(ref)) {

View File

@ -355,6 +355,8 @@ public:
Object GetNodeObject(NodeRef ref) const { return {scene_ref, GetNodeObjectRef(ref)}; }
void SetNodeObject(NodeRef ref, const Object &v) { SetNodeObject(ref, v.ref); }
std::vector<hg::Material *> GetMaterialsWithName(const std::string &name);
// light component
Light CreateLight();
void DestroyLight(ComponentRef ref);
@ -584,6 +586,8 @@ public:
Environment environment{};
void SetProbe(TextureRef irradiance, TextureRef radiance, TextureRef brdf);
// scene state
Node GetCurrentCamera() const { return {scene_ref, current_camera}; }
void SetCurrentCamera(NodeRef ref) { current_camera = ref; }

View File

@ -257,7 +257,7 @@ void SceneBullet3Physics::NodeCreatePhysics(const Node &node, const Reader &ir,
} else if (type == CT_Capsule) {
shapes.push_back(new btCapsuleShape(size.x, size.y));
} else if (type == CT_Cylinder) {
shapes.push_back(new btCylinderShape(btVector3(size.x, size.y, size.z)));
shapes.push_back(new btCylinderShape(btVector3(size.x, size.y * 0.5f, size.z)));
} else if (type == CT_Mesh) {
if (auto tree = LoadCollisionTree(ir, ip, col.GetCollisionResource().c_str()))
shapes.push_back(tree);

View File

@ -178,13 +178,17 @@ LuaObject SceneLuaVM::GetScriptValue(ComponentRef ref, const std::string &name)
return i == std::end(lua_scripts) ? LuaObject{} : Get(i->second, name);
}
bool SceneLuaVM::SetScriptValue(ComponentRef ref, const std::string &name, const LuaObject &v) {
bool SceneLuaVM::SetScriptValue(ComponentRef ref, const std::string &name, const LuaObject &v, bool notify) {
auto i = lua_scripts.find(ref);
if (i == std::end(lua_scripts))
return false;
SetForeign(i->second, name, v);
if (notify)
Call(ref, "OnSetScriptValue", {MakeLuaObj(L, name)});
return true;
}
@ -312,8 +316,10 @@ std::vector<ComponentRef> SceneLuaVM::GarbageCollect(const Scene &scene) const {
void SceneLuaVM::DestroyScripts(const std::vector<ComponentRef> &scripts) {
for (auto ref : scripts) {
auto i = lua_scripts.find(ref);
if (i != std::end(lua_scripts))
if (i != std::end(lua_scripts)) {
Call(ref, "OnDestroy", {});
lua_scripts.erase(i);
}
}
}

View File

@ -65,7 +65,7 @@ public:
/// Return the value of a script variable.
LuaObject GetScriptValue(ComponentRef script, const std::string &name) const;
/// Set the value of a script variable.
bool SetScriptValue(ComponentRef script, const std::string &name, const LuaObject &value);
bool SetScriptValue(ComponentRef script, const std::string &name, const LuaObject &value, bool notify = true);
/// Return the VM lua state.
lua_State *GetL() const { return L; }

View File

@ -118,16 +118,6 @@ static void CallScriptDetachFromNode(SceneLuaVM &vm, Node &node, const Script &s
//
static size_t SceneScriptsDestroyGarbageCall(SceneLuaVM &vm, Scene &scene) {
const auto garbage = vm.GarbageCollect(scene);
for (auto s : garbage) {
auto env = vm.GetScriptEnv(s);
if (auto on_destroy = Get(env, "OnDestroy")) {
on_destroy.Push();
hg_lua_OnDestroy(env.L(), -1);
}
}
vm.DestroyScripts(garbage);
return garbage.size();
}

File diff suppressed because it is too large Load Diff

View File

@ -164,6 +164,7 @@ set_property(TARGET foundation PROPERTY PUBLIC_HEADER "${HDRS}")
set_target_properties(foundation PROPERTIES FOLDER "harfang")
if(NOT WIN32)
find_package(uuid REQUIRED)
target_link_libraries(foundation PUBLIC uuid)
else()
target_link_libraries(foundation PUBLIC Iphlpapi)

View File

@ -156,7 +156,7 @@ bool LineIntersectCone(const Vec3 &a, const Vec3 &v, const Vec3 &c, const Vec3 &
if (((t0 < h0) || (t0 > h1)) && ((t1 < h0) || (t1 > h1))) {
return false;
}
} else if (dvac > h) {
} else if (ddac > h) {
return false;
}

View File

@ -15,6 +15,9 @@ static bool log_is_detailed = false;
void set_log_level(int level) { log_level = level; }
void set_log_detailed(bool is_detailed) { log_is_detailed = is_detailed; }
int get_log_level() { return log_level; }
bool get_log_detailed() { return log_is_detailed; }
//
static void default_log_hook(const char *msg, int mask, const char *details, void *user) {

View File

@ -17,5 +17,7 @@ void set_log_hook(void (*on_log)(const char *msg, int mask, const char *details,
void set_log_level(int log_level);
/// Enable detailed log output.
void set_log_detailed(bool is_detailed);
int get_log_level();
bool get_log_detailed();
} // namespace hg

View File

@ -9,6 +9,7 @@
#include <cctype>
#include <locale>
#include <sstream>
#include <memory>
#include <codecvt>

View File

@ -221,6 +221,14 @@ bool SaveFileDialog(const std::string &title, const std::vector<hg::FileFilter>
}
pFileSave->Release();
}
// ensure extension is present
const auto ext = hg::GetFileExtension(output);
if (ext.empty() && !filters.empty())
if (filters[0].pattern.size() > 2)
output += &filters[0].pattern[1];
return SUCCEEDED(hr);
}

View File

@ -129,6 +129,7 @@ TEST(BGFX, RenderModelNoPipeline) {
}
//
/*
TEST(BGFX, SubmitModelToForwardPipeline) {
InputInit();
@ -192,6 +193,7 @@ TEST(BGFX, SubmitModelToForwardPipeline) {
RenderShutdown();
DestroyWindow(window);
}
*/
//
TEST(BGFX, AddModelToSceneAndSubmitToForwardPipeline) {

View File

@ -1 +1 @@
3.2.2
3.2.3

View File

@ -13,7 +13,7 @@ See https://www.harfang3d.com/license for licensing terms.
| **Quickstart**
1. Download the tutorials https://github.com/harfang3d/tutorials-hg2 and unzip them to your computer (eg. *d:/tutorials-hg2*).
2. To compile the tutorial resources, download **assetc** for your platform: https://www.harfang3d.com/releases/
2. To compile the tutorial resources, download **assetc** for your platform: https://dev.harfang3d.com/releases/
3. Drag and drop the tutorial resources folder on the **`assetc** executable -OR- execute **assetc** passing it the path to the tutorial resources folder (eg. *assetc d:/tutorials-hg2/resources*).
.. image:: https://raw.githubusercontent.com/harfang3d/image-storage/main/tutorials/assetc.gif

View File

@ -56,6 +56,12 @@ Physics API
Audio API
* Play/stream WAV/OGG formats
* 3D audio spatialization
Languages supported
* C++
* Python _(3.2+)_
* Lua _(5.3)_
* Go _(1+, experimental)_
<a name="subsection_1b"></a>
## Screenshots
@ -84,6 +90,7 @@ https://dev.harfang3d.com/releases
* CPython 3.2+
* Go 1+ _(for Harfang Go module)_
* Doxygen _(for Harfang C++ SDK documentation)_
* Autodesk FBX SDK _(for FBX Converter)_
### Windows
* Visual Studio 2019 _(C++ compiler and IDE)_

View File

@ -1,3 +1,49 @@
# [3.2.3] - 2022-08-13
This minor release brings several fixes to the rendering, physics, engine, foundation and tools.
### Framework integration and source code maintenance
- Added a CMake option to force MSVC to use updated __cplusplus macro.
- Build fixes for GCC 12.
### Toolchain
- Added a way to select the input channel from an input texture within a `construct` when processing textures in **Assetc**.
- Changed `BC6H_UF16` into `BC6H_SF16` to produce a valid DDS from a HDR file.
- **Assetc** now parses the shaders to check their dependencies for any modification and triggers a rebuild if needed.
- Properly quote **Luac** and **Recastc** invocations to support space in arguments.
### Binding
- Fixed `ImGuiMouseButton` enums (`ImGuiMouseButton_Left`, `ImGuiMouseButton_Right`, `ImGuiMouseButton_Middle`).
- Added a `SetProbe` function to set the radiance and irradiance map to a scene.
- :warning: Deprecated `SubmitModelToForwardPipeline`.
### Engine
- Added `GetMaterialsWithName`.
- Added `GetFullPathAsset`
- Added `get_log_level`, `get_log_detailed` functions.
- Fixed the ray/cone intersection.
- Ensure an extension is specified before returning output path from `SaveFileDialog`.
- Fixed the reserved texture units used by the **AAA** pipeline (see https://dev.harfang3d.com/docs/3.2.3/man.pipelineshader/). As a consequence, the `core\` folder will need to be updated if your project is using the **Forward** or **AAA** rendering pipelines.
- Fixed a nasty issue in forward pipeline texture table.
- :warning: Deprecated `UpdateForwardPipelineAO` and `UT_AmbientOcclusion`.
### Physics
- Fixed #14, Bullet uses half extend for cylinders.
### Audio
- Fixed #13, properly reset OpenAL source velocity when starting a stereo sound.
### Documentation
- Fixed a dead link in the API documentation.
- URLs updates (Quickstart, Wheel description, Readme file).
# [3.2.2] - 2022-06-03
This minor release brings several fixes, a better implementation of the AAA rendering pipeline including probe reprojection and a more stable screen space raytracer.<br>

View File

@ -714,7 +714,7 @@ static std::string Get_texconv_Format(const std::string &f) {
if (f == "BC5")
return "BC5_UNORM";
if (f == "BC6H")
return "BC6H_UF16";
return "BC6H_SF16";
if (f == "BC7")
return "BC7_UNORM";
return "";
@ -743,6 +743,10 @@ static bool PreprocessTexture(const json &i_preprocess_texture, std::map<std::st
dependencies.insert(path); // swizzle from input texture
else
dependencies.insert(channel_v); // swizzle from foreign texture
} else if (v.is_object()) { // channel or texture path
const auto dep_path = v["path"].get<std::string>();
const auto channel_v = v["channel"].get<std::string>();
dependencies.insert(dep_path);
}
}
} else {
@ -785,8 +789,8 @@ static bool PreprocessTexture(const json &i_preprocess_texture, std::map<std::st
// conform dependencies
for (auto i : picture_dependencies)
if (i.second.GetWidth() != out_width && i.second.GetHeight() != out_height) {
error(format("Cannot construct '%1' due to dependency '%2' with incompatible resolution").arg(path).arg(i.first));
return false;
// resize
picture_dependencies[i.first] = hg::Resize(i.second, out_width, out_height);
}
//
@ -872,6 +876,35 @@ static bool PreprocessTexture(const json &i_preprocess_texture, std::map<std::st
in_stride = size_of(in_pic.GetFormat());
}
for (uint16_t y = 0; y < out_height; ++y)
for (uint16_t x = 0; x < out_width; ++x) {
*out = *in;
in += in_stride;
out += out_stride;
}
} else if (v.is_object()) { // channel and texture path
const auto dep_path = v["path"].get<std::string>();
auto &in_pic = picture_dependencies[dep_path];
const char *channel_names[] = {"R", "G", "B", "A"};
const auto input_channel_v = v["channel"].get<std::string>();
size_t input_channel = 5;
for (size_t c = 0; c < 4; ++c)
if (input_channel_v == channel_names[c]) {
input_channel = c;
break;
}
if (GetChannelCount(in_pic.GetFormat()) <= input_channel) {
error(format("Cannot construct '%1' due to '%2' missing %3 channel").arg(path).arg(dep_path).arg(input_channel));
return false;
}
uint8_t *in = in_pic.GetData() + input_channel;
size_t in_stride = size_of(in_pic.GetFormat());
for (uint16_t y = 0; y < out_height; ++y)
for (uint16_t x = 0; x < out_width; ++x) {
*out = *in;
@ -1096,6 +1129,28 @@ void Geometry(std::map<std::string, Hash> &hashes, const std::string &path) {
}
}
//
void GatherShaderDependencies(const std::string &path, std::set<std::string> &deps, const std::string &base) {
const auto rel_path = base + path;
if (deps.find(rel_path) != std::end(deps))
return; // processed already, don't need no cyclic references
deps.insert(rel_path);
const auto src = hg::FileToString(FullInputPath(rel_path).c_str());
static std::regex include_regex("#include\\s*(?:\"|<)(.+)(?:\"|>)");
const auto base_path = hg::GetFilePath(rel_path); // #include directives are relative to the current source
for (std::sregex_iterator i = std::sregex_iterator(src.begin(), src.end(), include_regex); i != std::sregex_iterator(); ++i)
GatherShaderDependencies((*i)[1], deps, base_path); // recurse down the dependency tree
}
void GatherShaderDependencies(const std::set<std::string> &paths, std::set<std::string> &deps) {
for (const auto &path : paths)
GatherShaderDependencies(path, deps, "");
}
//
static void BuildComputeShader(std::map<std::string, Hash> &hashes, const std::string &cs_path, const std::string &defines) {
ProfilerPerfSection perf("Command/ComputeShader");
@ -1128,7 +1183,10 @@ static void BuildComputeShader(std::map<std::string, Hash> &hashes, const std::s
if (toolchain.shaderc.empty()) {
warn(" Skipping, no compiler found for compute resource");
} else {
if (NeedsCompilation(hashes, {cs_path}, {cs_path}, cs_build_ctx)) {
std::set<std::string> inputs;
GatherShaderDependencies({cs_path}, inputs);
if (NeedsCompilation(hashes, inputs, {cs_path}, cs_build_ctx)) {
if (!cs_profile.empty()) // GLES profile must be empty...
cs_profile = "-p " + cs_profile;
@ -1194,7 +1252,10 @@ static void BuildShader(std::map<std::string, Hash> &hashes, const std::string &
if (toolchain.shaderc.empty()) {
warn(" Skipping, no compiler found for shader resource");
} else {
if (NeedsCompilation(hashes, {vs_path, varying_path}, {vs_name}, vs_build_ctx)) {
std::set<std::string> inputs;
GatherShaderDependencies({vs_path, varying_path}, inputs);
if (NeedsCompilation(hashes, inputs, {vs_name}, vs_build_ctx)) {
if (!vs_profile.empty()) // GLES profile must be empty...
vs_profile = "-p " + vs_profile;
@ -1232,7 +1293,10 @@ static void BuildShader(std::map<std::string, Hash> &hashes, const std::string &
if (toolchain.shaderc.empty()) {
warn(" Skipping, no compiler found for shader resource");
} else {
if (NeedsCompilation(hashes, {fs_path, varying_path}, {fs_name}, fs_build_ctx)) {
std::set<std::string> inputs;
GatherShaderDependencies({fs_path, varying_path}, inputs);
if (NeedsCompilation(hashes, inputs, {fs_name}, fs_build_ctx)) {
if (!fs_profile.empty())
fs_profile = "-p " + fs_profile;
@ -1387,7 +1451,7 @@ static void LuaScript(std::map<std::string, Hash> &hashes, const std::string &pa
MkOutputTree(path);
CleanOutputs({path});
const auto cmd = format("%1 -o %3 -s %2").arg(toolchain.luac).arg(src).arg(dst);
const auto cmd = format("%1 -o \"%3\" -s \"%2\"").arg(toolchain.luac).arg(src).arg(dst);
PushAsyncProcessTask(path, cmd, cwd);
} else {
debug(" [O] Lua script up to date");
@ -1418,7 +1482,7 @@ static void PathFinding(std::map<std::string, Hash> &hashes, const std::string &
MkOutputTree(path);
CleanOutputs({path});
const auto cmd = format("%1 %2 %3 -root %4").arg(toolchain.recastc).arg(src).arg(dst).arg(input_dir);
const auto cmd = format("%1 \"%2\" \"%3\" -root \"%4\"").arg(toolchain.recastc).arg(src).arg(dst).arg(input_dir);
PushAsyncProcessTask(path, cmd, GetCurrentWorkingDirectory());
} else {
debug(" [O] Pathfinding resource up to date");